Merge "Add new SPN format for "WiFi Call"." into udc-dev
diff --git a/Android.bp b/Android.bp
index effd7ce..bc6cda3 100644
--- a/Android.bp
+++ b/Android.bp
@@ -224,7 +224,6 @@
         "android.hardware.radio.messaging-V2-java",
         "android.hardware.radio.modem-V2-java",
         "android.hardware.radio.network-V2-java",
-        "android.hardware.radio.satellite-V1-java",
         "android.hardware.radio.sim-V2-java",
         "android.hardware.radio.voice-V2-java",
         "android.hardware.thermal-V1.0-java-constants",
@@ -580,7 +579,7 @@
     "--hide Todo " +
     "--hide Typo " +
     "--hide UnavailableSymbol " +
-    "--manifest $(location core/res/AndroidManifest.xml) "
+    "--manifest $(location :frameworks-base-core-AndroidManifest.xml) "
 
 packages_to_document = [
     "android",
@@ -617,7 +616,7 @@
     sdk_version: "none",
     system_modules: "none",
     java_version: "1.8",
-    arg_files: ["core/res/AndroidManifest.xml"],
+    arg_files: [":frameworks-base-core-AndroidManifest.xml"],
     aidl: {
         local_include_dirs: [
             "media/aidl",
@@ -696,12 +695,3 @@
     "ProtoLibraries.bp",
     "TestProtoLibraries.bp",
 ]
-
-java_api_contribution {
-    name: "api-stubs-docs-non-updatable-public-stubs",
-    api_surface: "public",
-    api_file: "core/api/current.txt",
-    visibility: [
-        "//build/orchestrator/apis",
-    ],
-}
diff --git a/OWNERS b/OWNERS
index 09a721f..dad8bfe 100644
--- a/OWNERS
+++ b/OWNERS
@@ -30,8 +30,11 @@
 # Support bulk translation updates
 per-file */res*/values*/*.xml = byi@google.com, delphij@google.com
 
+per-file **.bp,**.mk = hansson@google.com
 per-file *.bp = file:platform/build/soong:/OWNERS #{LAST_RESORT_SUGGESTION}
 per-file Android.mk = file:platform/build/soong:/OWNERS #{LAST_RESORT_SUGGESTION}
 per-file framework-jarjar-rules.txt = file:platform/build/soong:/OWNERS #{LAST_RESORT_SUGGESTION}
 per-file TestProtoLibraries.bp = file:platform/platform_testing:/libraries/health/OWNERS
 per-file TestProtoLibraries.bp = file:platform/tools/tradefederation:/OWNERS
+
+per-file ZYGOTE_OWNERS = file:/ZYGOTE_OWNERS
diff --git a/StubLibraries.bp b/StubLibraries.bp
index 38413c2..b005591 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -36,8 +36,8 @@
     args: metalava_framework_docs_args,
     check_api: {
         current: {
-            api_file: "core/api/current.txt",
-            removed_api_file: "core/api/removed.txt",
+            api_file: ":non-updatable-current.txt",
+            removed_api_file: ":non-updatable-removed.txt",
         },
         last_released: {
             api_file: ":android-non-updatable.api.public.latest",
@@ -88,8 +88,8 @@
     args: metalava_framework_docs_args + priv_apps,
     check_api: {
         current: {
-            api_file: "core/api/system-current.txt",
-            removed_api_file: "core/api/system-removed.txt",
+            api_file: ":non-updatable-system-current.txt",
+            removed_api_file: ":non-updatable-system-removed.txt",
         },
         last_released: {
             api_file: ":android-non-updatable.api.system.latest",
@@ -99,7 +99,7 @@
         api_lint: {
             enabled: true,
             new_since: ":android.api.system.latest",
-            baseline_file: "core/api/system-lint-baseline.txt",
+            baseline_file: ":non-updatable-system-lint-baseline.txt",
         },
     },
     dists: [
@@ -127,12 +127,12 @@
     args: metalava_framework_docs_args + test + priv_apps_in_stubs,
     check_api: {
         current: {
-            api_file: "core/api/test-current.txt",
-            removed_api_file: "core/api/test-removed.txt",
+            api_file: ":non-updatable-test-current.txt",
+            removed_api_file: ":non-updatable-test-removed.txt",
         },
         api_lint: {
             enabled: true,
-            baseline_file: "core/api/test-lint-baseline.txt",
+            baseline_file: ":non-updatable-test-lint-baseline.txt",
         },
     },
     dists: [
@@ -172,8 +172,8 @@
     args: metalava_framework_docs_args + priv_apps_in_stubs + module_libs,
     check_api: {
         current: {
-            api_file: "core/api/module-lib-current.txt",
-            removed_api_file: "core/api/module-lib-removed.txt",
+            api_file: ":non-updatable-module-lib-current.txt",
+            removed_api_file: ":non-updatable-module-lib-removed.txt",
         },
         last_released: {
             api_file: ":android-non-updatable.api.module-lib.latest",
@@ -183,7 +183,7 @@
         api_lint: {
             enabled: true,
             new_since: ":android.api.module-lib.latest",
-            baseline_file: "core/api/module-lib-lint-baseline.txt",
+            baseline_file: ":non-updatable-module-lib-lint-baseline.txt",
         },
     },
     dists: [
@@ -364,15 +364,15 @@
 
 java_library {
     name: "android_system_server_stubs_current",
-    defaults: ["android_stubs_dists_default"],
+    defaults: [
+        "android.jar_defaults",
+        "android_stubs_dists_default",
+    ],
     srcs: [":services-non-updatable-stubs"],
     installable: false,
     static_libs: [
         "android_module_lib_stubs_current",
     ],
-    sdk_version: "none",
-    system_modules: "none",
-    java_version: "1.8",
     dist: {
         dir: "apistubs/android/system-server",
     },
@@ -575,20 +575,7 @@
 
 droidstubs {
     name: "hwbinder-stubs-docs",
-    srcs: [
-        "core/java/android/os/HidlSupport.java",
-        "core/java/android/os/HidlMemory.java",
-        "core/java/android/os/HwBinder.java",
-        "core/java/android/os/HwBlob.java",
-        "core/java/android/os/HwParcel.java",
-        "core/java/android/os/IHwBinder.java",
-        "core/java/android/os/IHwInterface.java",
-        "core/java/android/os/DeadObjectException.java",
-        "core/java/android/os/DeadSystemException.java",
-        "core/java/android/os/NativeHandle.java",
-        "core/java/android/os/RemoteException.java",
-        "core/java/android/util/AndroidException.java",
-    ],
+    srcs: [":hwbinder-stubs-srcs"],
     libs: ["framework-annotations-lib"],
     installable: false,
     sdk_version: "core_platform",
@@ -610,12 +597,3 @@
     ],
     visibility: ["//visibility:public"],
 }
-
-java_api_contribution {
-    name: "frameworks-base-core-api-module-lib-stubs",
-    api_surface: "module-lib",
-    api_file: "core/api/module-lib-current.txt",
-    visibility: [
-        "//build/orchestrator/apis",
-    ],
-}
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 9610f2c..81a3479 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -65,6 +65,15 @@
       ]
     },
     {
+      "name": "FrameworksInputMethodSystemServerTests",
+      "options": [
+        {"include-filter": "com.android.server.inputmethod"},
+        {"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
+        {"exclude-annotation": "androidx.test.filters.FlakyTest"},
+        {"exclude-annotation": "org.junit.Ignore"}
+      ]
+    },
+    {
       "name": "ExtServicesUnitTests",
       "options": [
         {
diff --git a/ZYGOTE_OWNERS b/ZYGOTE_OWNERS
index 90a185b..f6d15e0 100644
--- a/ZYGOTE_OWNERS
+++ b/ZYGOTE_OWNERS
@@ -1,4 +1,3 @@
-calin@google.com
 chriswailes@google.com
 maco@google.com
 narayan@google.com
diff --git a/apct-tests/perftests/core/OWNERS b/apct-tests/perftests/core/OWNERS
index 8fb057d..6abab6e 100644
--- a/apct-tests/perftests/core/OWNERS
+++ b/apct-tests/perftests/core/OWNERS
@@ -3,4 +3,12 @@
 
 # Bug component: 568761
 per-file /apct-tests/perftests/core/res/* = felkachang@google.com,zyy@google.com
+per-file /apct-tests/perftests/core/res/* = file:/core/java/android/content/om/OWNERS
+per-file /apct-tests/perftests/core/src/android/content/res/* = felkachang@google.com
+per-file /apct-tests/perftests/core/src/android/content/res/* = file:/core/java/android/content/res/OWNERS
+
+
+# Bug component: 568631
+per-file /apct-tests/perftests/core/src/android/content/om/* = felkachang@google.com
+per-file /apct-tests/perftests/core/src/android/content/om/* = file:/core/java/android/content/om/OWNERS
 
diff --git a/apct-tests/perftests/core/src/android/input/MotionPredictorBenchmark.kt b/apct-tests/perftests/core/src/android/input/MotionPredictorBenchmark.kt
index fabf889..9482591 100644
--- a/apct-tests/perftests/core/src/android/input/MotionPredictorBenchmark.kt
+++ b/apct-tests/perftests/core/src/android/input/MotionPredictorBenchmark.kt
@@ -33,7 +33,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 
 import org.junit.After
-import org.junit.Assert.assertEquals
 import org.junit.Assert.assertTrue
 import org.junit.Before
 import org.junit.Rule
@@ -132,8 +131,7 @@
             predictor.record(moveEvent)
             val predictionTime = eventTime + eventInterval
             val predicted = predictor.predict(predictionTime.toNanos())
-            assertEquals(1, predicted.size)
-            assertTrue(predicted[0].eventTime <= (predictionTime + offset).toMillis())
+            assertTrue(predicted.eventTime <= (predictionTime + offset).toMillis())
         }
     }
 
diff --git a/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTest.java b/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTest.java
index 2e44d82..e9c6c1a 100644
--- a/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTest.java
+++ b/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTest.java
@@ -76,6 +76,7 @@
         implements ManualBenchmarkState.CustomizedIterationListener {
     private static final String TAG = ImePerfTest.class.getSimpleName();
     private static final long ANIMATION_NOT_STARTED = -1;
+    private static final int WAIT_PROCESS_KILL_TIMEOUT_MS = 2000;
 
     @Rule
     public final PerfManualStatusReporter mPerfStatusReporter = new PerfManualStatusReporter();
@@ -248,19 +249,18 @@
         boolean shouldRetry = false;
         while (shouldRetry || state.keepRunning(measuredTimeNs)) {
             shouldRetry = false;
-            killBaselineIme();
+            killBaselineImeSync();
             try (ImeSession imeSession = new ImeSession(BaselineIme.getName(
                     getInstrumentation().getContext()))) {
+                if (!mIsTraceStarted) {
+                    startAsyncAtrace();
+                }
                 final AtomicReference<CountDownLatch> latchStart = new AtomicReference<>();
                 final Activity activity = getActivityWithFocus();
 
                 setImeListener(activity, latchStart, null /* latchEnd */);
                 latchStart.set(new CountDownLatch(1));
 
-                if (!mIsTraceStarted) {
-                    startAsyncAtrace();
-                }
-
                 final WindowInsetsController controller =
                         activity.getWindow().getDecorView().getWindowInsetsController();
                 AtomicLong startTime = new AtomicLong();
@@ -270,6 +270,7 @@
                 });
 
                 measuredTimeNs = waitForAnimationStart(latchStart, startTime);
+                stopAsyncAtraceAndDumpTraces();
 
                 if (measuredTimeNs == ANIMATION_NOT_STARTED) {
                     // Animation didn't start within timeout,
@@ -285,7 +286,7 @@
         addResultToState(state);
     }
 
-    private void killBaselineIme() {
+    private void killBaselineImeSync() {
         // pidof returns a space separated list of numeric PIDs.
         String result = SystemUtil.runShellCommand(
                 "pidof com.android.perftests.inputmethod:BaselineIME");
@@ -294,7 +295,13 @@
             if (TextUtils.isEmpty(pid)) {
                 continue;
             }
-            Process.killProcess(Integer.parseInt(pid));
+            final int pidToKill = Integer.parseInt(pid);
+            Process.killProcess(pidToKill);
+            try {
+                // Wait kill IME process being settled down.
+                Process.waitForProcessDeath(pidToKill, WAIT_PROCESS_KILL_TIMEOUT_MS);
+            } catch (Exception e) {
+            }
         }
     }
 
@@ -381,7 +388,7 @@
             }
         } finally {
             if (mIsTraceStarted) {
-                stopAsyncAtrace();
+                stopAsyncAtraceAndDumpTraces();
             }
         }
         mActivityRule.finishActivity();
@@ -488,7 +495,7 @@
         startAsyncAtrace("wm view");
     }
 
-    private void stopAsyncAtrace() {
+    private void stopAsyncAtraceAndDumpTraces() {
         if (!mIsTraceStarted) {
             return;
         }
@@ -504,6 +511,14 @@
         }
     }
 
+    private void stopAsyncAtrace() {
+        if (!mIsTraceStarted) {
+            return;
+        }
+        mIsTraceStarted = false;
+        getUiAutomation().executeShellCommand("atrace --async_stop");
+    }
+
     @Override
     public void onStart(int iteration) {
         // Do not capture trace when profiling because the result will be much slower.
diff --git a/apct-tests/perftests/settingsprovider/src/android/provider/SettingsProviderPerfTest.java b/apct-tests/perftests/settingsprovider/src/android/provider/SettingsProviderPerfTest.java
index e31162f..c00c8d5 100644
--- a/apct-tests/perftests/settingsprovider/src/android/provider/SettingsProviderPerfTest.java
+++ b/apct-tests/perftests/settingsprovider/src/android/provider/SettingsProviderPerfTest.java
@@ -39,6 +39,7 @@
     private static final String NAMESPACE = "test@namespace";
     private static final String SETTING_NAME1 = "test:setting1";
     private static final String SETTING_NAME2 = "test-setting2";
+    private static final String UNSET_SETTING = "test_unset_setting";
 
     private final ContentResolver mContentResolver;
 
@@ -93,6 +94,14 @@
     }
 
     @Test
+    public void testSettingsValueConsecutiveReadUnset() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Settings.Secure.getString(mContentResolver, UNSET_SETTING);
+        }
+    }
+
+    @Test
     public void testSettingsNamespaceConsecutiveRead() {
         final List<String> names = new ArrayList<>();
         names.add(SETTING_NAME1);
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfTestBase.java b/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfTestBase.java
index ca59137..804baf4 100644
--- a/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfTestBase.java
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfTestBase.java
@@ -73,7 +73,7 @@
     }
 
     public static void startAsyncAtrace(String tags) {
-        getUiAutomation().executeShellCommand("atrace -b 32768 --async_start " + tags);
+        getUiAutomation().executeShellCommand("atrace --async_start -b 32768 -c " + tags);
         // Avoid atrace isn't ready immediately.
         SystemClock.sleep(TimeUnit.NANOSECONDS.toMillis(TIME_1_S_IN_NS));
     }
diff --git a/apex/jobscheduler/service/java/com/android/server/JobSchedulerBackgroundThread.java b/apex/jobscheduler/service/java/com/android/server/AppSchedulingModuleThread.java
similarity index 69%
rename from apex/jobscheduler/service/java/com/android/server/JobSchedulerBackgroundThread.java
rename to apex/jobscheduler/service/java/com/android/server/AppSchedulingModuleThread.java
index a413f7b..d36f44f 100644
--- a/apex/jobscheduler/service/java/com/android/server/JobSchedulerBackgroundThread.java
+++ b/apex/jobscheduler/service/java/com/android/server/AppSchedulingModuleThread.java
@@ -20,29 +20,30 @@
 import android.os.HandlerExecutor;
 import android.os.HandlerThread;
 import android.os.Looper;
+import android.os.Process;
 import android.os.Trace;
 
 import java.util.concurrent.Executor;
 
 /**
- * Shared singleton background thread.
+ * Shared singleton default priority thread for the app scheduling module.
  *
  * @see com.android.internal.os.BackgroundThread
  */
-public final class JobSchedulerBackgroundThread extends HandlerThread {
+public final class AppSchedulingModuleThread extends HandlerThread {
     private static final long SLOW_DISPATCH_THRESHOLD_MS = 10_000;
     private static final long SLOW_DELIVERY_THRESHOLD_MS = 30_000;
-    private static JobSchedulerBackgroundThread sInstance;
+    private static AppSchedulingModuleThread sInstance;
     private static Handler sHandler;
     private static Executor sHandlerExecutor;
 
-    private JobSchedulerBackgroundThread() {
-        super("jobscheduler.bg", android.os.Process.THREAD_PRIORITY_BACKGROUND);
+    private AppSchedulingModuleThread() {
+        super("appscheduling.default", Process.THREAD_PRIORITY_DEFAULT);
     }
 
     private static void ensureThreadLocked() {
         if (sInstance == null) {
-            sInstance = new JobSchedulerBackgroundThread();
+            sInstance = new AppSchedulingModuleThread();
             sInstance.start();
             final Looper looper = sInstance.getLooper();
             looper.setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER);
@@ -53,25 +54,25 @@
         }
     }
 
-    /** Returns the JobSchedulerBackgroundThread singleton */
-    public static JobSchedulerBackgroundThread get() {
-        synchronized (JobSchedulerBackgroundThread.class) {
+    /** Returns the AppSchedulingModuleThread singleton */
+    public static AppSchedulingModuleThread get() {
+        synchronized (AppSchedulingModuleThread.class) {
             ensureThreadLocked();
             return sInstance;
         }
     }
 
-    /** Returns the singleton handler for JobSchedulerBackgroundThread */
+    /** Returns the singleton handler for AppSchedulingModuleThread */
     public static Handler getHandler() {
-        synchronized (JobSchedulerBackgroundThread.class) {
+        synchronized (AppSchedulingModuleThread.class) {
             ensureThreadLocked();
             return sHandler;
         }
     }
 
-    /** Returns the singleton handler executor for JobSchedulerBackgroundThread */
+    /** Returns the singleton handler executor for AppSchedulingModuleThread */
     public static Executor getExecutor() {
-        synchronized (JobSchedulerBackgroundThread.class) {
+        synchronized (AppSchedulingModuleThread.class) {
             ensureThreadLocked();
             return sHandlerExecutor;
         }
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 4caaa09..1d93eb3 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -79,6 +79,9 @@
 import android.os.Trace;
 import android.os.UserHandle;
 import android.provider.DeviceConfig;
+import android.telephony.TelephonyCallback;
+import android.telephony.TelephonyManager;
+import android.telephony.emergency.EmergencyNumber;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.AtomicFile;
@@ -146,15 +149,17 @@
        label="deep";
 
        STATE_ACTIVE [
-         label="STATE_ACTIVE\nScreen on OR Charging OR Alarm going off soon",
+         label="STATE_ACTIVE\nScreen on OR charging OR alarm going off soon\n"
+             + "OR active emergency call",
          color=black,shape=diamond
        ]
        STATE_INACTIVE [
-         label="STATE_INACTIVE\nScreen off AND Not charging",color=black,shape=diamond
+         label="STATE_INACTIVE\nScreen off AND not charging AND no active emergency call",
+         color=black,shape=diamond
        ]
        STATE_QUICK_DOZE_DELAY [
          label="STATE_QUICK_DOZE_DELAY\n"
-             + "Screen off AND Not charging\n"
+             + "Screen off AND not charging AND no active emergency call\n"
              + "Location, motion detection, and significant motion monitoring turned off",
          color=black,shape=diamond
        ]
@@ -237,11 +242,12 @@
        label="light"
 
        LIGHT_STATE_ACTIVE [
-         label="LIGHT_STATE_ACTIVE\nScreen on OR Charging OR Alarm going off soon",
+         label="LIGHT_STATE_ACTIVE\n"
+             + "Screen on OR charging OR alarm going off soon OR active emergency call",
          color=black,shape=diamond
        ]
        LIGHT_STATE_INACTIVE [
-         label="LIGHT_STATE_INACTIVE\nScreen off AND Not charging",
+         label="LIGHT_STATE_INACTIVE\nScreen off AND not charging AND no active emergency call",
          color=black,shape=diamond
        ]
        LIGHT_STATE_IDLE [label="LIGHT_STATE_IDLE\n",color=red,shape=box]
@@ -411,6 +417,7 @@
     private static final int ACTIVE_REASON_FROM_BINDER_CALL = 5;
     private static final int ACTIVE_REASON_FORCED = 6;
     private static final int ACTIVE_REASON_ALARM = 7;
+    private static final int ACTIVE_REASON_EMERGENCY_CALL = 8;
     @VisibleForTesting
     static final int SET_IDLE_FACTOR_RESULT_UNINIT = -1;
     @VisibleForTesting
@@ -765,6 +772,8 @@
         }
     };
 
+    private final EmergencyCallListener mEmergencyCallListener = new EmergencyCallListener();
+
     /** Post stationary status only to this listener. */
     private void postStationaryStatus(DeviceIdleInternal.StationaryListener listener) {
         mHandler.obtainMessage(MSG_REPORT_STATIONARY_STATUS, listener).sendToTarget();
@@ -1318,7 +1327,7 @@
                 IDLE_AFTER_INACTIVE_TIMEOUT = DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT_SMALL_BATTERY;
             }
             DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DEVICE_IDLE,
-                    JobSchedulerBackgroundThread.getExecutor(), this);
+                    AppSchedulingModuleThread.getExecutor(), this);
             // Load all the constants.
             onPropertiesChanged(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_DEVICE_IDLE));
         }
@@ -2323,6 +2332,39 @@
         }
     }
 
+    private class EmergencyCallListener extends TelephonyCallback implements
+            TelephonyCallback.OutgoingEmergencyCallListener,
+            TelephonyCallback.CallStateListener {
+        private volatile boolean mIsEmergencyCallActive;
+
+        @Override
+        public void onOutgoingEmergencyCall(EmergencyNumber placedEmergencyNumber,
+                int subscriptionId) {
+            mIsEmergencyCallActive = true;
+            if (DEBUG) Slog.d(TAG, "onOutgoingEmergencyCall(): subId = " + subscriptionId);
+            synchronized (DeviceIdleController.this) {
+                mActiveReason = ACTIVE_REASON_EMERGENCY_CALL;
+                becomeActiveLocked("emergency call", Process.myUid());
+            }
+        }
+
+        @Override
+        public void onCallStateChanged(int state) {
+            if (DEBUG) Slog.d(TAG, "onCallStateChanged(): state is " + state);
+            // An emergency call just finished
+            if (state == TelephonyManager.CALL_STATE_IDLE && mIsEmergencyCallActive) {
+                mIsEmergencyCallActive = false;
+                synchronized (DeviceIdleController.this) {
+                    becomeInactiveIfAppropriateLocked();
+                }
+            }
+        }
+
+        boolean isEmergencyCallActive() {
+            return mIsEmergencyCallActive;
+        }
+    }
+
     static class Injector {
         private final Context mContext;
         private ConnectivityManager mConnectivityManager;
@@ -2360,7 +2402,6 @@
             return mConstants;
         }
 
-
         /** Returns the current elapsed realtime in milliseconds. */
         long getElapsedRealtime() {
             return SystemClock.elapsedRealtime();
@@ -2374,7 +2415,7 @@
         }
 
         MyHandler getHandler(DeviceIdleController controller) {
-            return controller.new MyHandler(JobSchedulerBackgroundThread.getHandler().getLooper());
+            return controller.new MyHandler(AppSchedulingModuleThread.getHandler().getLooper());
         }
 
         Sensor getMotionSensor() {
@@ -2406,6 +2447,10 @@
             return mContext.getSystemService(SensorManager.class);
         }
 
+        TelephonyManager getTelephonyManager() {
+            return mContext.getSystemService(TelephonyManager.class);
+        }
+
         ConstraintController getConstraintController(Handler handler,
                 DeviceIdleInternal localService) {
             if (mContext.getPackageManager()
@@ -2442,7 +2487,7 @@
         mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml"));
         mHandler = mInjector.getHandler(this);
         mAppStateTracker = mInjector.getAppStateTracker(context,
-                JobSchedulerBackgroundThread.get().getLooper());
+                AppSchedulingModuleThread.get().getLooper());
         LocalServices.addService(AppStateTracker.class, mAppStateTracker);
         mUseMotionSensor = mInjector.useMotionSensor();
     }
@@ -2634,6 +2679,9 @@
 
                 mLocalActivityTaskManager.registerScreenObserver(mScreenObserver);
 
+                mInjector.getTelephonyManager().registerTelephonyCallback(
+                        AppSchedulingModuleThread.getExecutor(), mEmergencyCallListener);
+
                 passWhiteListsToForceAppStandbyTrackerLocked();
                 updateInteractivityLocked();
             }
@@ -3435,6 +3483,7 @@
 
         final boolean isScreenBlockingInactive =
                 mScreenOn && (!mConstants.WAIT_FOR_UNLOCK || !mScreenLocked);
+        final boolean isEmergencyCallActive = mEmergencyCallListener.isEmergencyCallActive();
         if (DEBUG) {
             Slog.d(TAG, "becomeInactiveIfAppropriateLocked():"
                     + " isScreenBlockingInactive=" + isScreenBlockingInactive
@@ -3442,10 +3491,11 @@
                     + ", WAIT_FOR_UNLOCK=" + mConstants.WAIT_FOR_UNLOCK
                     + ", mScreenLocked=" + mScreenLocked + ")"
                     + " mCharging=" + mCharging
+                    + " emergencyCall=" + isEmergencyCallActive
                     + " mForceIdle=" + mForceIdle
             );
         }
-        if (!mForceIdle && (mCharging || isScreenBlockingInactive)) {
+        if (!mForceIdle && (mCharging || isScreenBlockingInactive || isEmergencyCallActive)) {
             return;
         }
         // Become inactive and determine if we will ultimately go idle.
@@ -3568,6 +3618,17 @@
         }
         EventLogTags.writeDeviceIdleLightStep();
 
+        if (mEmergencyCallListener.isEmergencyCallActive()) {
+            // The emergency call should have raised the state to ACTIVE and kept it there,
+            // so this method shouldn't be called. Don't proceed further.
+            Slog.wtf(TAG, "stepLightIdleStateLocked called when emergency call is active");
+            if (mLightState != LIGHT_STATE_ACTIVE) {
+                mActiveReason = ACTIVE_REASON_EMERGENCY_CALL;
+                becomeActiveLocked("emergency", Process.myUid());
+            }
+            return;
+        }
+
         switch (mLightState) {
             case LIGHT_STATE_INACTIVE:
                 mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
@@ -3650,6 +3711,17 @@
         if (DEBUG) Slog.d(TAG, "stepIdleStateLocked: mState=" + mState);
         EventLogTags.writeDeviceIdleStep();
 
+        if (mEmergencyCallListener.isEmergencyCallActive()) {
+            // The emergency call should have raised the state to ACTIVE and kept it there,
+            // so this method shouldn't be called. Don't proceed further.
+            Slog.wtf(TAG, "stepIdleStateLocked called when emergency call is active");
+            if (mState != STATE_ACTIVE) {
+                mActiveReason = ACTIVE_REASON_EMERGENCY_CALL;
+                becomeActiveLocked("emergency", Process.myUid());
+            }
+            return;
+        }
+
         if (isUpcomingAlarmClock()) {
             // Whoops, there is an upcoming alarm.  We don't actually want to go idle.
             if (mState != STATE_ACTIVE) {
@@ -3746,6 +3818,7 @@
 
                 // Everything is in place to go into IDLE state.
             case STATE_IDLE_MAINTENANCE:
+                moveToStateLocked(STATE_IDLE, reason);
                 scheduleAlarmLocked(mNextIdleDelay, true);
                 if (DEBUG) Slog.d(TAG, "Moved to STATE_IDLE. Next alarm in " + mNextIdleDelay +
                         " ms.");
@@ -3756,7 +3829,6 @@
                 if (mNextIdleDelay < mConstants.IDLE_TIMEOUT) {
                     mNextIdleDelay = mConstants.IDLE_TIMEOUT;
                 }
-                moveToStateLocked(STATE_IDLE, reason);
                 if (mLightState != LIGHT_STATE_OVERRIDE) {
                     moveToLightStateLocked(LIGHT_STATE_OVERRIDE, "deep");
                     cancelLightAlarmLocked();
@@ -3769,6 +3841,7 @@
                 // We have been idling long enough, now it is time to do some work.
                 mActiveIdleOpCount = 1;
                 mActiveIdleWakeLock.acquire();
+                moveToStateLocked(STATE_IDLE_MAINTENANCE, reason);
                 scheduleAlarmLocked(mNextIdlePendingDelay, false);
                 if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE to STATE_IDLE_MAINTENANCE. " +
                         "Next alarm in " + mNextIdlePendingDelay + " ms.");
@@ -3778,7 +3851,6 @@
                 if (mNextIdlePendingDelay < mConstants.IDLE_PENDING_TIMEOUT) {
                     mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;
                 }
-                moveToStateLocked(STATE_IDLE_MAINTENANCE, reason);
                 addEvent(EVENT_DEEP_MAINTENANCE, null);
                 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
                 break;
@@ -3984,6 +4056,11 @@
         }
     }
 
+    @VisibleForTesting
+    boolean isEmergencyCallActive() {
+        return mEmergencyCallListener.isEmergencyCallActive();
+    }
+
     @GuardedBy("this")
     boolean isOpsInactiveLocked() {
         return mActiveIdleOpCount <= 0 && !mJobsActive && !mAlarmsActive;
@@ -5199,6 +5276,8 @@
             pw.print("  mScreenLocked="); pw.println(mScreenLocked);
             pw.print("  mNetworkConnected="); pw.println(mNetworkConnected);
             pw.print("  mCharging="); pw.println(mCharging);
+            pw.print("  activeEmergencyCall=");
+            pw.println(mEmergencyCallListener.isEmergencyCallActive());
             if (mConstraints.size() != 0) {
                 pw.println("  mConstraints={");
                 for (int i = 0; i < mConstraints.size(); i++) {
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index deb8a63..1151bb7 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -147,12 +147,12 @@
 import com.android.internal.util.RingBuffer;
 import com.android.internal.util.StatLogger;
 import com.android.server.AlarmManagerInternal;
+import com.android.server.AppSchedulingModuleThread;
 import com.android.server.AppStateTracker;
 import com.android.server.AppStateTrackerImpl;
 import com.android.server.AppStateTrackerImpl.Listener;
 import com.android.server.DeviceIdleInternal;
 import com.android.server.EventLogTags;
-import com.android.server.JobSchedulerBackgroundThread;
 import com.android.server.LocalServices;
 import com.android.server.SystemClockTime;
 import com.android.server.SystemClockTime.TimeConfidence;
@@ -4691,7 +4691,7 @@
 
         void registerDeviceConfigListener(DeviceConfig.OnPropertiesChangedListener listener) {
             DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ALARM_MANAGER,
-                    JobSchedulerBackgroundThread.getExecutor(), listener);
+                    AppSchedulingModuleThread.getExecutor(), listener);
         }
     }
 
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
index 272a79e..89eb1a9 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
@@ -62,7 +62,7 @@
 import com.android.internal.app.procstats.ProcessStats;
 import com.android.internal.util.MemInfoReader;
 import com.android.internal.util.StatLogger;
-import com.android.server.JobSchedulerBackgroundThread;
+import com.android.server.AppSchedulingModuleThread;
 import com.android.server.LocalServices;
 import com.android.server.job.controllers.JobStatus;
 import com.android.server.job.controllers.StateController;
@@ -499,7 +499,7 @@
         mInjector = injector;
         mNotificationCoordinator = new JobNotificationCoordinator();
 
-        mHandler = JobSchedulerBackgroundThread.getHandler();
+        mHandler = AppSchedulingModuleThread.getHandler();
 
         mGracePeriodObserver = new GracePeriodObserver(mContext);
         mShouldRestrictBgUser = mContext.getResources().getBoolean(
@@ -533,7 +533,8 @@
             mIdleContexts.add(
                     mInjector.createJobServiceContext(mService, this,
                             mNotificationCoordinator, batteryStats,
-                            mService.mJobPackageTracker, mContext.getMainLooper()));
+                            mService.mJobPackageTracker,
+                            AppSchedulingModuleThread.get().getLooper()));
         }
     }
 
@@ -1925,7 +1926,7 @@
         return mInjector.createJobServiceContext(mService, this, mNotificationCoordinator,
                 IBatteryStats.Stub.asInterface(
                         ServiceManager.getService(BatteryStats.SERVICE_NAME)),
-                mService.mJobPackageTracker, mContext.getMainLooper());
+                mService.mJobPackageTracker, AppSchedulingModuleThread.get().getLooper());
     }
 
     @GuardedBy("mLock")
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 0af191a..3cc67e7 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -105,10 +105,10 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FrameworkStatsLog;
+import com.android.server.AppSchedulingModuleThread;
 import com.android.server.AppStateTracker;
 import com.android.server.AppStateTrackerImpl;
 import com.android.server.DeviceIdleInternal;
-import com.android.server.JobSchedulerBackgroundThread;
 import com.android.server.LocalServices;
 import com.android.server.job.JobSchedulerServiceDumpProto.PendingJob;
 import com.android.server.job.controllers.BackgroundJobsController;
@@ -411,7 +411,7 @@
             EconomyManagerInternal.TareStateChangeListener {
         public void start() {
             DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
-                    JobSchedulerBackgroundThread.getExecutor(), this);
+                    AppSchedulingModuleThread.getExecutor(), this);
             final EconomyManagerInternal economyManagerInternal =
                     LocalServices.getService(EconomyManagerInternal.class);
             economyManagerInternal
@@ -2009,7 +2009,7 @@
         mActivityManagerInternal = Objects.requireNonNull(
                 LocalServices.getService(ActivityManagerInternal.class));
 
-        mHandler = new JobHandler(context.getMainLooper());
+        mHandler = new JobHandler(AppSchedulingModuleThread.get().getLooper());
         mConstants = new Constants();
         mConstantsObserver = new ConstantsObserver();
         mJobSchedulerStub = new JobSchedulerStub();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index 29ab455..e60ed4a 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -727,8 +727,11 @@
                     // Exception-throwing-can down the road to JobParameters.completeWork >:(
                     return true;
                 }
-                mService.mJobs.touchJob(mRunningJob);
-                return mRunningJob.completeWorkLocked(workId);
+                if (mRunningJob.completeWorkLocked(workId)) {
+                    mService.mJobs.touchJob(mRunningJob);
+                    return true;
+                }
+                return false;
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java
index 2ca3f8f..4c55dac 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java
@@ -35,7 +35,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.JobSchedulerBackgroundThread;
+import com.android.server.AppSchedulingModuleThread;
 import com.android.server.LocalServices;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.job.StateControllerProto;
@@ -151,7 +151,7 @@
     @GuardedBy("mLock")
     public void onBatteryStateChangedLocked() {
         // Update job bookkeeping out of band.
-        JobSchedulerBackgroundThread.getHandler().post(() -> {
+        AppSchedulingModuleThread.getHandler().post(() -> {
             synchronized (mLock) {
                 maybeReportNewChargingStateLocked();
             }
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 2a9186a..e55bda7 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
@@ -52,7 +52,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.JobSchedulerBackgroundThread;
+import com.android.server.AppSchedulingModuleThread;
 import com.android.server.LocalServices;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.job.JobSchedulerService.Constants;
@@ -256,7 +256,7 @@
     public ConnectivityController(JobSchedulerService service,
             @NonNull FlexibilityController flexibilityController) {
         super(service);
-        mHandler = new CcHandler(mContext.getMainLooper());
+        mHandler = new CcHandler(AppSchedulingModuleThread.get().getLooper());
 
         mConnManager = mContext.getSystemService(ConnectivityManager.class);
         mNetPolicyManagerInternal = LocalServices.getService(NetworkPolicyManagerInternal.class);
@@ -1347,7 +1347,7 @@
                 TelephonyManager idTm = telephonyManager.createForSubscriptionId(subId);
                 CellSignalStrengthCallback callback = new CellSignalStrengthCallback();
                 idTm.registerTelephonyCallback(
-                        JobSchedulerBackgroundThread.getExecutor(), callback);
+                        AppSchedulingModuleThread.getExecutor(), callback);
                 mSignalStrengths.put(subId, callback);
 
                 final SignalStrength signalStrength = idTm.getSignalStrength();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ContentObserverController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ContentObserverController.java
index 847a1bf..122fe69 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ContentObserverController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ContentObserverController.java
@@ -33,6 +33,7 @@
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.server.AppSchedulingModuleThread;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.job.StateControllerProto;
 import com.android.server.job.StateControllerProto.ContentObserverController.Observer.TriggerContentData;
@@ -70,7 +71,7 @@
 
     public ContentObserverController(JobSchedulerService service) {
         super(service);
-        mHandler = new Handler(mContext.getMainLooper());
+        mHandler = new Handler(AppSchedulingModuleThread.get().getLooper());
     }
 
     @Override
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java
index bdf72b6..d5c9ae6 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java
@@ -36,6 +36,7 @@
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.util.ArrayUtils;
+import com.android.server.AppSchedulingModuleThread;
 import com.android.server.DeviceIdleInternal;
 import com.android.server.LocalServices;
 import com.android.server.job.JobSchedulerService;
@@ -127,7 +128,7 @@
     public DeviceIdleJobsController(JobSchedulerService service) {
         super(service);
 
-        mHandler = new DeviceIdleJobsDelayHandler(mContext.getMainLooper());
+        mHandler = new DeviceIdleJobsDelayHandler(AppSchedulingModuleThread.get().getLooper());
         // Register for device idle mode changes
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mLocalDeviceIdleController =
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 4c17692..620c48d 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
@@ -44,7 +44,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.JobSchedulerBackgroundThread;
+import com.android.server.AppSchedulingModuleThread;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.utils.AlarmQueue;
 
@@ -183,7 +183,7 @@
         mFlexibilityTracker = new FlexibilityTracker(NUM_FLEXIBLE_CONSTRAINTS);
         mFcConfig = new FcConfig();
         mFlexibilityAlarmQueue = new FlexibilityAlarmQueue(
-                mContext, JobSchedulerBackgroundThread.get().getLooper());
+                mContext, AppSchedulingModuleThread.get().getLooper());
         mPercentToDropConstraints =
                 mFcConfig.DEFAULT_PERCENT_TO_DROP_FLEXIBLE_CONSTRAINTS;
         mPrefetchController = prefetchController;
@@ -427,7 +427,7 @@
     @GuardedBy("mLock")
     public void onConstantsUpdatedLocked() {
         if (mFcConfig.mShouldReevaluateConstraints) {
-            JobSchedulerBackgroundThread.getHandler().post(() -> {
+            AppSchedulingModuleThread.getHandler().post(() -> {
                 final ArraySet<JobStatus> changedJobs = new ArraySet<>();
                 synchronized (mLock) {
                     final long nowElapsed = sElapsedRealtimeClock.millis();
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 1971a11..537a670 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
@@ -828,6 +828,10 @@
         }
     }
 
+    /**
+     * Returns {@code true} if the JobWorkItem queue was updated,
+     * and {@code false} if nothing changed.
+     */
     public boolean completeWorkLocked(int workId) {
         if (executingWork != null) {
             final int N = executingWork.size();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/PrefetchController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/PrefetchController.java
index c46ffd7..2b7438c 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/PrefetchController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/PrefetchController.java
@@ -46,7 +46,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.SomeArgs;
-import com.android.server.JobSchedulerBackgroundThread;
+import com.android.server.AppSchedulingModuleThread;
 import com.android.server.LocalServices;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.utils.AlarmQueue;
@@ -130,9 +130,9 @@
     public PrefetchController(JobSchedulerService service) {
         super(service);
         mPcConstants = new PcConstants();
-        mHandler = new PcHandler(mContext.getMainLooper());
+        mHandler = new PcHandler(AppSchedulingModuleThread.get().getLooper());
         mThresholdAlarmListener = new ThresholdAlarmListener(
-                mContext, JobSchedulerBackgroundThread.get().getLooper());
+                mContext, AppSchedulingModuleThread.get().getLooper());
         mUsageStatsManagerInternal = LocalServices.getService(UsageStatsManagerInternal.class);
 
         mUsageStatsManagerInternal
@@ -400,7 +400,7 @@
     public void onConstantsUpdatedLocked() {
         if (mPcConstants.mShouldReevaluateConstraints) {
             // Update job bookkeeping out of band.
-            JobSchedulerBackgroundThread.getHandler().post(() -> {
+            AppSchedulingModuleThread.getHandler().post(() -> {
                 final ArraySet<JobStatus> changedJobs = new ArraySet<>();
                 synchronized (mLock) {
                     final long nowElapsed = sElapsedRealtimeClock.millis();
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 cbfad94..aca0a6e 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
@@ -65,7 +65,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
-import com.android.server.JobSchedulerBackgroundThread;
+import com.android.server.AppSchedulingModuleThread;
 import com.android.server.LocalServices;
 import com.android.server.PowerAllowlistInternal;
 import com.android.server.job.ConstantsProto;
@@ -560,13 +560,14 @@
             @NonNull BackgroundJobsController backgroundJobsController,
             @NonNull ConnectivityController connectivityController) {
         super(service);
-        mHandler = new QcHandler(mContext.getMainLooper());
+        mHandler = new QcHandler(AppSchedulingModuleThread.get().getLooper());
         mAlarmManager = mContext.getSystemService(AlarmManager.class);
         mQcConstants = new QcConstants();
         mBackgroundJobsController = backgroundJobsController;
         mConnectivityController = connectivityController;
         mIsEnabled = !mConstants.USE_TARE_POLICY;
-        mInQuotaAlarmQueue = new InQuotaAlarmQueue(mContext, mContext.getMainLooper());
+        mInQuotaAlarmQueue =
+                new InQuotaAlarmQueue(mContext, AppSchedulingModuleThread.get().getLooper());
 
         // Set up the app standby bucketing tracker
         AppStandbyInternal appStandby = LocalServices.getService(AppStandbyInternal.class);
@@ -1649,7 +1650,7 @@
         mEJPkgTimers.forEach(mTimerChargingUpdateFunctor);
         mPkgTimers.forEach(mTimerChargingUpdateFunctor);
         // Now update jobs out of band so broadcast processing can proceed.
-        JobSchedulerBackgroundThread.getHandler().post(() -> {
+        AppSchedulingModuleThread.getHandler().post(() -> {
             synchronized (mLock) {
                 maybeUpdateAllConstraintsLocked();
             }
@@ -2486,7 +2487,7 @@
         public void onAppIdleStateChanged(final String packageName, final @UserIdInt int userId,
                 boolean idle, int bucket, int reason) {
             // Update job bookkeeping out of band.
-            JobSchedulerBackgroundThread.getHandler().post(() -> {
+            AppSchedulingModuleThread.getHandler().post(() -> {
                 final int bucketIndex = JobSchedulerService.standbyBucketToBucketIndex(bucket);
                 updateStandbyBucket(userId, packageName, bucketIndex);
             });
@@ -2938,7 +2939,7 @@
         if (mQcConstants.mShouldReevaluateConstraints || mIsEnabled == mConstants.USE_TARE_POLICY) {
             mIsEnabled = !mConstants.USE_TARE_POLICY;
             // Update job bookkeeping out of band.
-            JobSchedulerBackgroundThread.getHandler().post(() -> {
+            AppSchedulingModuleThread.getHandler().post(() -> {
                 synchronized (mLock) {
                     invalidateAllExecutionStatsLocked();
                     maybeUpdateAllConstraintsLocked();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/TareController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/TareController.java
index 792155b..7408088 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/TareController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/TareController.java
@@ -30,7 +30,7 @@
 import android.util.SparseArrayMap;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.server.JobSchedulerBackgroundThread;
+import com.android.server.AppSchedulingModuleThread;
 import com.android.server.LocalServices;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.tare.EconomicPolicy;
@@ -424,7 +424,7 @@
         if (mIsEnabled != mConstants.USE_TARE_POLICY) {
             mIsEnabled = mConstants.USE_TARE_POLICY;
             // Update job bookkeeping out of band.
-            JobSchedulerBackgroundThread.getHandler().post(() -> {
+            AppSchedulingModuleThread.getHandler().post(() -> {
                 synchronized (mLock) {
                     final long nowElapsed = sElapsedRealtimeClock.millis();
                     mService.getJobStore().forEachJob((jobStatus) -> {
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
index 47b7e13..c458cae 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
@@ -24,7 +24,7 @@
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 
-import com.android.server.JobSchedulerBackgroundThread;
+import com.android.server.AppSchedulingModuleThread;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.job.StateControllerProto;
@@ -91,7 +91,7 @@
         filter.addAction(ACTION_UNFORCE_IDLE);
         filter.addAction(ActivityManagerService.ACTION_TRIGGER_IDLE);
 
-        context.registerReceiver(this, filter, null, JobSchedulerBackgroundThread.getHandler());
+        context.registerReceiver(this, filter, null, AppSchedulingModuleThread.getHandler());
     }
 
     @Override
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java
index 15d6766..c943e73 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java
@@ -31,7 +31,7 @@
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 
-import com.android.server.JobSchedulerBackgroundThread;
+import com.android.server.AppSchedulingModuleThread;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.job.StateControllerProto;
@@ -102,10 +102,10 @@
         filter.addAction(Intent.ACTION_DOCK_IDLE);
         filter.addAction(Intent.ACTION_DOCK_ACTIVE);
 
-        context.registerReceiver(this, filter, null, JobSchedulerBackgroundThread.getHandler());
+        context.registerReceiver(this, filter, null, AppSchedulingModuleThread.getHandler());
 
         context.getSystemService(UiModeManager.class).addOnProjectionStateChangedListener(
-                UiModeManager.PROJECTION_TYPE_ALL, JobSchedulerBackgroundThread.getExecutor(),
+                UiModeManager.PROJECTION_TYPE_ALL, AppSchedulingModuleThread.getExecutor(),
                 mOnProjectionStateChangedListener);
     }
 
@@ -226,7 +226,7 @@
             }
             mAlarm.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                     when, mIdleWindowSlop, "JS idleness",
-                    JobSchedulerBackgroundThread.getExecutor(), mIdleAlarmListener);
+                    AppSchedulingModuleThread.getExecutor(), mIdleAlarmListener);
         }
     }
 
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 a3d566b..c3118ff 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -125,7 +125,7 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.ConcurrentUtils;
 import com.android.server.AlarmManagerInternal;
-import com.android.server.JobSchedulerBackgroundThread;
+import com.android.server.AppSchedulingModuleThread;
 import com.android.server.LocalServices;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.usage.AppIdleHistory.AppUsageHistory;
@@ -592,7 +592,7 @@
     }
 
     public AppStandbyController(Context context) {
-        this(new Injector(context, JobSchedulerBackgroundThread.get().getLooper()));
+        this(new Injector(context, AppSchedulingModuleThread.get().getLooper()));
     }
 
     AppStandbyController(Injector injector) {
@@ -2761,7 +2761,7 @@
         void registerDeviceConfigPropertiesChangedListener(
                 @NonNull DeviceConfig.OnPropertiesChangedListener listener) {
             DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_APP_STANDBY,
-                    JobSchedulerBackgroundThread.getExecutor(), listener);
+                    AppSchedulingModuleThread.getExecutor(), listener);
         }
 
         void dump(PrintWriter pw) {
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING b/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
index a6a3aaf..6a4a52a 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
+++ b/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
@@ -4,6 +4,7 @@
       "name": "CtsUsageStatsTestCases",
       "options": [
         {"include-filter": "android.app.usage.cts.UsageStatsTest"},
+        {"include-filter": "android.app.usage.cts.BroadcastResponseStatsTest"},
         {"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
         {"exclude-annotation": "androidx.test.filters.FlakyTest"},
         {"exclude-annotation": "androidx.test.filters.MediumTest"},
@@ -19,18 +20,6 @@
       ]
     }
   ],
-  "presubmit-large": [
-    {
-      "name": "CtsUsageStatsTestCases",
-      "options": [
-        {"include-filter": "android.app.usage.cts.BroadcastResponseStatsTest"},
-        {"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
-        {"exclude-annotation": "androidx.test.filters.FlakyTest"},
-        {"exclude-annotation": "androidx.test.filters.MediumTest"},
-        {"exclude-annotation": "androidx.test.filters.LargeTest"}
-      ]
-    }
-  ],
   "postsubmit": [
     {
       "name": "CtsUsageStatsTestCases"
diff --git a/api/Android.bp b/api/Android.bp
index 78ddc6a..73dbd28 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -31,10 +31,12 @@
         "blueprint",
         "soong",
         "soong-android",
+        "soong-bp2build",
         "soong-genrule",
         "soong-java",
     ],
     srcs: ["api.go"],
+    testSrcs: ["api_test.go"],
     pluginFor: ["soong_build"],
 }
 
@@ -261,3 +263,15 @@
     out: ["combined-removed-dex.txt"],
     cmd: "$(location gen_combined_removed_dex.sh) $(location metalava) $(genDir) $(in) > $(out)",
 }
+
+java_genrule {
+    name: "api_fingerprint",
+    srcs: [
+        ":frameworks-base-api-current.txt",
+        ":frameworks-base-api-system-current.txt",
+        ":frameworks-base-api-module-lib-current.txt",
+        ":frameworks-base-api-system-server-current.txt",
+    ],
+    out: ["api_fingerprint.txt"],
+    cmd: "cat $(in) | md5sum | cut -d' ' -f1 > $(out)",
+}
diff --git a/api/api.go b/api/api.go
index 077ab96..25d9728 100644
--- a/api/api.go
+++ b/api/api.go
@@ -20,6 +20,7 @@
 	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
+	"android/soong/bazel"
 	"android/soong/genrule"
 	"android/soong/java"
 )
@@ -30,6 +31,7 @@
 const virtualization = "framework-virtualization"
 
 var core_libraries_modules = []string{art, conscrypt, i18n}
+
 // List of modules that are not yet updatable, and hence they can still compile
 // against hidden APIs. These modules are filtered out when building the
 // updatable-framework-module-impl (because updatable-framework-module-impl is
@@ -59,6 +61,7 @@
 
 type CombinedApis struct {
 	android.ModuleBase
+	android.BazelModuleBase
 
 	properties CombinedApisProperties
 }
@@ -99,6 +102,19 @@
 	Visibility []string
 }
 
+type Bazel_module struct {
+	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"
@@ -144,7 +160,7 @@
 		},
 	}
 	props.Visibility = []string{"//visibility:public"}
-	ctx.CreateModule(genrule.GenRuleFactory, &props)
+	ctx.CreateModule(genrule.GenRuleFactory, &props, &bp2buildNotAvailable)
 }
 
 func createMergedAnnotationsFilegroups(ctx android.LoadHookContext, modules, system_server_modules []string) {
@@ -174,7 +190,7 @@
 		props := fgProps{}
 		props.Name = proptools.StringPtr(i.name)
 		props.Srcs = createSrcs(i.modules, i.tag)
-		ctx.CreateModule(android.FileGroupFactory, &props)
+		ctx.CreateModule(android.FileGroupFactory, &props, &bp2buildNotAvailable)
 	}
 }
 
@@ -223,7 +239,7 @@
 		props.Tools = []string{"api_versions_trimmer"}
 		props.Cmd = proptools.StringPtr("$(location api_versions_trimmer) $(out) $(in)")
 		props.Dists = []android.Dist{{Targets: []string{"sdk"}}}
-		ctx.CreateModule(genrule.GenRuleFactory, &props)
+		ctx.CreateModule(genrule.GenRuleFactory, &props, &bp2buildNotAvailable)
 	}
 }
 
@@ -315,7 +331,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)
+	ctx.CreateModule(android.FileGroupFactory, &props, &bp2buildNotAvailable)
 }
 
 func createMergedTxts(ctx android.LoadHookContext, bootclasspath, system_server_classpath []string) {
@@ -389,9 +405,57 @@
 	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.TopDownMutatorContext) {
+	basePrefix := "non-updatable"
+	scopeNames := []string{"public", "system", "module-lib", "system-server"}
+	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 := range scopeNames{
+		suffix := scopeToSuffix[scopeName]
+		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
new file mode 100644
index 0000000..15b695c
--- /dev/null
+++ b/api/api_test.go
@@ -0,0 +1,68 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package api
+
+import (
+	"testing"
+
+	"android/soong/android"
+	"android/soong/bp2build"
+)
+
+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) {})
+}
+
+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"],
+}
+`,
+		ExpectedBazelTargets: []string{
+			bp2build.MakeBazelTargetNoRestrictions("merged_txts", "foo-current.txt", bp2build.AttrNameToString{
+				"scope": `"public"`,
+				"base":  `":non-updatable-current.txt__BP2BUILD__MISSING__DEP"`,
+				"deps":  `[":bcp__BP2BUILD__MISSING__DEP"]`,
+			}),
+			bp2build.MakeBazelTargetNoRestrictions("merged_txts", "foo-system-current.txt", bp2build.AttrNameToString{
+				"scope": `"system"`,
+				"base":  `":non-updatable-system-current.txt__BP2BUILD__MISSING__DEP"`,
+				"deps":  `[":bcp__BP2BUILD__MISSING__DEP"]`,
+			}),
+			bp2build.MakeBazelTargetNoRestrictions("merged_txts", "foo-module-lib-current.txt", bp2build.AttrNameToString{
+				"scope": `"module-lib"`,
+				"base":  `":non-updatable-module-lib-current.txt__BP2BUILD__MISSING__DEP"`,
+				"deps":  `[":bcp__BP2BUILD__MISSING__DEP"]`,
+			}),
+			bp2build.MakeBazelTargetNoRestrictions("merged_txts", "foo-system-server-current.txt", bp2build.AttrNameToString{
+				"scope": `"system-server"`,
+				"base":  `":non-updatable-system-server-current.txt__BP2BUILD__MISSING__DEP"`,
+				"deps":  `[":ssc__BP2BUILD__MISSING__DEP"]`,
+			}),
+		},
+	})
+}
diff --git a/config/preloaded-classes b/config/preloaded-classes
index 95070bd..09ec220 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -14799,7 +14799,6 @@
 java.util.ImmutableCollections$Set12
 java.util.ImmutableCollections$SetN
 java.util.ImmutableCollections$SubList
-java.util.ImmutableCollections
 java.util.InputMismatchException
 java.util.Iterator
 java.util.JumboEnumSet$EnumSetIterator
diff --git a/config/preloaded-classes-denylist b/config/preloaded-classes-denylist
index 502d8c6..a413bbd 100644
--- a/config/preloaded-classes-denylist
+++ b/config/preloaded-classes-denylist
@@ -9,4 +9,5 @@
 android.net.rtp.AudioStream
 android.net.rtp.RtpStream
 java.util.concurrent.ThreadLocalRandom
+java.util.ImmutableCollections
 com.android.internal.jank.InteractionJankMonitor$InstanceHolder
diff --git a/core/api/Android.bp b/core/api/Android.bp
index 114a957..71a2ca2 100644
--- a/core/api/Android.bp
+++ b/core/api/Android.bp
@@ -13,7 +13,10 @@
 // limitations under the License.
 
 package {
-    default_visibility: ["//visibility:private"],
+    default_visibility: [
+        "//frameworks/base",
+        "//frameworks/base/api",
+    ],
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "frameworks_base_license"
@@ -27,31 +30,33 @@
 filegroup {
     name: "non-updatable-current.txt",
     srcs: ["current.txt"],
-    visibility: ["//frameworks/base/api"],
 }
 
 filegroup {
     name: "non-updatable-removed.txt",
     srcs: ["removed.txt"],
-    visibility: ["//frameworks/base/api"],
 }
 
 filegroup {
     name: "non-updatable-system-current.txt",
     srcs: ["system-current.txt"],
-    visibility: ["//frameworks/base/api"],
 }
 
 filegroup {
     name: "non-updatable-system-removed.txt",
     srcs: ["system-removed.txt"],
-    visibility: ["//frameworks/base/api"],
+}
+
+filegroup {
+    name: "non-updatable-system-lint-baseline.txt",
+    srcs: ["system-lint-baseline.txt"],
 }
 
 filegroup {
     name: "non-updatable-module-lib-current.txt",
     srcs: ["module-lib-current.txt"],
     visibility: [
+        "//frameworks/base",
         "//frameworks/base/api",
         "//cts/tests/signature/api",
     ],
@@ -61,7 +66,46 @@
     name: "non-updatable-module-lib-removed.txt",
     srcs: ["module-lib-removed.txt"],
     visibility: [
+        "//frameworks/base",
         "//frameworks/base/api",
         "//cts/tests/signature/api",
     ],
 }
+
+filegroup {
+    name: "non-updatable-module-lib-lint-baseline.txt",
+    srcs: ["module-lib-lint-baseline.txt"],
+}
+
+filegroup {
+    name: "non-updatable-test-current.txt",
+    srcs: ["test-current.txt"],
+}
+
+filegroup {
+    name: "non-updatable-test-removed.txt",
+    srcs: ["test-removed.txt"],
+}
+
+filegroup {
+    name: "non-updatable-test-lint-baseline.txt",
+    srcs: ["test-lint-baseline.txt"],
+}
+
+java_api_contribution {
+    name: "api-stubs-docs-non-updatable-public-stubs",
+    api_surface: "public",
+    api_file: "current.txt",
+    visibility: [
+        "//build/orchestrator/apis",
+    ],
+}
+
+java_api_contribution {
+    name: "frameworks-base-core-api-module-lib-stubs",
+    api_surface: "module-lib",
+    api_file: "module-lib-current.txt",
+    visibility: [
+        "//build/orchestrator/apis",
+    ],
+}
diff --git a/core/api/current.txt b/core/api/current.txt
index 8a6bb7b..dd4f213 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -375,7 +375,7 @@
   public static final class R.attr {
     ctor public R.attr();
     field public static final int absListViewStyle = 16842858; // 0x101006a
-    field public static final int accessibilityDataPrivate;
+    field public static final int accessibilityDataSensitive;
     field public static final int accessibilityEventTypes = 16843648; // 0x1010380
     field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
     field public static final int accessibilityFlags = 16843652; // 0x1010384
@@ -4492,8 +4492,8 @@
     method public void openOptionsMenu();
     method public void overrideActivityTransition(int, @AnimRes int, @AnimRes int);
     method public void overrideActivityTransition(int, @AnimRes int, @AnimRes int, @ColorInt int);
-    method public void overridePendingTransition(int, int);
-    method public void overridePendingTransition(int, int, int);
+    method @Deprecated public void overridePendingTransition(int, int);
+    method @Deprecated public void overridePendingTransition(int, int, int);
     method public void postponeEnterTransition();
     method public void recreate();
     method public void registerActivityLifecycleCallbacks(@NonNull android.app.Application.ActivityLifecycleCallbacks);
@@ -5279,10 +5279,28 @@
   }
 
   public class BroadcastOptions {
-    ctor public BroadcastOptions();
+    method public void clearDeferralPolicy();
+    method public void clearDeliveryGroupMatchingFilter();
+    method public void clearDeliveryGroupMatchingKey();
+    method public void clearDeliveryGroupPolicy();
+    method @NonNull public static android.app.BroadcastOptions fromBundle(@NonNull android.os.Bundle);
+    method public int getDeferralPolicy();
+    method @Nullable public android.content.IntentFilter getDeliveryGroupMatchingFilter();
+    method @Nullable public String getDeliveryGroupMatchingKey();
+    method public int getDeliveryGroupPolicy();
     method public boolean isShareIdentityEnabled();
+    method @NonNull public static android.app.BroadcastOptions makeBasic();
+    method @NonNull public android.app.BroadcastOptions setDeferralPolicy(int);
+    method @NonNull public android.app.BroadcastOptions setDeliveryGroupMatchingFilter(@NonNull android.content.IntentFilter);
+    method @NonNull public android.app.BroadcastOptions setDeliveryGroupMatchingKey(@NonNull String, @NonNull String);
+    method @NonNull public android.app.BroadcastOptions setDeliveryGroupPolicy(int);
     method @NonNull public android.app.BroadcastOptions setShareIdentityEnabled(boolean);
     method @NonNull public android.os.Bundle toBundle();
+    field public static final int DEFERRAL_POLICY_DEFAULT = 0; // 0x0
+    field public static final int DEFERRAL_POLICY_NONE = 1; // 0x1
+    field public static final int DEFERRAL_POLICY_UNTIL_ACTIVE = 2; // 0x2
+    field public static final int DELIVERY_GROUP_POLICY_ALL = 0; // 0x0
+    field public static final int DELIVERY_GROUP_POLICY_MOST_RECENT = 1; // 0x1
   }
 
   public class DatePickerDialog extends android.app.AlertDialog implements android.widget.DatePicker.OnDateChangedListener android.content.DialogInterface.OnClickListener {
@@ -6784,7 +6802,7 @@
     method public boolean areNotificationsEnabled();
     method public boolean areNotificationsPaused();
     method public boolean canNotifyAsPackage(@NonNull String);
-    method public boolean canSendFullScreenIntent();
+    method public boolean canUseFullScreenIntent();
     method public void cancel(int);
     method public void cancel(@Nullable String, int);
     method public void cancelAll();
@@ -7269,6 +7287,13 @@
     method public void onSharedElementsReady();
   }
 
+  public final class StartForegroundCalledOnStoppedServiceException extends java.lang.IllegalStateException implements android.os.Parcelable {
+    ctor public StartForegroundCalledOnStoppedServiceException(@NonNull String);
+    method public int describeContents();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.app.StartForegroundCalledOnStoppedServiceException> CREATOR;
+  }
+
   public class StatusBarManager {
     method @RequiresPermission(android.Manifest.permission.LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE) public boolean canLaunchCaptureContentActivityForNote(@NonNull android.app.Activity);
     method public void requestAddTileService(@NonNull android.content.ComponentName, @NonNull CharSequence, @NonNull android.graphics.drawable.Icon, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
@@ -7391,12 +7416,15 @@
   }
 
   public class UiModeManager {
+    method public void addContrastChangeListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.UiModeManager.ContrastChangeListener);
     method public void disableCarMode(int);
     method public void enableCarMode(int);
+    method @FloatRange(from=-1.0F, to=1.0f) public float getContrast();
     method public int getCurrentModeType();
     method @NonNull public java.time.LocalTime getCustomNightModeEnd();
     method @NonNull public java.time.LocalTime getCustomNightModeStart();
     method public int getNightMode();
+    method public void removeContrastChangeListener(@NonNull android.app.UiModeManager.ContrastChangeListener);
     method public void setApplicationNightMode(int);
     method public void setCustomNightModeEnd(@NonNull java.time.LocalTime);
     method public void setCustomNightModeStart(@NonNull java.time.LocalTime);
@@ -7414,6 +7442,10 @@
     field public static final int MODE_NIGHT_YES = 2; // 0x2
   }
 
+  public static interface UiModeManager.ContrastChangeListener {
+    method public void onContrastChanged(@FloatRange(from=-1.0F, to=1.0f) float);
+  }
+
   public final class VoiceInteractor {
     method public android.app.VoiceInteractor.Request getActiveRequest(String);
     method public android.app.VoiceInteractor.Request[] getActiveRequests();
@@ -8300,7 +8332,7 @@
     field public static final int RESULT_FAILURE_STORAGE_LIMIT_REACHED = 3; // 0x3
     field public static final int RESULT_FAILURE_UNKNOWN = -1; // 0xffffffff
     field public static final int RESULT_POLICY_CLEARED = 2; // 0x2
-    field public static final int RESULT_SUCCESS = 0; // 0x0
+    field public static final int RESULT_POLICY_SET = 0; // 0x0
   }
 
   public final class PreferentialNetworkServiceConfig implements android.os.Parcelable {
@@ -9646,6 +9678,7 @@
     method @Nullable public String getAttributionTag();
     method @Nullable public android.content.AttributionSource getNext();
     method @Nullable public String getPackageName();
+    method public int getPid();
     method public int getUid();
     method public boolean isTrusted(@NonNull android.content.Context);
     method @NonNull public static android.content.AttributionSource myAttributionSource();
@@ -9660,6 +9693,7 @@
     method @NonNull public android.content.AttributionSource.Builder setAttributionTag(@Nullable String);
     method @NonNull public android.content.AttributionSource.Builder setNext(@Nullable android.content.AttributionSource);
     method @NonNull public android.content.AttributionSource.Builder setPackageName(@Nullable String);
+    method @NonNull public android.content.AttributionSource.Builder setPid(int);
   }
 
   public abstract class BroadcastReceiver {
@@ -10326,7 +10360,7 @@
     field public static final int BIND_AUTO_CREATE = 1; // 0x1
     field public static final int BIND_DEBUG_UNBIND = 2; // 0x2
     field public static final int BIND_EXTERNAL_SERVICE = -2147483648; // 0x80000000
-    field public static final long BIND_EXTERNAL_SERVICE_LONG = -9223372036854775808L; // 0x8000000000000000L
+    field public static final long BIND_EXTERNAL_SERVICE_LONG = 4611686018427387904L; // 0x4000000000000000L
     field public static final int BIND_IMPORTANT = 64; // 0x40
     field public static final int BIND_INCLUDE_CAPABILITIES = 4096; // 0x1000
     field public static final int BIND_NOT_FOREGROUND = 4; // 0x4
@@ -10434,7 +10468,6 @@
   }
 
   public static final class Context.BindServiceFlags {
-    method public long getValue();
     method @NonNull public static android.content.Context.BindServiceFlags of(long);
   }
 
@@ -11151,6 +11184,7 @@
     method public final String getDataScheme(int);
     method public final android.os.PatternMatcher getDataSchemeSpecificPart(int);
     method public final String getDataType(int);
+    method @NonNull public final android.os.PersistableBundle getExtras();
     method public final int getPriority();
     method public final boolean hasAction(String);
     method public final boolean hasCategory(String);
@@ -11169,6 +11203,7 @@
     method public void readFromXml(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public final java.util.Iterator<android.os.PatternMatcher> schemeSpecificPartsIterator();
     method public final java.util.Iterator<java.lang.String> schemesIterator();
+    method public final void setExtras(@NonNull android.os.PersistableBundle);
     method public final void setPriority(int);
     method public final java.util.Iterator<java.lang.String> typesIterator();
     method public final void writeToParcel(android.os.Parcel, int);
@@ -12725,6 +12760,7 @@
     field public static final String FEATURE_VULKAN_HARDWARE_COMPUTE = "android.hardware.vulkan.compute";
     field public static final String FEATURE_VULKAN_HARDWARE_LEVEL = "android.hardware.vulkan.level";
     field public static final String FEATURE_VULKAN_HARDWARE_VERSION = "android.hardware.vulkan.version";
+    field public static final String FEATURE_WALLET_LOCATION_BASED_SUGGESTIONS = "android.software.wallet_location_based_suggestions";
     field public static final String FEATURE_WATCH = "android.hardware.type.watch";
     field public static final String FEATURE_WEBVIEW = "android.software.webview";
     field public static final String FEATURE_WIFI = "android.hardware.wifi";
@@ -12778,6 +12814,7 @@
     field public static final long MAXIMUM_VERIFICATION_TIMEOUT = 3600000L; // 0x36ee80L
     field public static final int PERMISSION_DENIED = -1; // 0xffffffff
     field public static final int PERMISSION_GRANTED = 0; // 0x0
+    field public static final String PROPERTY_COMPAT_OVERRIDE_LANDSCAPE_TO_PORTRAIT = "android.camera.PROPERTY_COMPAT_OVERRIDE_LANDSCAPE_TO_PORTRAIT";
     field public static final String PROPERTY_MEDIA_CAPABILITIES = "android.media.PROPERTY_MEDIA_CAPABILITIES";
     field public static final String PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES = "android.net.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES";
     field public static final String PROPERTY_SPECIAL_USE_FGS_SUBTYPE = "android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE";
@@ -13587,12 +13624,11 @@
   }
 
   public static final class CreateCredentialRequest.Builder {
-    ctor public CreateCredentialRequest.Builder(@NonNull android.os.Bundle, @NonNull android.os.Bundle);
+    ctor public CreateCredentialRequest.Builder(@NonNull String, @NonNull android.os.Bundle, @NonNull android.os.Bundle);
     method @NonNull public android.credentials.CreateCredentialRequest build();
     method @NonNull public android.credentials.CreateCredentialRequest.Builder setAlwaysSendAppInfoToProvider(boolean);
     method @NonNull public android.credentials.CreateCredentialRequest.Builder setIsSystemProviderRequired(boolean);
     method @NonNull @RequiresPermission(android.Manifest.permission.CREDENTIAL_MANAGER_SET_ORIGIN) public android.credentials.CreateCredentialRequest.Builder setOrigin(@NonNull String);
-    method @NonNull public android.credentials.CreateCredentialRequest.Builder setType(@NonNull String);
   }
 
   public final class CreateCredentialResponse implements android.os.Parcelable {
@@ -15479,14 +15515,14 @@
     method @NonNull public float getMinDisplayRatioForHdrTransition();
     method @NonNull public float[] getRatioMax();
     method @NonNull public float[] getRatioMin();
-    method @NonNull public void setDisplayRatioForFullHdr(float);
-    method @NonNull public void setEpsilonHdr(float, float, float);
-    method @NonNull public void setEpsilonSdr(float, float, float);
+    method public void setDisplayRatioForFullHdr(@FloatRange(from=1.0f) float);
+    method public void setEpsilonHdr(float, float, float);
+    method public void setEpsilonSdr(float, float, float);
     method public void setGainmapContents(@NonNull android.graphics.Bitmap);
-    method @NonNull public void setGamma(float, float, float);
-    method @NonNull public void setMinDisplayRatioForHdrTransition(@FloatRange(from=1.0f) float);
-    method @NonNull public void setRatioMax(float, float, float);
-    method @NonNull public void setRatioMin(float, float, float);
+    method public void setGamma(float, float, float);
+    method public void setMinDisplayRatioForHdrTransition(@FloatRange(from=1.0f) float);
+    method public void setRatioMax(float, float, float);
+    method public void setRatioMin(float, float, float);
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.graphics.Gainmap> CREATOR;
   }
@@ -19527,9 +19563,9 @@
 
   public final class DisplayManager {
     method public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, @IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @Nullable android.view.Surface, int);
-    method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, @IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, float, @Nullable android.view.Surface, int);
     method public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, @IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @Nullable android.view.Surface, int, @Nullable android.hardware.display.VirtualDisplay.Callback, @Nullable android.os.Handler);
-    method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, @IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, float, @Nullable android.view.Surface, int, @Nullable android.os.Handler, @Nullable android.hardware.display.VirtualDisplay.Callback);
+    method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull android.hardware.display.VirtualDisplayConfig);
+    method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull android.hardware.display.VirtualDisplayConfig, @Nullable android.os.Handler, @Nullable android.hardware.display.VirtualDisplay.Callback);
     method public android.view.Display getDisplay(int);
     method public android.view.Display[] getDisplays();
     method public android.view.Display[] getDisplays(String);
@@ -19584,6 +19620,30 @@
     method public void onStopped();
   }
 
+  public final class VirtualDisplayConfig implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getDensityDpi();
+    method @NonNull public java.util.Set<java.lang.String> getDisplayCategories();
+    method public int getFlags();
+    method public int getHeight();
+    method @NonNull public String getName();
+    method public float getRequestedRefreshRate();
+    method @Nullable public android.view.Surface getSurface();
+    method public int getWidth();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.display.VirtualDisplayConfig> CREATOR;
+  }
+
+  public static final class VirtualDisplayConfig.Builder {
+    ctor public VirtualDisplayConfig.Builder(@NonNull String, @IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int);
+    method @NonNull public android.hardware.display.VirtualDisplayConfig.Builder addDisplayCategory(@NonNull String);
+    method @NonNull public android.hardware.display.VirtualDisplayConfig build();
+    method @NonNull public android.hardware.display.VirtualDisplayConfig.Builder setDisplayCategories(@NonNull java.util.Set<java.lang.String>);
+    method @NonNull public android.hardware.display.VirtualDisplayConfig.Builder setFlags(int);
+    method @NonNull public android.hardware.display.VirtualDisplayConfig.Builder setRequestedRefreshRate(@FloatRange(from=0.0f) float);
+    method @NonNull public android.hardware.display.VirtualDisplayConfig.Builder setSurface(@Nullable android.view.Surface);
+  }
+
 }
 
 package android.hardware.fingerprint {
@@ -20358,7 +20418,7 @@
   public final class GnssCapabilities implements android.os.Parcelable {
     method public int describeContents();
     method @NonNull public java.util.List<android.location.GnssSignalType> getGnssSignalTypes();
-    method public boolean hasAccumulatedDeltaRange();
+    method public int hasAccumulatedDeltaRange();
     method public boolean hasAntennaInfo();
     method public boolean hasGeofencing();
     method @Deprecated public boolean hasGnssAntennaInfo();
@@ -20384,8 +20444,10 @@
     method public boolean hasSatellitePvt();
     method public boolean hasScheduling();
     method public boolean hasSingleShotFix();
-    method public boolean isAccumulatedDeltaRangeCapabilityKnown();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field public static final int CAPABILITY_SUPPORTED = 1; // 0x1
+    field public static final int CAPABILITY_UNKNOWN = 0; // 0x0
+    field public static final int CAPABILITY_UNSUPPORTED = 2; // 0x2
     field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssCapabilities> CREATOR;
   }
 
@@ -20393,9 +20455,8 @@
     ctor public GnssCapabilities.Builder();
     ctor public GnssCapabilities.Builder(@NonNull android.location.GnssCapabilities);
     method @NonNull public android.location.GnssCapabilities build();
-    method @NonNull public android.location.GnssCapabilities.Builder clearIsAccumulatedDeltaRangeCapabilityKnown();
     method @NonNull public android.location.GnssCapabilities.Builder setGnssSignalTypes(@NonNull java.util.List<android.location.GnssSignalType>);
-    method @NonNull public android.location.GnssCapabilities.Builder setHasAccumulatedDeltaRange(boolean);
+    method @NonNull public android.location.GnssCapabilities.Builder setHasAccumulatedDeltaRange(int);
     method @NonNull public android.location.GnssCapabilities.Builder setHasAntennaInfo(boolean);
     method @NonNull public android.location.GnssCapabilities.Builder setHasGeofencing(boolean);
     method @NonNull public android.location.GnssCapabilities.Builder setHasLowPowerMode(boolean);
@@ -26245,9 +26306,9 @@
 
   public final class MediaProjection {
     method public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, int, int, int, int, @Nullable android.view.Surface, @Nullable android.hardware.display.VirtualDisplay.Callback, @Nullable android.os.Handler);
-    method public void registerCallback(android.media.projection.MediaProjection.Callback, android.os.Handler);
+    method public void registerCallback(@NonNull android.media.projection.MediaProjection.Callback, @Nullable android.os.Handler);
     method public void stop();
-    method public void unregisterCallback(android.media.projection.MediaProjection.Callback);
+    method public void unregisterCallback(@NonNull android.media.projection.MediaProjection.Callback);
   }
 
   public abstract static class MediaProjection.Callback {
@@ -26724,9 +26785,7 @@
   }
 
   public final class TableResponse extends android.media.tv.BroadcastInfoResponse implements android.os.Parcelable {
-    ctor public TableResponse(int, int, int, @Nullable android.net.Uri, int, int);
-    ctor public TableResponse(int, int, int, @NonNull byte[], int, int);
-    ctor public TableResponse(int, int, int, @NonNull android.os.SharedMemory, int, int);
+    ctor @Deprecated public TableResponse(int, int, int, @Nullable android.net.Uri, int, int);
     method public int getSize();
     method @Nullable public byte[] getTableByteArray();
     method @Nullable public android.os.SharedMemory getTableSharedMemory();
@@ -26735,6 +26794,14 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.TableResponse> CREATOR;
   }
 
+  public static final class TableResponse.Builder {
+    ctor public TableResponse.Builder(int, int, int, int, int);
+    method @NonNull public android.media.tv.TableResponse build();
+    method @NonNull public android.media.tv.TableResponse.Builder setTableByteArray(@NonNull byte[]);
+    method @NonNull public android.media.tv.TableResponse.Builder setTableSharedMemory(@NonNull android.os.SharedMemory);
+    method @NonNull public android.media.tv.TableResponse.Builder setTableUri(@NonNull android.net.Uri);
+  }
+
   public final class TimelineRequest extends android.media.tv.BroadcastInfoRequest implements android.os.Parcelable {
     ctor public TimelineRequest(int, int, int);
     ctor public TimelineRequest(int, int, int, @NonNull String);
@@ -27278,8 +27345,12 @@
     field public static final int TIME_SHIFT_STATUS_UNAVAILABLE = 2; // 0x2
     field public static final int TIME_SHIFT_STATUS_UNKNOWN = 0; // 0x0
     field public static final int TIME_SHIFT_STATUS_UNSUPPORTED = 1; // 0x1
-    field public static final String TV_MESSAGE_TYPE_CLOSED_CAPTION = "CC";
-    field public static final String TV_MESSAGE_TYPE_WATERMARK = "Watermark";
+    field public static final String TV_MESSAGE_KEY_RAW_DATA = "android.media.tv.TvInputManager.raw_data";
+    field public static final String TV_MESSAGE_KEY_STREAM_ID = "android.media.tv.TvInputManager.stream_id";
+    field public static final String TV_MESSAGE_KEY_SUBTYPE = "android.media.tv.TvInputManager.subtype";
+    field public static final int TV_MESSAGE_TYPE_CLOSED_CAPTION = 2; // 0x2
+    field public static final int TV_MESSAGE_TYPE_OTHER = 1000; // 0x3e8
+    field public static final int TV_MESSAGE_TYPE_WATERMARK = 1; // 0x1
     field public static final int VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY = 4; // 0x4
     field public static final int VIDEO_UNAVAILABLE_REASON_BUFFERING = 3; // 0x3
     field public static final int VIDEO_UNAVAILABLE_REASON_CAS_BLACKOUT = 16; // 0x10
@@ -27370,10 +27441,10 @@
     method public void notifyTrackSelected(int, String);
     method public void notifyTracksChanged(java.util.List<android.media.tv.TvTrackInfo>);
     method public void notifyTuned(@NonNull android.net.Uri);
-    method public void notifyTvMessage(@NonNull String, @NonNull android.os.Bundle);
+    method public void notifyTvMessage(int, @NonNull android.os.Bundle);
     method public void notifyVideoAvailable();
     method public void notifyVideoUnavailable(int);
-    method public void onAdBuffer(@NonNull android.media.tv.AdBuffer);
+    method public void onAdBufferReady(@NonNull android.media.tv.AdBuffer);
     method public void onAppPrivateCommand(@NonNull String, android.os.Bundle);
     method public android.view.View onCreateOverlayView();
     method public boolean onGenericMotionEvent(android.view.MotionEvent);
@@ -27392,7 +27463,7 @@
     method public void onSetInteractiveAppNotificationEnabled(boolean);
     method public abstract void onSetStreamVolume(@FloatRange(from=0.0, to=1.0) float);
     method public abstract boolean onSetSurface(@Nullable android.view.Surface);
-    method public void onSetTvMessageEnabled(@NonNull String, boolean);
+    method public void onSetTvMessageEnabled(int, boolean);
     method public void onSurfaceChanged(int, int, int);
     method public long onTimeShiftGetCurrentPosition();
     method public long onTimeShiftGetStartPosition();
@@ -27406,6 +27477,7 @@
     method public boolean onTrackballEvent(android.view.MotionEvent);
     method public abstract boolean onTune(android.net.Uri);
     method public boolean onTune(android.net.Uri, android.os.Bundle);
+    method public void onTvMessage(@NonNull String, @NonNull android.os.Bundle);
     method public void onUnblockContent(android.media.tv.TvContentRating);
     method public void setOverlayViewEnabled(boolean);
   }
@@ -27441,17 +27513,17 @@
     method @NonNull public android.net.Uri getChannelUri();
     method @NonNull public java.util.List<android.media.tv.TvContentRating> getContentRatings();
     method @NonNull public String getDescription();
-    method @NonNull public long getEndPaddingMillis();
+    method public long getEndPaddingMillis();
     method @NonNull public String getName();
     method @Nullable public android.net.Uri getProgramUri();
-    method @IntRange(from=0xffffffff) @NonNull public long getRecordingDurationMillis();
+    method @IntRange(from=0xffffffff) public long getRecordingDurationMillis();
     method @NonNull public String getRecordingId();
-    method @IntRange(from=0xffffffff) @NonNull public long getRecordingStartTimeMillis();
+    method @IntRange(from=0xffffffff) public long getRecordingStartTimeMillis();
     method @Nullable public android.net.Uri getRecordingUri();
-    method @NonNull public int getRepeatDays();
-    method @IntRange(from=0) @NonNull public long getScheduledDurationMillis();
-    method @IntRange(from=0) @NonNull public long getScheduledStartTimeMillis();
-    method @NonNull public long getStartPaddingMillis();
+    method public int getRepeatDays();
+    method @IntRange(from=0) public long getScheduledDurationMillis();
+    method @IntRange(from=0) public long getScheduledStartTimeMillis();
+    method public long getStartPaddingMillis();
     method public void setDescription(@NonNull String);
     method public void setName(@NonNull String);
     method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -27534,7 +27606,7 @@
     method public void setOnUnhandledInputEventListener(android.media.tv.TvView.OnUnhandledInputEventListener);
     method public void setStreamVolume(@FloatRange(from=0.0, to=1.0) float);
     method public void setTimeShiftPositionCallback(@Nullable android.media.tv.TvView.TimeShiftPositionCallback);
-    method public void setTvMessageEnabled(@NonNull String, boolean);
+    method public void setTvMessageEnabled(int, boolean);
     method public void setZOrderMediaOverlay(boolean);
     method public void setZOrderOnTop(boolean);
     method public void timeShiftPause();
@@ -27575,7 +27647,7 @@
     method public void onTrackSelected(String, int, String);
     method public void onTracksChanged(String, java.util.List<android.media.tv.TvTrackInfo>);
     method public void onTuned(@NonNull String, @NonNull android.net.Uri);
-    method public void onTvMessage(@NonNull String, @NonNull String, @NonNull android.os.Bundle);
+    method public void onTvMessage(@NonNull String, int, @NonNull android.os.Bundle);
     method public void onVideoAvailable(String);
     method public void onVideoSizeChanged(String, int, int);
     method public void onVideoUnavailable(String, int);
@@ -27683,7 +27755,7 @@
     ctor public TvInteractiveAppService.Session(@NonNull android.content.Context);
     method public boolean isMediaViewEnabled();
     method @CallSuper public void layoutSurface(int, int, int, int);
-    method @CallSuper public void notifyAdBuffer(@NonNull android.media.tv.AdBuffer);
+    method @CallSuper public void notifyAdBufferReady(@NonNull android.media.tv.AdBuffer);
     method @CallSuper public final void notifyBiInteractiveAppCreated(@NonNull android.net.Uri, @Nullable String);
     method @CallSuper public void notifySessionStateChanged(int, int);
     method @CallSuper public final void notifyTeletextAppStateChanged(int);
@@ -27735,7 +27807,7 @@
     method public boolean onTrackballEvent(@NonNull android.view.MotionEvent);
     method public void onTracksChanged(@NonNull java.util.List<android.media.tv.TvTrackInfo>);
     method public void onTuned(@NonNull android.net.Uri);
-    method public void onTvMessage(@NonNull String, @NonNull android.os.Bundle);
+    method public void onTvMessage(int, @NonNull android.os.Bundle);
     method public void onTvRecordingInfo(@Nullable android.media.tv.TvRecordingInfo);
     method public void onTvRecordingInfoList(@NonNull java.util.List<android.media.tv.TvRecordingInfo>);
     method public void onVideoAvailable();
@@ -27757,7 +27829,7 @@
     method @CallSuper public void requestTimeShiftMode();
     method @CallSuper public void requestTrackInfoList();
     method @CallSuper public void requestTvRecordingInfo(@NonNull String);
-    method @CallSuper public void requestTvRecordingInfoList(@NonNull int);
+    method @CallSuper public void requestTvRecordingInfoList(int);
     method @CallSuper public void sendPlaybackCommandRequest(@NonNull String, @Nullable android.os.Bundle);
     method @CallSuper public void sendTimeShiftCommandRequest(@NonNull String, @Nullable android.os.Bundle);
     method @CallSuper public void setMediaViewEnabled(boolean);
@@ -27799,7 +27871,7 @@
     method public void notifyTimeShiftPlaybackParams(@NonNull android.media.PlaybackParams);
     method public void notifyTimeShiftStartPositionChanged(@NonNull String, long);
     method public void notifyTimeShiftStatusChanged(@NonNull String, int);
-    method public void notifyTvMessage(@NonNull String, @NonNull android.os.Bundle);
+    method public void notifyTvMessage(@NonNull int, @NonNull android.os.Bundle);
     method public void onAttachedToWindow();
     method public void onDetachedFromWindow();
     method public void onLayout(boolean, int, int, int, int);
@@ -27856,7 +27928,7 @@
     method public void onRequestTimeShiftMode(@NonNull String);
     method public void onRequestTrackInfoList(@NonNull String);
     method public void onRequestTvRecordingInfo(@NonNull String, @NonNull String);
-    method public void onRequestTvRecordingInfoList(@NonNull String, @NonNull int);
+    method public void onRequestTvRecordingInfoList(@NonNull String, int);
     method public void onSetTvRecordingInfo(@NonNull String, @NonNull String, @NonNull android.media.tv.TvRecordingInfo);
     method public void onSetVideoBounds(@NonNull String, @NonNull android.graphics.Rect);
     method public void onStateChanged(@NonNull String, int, int);
@@ -33542,6 +33614,7 @@
     method @Deprecated public static final boolean supportsProcesses();
     field public static final int BLUETOOTH_UID = 1002; // 0x3ea
     field public static final int FIRST_APPLICATION_UID = 10000; // 0x2710
+    field public static final int INVALID_PID = -1; // 0xffffffff
     field public static final int INVALID_UID = -1; // 0xffffffff
     field public static final int LAST_APPLICATION_UID = 19999; // 0x4e1f
     field public static final int PHONE_UID = 1001; // 0x3e9
@@ -33803,6 +33876,7 @@
     method public android.os.Bundle getUserRestrictions();
     method @RequiresPermission(anyOf={"android.permission.MANAGE_USERS", "android.permission.INTERACT_ACROSS_USERS"}, conditional=true) public android.os.Bundle getUserRestrictions(android.os.UserHandle);
     method public boolean hasUserRestriction(String);
+    method public boolean isAdminUser();
     method public boolean isDemoUser();
     method public static boolean isHeadlessSystemUserMode();
     method public boolean isManagedProfile();
@@ -36858,6 +36932,7 @@
     method public String[] getDocumentStreamTypes(String, String);
     method public String getDocumentType(String) throws java.io.FileNotFoundException;
     method public final String getType(android.net.Uri);
+    method @Nullable public final String getTypeAnonymous(@NonNull android.net.Uri);
     method public final android.net.Uri insert(android.net.Uri, android.content.ContentValues);
     method public boolean isChildDocument(String, String);
     method public String moveDocument(String, String, String) throws java.io.FileNotFoundException;
@@ -39734,6 +39809,7 @@
     method @NonNull public android.service.autofill.Dataset.Builder setAuthentication(@Nullable android.content.IntentSender);
     method @NonNull public android.service.autofill.Dataset.Builder setField(@NonNull android.view.autofill.AutofillId, @Nullable android.service.autofill.Field);
     method @NonNull public android.service.autofill.Dataset.Builder setField(@NonNull String, @NonNull android.service.autofill.Field);
+    method @NonNull public android.service.autofill.Dataset.Builder setFieldForAllHints(@NonNull android.service.autofill.Field);
     method @NonNull public android.service.autofill.Dataset.Builder setId(@Nullable String);
     method @Deprecated @NonNull public android.service.autofill.Dataset.Builder setInlinePresentation(@NonNull android.service.autofill.InlinePresentation);
     method @Deprecated @NonNull public android.service.autofill.Dataset.Builder setInlinePresentation(@NonNull android.service.autofill.InlinePresentation, @NonNull android.service.autofill.InlinePresentation);
@@ -39830,6 +39906,7 @@
     field public static final int TYPE_DATASET_AUTHENTICATION_SELECTED = 1; // 0x1
     field public static final int TYPE_DATASET_SELECTED = 0; // 0x0
     field public static final int TYPE_SAVE_SHOWN = 3; // 0x3
+    field public static final int TYPE_VIEW_REQUESTED_AUTOFILL = 6; // 0x6
     field public static final int UI_TYPE_DIALOG = 3; // 0x3
     field public static final int UI_TYPE_INLINE = 2; // 0x2
     field public static final int UI_TYPE_MENU = 1; // 0x1
@@ -40506,7 +40583,7 @@
     ctor public BeginCreateCredentialResponse();
     method public int describeContents();
     method @NonNull public java.util.List<android.service.credentials.CreateEntry> getCreateEntries();
-    method @Nullable public android.service.credentials.CreateEntry getRemoteCreateEntry();
+    method @Nullable public android.service.credentials.RemoteEntry getRemoteCreateEntry();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.BeginCreateCredentialResponse> CREATOR;
   }
@@ -40516,7 +40593,7 @@
     method @NonNull public android.service.credentials.BeginCreateCredentialResponse.Builder addCreateEntry(@NonNull android.service.credentials.CreateEntry);
     method @NonNull public android.service.credentials.BeginCreateCredentialResponse build();
     method @NonNull public android.service.credentials.BeginCreateCredentialResponse.Builder setCreateEntries(@NonNull java.util.List<android.service.credentials.CreateEntry>);
-    method @NonNull public android.service.credentials.BeginCreateCredentialResponse.Builder setRemoteCreateEntry(@Nullable android.service.credentials.CreateEntry);
+    method @NonNull @RequiresPermission("android.permission.PROVIDE_REMOTE_CREDENTIALS") public android.service.credentials.BeginCreateCredentialResponse.Builder setRemoteCreateEntry(@Nullable android.service.credentials.RemoteEntry);
   }
 
   public class BeginGetCredentialOption implements android.os.Parcelable {
@@ -40551,7 +40628,7 @@
     method @NonNull public java.util.List<android.service.credentials.Action> getActions();
     method @NonNull public java.util.List<android.service.credentials.Action> getAuthenticationActions();
     method @NonNull public java.util.List<android.service.credentials.CredentialEntry> getCredentialEntries();
-    method @Nullable public android.service.credentials.CredentialEntry getRemoteCredentialEntry();
+    method @Nullable public android.service.credentials.RemoteEntry getRemoteCredentialEntry();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.BeginGetCredentialResponse> CREATOR;
   }
@@ -40565,7 +40642,7 @@
     method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder setActions(@NonNull java.util.List<android.service.credentials.Action>);
     method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder setAuthenticationActions(@NonNull java.util.List<android.service.credentials.Action>);
     method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder setCredentialEntries(@NonNull java.util.List<android.service.credentials.CredentialEntry>);
-    method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder setRemoteCredentialEntry(@Nullable android.service.credentials.CredentialEntry);
+    method @NonNull @RequiresPermission("android.permission.PROVIDE_REMOTE_CREDENTIALS") public android.service.credentials.BeginGetCredentialResponse.Builder setRemoteCredentialEntry(@Nullable android.service.credentials.RemoteEntry);
   }
 
   public final class CallingAppInfo implements android.os.Parcelable {
@@ -40607,9 +40684,11 @@
   }
 
   public class CredentialEntry implements android.os.Parcelable {
+    ctor public CredentialEntry(@NonNull String, @NonNull String, @NonNull android.app.slice.Slice);
     ctor public CredentialEntry(@NonNull android.service.credentials.BeginGetCredentialOption, @NonNull android.app.slice.Slice);
+    ctor public CredentialEntry(@NonNull String, @NonNull android.app.slice.Slice);
     method public int describeContents();
-    method @NonNull public android.service.credentials.BeginGetCredentialOption getBeginGetCredentialOption();
+    method @NonNull public String getBeginGetCredentialOptionId();
     method @NonNull public android.app.slice.Slice getSlice();
     method @NonNull public String getType();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -40635,14 +40714,22 @@
   }
 
   public final class GetCredentialRequest implements android.os.Parcelable {
-    ctor public GetCredentialRequest(@NonNull android.service.credentials.CallingAppInfo, @NonNull android.credentials.CredentialOption);
+    ctor public GetCredentialRequest(@NonNull android.service.credentials.CallingAppInfo, @NonNull java.util.List<android.credentials.CredentialOption>);
     method public int describeContents();
     method @NonNull public android.service.credentials.CallingAppInfo getCallingAppInfo();
-    method @NonNull public android.credentials.CredentialOption getCredentialOption();
+    method @NonNull public java.util.List<android.credentials.CredentialOption> getCredentialOptions();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.GetCredentialRequest> CREATOR;
   }
 
+  public class RemoteEntry implements android.os.Parcelable {
+    ctor public RemoteEntry(@NonNull android.app.slice.Slice);
+    method public int describeContents();
+    method @NonNull public android.app.slice.Slice getSlice();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.RemoteEntry> CREATOR;
+  }
+
 }
 
 package android.service.dreams {
@@ -41062,6 +41149,7 @@
     method @NonNull public String getCardId();
     method @NonNull public android.graphics.drawable.Icon getCardImage();
     method @Nullable public CharSequence getCardLabel();
+    method @NonNull public java.util.List<android.location.Location> getCardLocations();
     method @NonNull public int getCardType();
     method @NonNull public CharSequence getContentDescription();
     method @Nullable public android.graphics.drawable.Icon getNonPaymentCardSecondaryImage();
@@ -41079,6 +41167,7 @@
     method @NonNull public android.service.quickaccesswallet.WalletCard build();
     method @NonNull public android.service.quickaccesswallet.WalletCard.Builder setCardIcon(@Nullable android.graphics.drawable.Icon);
     method @NonNull public android.service.quickaccesswallet.WalletCard.Builder setCardLabel(@Nullable CharSequence);
+    method @NonNull public android.service.quickaccesswallet.WalletCard.Builder setCardLocations(@NonNull java.util.List<android.location.Location>);
     method @NonNull public android.service.quickaccesswallet.WalletCard.Builder setNonPaymentCardSecondaryImage(@Nullable android.graphics.drawable.Icon);
   }
 
@@ -41471,7 +41560,6 @@
 
   public abstract class RecognitionService extends android.app.Service {
     ctor public RecognitionService();
-    method public void clearModelDownloadListener(@NonNull android.content.Intent, @NonNull android.content.AttributionSource);
     method public int getMaxConcurrentSessionsCount();
     method public final android.os.IBinder onBind(android.content.Intent);
     method protected abstract void onCancel(android.speech.RecognitionService.Callback);
@@ -41481,7 +41569,7 @@
     method protected abstract void onStopListening(android.speech.RecognitionService.Callback);
     method public void onTriggerModelDownload(@NonNull android.content.Intent);
     method public void onTriggerModelDownload(@NonNull android.content.Intent, @NonNull android.content.AttributionSource);
-    method public void setModelDownloadListener(@NonNull android.content.Intent, @NonNull android.content.AttributionSource, @NonNull android.speech.ModelDownloadListener);
+    method public void onTriggerModelDownload(@NonNull android.content.Intent, @NonNull android.content.AttributionSource, @NonNull android.speech.ModelDownloadListener);
     field public static final String SERVICE_INTERFACE = "android.speech.RecognitionService";
     field public static final String SERVICE_META_DATA = "android.speech";
   }
@@ -41606,18 +41694,17 @@
   public class SpeechRecognizer {
     method @MainThread public void cancel();
     method public void checkRecognitionSupport(@NonNull android.content.Intent, @NonNull java.util.concurrent.Executor, @NonNull android.speech.RecognitionSupportCallback);
-    method public void clearModelDownloadListener(@NonNull android.content.Intent);
     method @MainThread @NonNull public static android.speech.SpeechRecognizer createOnDeviceSpeechRecognizer(@NonNull android.content.Context);
     method @MainThread public static android.speech.SpeechRecognizer createSpeechRecognizer(android.content.Context);
     method @MainThread public static android.speech.SpeechRecognizer createSpeechRecognizer(android.content.Context, android.content.ComponentName);
     method public void destroy();
     method public static boolean isOnDeviceRecognitionAvailable(@NonNull android.content.Context);
     method public static boolean isRecognitionAvailable(@NonNull android.content.Context);
-    method public void setModelDownloadListener(@NonNull android.content.Intent, @NonNull java.util.concurrent.Executor, @NonNull android.speech.ModelDownloadListener);
     method @MainThread public void setRecognitionListener(android.speech.RecognitionListener);
     method @MainThread public void startListening(android.content.Intent);
     method @MainThread public void stopListening();
     method public void triggerModelDownload(@NonNull android.content.Intent);
+    method public void triggerModelDownload(@NonNull android.content.Intent, @NonNull java.util.concurrent.Executor, @NonNull android.speech.ModelDownloadListener);
     field public static final String CONFIDENCE_SCORES = "confidence_scores";
     field public static final String DETECTED_LANGUAGE = "detected_language";
     field public static final int ERROR_AUDIO = 3; // 0x3
@@ -51402,7 +51489,7 @@
   public final class MotionPredictor {
     ctor public MotionPredictor(@NonNull android.content.Context);
     method public boolean isPredictionAvailable(int, int);
-    method @NonNull public java.util.List<android.view.MotionEvent> predict(long);
+    method @Nullable public android.view.MotionEvent predict(long);
     method public void record(@NonNull android.view.MotionEvent);
   }
 
@@ -51991,8 +52078,8 @@
     method @Nullable public CharSequence getAccessibilityPaneTitle();
     method @IdRes public int getAccessibilityTraversalAfter();
     method @IdRes public int getAccessibilityTraversalBefore();
-    method @NonNull public String getAllowedHandwritingDelegatePackageName();
-    method @NonNull public String getAllowedHandwritingDelegatorPackageName();
+    method @Nullable public String getAllowedHandwritingDelegatePackageName();
+    method @Nullable public String getAllowedHandwritingDelegatorPackageName();
     method public float getAlpha();
     method public android.view.animation.Animation getAnimation();
     method @Nullable public android.graphics.Matrix getAnimationMatrix();
@@ -52186,7 +52273,7 @@
     method public void invalidate();
     method public void invalidateDrawable(@NonNull android.graphics.drawable.Drawable);
     method public void invalidateOutline();
-    method public boolean isAccessibilityDataPrivate();
+    method public boolean isAccessibilityDataSensitive();
     method public boolean isAccessibilityFocused();
     method public boolean isAccessibilityHeading();
     method public boolean isActivated();
@@ -52366,7 +52453,7 @@
     method public void scrollTo(int, int);
     method public void sendAccessibilityEvent(int);
     method public void sendAccessibilityEventUnchecked(android.view.accessibility.AccessibilityEvent);
-    method public void setAccessibilityDataPrivate(int);
+    method public void setAccessibilityDataSensitive(int);
     method public void setAccessibilityDelegate(@Nullable android.view.View.AccessibilityDelegate);
     method public void setAccessibilityHeading(boolean);
     method public void setAccessibilityLiveRegion(int);
@@ -52375,8 +52462,8 @@
     method public void setAccessibilityTraversalBefore(@IdRes int);
     method public void setActivated(boolean);
     method public void setAllowClickWhenDisabled(boolean);
-    method public void setAllowedHandwritingDelegatePackage(@NonNull String);
-    method public void setAllowedHandwritingDelegatorPackage(@NonNull String);
+    method public void setAllowedHandwritingDelegatePackage(@Nullable String);
+    method public void setAllowedHandwritingDelegatorPackage(@Nullable String);
     method public void setAlpha(@FloatRange(from=0.0, to=1.0) float);
     method public void setAnimation(android.view.animation.Animation);
     method public void setAnimationMatrix(@Nullable android.graphics.Matrix);
@@ -52552,9 +52639,9 @@
     method @CallSuper protected boolean verifyDrawable(@NonNull android.graphics.drawable.Drawable);
     method @Deprecated public boolean willNotCacheDrawing();
     method public boolean willNotDraw();
-    field public static final int ACCESSIBILITY_DATA_PRIVATE_AUTO = 0; // 0x0
-    field public static final int ACCESSIBILITY_DATA_PRIVATE_NO = 2; // 0x2
-    field public static final int ACCESSIBILITY_DATA_PRIVATE_YES = 1; // 0x1
+    field public static final int ACCESSIBILITY_DATA_SENSITIVE_AUTO = 0; // 0x0
+    field public static final int ACCESSIBILITY_DATA_SENSITIVE_NO = 2; // 0x2
+    field public static final int ACCESSIBILITY_DATA_SENSITIVE_YES = 1; // 0x1
     field public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 2; // 0x2
     field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
     field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
@@ -54024,11 +54111,11 @@
     method public int getSpeechStateChangeTypes();
     method public int getWindowChanges();
     method public void initFromParcel(android.os.Parcel);
-    method public boolean isAccessibilityDataPrivate();
+    method public boolean isAccessibilityDataSensitive();
     method @Deprecated public static android.view.accessibility.AccessibilityEvent obtain(int);
     method @Deprecated public static android.view.accessibility.AccessibilityEvent obtain(android.view.accessibility.AccessibilityEvent);
     method @Deprecated public static android.view.accessibility.AccessibilityEvent obtain();
-    method public void setAccessibilityDataPrivate(boolean);
+    method public void setAccessibilityDataSensitive(boolean);
     method public void setAction(int);
     method public void setContentChangeTypes(int);
     method public void setEventTime(long);
@@ -54113,14 +54200,12 @@
     method public void addAudioDescriptionRequestedChangeListener(@NonNull java.util.concurrent.Executor, @NonNull android.view.accessibility.AccessibilityManager.AudioDescriptionRequestedChangeListener);
     method public boolean addTouchExplorationStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener);
     method public void addTouchExplorationStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener, @Nullable android.os.Handler);
-    method public void addUiContrastChangeListener(@NonNull java.util.concurrent.Executor, @NonNull android.view.accessibility.AccessibilityManager.UiContrastChangeListener);
     method @ColorInt public int getAccessibilityFocusColor();
     method public int getAccessibilityFocusStrokeWidth();
     method @Deprecated public java.util.List<android.content.pm.ServiceInfo> getAccessibilityServiceList();
     method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int);
     method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAccessibilityServiceList();
     method public int getRecommendedTimeoutMillis(int, int);
-    method @FloatRange(from=-1.0F, to=1.0f) public float getUiContrast();
     method public void interrupt();
     method public static boolean isAccessibilityButtonSupported();
     method public boolean isAudioDescriptionRequested();
@@ -54132,7 +54217,6 @@
     method public boolean removeAccessibilityStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener);
     method public boolean removeAudioDescriptionRequestedChangeListener(@NonNull android.view.accessibility.AccessibilityManager.AudioDescriptionRequestedChangeListener);
     method public boolean removeTouchExplorationStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener);
-    method public void removeUiContrastChangeListener(@NonNull android.view.accessibility.AccessibilityManager.UiContrastChangeListener);
     method public void sendAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
     field public static final int FLAG_CONTENT_CONTROLS = 4; // 0x4
     field public static final int FLAG_CONTENT_ICONS = 1; // 0x1
@@ -54155,10 +54239,6 @@
     method public void onTouchExplorationStateChanged(boolean);
   }
 
-  public static interface AccessibilityManager.UiContrastChangeListener {
-    method public void onUiContrastChanged(@FloatRange(from=-1.0F, to=1.0f) float);
-  }
-
   public class AccessibilityNodeInfo implements android.os.Parcelable {
     ctor public AccessibilityNodeInfo();
     ctor public AccessibilityNodeInfo(@NonNull android.view.View);
@@ -54219,6 +54299,7 @@
     method public int getWindowId();
     method public boolean hasRequestInitialAccessibilityFocus();
     method public boolean hasRequestTouchPassthrough();
+    method public boolean isAccessibilityDataSensitive();
     method public boolean isAccessibilityFocused();
     method public boolean isCheckable();
     method public boolean isChecked();
@@ -54255,6 +54336,7 @@
     method public boolean removeAction(android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction);
     method public boolean removeChild(android.view.View);
     method public boolean removeChild(android.view.View, int);
+    method public void setAccessibilityDataSensitive(boolean);
     method public void setAccessibilityFocused(boolean);
     method public void setAvailableExtraData(java.util.List<java.lang.String>);
     method @Deprecated public void setBoundsInParent(android.graphics.Rect);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 77fb8d0..d573e33 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -33,6 +33,7 @@
     field public static final String ADD_TRUSTED_DISPLAY = "android.permission.ADD_TRUSTED_DISPLAY";
     field public static final String ADJUST_RUNTIME_PERMISSIONS_POLICY = "android.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY";
     field public static final String ALLOCATE_AGGRESSIVE = "android.permission.ALLOCATE_AGGRESSIVE";
+    field public static final String ALLOWLISTED_WRITE_DEVICE_CONFIG = "android.permission.ALLOWLISTED_WRITE_DEVICE_CONFIG";
     field public static final String ALLOW_ANY_CODEC_FOR_PLAYBACK = "android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK";
     field public static final String ALLOW_PLACE_IN_MULTI_PANE_SETTINGS = "android.permission.ALLOW_PLACE_IN_MULTI_PANE_SETTINGS";
     field public static final String ALLOW_SLIPPERY_TOUCHES = "android.permission.ALLOW_SLIPPERY_TOUCHES";
@@ -160,7 +161,7 @@
     field public static final String LOCAL_MAC_ADDRESS = "android.permission.LOCAL_MAC_ADDRESS";
     field public static final String LOCATION_BYPASS = "android.permission.LOCATION_BYPASS";
     field public static final String LOCK_DEVICE = "android.permission.LOCK_DEVICE";
-    field public static final String LOG_PROCESS_ACTIVITIES = "android.permission.LOG_PROCESS_ACTIVITIES";
+    field public static final String LOG_FOREGROUND_RESOURCE_USE = "android.permission.LOG_FOREGROUND_RESOURCE_USE";
     field public static final String LOOP_RADIO = "android.permission.LOOP_RADIO";
     field public static final String MANAGE_ACCESSIBILITY = "android.permission.MANAGE_ACCESSIBILITY";
     field @Deprecated public static final String MANAGE_ACTIVITY_STACKS = "android.permission.MANAGE_ACTIVITY_STACKS";
@@ -254,7 +255,7 @@
     field public static final String PERFORM_SIM_ACTIVATION = "android.permission.PERFORM_SIM_ACTIVATION";
     field public static final String POWER_SAVER = "android.permission.POWER_SAVER";
     field public static final String PROVIDE_DEFAULT_ENABLED_CREDENTIAL_SERVICE = "android.permission.PROVIDE_DEFAULT_ENABLED_CREDENTIAL_SERVICE";
-    field public static final String PROVIDE_HYBRID_CREDENTIAL_SERVICE = "android.permission.PROVIDE_HYBRID_CREDENTIAL_SERVICE";
+    field public static final String PROVIDE_REMOTE_CREDENTIALS = "android.permission.PROVIDE_REMOTE_CREDENTIALS";
     field public static final String PROVIDE_RESOLVER_RANKER_SERVICE = "android.permission.PROVIDE_RESOLVER_RANKER_SERVICE";
     field public static final String PROVIDE_TRUST_AGENT = "android.permission.PROVIDE_TRUST_AGENT";
     field public static final String PROVISION_DEMO_DEVICE = "android.permission.PROVISION_DEMO_DEVICE";
@@ -287,6 +288,7 @@
     field public static final String READ_SYSTEM_UPDATE_INFO = "android.permission.READ_SYSTEM_UPDATE_INFO";
     field public static final String READ_WALLPAPER_INTERNAL = "android.permission.READ_WALLPAPER_INTERNAL";
     field public static final String READ_WIFI_CREDENTIAL = "android.permission.READ_WIFI_CREDENTIAL";
+    field public static final String READ_WRITE_SYNC_DISABLED_MODE_CONFIG = "android.permission.READ_WRITE_SYNC_DISABLED_MODE_CONFIG";
     field public static final String REAL_GET_TASKS = "android.permission.REAL_GET_TASKS";
     field public static final String RECEIVE_BLUETOOTH_MAP = "android.permission.RECEIVE_BLUETOOTH_MAP";
     field public static final String RECEIVE_DATA_ACTIVITY_CHANGE = "android.permission.RECEIVE_DATA_ACTIVITY_CHANGE";
@@ -536,15 +538,15 @@
     method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getUidImportance(int);
     method @RequiresPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) public void killProcessesWhenImperceptible(@NonNull int[], @NonNull String);
     method @RequiresPermission(android.Manifest.permission.KILL_UID) public void killUid(int, String);
-    method @RequiresPermission(android.Manifest.permission.LOG_PROCESS_ACTIVITIES) public void noteForegroundResourceUse(int, int, int, int);
+    method @RequiresPermission(android.Manifest.permission.LOG_FOREGROUND_RESOURCE_USE) public void noteForegroundResourceUseBegin(int, int, int) throws java.lang.SecurityException;
+    method @RequiresPermission(android.Manifest.permission.LOG_FOREGROUND_RESOURCE_USE) public void noteForegroundResourceUseEnd(int, int, int) throws java.lang.SecurityException;
     method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener);
     method public void setDeviceLocales(@NonNull android.os.LocaleList);
     method @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) public static void setPersistentVrThread(int);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public boolean startProfile(@NonNull android.os.UserHandle);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public boolean stopProfile(@NonNull android.os.UserHandle);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean switchUser(@NonNull android.os.UserHandle);
-    field public static final int FOREGROUND_SERVICE_API_EVENT_BEGIN = 1; // 0x1
-    field public static final int FOREGROUND_SERVICE_API_EVENT_END = 2; // 0x2
+    field public static final int FOREGROUND_SERVICE_API_TYPE_AUDIO = 5; // 0x5
     field public static final int FOREGROUND_SERVICE_API_TYPE_BLUETOOTH = 2; // 0x2
     field public static final int FOREGROUND_SERVICE_API_TYPE_CAMERA = 1; // 0x1
     field public static final int FOREGROUND_SERVICE_API_TYPE_CDM = 9; // 0x9
@@ -834,23 +836,11 @@
   }
 
   public class BroadcastOptions {
-    method public void clearDeliveryGroupMatchingFilter();
-    method public void clearDeliveryGroupMatchingKey();
-    method public void clearDeliveryGroupPolicy();
     method public void clearRequireCompatChange();
-    method @Nullable public android.content.IntentFilter getDeliveryGroupMatchingFilter();
-    method @Nullable public String getDeliveryGroupMatchingKey();
-    method public int getDeliveryGroupPolicy();
     method public int getPendingIntentBackgroundActivityStartMode();
-    method public boolean isDeferUntilActive();
     method @Deprecated public boolean isPendingIntentBackgroundActivityLaunchAllowed();
-    method @Deprecated @NonNull public static android.app.BroadcastOptions makeBasic();
     method @RequiresPermission(android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS) public void recordResponseEventWhileInBackground(@IntRange(from=0) long);
     method @RequiresPermission(android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND) public void setBackgroundActivityStartsAllowed(boolean);
-    method @NonNull public android.app.BroadcastOptions setDeferUntilActive(boolean);
-    method @NonNull public android.app.BroadcastOptions setDeliveryGroupMatchingFilter(@NonNull android.content.IntentFilter);
-    method @NonNull public android.app.BroadcastOptions setDeliveryGroupMatchingKey(@NonNull String, @NonNull String);
-    method @NonNull public android.app.BroadcastOptions setDeliveryGroupPolicy(int);
     method public void setDontSendToRestrictedApps(boolean);
     method @Deprecated public void setPendingIntentBackgroundActivityLaunchAllowed(boolean);
     method @NonNull public android.app.BroadcastOptions setPendingIntentBackgroundActivityStartMode(int);
@@ -859,8 +849,6 @@
     method public void setRequireNoneOfPermissions(@Nullable String[]);
     method @RequiresPermission(anyOf={android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST, android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND, android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND}) public void setTemporaryAppAllowlist(long, int, int, @Nullable String);
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST, android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND, android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND}) public void setTemporaryAppWhitelistDuration(long);
-    field public static final int DELIVERY_GROUP_POLICY_ALL = 0; // 0x0
-    field public static final int DELIVERY_GROUP_POLICY_MOST_RECENT = 1; // 0x1
   }
 
   public class DownloadManager {
@@ -935,7 +923,7 @@
 
   public class KeyguardManager {
     method @RequiresPermission(android.Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN) public long addWeakEscrowToken(@NonNull byte[], @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull android.app.KeyguardManager.WeakEscrowTokenActivatedListener);
-    method @NonNull @RequiresPermission(android.Manifest.permission.CHECK_REMOTE_LOCKSCREEN) public android.content.Intent createConfirmDeviceCredentialForRemoteValidationIntent(@NonNull android.app.StartLockscreenValidationRequest, @NonNull android.content.ComponentName, @Nullable CharSequence, @Nullable CharSequence, @Nullable CharSequence, @Nullable CharSequence);
+    method @NonNull @RequiresPermission(android.Manifest.permission.CHECK_REMOTE_LOCKSCREEN) public android.content.Intent createConfirmDeviceCredentialForRemoteValidationIntent(@NonNull android.app.RemoteLockscreenValidationSession, @NonNull android.content.ComponentName, @Nullable CharSequence, @Nullable CharSequence, @Nullable CharSequence, @Nullable CharSequence);
     method public android.content.Intent createConfirmFactoryResetCredentialIntent(CharSequence, CharSequence, CharSequence);
     method @RequiresPermission("android.permission.SET_INITIAL_LOCK") public int getMinLockLength(boolean, int);
     method @RequiresPermission(android.Manifest.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS) public boolean getPrivateNotificationsAllowed();
@@ -947,7 +935,7 @@
     method @RequiresPermission(android.Manifest.permission.SHOW_KEYGUARD_MESSAGE) public void requestDismissKeyguard(@NonNull android.app.Activity, @Nullable CharSequence, @Nullable android.app.KeyguardManager.KeyguardDismissCallback);
     method @RequiresPermission("android.permission.SET_INITIAL_LOCK") public boolean setLock(int, @NonNull byte[], int);
     method @RequiresPermission(android.Manifest.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS) public void setPrivateNotificationsAllowed(boolean);
-    method @NonNull @RequiresPermission(android.Manifest.permission.CHECK_REMOTE_LOCKSCREEN) public android.app.StartLockscreenValidationRequest startRemoteLockscreenValidation();
+    method @NonNull @RequiresPermission(android.Manifest.permission.CHECK_REMOTE_LOCKSCREEN) public android.app.RemoteLockscreenValidationSession startRemoteLockscreenValidation();
     method @RequiresPermission(android.Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN) public boolean unregisterWeakEscrowTokenRemovedListener(@NonNull android.app.KeyguardManager.WeakEscrowTokenRemovedListener);
     method @NonNull @RequiresPermission(android.Manifest.permission.CHECK_REMOTE_LOCKSCREEN) public android.app.RemoteLockscreenValidationResult validateRemoteLockscreen(@NonNull byte[]);
     field public static final int PASSWORD = 0; // 0x0
@@ -1036,6 +1024,7 @@
     field public static final int RESULT_GUESS_VALID = 1; // 0x1
     field public static final int RESULT_LOCKOUT = 3; // 0x3
     field public static final int RESULT_NO_REMAINING_ATTEMPTS = 4; // 0x4
+    field public static final int RESULT_SESSION_EXPIRED = 5; // 0x5
   }
 
   public static final class RemoteLockscreenValidationResult.Builder {
@@ -1045,6 +1034,23 @@
     method @NonNull public android.app.RemoteLockscreenValidationResult.Builder setTimeoutMillis(long);
   }
 
+  public final class RemoteLockscreenValidationSession implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getLockType();
+    method public int getRemainingAttempts();
+    method @NonNull public byte[] getSourcePublicKey();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.app.RemoteLockscreenValidationSession> CREATOR;
+  }
+
+  public static final class RemoteLockscreenValidationSession.Builder {
+    ctor public RemoteLockscreenValidationSession.Builder();
+    method @NonNull public android.app.RemoteLockscreenValidationSession build();
+    method @NonNull public android.app.RemoteLockscreenValidationSession.Builder setLockType(int);
+    method @NonNull public android.app.RemoteLockscreenValidationSession.Builder setRemainingAttempts(int);
+    method @NonNull public android.app.RemoteLockscreenValidationSession.Builder setSourcePublicKey(@NonNull byte[]);
+  }
+
   public final class RuntimeAppOpAccessMessage implements android.os.Parcelable {
     ctor public RuntimeAppOpAccessMessage(@IntRange(from=0L) int, @IntRange(from=0L) int, @NonNull String, @Nullable String, @NonNull String, int);
     method public int describeContents();
@@ -1062,23 +1068,6 @@
     method public void launchAssist(@Nullable android.os.Bundle);
   }
 
-  public final class StartLockscreenValidationRequest implements android.os.Parcelable {
-    method public int describeContents();
-    method public int getLockscreenUiType();
-    method public int getRemainingAttempts();
-    method @NonNull public byte[] getSourcePublicKey();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.app.StartLockscreenValidationRequest> CREATOR;
-  }
-
-  public static final class StartLockscreenValidationRequest.Builder {
-    ctor public StartLockscreenValidationRequest.Builder();
-    method @NonNull public android.app.StartLockscreenValidationRequest build();
-    method @NonNull public android.app.StartLockscreenValidationRequest.Builder setLockscreenUiType(int);
-    method @NonNull public android.app.StartLockscreenValidationRequest.Builder setRemainingAttempts(int);
-    method @NonNull public android.app.StartLockscreenValidationRequest.Builder setSourcePublicKey(@NonNull byte[]);
-  }
-
   public class StatusBarManager {
     method @NonNull @RequiresPermission(android.Manifest.permission.STATUS_BAR) public android.app.StatusBarManager.DisableInfo getDisableInfo();
     method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public int getNavBarMode();
@@ -1699,7 +1688,7 @@
     method @RequiresPermission(android.Manifest.permission.BACKUP) public boolean isBackupEnabled();
     method @RequiresPermission(android.Manifest.permission.BACKUP) public boolean isBackupServiceActive(android.os.UserHandle);
     method @RequiresPermission(android.Manifest.permission.BACKUP) public String[] listAllTransports();
-    method @NonNull public void reportDelayedRestoreResult(@NonNull android.app.backup.BackupRestoreEventLogger);
+    method public void reportDelayedRestoreResult(@NonNull android.app.backup.BackupRestoreEventLogger);
     method @RequiresPermission(android.Manifest.permission.BACKUP) public int requestBackup(String[], android.app.backup.BackupObserver);
     method @RequiresPermission(android.Manifest.permission.BACKUP) public int requestBackup(String[], android.app.backup.BackupObserver, android.app.backup.BackupManagerMonitor, int);
     method @Deprecated public int requestRestore(android.app.backup.RestoreObserver, android.app.backup.BackupManagerMonitor);
@@ -1808,25 +1797,19 @@
     field public final long bytesTransferred;
   }
 
-  public class BackupRestoreEventLogger {
-    method public void logBackupMetaData(@android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull String, @NonNull String);
-    method public void logItemsBackedUp(@android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull String, int);
-    method public void logItemsBackupFailed(@android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull String, int, @android.app.backup.BackupRestoreEventLogger.BackupRestoreError @Nullable String);
-    method public void logItemsRestoreFailed(@android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull String, int, @android.app.backup.BackupRestoreEventLogger.BackupRestoreError @Nullable String);
-    method public void logItemsRestored(@android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull String, int);
-    method public void logRestoreMetadata(@android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull String, @NonNull String);
-  }
-
-  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface BackupRestoreEventLogger.BackupRestoreDataType {
-  }
-
-  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface BackupRestoreEventLogger.BackupRestoreError {
+  public final class BackupRestoreEventLogger {
+    method public void logBackupMetadata(@NonNull String, @NonNull String);
+    method public void logItemsBackedUp(@NonNull String, int);
+    method public void logItemsBackupFailed(@NonNull String, int, @Nullable String);
+    method public void logItemsRestoreFailed(@NonNull String, int, @Nullable String);
+    method public void logItemsRestored(@NonNull String, int);
+    method public void logRestoreMetadata(@NonNull String, @NonNull String);
   }
 
   public static final class BackupRestoreEventLogger.DataTypeResult implements android.os.Parcelable {
     ctor public BackupRestoreEventLogger.DataTypeResult(@NonNull String);
     method public int describeContents();
-    method @android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull public String getDataType();
+    method @NonNull public String getDataType();
     method @NonNull public java.util.Map<java.lang.String,java.lang.Integer> getErrors();
     method public int getFailCount();
     method @Nullable public byte[] getMetadataHash();
@@ -2363,6 +2346,8 @@
     method @NonNull public String getTargetId();
     method @NonNull public java.util.List<java.lang.String> getTargetIds();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field public static final int ACTION_DELETE = 9; // 0x9
+    field public static final int ACTION_DISMISS = 10; // 0xa
     field public static final int ACTION_DRAGNDROP = 7; // 0x7
     field public static final int ACTION_LAUNCH_KEYBOARD_FOCUS = 6; // 0x6
     field public static final int ACTION_LAUNCH_TOUCH = 5; // 0x5
@@ -3217,8 +3202,8 @@
     method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void close();
     method @NonNull public android.content.Context createContext();
     method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.companion.virtual.audio.VirtualAudioDevice createVirtualAudioDevice(@NonNull android.hardware.display.VirtualDisplay, @Nullable java.util.concurrent.Executor, @Nullable android.companion.virtual.audio.VirtualAudioDevice.AudioConfigurationChangeCallback);
-    method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @Nullable android.view.Surface, int, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.display.VirtualDisplay.Callback);
-    method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @NonNull java.util.List<java.lang.String>, @Nullable android.view.Surface, int, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.display.VirtualDisplay.Callback);
+    method @Deprecated @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @Nullable android.view.Surface, int, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.display.VirtualDisplay.Callback);
+    method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull android.hardware.display.VirtualDisplayConfig, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.display.VirtualDisplay.Callback);
     method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualDpad createVirtualDpad(@NonNull android.hardware.input.VirtualDpadConfig);
     method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualKeyboard createVirtualKeyboard(@NonNull android.hardware.input.VirtualKeyboardConfig);
     method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualKeyboard createVirtualKeyboard(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int);
@@ -3247,7 +3232,6 @@
     method @NonNull public java.util.Set<android.content.ComponentName> getBlockedCrossTaskNavigations();
     method public int getDefaultActivityPolicy();
     method public int getDefaultNavigationPolicy();
-    method public int getDefaultRecentsPolicy();
     method public int getDevicePolicy(int);
     method public int getLockState();
     method @Nullable public String getName();
@@ -3264,8 +3248,8 @@
     field public static final int NAVIGATION_POLICY_DEFAULT_ALLOWED = 0; // 0x0
     field public static final int NAVIGATION_POLICY_DEFAULT_BLOCKED = 1; // 0x1
     field public static final int POLICY_TYPE_AUDIO = 1; // 0x1
+    field public static final int POLICY_TYPE_RECENTS = 2; // 0x2
     field public static final int POLICY_TYPE_SENSORS = 0; // 0x0
-    field public static final int RECENTS_POLICY_ALLOW_IN_HOST_DEVICE_RECENTS = 1; // 0x1
   }
 
   public static final class VirtualDeviceParams.Builder {
@@ -3278,7 +3262,6 @@
     method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setAudioRecordingSessionId(int);
     method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setBlockedActivities(@NonNull java.util.Set<android.content.ComponentName>);
     method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setBlockedCrossTaskNavigations(@NonNull java.util.Set<android.content.ComponentName>);
-    method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setDefaultRecentsPolicy(int);
     method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setDevicePolicy(int, int);
     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);
@@ -3347,10 +3330,15 @@
 
   public interface VirtualSensorCallback {
     method public void onConfigurationChanged(@NonNull android.companion.virtual.sensor.VirtualSensor, boolean, @NonNull java.time.Duration, @NonNull java.time.Duration);
+    method public default void onDirectChannelConfigured(@IntRange(from=1) int, @NonNull android.companion.virtual.sensor.VirtualSensor, int, @IntRange(from=1) int);
+    method public default void onDirectChannelCreated(@IntRange(from=1) int, @NonNull android.os.SharedMemory);
+    method public default void onDirectChannelDestroyed(@IntRange(from=1) int);
   }
 
   public final class VirtualSensorConfig implements android.os.Parcelable {
     method public int describeContents();
+    method public int getDirectChannelTypesSupported();
+    method public int getHighestDirectReportRateLevel();
     method @NonNull public String getName();
     method public int getType();
     method @Nullable public String getVendor();
@@ -3359,8 +3347,10 @@
   }
 
   public static final class VirtualSensorConfig.Builder {
-    ctor public VirtualSensorConfig.Builder(int, @NonNull String);
+    ctor public VirtualSensorConfig.Builder(@IntRange(from=1) int, @NonNull String);
     method @NonNull public android.companion.virtual.sensor.VirtualSensorConfig build();
+    method @NonNull public android.companion.virtual.sensor.VirtualSensorConfig.Builder setDirectChannelTypesSupported(int);
+    method @NonNull public android.companion.virtual.sensor.VirtualSensorConfig.Builder setHighestDirectReportRateLevel(int);
     method @NonNull public android.companion.virtual.sensor.VirtualSensorConfig.Builder setVendor(@Nullable String);
   }
 
@@ -3574,9 +3564,7 @@
   }
 
   public class IntentFilter implements android.os.Parcelable {
-    method @NonNull public final android.os.PersistableBundle getExtras();
     method public final int getOrder();
-    method public final void setExtras(@NonNull android.os.PersistableBundle);
     method public final void setOrder(int);
   }
 
@@ -9116,8 +9104,7 @@
     method public int getProtocolCapability();
   }
 
-  public class IptvFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
-    method @NonNull public static android.media.tv.tuner.frontend.IptvFrontendSettings.Builder builder();
+  public final class IptvFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
     method @IntRange(from=0) public long getBitrate();
     method @NonNull public String getContentUrl();
     method @NonNull @Size(min=4, max=16) public byte[] getDstIpAddress();
@@ -9138,6 +9125,7 @@
   }
 
   public static final class IptvFrontendSettings.Builder {
+    ctor public IptvFrontendSettings.Builder();
     method @NonNull public android.media.tv.tuner.frontend.IptvFrontendSettings build();
     method @NonNull public android.media.tv.tuner.frontend.IptvFrontendSettings.Builder setBitrate(@IntRange(from=0) long);
     method @NonNull public android.media.tv.tuner.frontend.IptvFrontendSettings.Builder setContentUrl(@NonNull String);
@@ -9150,8 +9138,7 @@
     method @NonNull public android.media.tv.tuner.frontend.IptvFrontendSettings.Builder setSrcPort(int);
   }
 
-  public class IptvFrontendSettingsFec {
-    method @NonNull public static android.media.tv.tuner.frontend.IptvFrontendSettingsFec.Builder builder();
+  public final class IptvFrontendSettingsFec {
     method @IntRange(from=0) public int getFecColNum();
     method @IntRange(from=0) public int getFecRowNum();
     method public int getFecType();
@@ -9162,6 +9149,7 @@
   }
 
   public static final class IptvFrontendSettingsFec.Builder {
+    ctor public IptvFrontendSettingsFec.Builder();
     method @NonNull public android.media.tv.tuner.frontend.IptvFrontendSettingsFec build();
     method @NonNull public android.media.tv.tuner.frontend.IptvFrontendSettingsFec.Builder setFecColNum(@IntRange(from=0) int);
     method @NonNull public android.media.tv.tuner.frontend.IptvFrontendSettingsFec.Builder setFecRowNum(@IntRange(from=0) int);
@@ -9994,49 +9982,81 @@
 
 package android.net.wifi.sharedconnectivity.app {
 
-  public final class DeviceInfo implements android.os.Parcelable {
+  public final class HotspotNetwork implements android.os.Parcelable {
     method public int describeContents();
-    method @IntRange(from=0, to=100) public int getBatteryPercentage();
-    method @IntRange(from=0, to=3) public int getConnectionStrength();
-    method @NonNull public String getDeviceName();
-    method public int getDeviceType();
-    method @NonNull public String getModelName();
+    method public long getDeviceId();
+    method public int getHostNetworkType();
+    method @Nullable public String getHotspotBssid();
+    method @NonNull public java.util.Set<java.lang.Integer> getHotspotSecurityTypes();
+    method @Nullable public String getHotspotSsid();
+    method @NonNull public String getNetworkName();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo getNetworkProviderInfo();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.DeviceInfo> CREATOR;
-    field public static final int DEVICE_TYPE_LAPTOP = 3; // 0x3
-    field public static final int DEVICE_TYPE_PHONE = 1; // 0x1
-    field public static final int DEVICE_TYPE_TABLET = 2; // 0x2
-    field public static final int DEVICE_TYPE_UNKNOWN = 0; // 0x0
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.HotspotNetwork> CREATOR;
+    field public static final int NETWORK_TYPE_CELLULAR = 1; // 0x1
+    field public static final int NETWORK_TYPE_ETHERNET = 3; // 0x3
+    field public static final int NETWORK_TYPE_UNKNOWN = 0; // 0x0
+    field public static final int NETWORK_TYPE_WIFI = 2; // 0x2
   }
 
-  public static final class DeviceInfo.Builder {
-    ctor public DeviceInfo.Builder();
-    method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo build();
-    method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo.Builder setBatteryPercentage(@IntRange(from=0, to=100) int);
-    method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo.Builder setConnectionStrength(@IntRange(from=0, to=3) int);
-    method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo.Builder setDeviceName(@NonNull String);
-    method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo.Builder setDeviceType(int);
-    method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo.Builder setModelName(@NonNull String);
+  public static final class HotspotNetwork.Builder {
+    ctor public HotspotNetwork.Builder();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder addHotspotSecurityType(int);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork build();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setDeviceId(long);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setHostNetworkType(int);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setHotspotBssid(@NonNull String);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setHotspotSsid(@NonNull String);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setNetworkName(@NonNull String);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setNetworkProviderInfo(@NonNull android.net.wifi.sharedconnectivity.app.NetworkProviderInfo);
+  }
+
+  public final class HotspotNetworkConnectionStatus implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public android.os.Bundle getExtras();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork getHotspotNetwork();
+    method public int getStatus();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field public static final int CONNECTION_STATUS_CONNECT_TO_HOTSPOT_FAILED = 9; // 0x9
+    field public static final int CONNECTION_STATUS_ENABLING_HOTSPOT = 1; // 0x1
+    field public static final int CONNECTION_STATUS_ENABLING_HOTSPOT_FAILED = 7; // 0x7
+    field public static final int CONNECTION_STATUS_ENABLING_HOTSPOT_TIMEOUT = 8; // 0x8
+    field public static final int CONNECTION_STATUS_NO_CELL_DATA = 6; // 0x6
+    field public static final int CONNECTION_STATUS_PROVISIONING_FAILED = 3; // 0x3
+    field public static final int CONNECTION_STATUS_TETHERING_TIMEOUT = 4; // 0x4
+    field public static final int CONNECTION_STATUS_TETHERING_UNSUPPORTED = 5; // 0x5
+    field public static final int CONNECTION_STATUS_UNKNOWN = 0; // 0x0
+    field public static final int CONNECTION_STATUS_UNKNOWN_ERROR = 2; // 0x2
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus> CREATOR;
+  }
+
+  public static final class HotspotNetworkConnectionStatus.Builder {
+    ctor public HotspotNetworkConnectionStatus.Builder();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus build();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.Builder setExtras(@NonNull android.os.Bundle);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.Builder setHotspotNetwork(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetwork);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.Builder setStatus(int);
   }
 
   public final class KnownNetwork implements android.os.Parcelable {
     method public int describeContents();
-    method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo getDeviceInfo();
+    method @Nullable public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo getNetworkProviderInfo();
     method public int getNetworkSource();
-    method @NonNull public int[] getSecurityTypes();
+    method @NonNull public java.util.Set<java.lang.Integer> getSecurityTypes();
     method @NonNull public String getSsid();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.KnownNetwork> CREATOR;
-    field public static final int NETWORK_SOURCE_CLOUD_SELF = 1; // 0x1
-    field public static final int NETWORK_SOURCE_NEARBY_SELF = 0; // 0x0
+    field public static final int NETWORK_SOURCE_CLOUD_SELF = 2; // 0x2
+    field public static final int NETWORK_SOURCE_NEARBY_SELF = 1; // 0x1
+    field public static final int NETWORK_SOURCE_UNKNOWN = 0; // 0x0
   }
 
   public static final class KnownNetwork.Builder {
     ctor public KnownNetwork.Builder();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder addSecurityType(int);
     method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork build();
-    method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder setDeviceInfo(@NonNull android.net.wifi.sharedconnectivity.app.DeviceInfo);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder setNetworkProviderInfo(@Nullable android.net.wifi.sharedconnectivity.app.NetworkProviderInfo);
     method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder setNetworkSource(int);
-    method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder setSecurityTypes(@NonNull int[]);
     method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder setSsid(@NonNull String);
   }
 
@@ -10060,29 +10080,56 @@
     method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus.Builder setStatus(int);
   }
 
+  public final class NetworkProviderInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method @IntRange(from=0, to=100) public int getBatteryPercentage();
+    method @IntRange(from=0, to=3) public int getConnectionStrength();
+    method @NonNull public String getDeviceName();
+    method public int getDeviceType();
+    method @NonNull public String getModelName();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.NetworkProviderInfo> CREATOR;
+    field public static final int DEVICE_TYPE_AUTO = 5; // 0x5
+    field public static final int DEVICE_TYPE_LAPTOP = 3; // 0x3
+    field public static final int DEVICE_TYPE_PHONE = 1; // 0x1
+    field public static final int DEVICE_TYPE_TABLET = 2; // 0x2
+    field public static final int DEVICE_TYPE_UNKNOWN = 0; // 0x0
+    field public static final int DEVICE_TYPE_WATCH = 4; // 0x4
+  }
+
+  public static final class NetworkProviderInfo.Builder {
+    ctor public NetworkProviderInfo.Builder(@NonNull String, @NonNull String);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo build();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setBatteryPercentage(@IntRange(from=0, to=100) int);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setConnectionStrength(@IntRange(from=0, to=3) int);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setDeviceName(@NonNull String);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setDeviceType(int);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setModelName(@NonNull String);
+  }
+
   public interface SharedConnectivityClientCallback {
+    method public void onHotspotNetworkConnectionStatusChanged(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus);
+    method public void onHotspotNetworksUpdated(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.HotspotNetwork>);
     method public void onKnownNetworkConnectionStatusChanged(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus);
     method public void onKnownNetworksUpdated(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.KnownNetwork>);
     method public void onRegisterCallbackFailed(@NonNull Exception);
     method public void onServiceConnected();
     method public void onServiceDisconnected();
     method public void onSharedConnectivitySettingsChanged(@NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState);
-    method public void onTetherNetworkConnectionStatusChanged(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus);
-    method public void onTetherNetworksUpdated(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.TetherNetwork>);
   }
 
   public class SharedConnectivityManager {
-    method public boolean connectKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
-    method public boolean connectTetherNetwork(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
-    method public boolean disconnectTetherNetwork(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
-    method public boolean forgetKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
-    method @Nullable public android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus getKnownNetworkConnectionStatus();
-    method @NonNull public java.util.List<android.net.wifi.sharedconnectivity.app.KnownNetwork> getKnownNetworks();
-    method @Nullable public android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState getSettingsState();
-    method @Nullable public android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus getTetherNetworkConnectionStatus();
-    method @NonNull public java.util.List<android.net.wifi.sharedconnectivity.app.TetherNetwork> getTetherNetworks();
-    method public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivityClientCallback);
-    method public boolean unregisterCallback(@NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivityClientCallback);
+    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean connectHotspotNetwork(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetwork);
+    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean connectKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
+    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean disconnectHotspotNetwork(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetwork);
+    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean forgetKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
+    method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus getHotspotNetworkConnectionStatus();
+    method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.net.wifi.sharedconnectivity.app.HotspotNetwork> getHotspotNetworks();
+    method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus getKnownNetworkConnectionStatus();
+    method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.net.wifi.sharedconnectivity.app.KnownNetwork> getKnownNetworks();
+    method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState getSettingsState();
+    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivityClientCallback);
+    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean unregisterCallback(@NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivityClientCallback);
   }
 
   public final class SharedConnectivitySettingsState implements android.os.Parcelable {
@@ -10100,78 +10147,24 @@
     method @NonNull public android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState.Builder setInstantTetherEnabled(boolean);
   }
 
-  public final class TetherNetwork implements android.os.Parcelable {
-    method public int describeContents();
-    method public long getDeviceId();
-    method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo getDeviceInfo();
-    method @Nullable public String getHotspotBssid();
-    method @Nullable public int[] getHotspotSecurityTypes();
-    method @Nullable public String getHotspotSsid();
-    method @NonNull public String getNetworkName();
-    method public int getNetworkType();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.TetherNetwork> CREATOR;
-    field public static final int NETWORK_TYPE_CELLULAR = 1; // 0x1
-    field public static final int NETWORK_TYPE_ETHERNET = 3; // 0x3
-    field public static final int NETWORK_TYPE_UNKNOWN = 0; // 0x0
-    field public static final int NETWORK_TYPE_WIFI = 2; // 0x2
-  }
-
-  public static final class TetherNetwork.Builder {
-    ctor public TetherNetwork.Builder();
-    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork build();
-    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setDeviceId(long);
-    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setDeviceInfo(@NonNull android.net.wifi.sharedconnectivity.app.DeviceInfo);
-    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setHotspotBssid(@NonNull String);
-    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setHotspotSecurityTypes(@NonNull int[]);
-    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setHotspotSsid(@NonNull String);
-    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setNetworkName(@NonNull String);
-    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setNetworkType(int);
-  }
-
-  public final class TetherNetworkConnectionStatus implements android.os.Parcelable {
-    method public int describeContents();
-    method @NonNull public android.os.Bundle getExtras();
-    method public int getStatus();
-    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork getTetherNetwork();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field public static final int CONNECTION_STATUS_CONNECT_TO_HOTSPOT_FAILED = 9; // 0x9
-    field public static final int CONNECTION_STATUS_ENABLING_HOTSPOT = 1; // 0x1
-    field public static final int CONNECTION_STATUS_ENABLING_HOTSPOT_FAILED = 7; // 0x7
-    field public static final int CONNECTION_STATUS_ENABLING_HOTSPOT_TIMEOUT = 8; // 0x8
-    field public static final int CONNECTION_STATUS_NO_CELL_DATA = 6; // 0x6
-    field public static final int CONNECTION_STATUS_PROVISIONING_FAILED = 3; // 0x3
-    field public static final int CONNECTION_STATUS_TETHERING_TIMEOUT = 4; // 0x4
-    field public static final int CONNECTION_STATUS_TETHERING_UNSUPPORTED = 5; // 0x5
-    field public static final int CONNECTION_STATUS_UNKNOWN = 0; // 0x0
-    field public static final int CONNECTION_STATUS_UNKNOWN_ERROR = 2; // 0x2
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus> CREATOR;
-  }
-
-  public static final class TetherNetworkConnectionStatus.Builder {
-    ctor public TetherNetworkConnectionStatus.Builder();
-    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus build();
-    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus.Builder setExtras(@NonNull android.os.Bundle);
-    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus.Builder setStatus(int);
-    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus.Builder setTetherNetwork(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
-  }
-
 }
 
 package android.net.wifi.sharedconnectivity.service {
 
   public abstract class SharedConnectivityService extends android.app.Service {
     ctor public SharedConnectivityService();
+    method public static boolean areHotspotNetworksEnabledForService(@NonNull android.content.Context);
+    method public static boolean areKnownNetworksEnabledForService(@NonNull android.content.Context);
     method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
+    method public abstract void onConnectHotspotNetwork(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetwork);
     method public abstract void onConnectKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
-    method public abstract void onConnectTetherNetwork(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
-    method public abstract void onDisconnectTetherNetwork(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
+    method public abstract void onDisconnectHotspotNetwork(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetwork);
     method public abstract void onForgetKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
+    method public final void setHotspotNetworks(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.HotspotNetwork>);
     method public final void setKnownNetworks(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.KnownNetwork>);
     method public final void setSettingsState(@NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState);
-    method public final void setTetherNetworks(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.TetherNetwork>);
+    method public final void updateHotspotNetworkConnectionStatus(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus);
     method public final void updateKnownNetworkConnectionStatus(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus);
-    method public final void updateTetherNetworkConnectionStatus(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus);
   }
 
 }
@@ -10952,7 +10945,6 @@
     method @NonNull @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", "android.permission.MANAGE_USERS"}) public java.util.Set<android.os.UserHandle> getVisibleUsers();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean hasRestrictedProfiles();
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean hasUserRestrictionForUser(@NonNull String, @NonNull android.os.UserHandle);
-    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isAdminUser();
     method public boolean isCloneProfile();
     method @Deprecated public boolean isCredentialSharableWithParent();
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isGuestUser();
@@ -13159,7 +13151,7 @@
     method @NonNull public android.service.voice.HotwordDetectedResult.Builder setScore(int);
   }
 
-  public abstract class HotwordDetectionService extends android.app.Service implements android.service.voice.SandboxedDetectionServiceBase {
+  public abstract class HotwordDetectionService extends android.app.Service implements android.service.voice.SandboxedDetectionInitializer {
     ctor public HotwordDetectionService();
     method @Deprecated public static int getMaxCustomInitializationStatus();
     method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
@@ -13231,7 +13223,7 @@
     method @NonNull public android.service.voice.HotwordRejectedResult.Builder setConfidenceLevel(int);
   }
 
-  public interface SandboxedDetectionServiceBase {
+  public interface SandboxedDetectionInitializer {
     method public static int getMaxCustomInitializationStatus();
     method public void onUpdateState(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory, long, @Nullable java.util.function.IntConsumer);
     field public static final int INITIALIZATION_STATUS_SUCCESS = 0; // 0x0
@@ -13253,24 +13245,20 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.service.voice.UnknownFailure> CREATOR;
   }
 
-  public abstract class VisualQueryDetectionService extends android.app.Service implements android.service.voice.SandboxedDetectionServiceBase {
+  public abstract class VisualQueryDetectionService extends android.app.Service implements android.service.voice.SandboxedDetectionInitializer {
     ctor public VisualQueryDetectionService();
+    method public final void finishQuery() throws java.lang.IllegalStateException;
+    method public final void gainedAttention();
+    method public final void lostAttention();
     method @Nullable public android.os.IBinder onBind(@NonNull android.content.Intent);
-    method public void onStartDetection(@NonNull android.service.voice.VisualQueryDetectionService.Callback);
+    method public void onStartDetection();
     method public void onStopDetection();
     method public void onUpdateState(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory, long, @Nullable java.util.function.IntConsumer);
+    method public final void rejectQuery() throws java.lang.IllegalStateException;
+    method public final void streamQuery(@NonNull String) throws java.lang.IllegalStateException;
     field public static final String SERVICE_INTERFACE = "android.service.voice.VisualQueryDetectionService";
   }
 
-  public static final class VisualQueryDetectionService.Callback {
-    ctor public VisualQueryDetectionService.Callback();
-    method public void onAttentionGained();
-    method public void onAttentionLost();
-    method public void onQueryDetected(@NonNull String) throws java.lang.IllegalStateException;
-    method public void onQueryFinished() throws java.lang.IllegalStateException;
-    method public void onQueryRejected() throws java.lang.IllegalStateException;
-  }
-
   public final class VisualQueryDetectionServiceFailure extends android.service.voice.DetectorFailure {
     method public int getErrorCode();
     method public int getSuggestedAction();
@@ -13785,7 +13773,7 @@
     field public static final String EXTRA_CALL_HAS_IN_BAND_RINGTONE = "android.telecom.extra.CALL_HAS_IN_BAND_RINGTONE";
     field public static final String EXTRA_CALL_SOURCE = "android.telecom.extra.CALL_SOURCE";
     field public static final String EXTRA_CALL_TECHNOLOGY_TYPE = "android.telecom.extra.CALL_TECHNOLOGY_TYPE";
-    field public static final String EXTRA_CLEAR_MISSED_CALLS_INTENT = "android.telecom.extra.CLEAR_MISSED_CALLS_INTENT";
+    field @Deprecated public static final String EXTRA_CLEAR_MISSED_CALLS_INTENT = "android.telecom.extra.CLEAR_MISSED_CALLS_INTENT";
     field public static final String EXTRA_CONNECTION_SERVICE = "android.telecom.extra.CONNECTION_SERVICE";
     field public static final String EXTRA_CURRENT_TTY_MODE = "android.telecom.extra.CURRENT_TTY_MODE";
     field public static final String EXTRA_IS_USER_INTENT_EMERGENCY_CALL = "android.telecom.extra.IS_USER_INTENT_EMERGENCY_CALL";
@@ -14620,7 +14608,6 @@
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int[] getCompleteActiveSubscriptionIdList();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEnabledSubscriptionId(int);
     method @NonNull public static android.content.res.Resources getResourcesForSubId(@NonNull android.content.Context, int);
-    method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION) public android.os.UserHandle getSubscriptionUserHandle(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isSubscriptionEnabled(int);
     method public void requestEmbeddedSubscriptionInfoListRefresh();
     method public void requestEmbeddedSubscriptionInfoListRefresh(int);
@@ -14630,7 +14617,6 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultVoiceSubscriptionId(int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPreferredDataSubscriptionId(int, boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setSubscriptionEnabled(int, boolean);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION) public void setSubscriptionUserHandle(int, @Nullable android.os.UserHandle);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUiccApplicationsEnabled(int, boolean);
     field @RequiresPermission(android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS) public static final String ACTION_SUBSCRIPTION_PLANS_CHANGED = "android.telephony.action.SUBSCRIPTION_PLANS_CHANGED";
     field @NonNull public static final android.net.Uri ADVANCED_CALLING_ENABLED_CONTENT_URI;
@@ -17283,9 +17269,9 @@
   public final class AccessibilityManager {
     method public int getAccessibilityWindowId(@Nullable android.os.IBinder);
     method @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public void performAccessibilityShortcut();
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public boolean registerDisplayProxy(@NonNull android.view.accessibility.AccessibilityDisplayProxy);
+    method @RequiresPermission(allOf={android.Manifest.permission.MANAGE_ACCESSIBILITY, android.Manifest.permission.CREATE_VIRTUAL_DEVICE}) public boolean registerDisplayProxy(@NonNull android.view.accessibility.AccessibilityDisplayProxy);
     method @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public void registerSystemAction(@NonNull android.app.RemoteAction, int);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public boolean unregisterDisplayProxy(@NonNull android.view.accessibility.AccessibilityDisplayProxy);
+    method @RequiresPermission(allOf={android.Manifest.permission.MANAGE_ACCESSIBILITY, android.Manifest.permission.CREATE_VIRTUAL_DEVICE}) public boolean unregisterDisplayProxy(@NonNull android.view.accessibility.AccessibilityDisplayProxy);
     method @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public void unregisterSystemAction(int);
   }
 
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 43fa6e2..445b957 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -5,6 +5,7 @@
     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";
+    field public static final String ALLOWLISTED_WRITE_DEVICE_CONFIG = "android.permission.ALLOWLISTED_WRITE_DEVICE_CONFIG";
     field public static final String APPROVE_INCIDENT_REPORTS = "android.permission.APPROVE_INCIDENT_REPORTS";
     field public static final String BACKGROUND_CAMERA = "android.permission.BACKGROUND_CAMERA";
     field public static final String BIND_CELL_BROADCAST_SERVICE = "android.permission.BIND_CELL_BROADCAST_SERVICE";
@@ -39,6 +40,7 @@
     field public static final String QUERY_AUDIO_STATE = "android.permission.QUERY_AUDIO_STATE";
     field public static final String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS";
     field public static final String READ_PRIVILEGED_PHONE_STATE = "android.permission.READ_PRIVILEGED_PHONE_STATE";
+    field public static final String READ_WRITE_SYNC_DISABLED_MODE_CONFIG = "android.permission.READ_WRITE_SYNC_DISABLED_MODE_CONFIG";
     field public static final String RECORD_BACKGROUND_AUDIO = "android.permission.RECORD_BACKGROUND_AUDIO";
     field public static final String REMAP_MODIFIER_KEYS = "android.permission.REMAP_MODIFIER_KEYS";
     field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS";
@@ -269,6 +271,7 @@
   }
 
   public class BroadcastOptions extends android.app.ComponentOptions {
+    ctor public BroadcastOptions();
     ctor public BroadcastOptions(@NonNull android.os.Bundle);
     method @Deprecated public int getMaxManifestReceiverApiLevel();
     method public long getTemporaryAppAllowlistDuration();
@@ -899,6 +902,7 @@
     field public static final float OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE = 1.5f;
     field public static final long OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY = 203647190L; // 0xc2368d6L
     field public static final long OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN = 208648326L; // 0xc6fb886L
+    field public static final long OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS = 237531167L; // 0xe28701fL
     field public static final int RESIZE_MODE_RESIZEABLE = 2; // 0x2
   }
 
@@ -1071,6 +1075,40 @@
 
 }
 
+package android.credentials {
+
+  public final class CredentialManager {
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.QUERY_ALL_PACKAGES, "android.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS"}) public java.util.List<android.credentials.CredentialProviderInfo> getCredentialProviderServicesForTesting(int);
+    method public static boolean isServiceEnabled(@NonNull android.content.Context);
+    field public static final int PROVIDER_FILTER_ALL_PROVIDERS = 0; // 0x0
+    field public static final int PROVIDER_FILTER_SYSTEM_PROVIDERS_ONLY = 1; // 0x1
+    field public static final int PROVIDER_FILTER_USER_PROVIDERS_ONLY = 2; // 0x2
+  }
+
+  public final class CredentialProviderInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public java.util.List<java.lang.String> getCapabilities();
+    method @NonNull public android.content.ComponentName getComponentName();
+    method @Nullable public CharSequence getLabel(@NonNull android.content.Context);
+    method @Nullable public android.graphics.drawable.Drawable getServiceIcon(@NonNull android.content.Context);
+    method @NonNull public android.content.pm.ServiceInfo getServiceInfo();
+    method @NonNull public boolean hasCapability(@NonNull String);
+    method public boolean isEnabled();
+    method public boolean isSystemProvider();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.credentials.CredentialProviderInfo> CREATOR;
+  }
+
+  public static final class CredentialProviderInfo.Builder {
+    ctor public CredentialProviderInfo.Builder(@NonNull android.content.pm.ServiceInfo);
+    method @NonNull public android.credentials.CredentialProviderInfo.Builder addCapabilities(@NonNull java.util.List<java.lang.String>);
+    method @NonNull public android.credentials.CredentialProviderInfo build();
+    method @NonNull public android.credentials.CredentialProviderInfo.Builder setEnabled(boolean);
+    method @NonNull public android.credentials.CredentialProviderInfo.Builder setSystemProvider(boolean);
+  }
+
+}
+
 package android.credentials.ui {
 
   public final class AuthenticationEntry implements android.os.Parcelable {
@@ -1110,7 +1148,6 @@
 
   public final class Entry implements android.os.Parcelable {
     ctor public Entry(@NonNull String, @NonNull String, @NonNull android.app.slice.Slice);
-    ctor public Entry(@NonNull String, @NonNull String, @NonNull android.app.slice.Slice, @NonNull android.app.PendingIntent, @NonNull android.content.Intent);
     ctor public Entry(@NonNull String, @NonNull String, @NonNull android.app.slice.Slice, @NonNull android.content.Intent);
     method public int describeContents();
     method @Nullable public android.content.Intent getFrameworkExtrasIntent();
@@ -1921,6 +1958,10 @@
     method public void removeHardwareDevice(int);
   }
 
+  public class TvView extends android.view.ViewGroup {
+    method public void notifyTvMessage(int, @NonNull android.os.Bundle);
+  }
+
 }
 
 package android.media.tv.tuner {
@@ -1986,7 +2027,9 @@
     method public static boolean is64BitAbi(String);
     method public static boolean isDebuggable();
     field @Nullable public static final String BRAND_FOR_ATTESTATION;
+    field @Nullable public static final String DEVICE_FOR_ATTESTATION;
     field public static final boolean IS_EMULATOR;
+    field @Nullable public static final String MANUFACTURER_FOR_ATTESTATION;
     field @Nullable public static final String MODEL_FOR_ATTESTATION;
     field @Nullable public static final String PRODUCT_FOR_ATTESTATION;
   }
@@ -2629,8 +2672,13 @@
     method @Nullable public android.content.IntentSender getAuthentication();
     method @Nullable public java.util.ArrayList<java.lang.String> getAutofillDatatypes();
     method @Nullable public android.content.ClipData getFieldContent();
+    method @Nullable public android.widget.RemoteViews getFieldDialogPresentation(int);
     method @Nullable public java.util.ArrayList<android.view.autofill.AutofillId> getFieldIds();
+    method @Nullable public android.service.autofill.InlinePresentation getFieldInlinePresentation(int);
+    method @Nullable public android.service.autofill.InlinePresentation getFieldInlineTooltipPresentation(int);
+    method @Nullable public android.widget.RemoteViews getFieldPresentation(int);
     method @Nullable public java.util.ArrayList<android.view.autofill.AutofillValue> getFieldValues();
+    method @Nullable public android.service.autofill.Dataset.DatasetFieldFilter getFilter(int);
     method @Nullable public String getId();
     method public boolean isEmpty();
   }
@@ -2639,6 +2687,13 @@
     method @NonNull public android.service.autofill.Dataset.Builder setContent(@NonNull android.view.autofill.AutofillId, @Nullable android.content.ClipData);
   }
 
+  public static final class Dataset.DatasetFieldFilter implements android.os.Parcelable {
+    method public int describeContents();
+    method @Nullable public java.util.regex.Pattern getPattern();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.autofill.Dataset.DatasetFieldFilter> CREATOR;
+  }
+
   public final class DateTransformation extends android.service.autofill.InternalTransformation implements android.os.Parcelable android.service.autofill.Transformation {
     method public void apply(@NonNull android.service.autofill.ValueFinder, @NonNull android.widget.RemoteViews, int) throws java.lang.Exception;
   }
@@ -2812,7 +2867,7 @@
     method @NonNull public android.service.voice.AlwaysOnHotwordDetector.EventPayload.Builder setKeyphraseRecognitionExtras(@NonNull java.util.List<android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra>);
   }
 
-  public abstract class HotwordDetectionService extends android.app.Service implements android.service.voice.SandboxedDetectionServiceBase {
+  public abstract class HotwordDetectionService extends android.app.Service implements android.service.voice.SandboxedDetectionInitializer {
     field public static final boolean ENABLE_PROXIMITY_RESULT = true;
   }
 
@@ -2977,7 +3032,6 @@
     field public static final int HAL_SERVICE_MESSAGING = 2; // 0x2
     field public static final int HAL_SERVICE_MODEM = 3; // 0x3
     field public static final int HAL_SERVICE_NETWORK = 4; // 0x4
-    field public static final int HAL_SERVICE_SATELLITE = 8; // 0x8
     field public static final int HAL_SERVICE_SIM = 5; // 0x5
     field public static final int HAL_SERVICE_VOICE = 6; // 0x6
     field public static final android.util.Pair HAL_VERSION_UNKNOWN;
@@ -3291,7 +3345,9 @@
   }
 
   @UiThread public class View implements android.view.accessibility.AccessibilityEventSource android.graphics.drawable.Drawable.Callback android.view.KeyEvent.Callback {
+    method public void getBoundsOnScreen(@NonNull android.graphics.Rect, boolean);
     method public android.view.View getTooltipView();
+    method public void getWindowDisplayFrame(@NonNull android.graphics.Rect);
     method public boolean isAutofilled();
     method public static boolean isDefaultFocusHighlightEnabled();
     method public boolean isDefaultFocusHighlightNeeded(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
@@ -3342,6 +3398,7 @@
     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
   }
 
   public static class WindowManager.LayoutParams extends android.view.ViewGroup.LayoutParams implements android.os.Parcelable {
@@ -3418,6 +3475,7 @@
   }
 
   public final class AutofillManager {
+    field public static final String ANY_HINT = "any";
     field public static final int FLAG_SMART_SUGGESTION_OFF = 0; // 0x0
     field public static final int FLAG_SMART_SUGGESTION_SYSTEM = 1; // 0x1
     field public static final int MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS = 120000; // 0x1d4c0
@@ -3772,6 +3830,7 @@
   public final class TaskFragmentInfo implements android.os.Parcelable {
     method public boolean equalsForTaskFragmentOrganizer(@Nullable android.window.TaskFragmentInfo);
     method @NonNull public java.util.List<android.os.IBinder> getActivities();
+    method @NonNull public java.util.List<android.os.IBinder> getActivitiesRequestedInTaskFragment();
     method @NonNull public android.content.res.Configuration getConfiguration();
     method @NonNull public android.os.IBinder getFragmentToken();
     method @NonNull public android.graphics.Point getPositionInParent();
@@ -3921,6 +3980,19 @@
     method public abstract void onTransactionReady(int, @NonNull android.view.SurfaceControl.Transaction);
   }
 
+  public class WindowInfosListenerForTest {
+    ctor public WindowInfosListenerForTest();
+    method @RequiresPermission(android.Manifest.permission.ACCESS_SURFACE_FLINGER) public void addWindowInfosListener(@NonNull java.util.function.Consumer<java.util.List<android.window.WindowInfosListenerForTest.WindowInfo>>);
+    method public void removeWindowInfosListener(@NonNull java.util.function.Consumer<java.util.List<android.window.WindowInfosListenerForTest.WindowInfo>>);
+  }
+
+  public static class WindowInfosListenerForTest.WindowInfo {
+    field @NonNull public final android.graphics.Rect bounds;
+    field public final boolean isTrustedOverlay;
+    field @NonNull public final String name;
+    field @NonNull public final android.os.IBinder windowToken;
+  }
+
   public class WindowOrganizer {
     ctor public WindowOrganizer();
     method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public int applySyncTransaction(@NonNull android.window.WindowContainerTransaction, @NonNull android.window.WindowContainerTransactionCallback);
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 738e2de..3969577 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -285,6 +285,28 @@
     ],
 }
 
+filegroup {
+    name: "hwbinder-stubs-srcs",
+    srcs: [
+        "android/os/HidlSupport.java",
+        "android/os/HidlMemory.java",
+        "android/os/HwBinder.java",
+        "android/os/HwBlob.java",
+        "android/os/HwParcel.java",
+        "android/os/IHwBinder.java",
+        "android/os/IHwInterface.java",
+        "android/os/DeadObjectException.java",
+        "android/os/DeadSystemException.java",
+        "android/os/NativeHandle.java",
+        "android/os/RemoteException.java",
+        "android/util/AndroidException.java",
+    ],
+    visibility: [
+        "//frameworks/base",
+        "//frameworks/base/api",
+    ],
+}
+
 cc_defaults {
     name: "incremental_default",
     cflags: [
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index d9c7a27..125e727 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -6621,7 +6621,9 @@
      * the incoming activity.  Use 0 for no animation.
      * @param exitAnim A resource ID of the animation resource to use for
      * the outgoing activity.  Use 0 for no animation.
+     * @deprecated Use {@link #overrideActivityTransition(int, int, int)}} instead.
      */
+    @Deprecated
     public void overridePendingTransition(int enterAnim, int exitAnim) {
         overridePendingTransition(enterAnim, exitAnim, 0);
     }
@@ -6644,7 +6646,9 @@
      * the outgoing activity.  Use 0 for no animation.
      * @param backgroundColor The background color to use for the background during the animation if
      * the animation requires a background. Set to 0 to not override the default color.
+     * @deprecated Use {@link #overrideActivityTransition(int, int, int, int)}} instead.
      */
+    @Deprecated
     public void overridePendingTransition(int enterAnim, int exitAnim, int backgroundColor) {
         ActivityClient.getInstance().overridePendingTransition(mToken, getPackageName(), enterAnim,
                 exitAnim, backgroundColor);
diff --git a/core/java/android/app/ActivityClient.java b/core/java/android/app/ActivityClient.java
index 44327af..b35e87b 100644
--- a/core/java/android/app/ActivityClient.java
+++ b/core/java/android/app/ActivityClient.java
@@ -598,6 +598,23 @@
     }
 
     /**
+     * Returns {@code true} if the activity was explicitly requested to be launched in the
+     * TaskFragment.
+     *
+     * @param activityToken The token of the Activity.
+     * @param taskFragmentToken The token of the TaskFragment.
+     */
+    public boolean isRequestedToLaunchInTaskFragment(IBinder activityToken,
+            IBinder taskFragmentToken) {
+        try {
+            return getActivityClientController().isRequestedToLaunchInTaskFragment(activityToken,
+                    taskFragmentToken);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Shows or hides a Camera app compat toggle for stretched issues with the requested state.
      *
      * @param token The token for the window that needs a control.
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index ba36d93..ff75098 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -630,7 +630,7 @@
             PROCESS_CAPABILITY_FOREGROUND_LOCATION,
             PROCESS_CAPABILITY_FOREGROUND_CAMERA,
             PROCESS_CAPABILITY_FOREGROUND_MICROPHONE,
-            PROCESS_CAPABILITY_NETWORK,
+            PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK,
             PROCESS_CAPABILITY_BFSL,
     })
     @Retention(RetentionPolicy.SOURCE)
@@ -666,6 +666,7 @@
      * Used to log FGS API events from Audio API
      * @hide
      */
+    @SystemApi
     public static final int FOREGROUND_SERVICE_API_TYPE_AUDIO = 5;
     /**
      * Used to log FGS API events from microphone API
@@ -715,13 +716,11 @@
      * Used to log a start event for an FGS API
      * @hide
      */
-    @SystemApi
     public static final int FOREGROUND_SERVICE_API_EVENT_BEGIN = 1;
     /**
      * Used to log a stop event for an FGS API
      * @hide
      */
-    @SystemApi
     public static final int FOREGROUND_SERVICE_API_EVENT_END = 2;
     /**
      * Constants used to denote API state
@@ -791,7 +790,7 @@
     public static final int PROCESS_CAPABILITY_ALL = PROCESS_CAPABILITY_FOREGROUND_LOCATION
             | PROCESS_CAPABILITY_FOREGROUND_CAMERA
             | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
-            | PROCESS_CAPABILITY_NETWORK
+            | PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK
             | PROCESS_CAPABILITY_BFSL;
 
     /**
@@ -810,7 +809,7 @@
         pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0 ? 'L' : '-');
         pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0 ? 'C' : '-');
         pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0 ? 'M' : '-');
-        pw.print((caps & PROCESS_CAPABILITY_NETWORK) != 0 ? 'N' : '-');
+        pw.print((caps & PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0 ? 'N' : '-');
         pw.print((caps & PROCESS_CAPABILITY_BFSL) != 0 ? 'F' : '-');
     }
 
@@ -819,7 +818,7 @@
         sb.append((caps & PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0 ? 'L' : '-');
         sb.append((caps & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0 ? 'C' : '-');
         sb.append((caps & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0 ? 'M' : '-');
-        sb.append((caps & PROCESS_CAPABILITY_NETWORK) != 0 ? 'N' : '-');
+        sb.append((caps & PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0 ? 'N' : '-');
         sb.append((caps & PROCESS_CAPABILITY_BFSL) != 0 ? 'F' : '-');
     }
 
@@ -4208,8 +4207,8 @@
      * processes to reclaim memory; the system will take care of restarting
      * these processes in the future as needed.
      *
-     * <p class="note">On devices with a {@link Build.VERSION#SECURITY_PATCH} of 2022-12-01 or
-     * greater, third party applications can only use this API to kill their own processes.
+     * <p class="note">On devices that run Android 14 or higher,
+     * third party applications can only use this API to kill their own processes.
      * </p>
      *
      * @param packageName The name of the package whose processes are to
@@ -5617,23 +5616,32 @@
      *
      */
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.LOG_PROCESS_ACTIVITIES)
-    public void noteForegroundResourceUse(@ForegroundServiceApiType int apiType,
-            @ForegroundServiceApiEvent int apiEvent, int uid, int pid) {
+    @RequiresPermission(android.Manifest.permission.LOG_FOREGROUND_RESOURCE_USE)
+    public void noteForegroundResourceUseBegin(@ForegroundServiceApiType int apiType,
+            int uid, int pid) throws SecurityException {
         try {
-            switch (apiEvent) {
-                case FOREGROUND_SERVICE_API_EVENT_BEGIN:
-                    getService().logFgsApiBegin(apiType, uid, pid);
-                    break;
-                case FOREGROUND_SERVICE_API_EVENT_END:
-                    getService().logFgsApiEnd(apiType, uid, pid);
-                    break;
-                default:
-                    throw new IllegalArgumentException("Argument of "
-                            + apiType + " not supported for foreground resource use logging");
-            }
+            getService().logFgsApiBegin(apiType, uid, pid);
         } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Internal method for logging API end. Used with
+     * FGS metrics logging. Is called by APIs that are
+     * used with FGS to log an API event (eg when
+     * the camera starts).
+     * @hide
+     *
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.LOG_FOREGROUND_RESOURCE_USE)
+    public void noteForegroundResourceUseEnd(@ForegroundServiceApiType int apiType,
+            int uid, int pid) throws SecurityException {
+        try {
+            getService().logFgsApiEnd(apiType, uid, pid);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index b9f38d3..90427cb 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -18,6 +18,7 @@
 
 import static android.app.ActivityManager.StopUserOnSwitch;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.PermissionMethod;
@@ -47,6 +48,8 @@
 
 import com.android.internal.os.TimeoutRecord;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -968,14 +971,6 @@
     public abstract void stopForegroundServiceDelegate(@NonNull ServiceConnection connection);
 
     /**
-     * Called by PowerManager. Return whether a given procstate is allowed to hold
-     * wake locks in deep doze. Because it's called with the power manager lock held, we can't
-     * hold AM locks in it.
-     * @hide
-     */
-    public abstract boolean canHoldWakeLocksInDeepDoze(int uid, int procstate);
-
-    /**
      * Same as {@link android.app.IActivityManager#startProfile(int userId)}, but it would succeed
      * even if the profile is disabled - it should only be called by
      * {@link com.android.server.devicepolicy.DevicePolicyManagerService} when starting a profile
@@ -999,4 +994,48 @@
      */
     public abstract void logFgsApiEnd(int apiType, int uid, int pid);
 
+    /**
+     * The list of the events about the {@link android.media.projection.IMediaProjection} itself.
+     *
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+        MEDIA_PROJECTION_TOKEN_EVENT_CREATED,
+        MEDIA_PROJECTION_TOKEN_EVENT_DESTROYED,
+    })
+    public @interface MediaProjectionTokenEvent{};
+
+    /**
+     * An instance of {@link android.media.projection.IMediaProjection} has been created
+     * by the system.
+     *
+     * @hide
+     */
+    public static final @MediaProjectionTokenEvent int MEDIA_PROJECTION_TOKEN_EVENT_CREATED = 0;
+
+    /**
+     * An instance of {@link android.media.projection.IMediaProjection} has been destroyed
+     * by the system.
+     *
+     * @hide
+     */
+    public static final @MediaProjectionTokenEvent int MEDIA_PROJECTION_TOKEN_EVENT_DESTROYED = 1;
+
+    /**
+     * Called after the system created/destroyed a media projection for an app, if the user
+     * has granted the permission to start a media projection from this app.
+     *
+     * <p>This API is specifically for the use case of enforcing the FGS type
+     * {@code android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION},
+     * where the app who is starting this type of FGS must have been granted with the permission
+     * to start the projection via the {@link android.media.projection.MediaProjection} APIs.
+     *
+     * @param uid The uid of the app which the system created/destroyed a media projection for.
+     * @param projectionToken The {@link android.media.projection.IMediaProjection} token that
+     *                        the system created/destroyed.
+     * @param event The actual event happening to the given {@code projectionToken}.
+     */
+    public abstract void notifyMediaProjectionEvent(int uid, @NonNull IBinder projectionToken,
+            @MediaProjectionTokenEvent int event);
 }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index b0929b5..28d4433 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -36,6 +36,7 @@
 import static android.window.ConfigurationHelper.shouldUpdateResources;
 
 import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
+import static com.android.internal.os.SafeZipPathValidatorCallback.VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -49,6 +50,7 @@
 import android.app.backup.BackupAgent;
 import android.app.backup.BackupAnnotations.BackupDestination;
 import android.app.backup.BackupAnnotations.OperationType;
+import android.app.compat.CompatChanges;
 import android.app.servertransaction.ActivityLifecycleItem;
 import android.app.servertransaction.ActivityLifecycleItem.LifecycleState;
 import android.app.servertransaction.ActivityRelaunchItem;
@@ -206,6 +208,7 @@
 import com.android.internal.os.BinderCallsStats;
 import com.android.internal.os.BinderInternal;
 import com.android.internal.os.RuntimeInit;
+import com.android.internal.os.SafeZipPathValidatorCallback;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.policy.DecorView;
 import com.android.internal.util.ArrayUtils;
@@ -219,6 +222,7 @@
 import dalvik.system.CloseGuard;
 import dalvik.system.VMDebug;
 import dalvik.system.VMRuntime;
+import dalvik.system.ZipPathValidator;
 
 import libcore.io.ForwardingOs;
 import libcore.io.IoUtils;
@@ -554,9 +558,6 @@
         boolean hideForNow;
         Configuration createdConfig;
         Configuration overrideConfig;
-        // TODO(b/263402465): pass deviceId directly in LaunchActivityItem#execute
-        // The deviceId assigned by the server when this activity was first started.
-        int mDeviceId;
         // Used for consolidating configs before sending on to Activity.
         private Configuration tmpConfig = new Configuration();
         // Callback used for updating activity override config and camera compat control state.
@@ -619,7 +620,7 @@
         }
 
         public ActivityClientRecord(IBinder token, Intent intent, int ident,
-                ActivityInfo info, Configuration overrideConfig, int deviceId,
+                ActivityInfo info, Configuration overrideConfig,
                 String referrer, IVoiceInteractor voiceInteractor, Bundle state,
                 PersistableBundle persistentState, List<ResultInfo> pendingResults,
                 List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions,
@@ -641,7 +642,6 @@
             this.isForward = isForward;
             this.profilerInfo = profilerInfo;
             this.overrideConfig = overrideConfig;
-            this.mDeviceId = deviceId;
             this.packageInfo = client.getPackageInfoNoCheck(activityInfo.applicationInfo);
             mActivityOptions = activityOptions;
             mLaunchedFromBubble = launchedFromBubble;
@@ -849,8 +849,10 @@
         @UnsupportedAppUsage
         Intent intent;
         boolean rebind;
+        long bindSeq;
         public String toString() {
-            return "BindServiceData{token=" + token + " intent=" + intent + "}";
+            return "BindServiceData{token=" + token + " intent=" + intent
+                    + " bindSeq=" + bindSeq + "}";
         }
     }
 
@@ -1107,12 +1109,13 @@
         }
 
         public final void scheduleBindService(IBinder token, Intent intent,
-                boolean rebind, int processState) {
+                boolean rebind, int processState, long bindSeq) {
             updateProcessState(processState, false);
             BindServiceData s = new BindServiceData();
             s.token = token;
             s.intent = intent;
             s.rebind = rebind;
+            s.bindSeq = bindSeq;
 
             if (DEBUG_SERVICE)
                 Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
@@ -1124,6 +1127,7 @@
             BindServiceData s = new BindServiceData();
             s.token = token;
             s.intent = intent;
+            s.bindSeq = -1;
 
             sendMessage(H.UNBIND_SERVICE, s);
         }
@@ -1154,6 +1158,11 @@
         }
 
         @Override
+        public final void schedulePing(RemoteCallback pong) {
+            sendMessage(H.PING, pong);
+        }
+
+        @Override
         public final void bindApplication(String processName, ApplicationInfo appInfo,
                 String sdkSandboxClientAppVolumeUuid, String sdkSandboxClientAppPackage,
                 ProviderInfoList providerList, ComponentName instrumentationName,
@@ -2154,6 +2163,7 @@
         public static final int DUMP_GFXINFO = 165;
         public static final int DUMP_RESOURCES = 166;
         public static final int TIMEOUT_SERVICE = 167;
+        public static final int PING = 168;
 
         public static final int INSTRUMENT_WITHOUT_RESTART = 170;
         public static final int FINISH_INSTRUMENTATION_WITHOUT_RESTART = 171;
@@ -2209,6 +2219,7 @@
                         return "FINISH_INSTRUMENTATION_WITHOUT_RESTART";
                     case DUMP_RESOURCES: return "DUMP_RESOURCES";
                     case TIMEOUT_SERVICE: return "TIMEOUT_SERVICE";
+                    case PING: return "PING";
                 }
             }
             return Integer.toString(code);
@@ -2292,6 +2303,9 @@
                     handleTimeoutService((IBinder) msg.obj, msg.arg1);
                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                     break;
+                case PING:
+                    ((RemoteCallback) msg.obj).sendResult(null);
+                    break;
                 case CONFIGURATION_CHANGED:
                     mConfigurationController.handleConfigurationChanged((Configuration) msg.obj);
                     break;
@@ -3547,8 +3561,13 @@
             if (mLastProcessState == processState) {
                 return;
             }
+            // Do not issue a transitional GC if we are transitioning between 2 cached states.
+            // Only update if the state flips between cached and uncached or vice versa
+            if (ActivityManager.isProcStateCached(mLastProcessState)
+                    != ActivityManager.isProcStateCached(processState)) {
+                updateVmProcessState(processState);
+            }
             mLastProcessState = processState;
-            updateVmProcessState(processState);
             if (localLOGV) {
                 Slog.i(TAG, "******************* PROCESS STATE CHANGED TO: " + processState
                         + (fromIpc ? " (from ipc" : ""));
@@ -3557,12 +3576,16 @@
     }
 
     /** Update VM state based on ActivityManager.PROCESS_STATE_* constants. */
+    // Currently ART VM only uses state updates for Transitional GC, and thus
+    // this function initiates a Transitional GC for transitions into Cached apps states.
     private void updateVmProcessState(int processState) {
-        // TODO: Tune this since things like gmail sync are important background but not jank
-        // perceptible.
-        final int state = processState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
-                ? VM_PROCESS_STATE_JANK_PERCEPTIBLE
-                : VM_PROCESS_STATE_JANK_IMPERCEPTIBLE;
+        // Only a transition into Cached state should result in a Transitional GC request
+        // to the ART runtime. Update VM state to JANK_IMPERCEPTIBLE in that case.
+        // Note that there are 4 possible cached states currently, all of which are
+        // JANK_IMPERCEPTIBLE from GC point of view.
+        final int state = ActivityManager.isProcStateCached(processState)
+                ? VM_PROCESS_STATE_JANK_IMPERCEPTIBLE
+                : VM_PROCESS_STATE_JANK_PERCEPTIBLE;
         VMRuntime.getRuntime().updateProcessState(state);
     }
 
@@ -3872,7 +3895,7 @@
      */
     @Override
     public Activity handleLaunchActivity(ActivityClientRecord r,
-            PendingTransactionActions pendingActions, Intent customIntent) {
+            PendingTransactionActions pendingActions, int deviceId, Intent customIntent) {
         // If we are getting ready to gc after going to the background, well
         // we are back active so skip it.
         unscheduleGcIdler();
@@ -3885,7 +3908,7 @@
 
         // Make sure we are running with the most recent config.
         mConfigurationController.handleConfigurationChanged(null, null);
-        updateDeviceIdForNonUIContexts(r.mDeviceId);
+        updateDeviceIdForNonUIContexts(deviceId);
 
         if (localLOGV) Slog.v(
             TAG, "Handling launch of " + r);
@@ -5942,7 +5965,7 @@
         r.startsNotResumed = startsNotResumed;
         r.overrideConfig = overrideConfig;
 
-        handleLaunchActivity(r, pendingActions, customIntent);
+        handleLaunchActivity(r, pendingActions, mLastReportedDeviceId, customIntent);
     }
 
     @Override
@@ -6703,6 +6726,11 @@
         // Let libcore handle any compat changes after installing the list of compat changes.
         AppSpecializationHooks.handleCompatChangesBeforeBindingApplication();
 
+        // Initialize the zip path validator callback depending on the targetSdk.
+        // This has to be after AppCompatCallbacks#install() so that the Compat
+        // checks work accordingly.
+        initZipPathValidatorCallback();
+
         mBoundApplication = data;
         mConfigurationController.setConfiguration(data.config);
         mConfigurationController.setCompatConfiguration(data.config);
@@ -7070,6 +7098,18 @@
         }
     }
 
+    /**
+     * If targetSDK >= U: set the safe zip path validator callback which disallows dangerous zip
+     * entry names.
+     * Otherwise: clear the callback to the default validation.
+     */
+    private void initZipPathValidatorCallback() {
+        if (CompatChanges.isChangeEnabled(VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL)) {
+            ZipPathValidator.setCallback(new SafeZipPathValidatorCallback());
+        } else {
+            ZipPathValidator.clearCallback();
+        }
+    }
 
     private void handleSetContentCaptureOptionsCallback(String packageName) {
         if (mContentCaptureOptionsCallback != null) {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 9bf9e0c..265b564 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -2217,8 +2217,7 @@
     /** Whether noting for an appop should be collected */
     private static final @ShouldCollectNoteOp byte[] sAppOpsToNote = new byte[_NUM_OP];
 
-    private static final int[] RUNTIME_AND_APPOP_PERMISSIONS_OPS = {
-            // RUNTIME PERMISSIONS
+    private static final int[] RUNTIME_PERMISSION_OPS = {
             // Contacts
             OP_READ_CONTACTS,
             OP_WRITE_CONTACTS,
@@ -2275,8 +2274,13 @@
             OP_NEARBY_WIFI_DEVICES,
             // Notifications
             OP_POST_NOTIFICATION,
+    };
 
-            // APPOP PERMISSIONS
+    /**
+     * Ops for app op permissions that are setting the per-package mode for certain reasons. Most
+     * app op permissions should set the per-UID mode instead.
+     */
+    private static final int[] APP_OP_PERMISSION_PACKAGE_OPS = {
             OP_ACCESS_NOTIFICATIONS,
             OP_SYSTEM_ALERT_WINDOW,
             OP_WRITE_SETTINGS,
@@ -2285,9 +2289,16 @@
             OP_SMS_FINANCIAL_TRANSACTIONS,
             OP_MANAGE_IPSEC_TUNNELS,
             OP_INSTANT_APP_START_FOREGROUND,
+            OP_LOADER_USAGE_STATS
+    };
+
+    /**
+     * Ops for app op permissions that are setting the per-UID mode for certain reasons. This should
+     * be preferred over the per-package mode for new app op permissions.
+     */
+    private static final int[] APP_OP_PERMISSION_UID_OPS = {
             OP_MANAGE_EXTERNAL_STORAGE,
             OP_INTERACT_ACROSS_PROFILES,
-            OP_LOADER_USAGE_STATS,
             OP_MANAGE_ONGOING_CALLS,
             OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
             OP_SCHEDULE_EXACT_ALARM,
@@ -2777,7 +2788,17 @@
                 sOpStrToOp.put(sAppOpInfos[i].name, i);
             }
         }
-        for (int op : RUNTIME_AND_APPOP_PERMISSIONS_OPS) {
+        for (int op : RUNTIME_PERMISSION_OPS) {
+            if (sAppOpInfos[op].permission != null) {
+                sPermToOp.put(sAppOpInfos[op].permission, op);
+            }
+        }
+        for (int op : APP_OP_PERMISSION_PACKAGE_OPS) {
+            if (sAppOpInfos[op].permission != null) {
+                sPermToOp.put(sAppOpInfos[op].permission, op);
+            }
+        }
+        for (int op : APP_OP_PERMISSION_UID_OPS) {
             if (sAppOpInfos[op].permission != null) {
                 sPermToOp.put(sAppOpInfos[op].permission, op);
             }
@@ -2947,6 +2968,22 @@
     }
 
     /**
+     * Retrieve whether the op is a per-package op for an app op permission.
+     * @hide
+     */
+    public static boolean opIsPackageAppOpPermission(int op) {
+        return ArrayUtils.contains(APP_OP_PERMISSION_PACKAGE_OPS, op);
+    }
+
+    /**
+     * Retrieve whether the op is a per-package op for an app op permission.
+     * @hide
+     */
+    public static boolean opIsUidAppOpPermission(int op) {
+        return ArrayUtils.contains(APP_OP_PERMISSION_UID_OPS, op);
+    }
+
+    /**
      * Returns a listenerId suitable for use with {@link #noteOp(int, int, String, String, String)}.
      *
      * This is intended for use client side, when the receiver id must be created before the
@@ -7200,10 +7237,16 @@
         if (mContext != null) {
             final PackageManager pm = mContext.getPackageManager();
             try {
-                if (pm != null && pm.checkPermission(Manifest.permission.READ_DEVICE_CONFIG,
-                        mContext.getPackageName()) == PackageManager.PERMISSION_GRANTED) {
-                    DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_PRIVACY,
-                            mContext.getMainExecutor(), properties -> {
+                if (Build.IS_ENG
+                        && pm != null
+                        && pm.checkPermission(
+                                        Manifest.permission.READ_DEVICE_CONFIG,
+                                        mContext.getPackageName())
+                                == PackageManager.PERMISSION_GRANTED) {
+                    DeviceConfig.addOnPropertiesChangedListener(
+                            DeviceConfig.NAMESPACE_PRIVACY,
+                            mContext.getMainExecutor(),
+                            properties -> {
                                 if (properties.getKeyset().contains(FULL_LOG)) {
                                     sFullLog = properties.getBoolean(FULL_LOG, false);
                                 }
@@ -8365,9 +8408,9 @@
     public int noteProxyOp(int op, @Nullable String proxiedPackageName, int proxiedUid,
             @Nullable String proxiedAttributionTag, @Nullable String message) {
         return noteProxyOp(op, new AttributionSource(mContext.getAttributionSource(),
-                new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag,
-                        mContext.getAttributionSource().getToken())), message,
-                        /*skipProxyOperation*/ false);
+                new AttributionSource(proxiedUid, Process.INVALID_PID, proxiedPackageName,
+                        proxiedAttributionTag, mContext.getAttributionSource().getToken())),
+                        message, /*skipProxyOperation*/ false);
     }
 
     /**
@@ -8452,8 +8495,9 @@
             int proxiedUid, @Nullable String proxiedAttributionTag, @Nullable String message) {
         return noteProxyOpNoThrow(strOpToOp(op), new AttributionSource(
                 mContext.getAttributionSource(), new AttributionSource(proxiedUid,
-                        proxiedPackageName, proxiedAttributionTag, mContext.getAttributionSource()
-                        .getToken())), message,/*skipProxyOperation*/ false);
+                        Process.INVALID_PID, proxiedPackageName, proxiedAttributionTag,
+                        mContext.getAttributionSource().getToken())), message,
+                        /*skipProxyOperation*/ false);
     }
 
     /**
@@ -8863,9 +8907,9 @@
     public int startProxyOp(@NonNull String op, int proxiedUid, @NonNull String proxiedPackageName,
             @Nullable String proxiedAttributionTag, @Nullable String message) {
         return startProxyOp(op, new AttributionSource(mContext.getAttributionSource(),
-                new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag,
-                        mContext.getAttributionSource().getToken())), message,
-                        /*skipProxyOperation*/ false);
+                new AttributionSource(proxiedUid, Process.INVALID_PID, proxiedPackageName,
+                        proxiedAttributionTag, mContext.getAttributionSource().getToken())),
+                        message, /*skipProxyOperation*/ false);
     }
 
     /**
@@ -8911,7 +8955,7 @@
             @Nullable String message) {
         return startProxyOpNoThrow(AppOpsManager.strOpToOp(op), new AttributionSource(
                 mContext.getAttributionSource(), new AttributionSource(proxiedUid,
-                        proxiedPackageName, proxiedAttributionTag,
+                        Process.INVALID_PID, proxiedPackageName, proxiedAttributionTag,
                         mContext.getAttributionSource().getToken())), message,
                         /*skipProxyOperation*/ false);
     }
@@ -9060,8 +9104,8 @@
             @NonNull String proxiedPackageName, @Nullable String proxiedAttributionTag) {
         IBinder token = mContext.getAttributionSource().getToken();
         finishProxyOp(token, op, new AttributionSource(mContext.getAttributionSource(),
-                new AttributionSource(proxiedUid, proxiedPackageName,  proxiedAttributionTag,
-                        token)), /*skipProxyOperation*/ false);
+                new AttributionSource(proxiedUid, Process.INVALID_PID, proxiedPackageName,
+                        proxiedAttributionTag, token)), /*skipProxyOperation*/ false);
     }
 
     /**
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index a99815c..6301ad7 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -556,12 +556,7 @@
     @Override
     public ActivityInfo getActivityInfo(ComponentName className, ComponentInfoFlags flags)
             throws NameNotFoundException {
-        return getActivityInfoAsUser(className, flags, getUserId());
-    }
-
-    @Override
-    public ActivityInfo getActivityInfoAsUser(ComponentName className,
-            ComponentInfoFlags flags, @UserIdInt int userId) throws NameNotFoundException {
+        final int userId = getUserId();
         try {
             ActivityInfo ai = mPM.getActivityInfo(className,
                     updateFlagsForComponent(flags.getValue(), userId, null), userId);
diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java
index fe40a4c..a5095b2 100644
--- a/core/java/android/app/BroadcastOptions.java
+++ b/core/java/android/app/BroadcastOptions.java
@@ -60,11 +60,11 @@
     private String[] mRequireNoneOfPermissions;
     private long mRequireCompatChangeId = CHANGE_INVALID;
     private long mIdForResponseEvent;
-    private @Nullable IntentFilter mRemoveMatchingFilter;
     private @DeliveryGroupPolicy int mDeliveryGroupPolicy;
     private @Nullable String mDeliveryGroupMatchingKey;
     private @Nullable BundleMerger mDeliveryGroupExtrasMerger;
     private @Nullable IntentFilter mDeliveryGroupMatchingFilter;
+    private @DeferralPolicy int mDeferralPolicy;
 
     /** @hide */
     @IntDef(flag = true, prefix = { "FLAG_" }, value = {
@@ -72,8 +72,8 @@
             FLAG_ALLOW_BACKGROUND_ACTIVITY_STARTS,
             FLAG_REQUIRE_COMPAT_CHANGE_ENABLED,
             FLAG_IS_ALARM_BROADCAST,
-            FLAG_IS_DEFER_UNTIL_ACTIVE,
             FLAG_SHARE_IDENTITY,
+            FLAG_INTERACTIVE,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface Flags {}
@@ -82,8 +82,8 @@
     private static final int FLAG_ALLOW_BACKGROUND_ACTIVITY_STARTS = 1 << 1;
     private static final int FLAG_REQUIRE_COMPAT_CHANGE_ENABLED = 1 << 2;
     private static final int FLAG_IS_ALARM_BROADCAST = 1 << 3;
-    private static final int FLAG_IS_DEFER_UNTIL_ACTIVE = 1 << 4;
-    private static final int FLAG_SHARE_IDENTITY = 1 << 5;
+    private static final int FLAG_SHARE_IDENTITY = 1 << 4;
+    private static final int FLAG_INTERACTIVE = 1 << 5;
 
     /**
      * Change ID which is invalid.
@@ -190,12 +190,6 @@
             "android:broadcast.idForResponseEvent";
 
     /**
-     * Corresponds to {@link #setRemoveMatchingFilter}.
-     */
-    private static final String KEY_REMOVE_MATCHING_FILTER =
-            "android:broadcast.removeMatchingFilter";
-
-    /**
      * Corresponds to {@link #setDeliveryGroupPolicy(int)}.
      */
     private static final String KEY_DELIVERY_GROUP_POLICY =
@@ -220,11 +214,17 @@
             "android:broadcast.deliveryGroupMatchingFilter";
 
     /**
+     * Corresponds to {@link #setDeferralPolicy(int)}
+     */
+    private static final String KEY_DEFERRAL_POLICY =
+            "android:broadcast.deferralPolicy";
+
+    /**
      * The list of delivery group policies which specify how multiple broadcasts belonging to
      * the same delivery group has to be handled.
      * @hide
      */
-    @IntDef(flag = true, prefix = { "DELIVERY_GROUP_POLICY_" }, value = {
+    @IntDef(prefix = { "DELIVERY_GROUP_POLICY_" }, value = {
             DELIVERY_GROUP_POLICY_ALL,
             DELIVERY_GROUP_POLICY_MOST_RECENT,
             DELIVERY_GROUP_POLICY_MERGED,
@@ -235,19 +235,13 @@
     /**
      * Delivery group policy that indicates that all the broadcasts in the delivery group
      * need to be delivered as is.
-     *
-     * @hide
      */
-    @SystemApi
     public static final int DELIVERY_GROUP_POLICY_ALL = 0;
 
     /**
      * Delivery group policy that indicates that only the most recent broadcast in the delivery
      * group need to be delivered and the rest can be dropped.
-     *
-     * @hide
      */
-    @SystemApi
     public static final int DELIVERY_GROUP_POLICY_MOST_RECENT = 1;
 
     /**
@@ -258,36 +252,62 @@
      */
     public static final int DELIVERY_GROUP_POLICY_MERGED = 2;
 
+    /** {@hide} */
+    @IntDef(prefix = { "DEFERRAL_POLICY_" }, value = {
+            DEFERRAL_POLICY_DEFAULT,
+            DEFERRAL_POLICY_NONE,
+            DEFERRAL_POLICY_UNTIL_ACTIVE,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface DeferralPolicy {}
+
+    /**
+     * Deferral policy that indicates no desire has been expressed, and that the
+     * system should use a reasonable default behavior.
+     */
+    public static final int DEFERRAL_POLICY_DEFAULT = 0;
+
+    /**
+     * Deferral policy that indicates a strong desire that no receiver of this
+     * broadcast should be deferred.
+     */
+    public static final int DEFERRAL_POLICY_NONE = 1;
+
+    /**
+     * Deferral policy that indicates a strong desire that each receiver of this
+     * broadcast should be deferred until that receiver's process is in an
+     * active (non-cached) state. Whether an app's process state is considered
+     * active is independent of its standby bucket.
+     * <p>
+     * This policy only applies to runtime registered receivers of a broadcast,
+     * and does not apply to ordered broadcasts, alarm broadcasts, interactive
+     * broadcasts, or manifest broadcasts.
+     * <p>
+     * This policy means that a runtime registered receiver will not typically
+     * execute until that receiver's process is brought to an active state by
+     * some other action, such as a job, alarm, or service binding. As a result,
+     * the receiver may be delayed indefinitely.
+     * <p>
+     * When this policy is set on an unordered broadcast with a completion
+     * callback, the completion callback will run once all eligible processes
+     * have finished receiving the broadcast. Processes in inactive process
+     * state are not considered eligible and may not receive the broadcast prior
+     * to the completion callback.
+     */
+    public static final int DEFERRAL_POLICY_UNTIL_ACTIVE = 2;
+
     /**
      * Creates a basic {@link BroadcastOptions} with no options initially set.
      *
      * @return an instance of {@code BroadcastOptions} against which options can be set
-     *
-     * @deprecated Use {@link BroadcastOptions#BroadcastOptions()} instead.
-     * @hide
      */
-    @Deprecated
-    @SystemApi
     public static @NonNull BroadcastOptions makeBasic() {
         BroadcastOptions opts = new BroadcastOptions();
         return opts;
     }
 
-    /**
-     * {@hide}
-     * @deprecated use {@link #setDeliveryGroupMatchingFilter(IntentFilter)} instead.
-     */
-    @Deprecated
-    public static @NonNull BroadcastOptions makeRemovingMatchingFilter(
-            @NonNull IntentFilter removeMatchingFilter) {
-        BroadcastOptions opts = new BroadcastOptions();
-        opts.setRemoveMatchingFilter(removeMatchingFilter);
-        return opts;
-    }
-
-    /**
-     * Creates a new {@code BroadcastOptions} with no options initially set.
-     */
+    /** @hide */
+    @TestApi
     public BroadcastOptions() {
         super();
         resetTemporaryAppAllowlist();
@@ -315,8 +335,6 @@
         mRequireNoneOfPermissions = opts.getStringArray(KEY_REQUIRE_NONE_OF_PERMISSIONS);
         mRequireCompatChangeId = opts.getLong(KEY_REQUIRE_COMPAT_CHANGE_ID, CHANGE_INVALID);
         mIdForResponseEvent = opts.getLong(KEY_ID_FOR_RESPONSE_EVENT);
-        mRemoveMatchingFilter = opts.getParcelable(KEY_REMOVE_MATCHING_FILTER,
-                IntentFilter.class);
         mDeliveryGroupPolicy = opts.getInt(KEY_DELIVERY_GROUP_POLICY,
                 DELIVERY_GROUP_POLICY_ALL);
         mDeliveryGroupMatchingKey = opts.getString(KEY_DELIVERY_GROUP_KEY);
@@ -324,6 +342,7 @@
                 BundleMerger.class);
         mDeliveryGroupMatchingFilter = opts.getParcelable(KEY_DELIVERY_GROUP_MATCHING_FILTER,
                 IntentFilter.class);
+        mDeferralPolicy = opts.getInt(KEY_DEFERRAL_POLICY, DEFERRAL_POLICY_DEFAULT);
     }
 
     /**
@@ -749,85 +768,52 @@
         return mIdForResponseEvent;
     }
 
-    /**
-     * Sets whether the broadcast should not run until the process is in an active process state
-     * (ie, a process exists for the app and the app is not in a cached process state).
-     *
-     * Whether an app's process state is considered active is independent of its standby bucket.
-     *
-     * A broadcast that is deferred until the process is active will not execute until the process
-     * is brought to an active state by some other action, like a job, alarm, or service binding. As
-     * a result, the broadcast may be delayed indefinitely. This deferral only applies to runtime
-     * registered receivers of a broadcast. Any manifest receivers will run immediately, similar to
-     * how a manifest receiver would start a new process in order to run a broadcast receiver.
-     *
-     * Ordered broadcasts, alarm broadcasts, interactive broadcasts, and manifest broadcasts are
-     * never deferred.
-     *
-     * Unordered broadcasts and unordered broadcasts with completion callbacks may be
-     * deferred. Completion callbacks for broadcasts deferred until active are
-     * best-effort. Completion callbacks will run when all eligible processes have finished
-     * executing the broadcast. Processes in inactive process states that defer the broadcast are
-     * not considered eligible and may not execute the broadcast prior to the completion callback.
-     *
-     * @hide
-     */
-    @SystemApi
+    /** {@hide} */
+    @Deprecated
     public @NonNull BroadcastOptions setDeferUntilActive(boolean shouldDefer) {
         if (shouldDefer) {
-            mFlags |= FLAG_IS_DEFER_UNTIL_ACTIVE;
+            setDeferralPolicy(DEFERRAL_POLICY_UNTIL_ACTIVE);
         } else {
-            mFlags &= ~FLAG_IS_DEFER_UNTIL_ACTIVE;
+            setDeferralPolicy(DEFERRAL_POLICY_NONE);
         }
         return this;
     }
 
-    /**
-     * Returns if this broadcast should not run until the process is in an active process state.
-     *
-     * @return {@code true} if this broadcast should not run until the process is in an active
-     *                      process state. Otherwise, {@code false}.
-     * @see #setDeferUntilActive(boolean)
-     *
-     * @hide
-     */
-    @SystemApi
-    public boolean isDeferUntilActive() {
-        return (mFlags & FLAG_IS_DEFER_UNTIL_ACTIVE) != 0;
-    }
-
-    /**
-     * When enqueuing this broadcast, remove all pending broadcasts previously
-     * sent by this app which match the given filter.
-     * <p>
-     * For example, sending {@link Intent#ACTION_SCREEN_ON} would typically want
-     * to remove any pending {@link Intent#ACTION_SCREEN_OFF} broadcasts.
-     *
-     * @hide
-     * @deprecated use {@link #setDeliveryGroupMatchingFilter(IntentFilter)} instead.
-     */
+    /** {@hide} */
     @Deprecated
-    public void setRemoveMatchingFilter(@NonNull IntentFilter removeMatchingFilter) {
-        mRemoveMatchingFilter = Objects.requireNonNull(removeMatchingFilter);
+    public boolean isDeferUntilActive() {
+        return (mDeferralPolicy == DEFERRAL_POLICY_UNTIL_ACTIVE);
     }
 
-    /** @hide */
-    public void clearRemoveMatchingFilter() {
-        mRemoveMatchingFilter = null;
+    /**
+     * Sets deferral policy for this broadcast that specifies how this broadcast
+     * can be deferred for delivery at some future point.
+     */
+    public @NonNull BroadcastOptions setDeferralPolicy(@DeferralPolicy int deferralPolicy) {
+        mDeferralPolicy = deferralPolicy;
+        return this;
     }
 
-    /** @hide */
-    public @Nullable IntentFilter getRemoveMatchingFilter() {
-        return mRemoveMatchingFilter;
+    /**
+     * Gets deferral policy for this broadcast that specifies how this broadcast
+     * can be deferred for delivery at some future point.
+     */
+    public @DeferralPolicy int getDeferralPolicy() {
+        return mDeferralPolicy;
+    }
+
+    /**
+     * Clears any deferral policy for this broadcast that specifies how this
+     * broadcast can be deferred for delivery at some future point.
+     */
+    public void clearDeferralPolicy() {
+        mDeferralPolicy = DEFERRAL_POLICY_DEFAULT;
     }
 
     /**
      * Set delivery group policy for this broadcast to specify how multiple broadcasts belonging to
      * the same delivery group has to be handled.
-     *
-     * @hide
      */
-    @SystemApi
     @NonNull
     public BroadcastOptions setDeliveryGroupPolicy(@DeliveryGroupPolicy int policy) {
         mDeliveryGroupPolicy = policy;
@@ -837,10 +823,7 @@
     /**
      * Get the delivery group policy for this broadcast that specifies how multiple broadcasts
      * belonging to the same delivery group has to be handled.
-     *
-     * @hide
      */
-    @SystemApi
     public @DeliveryGroupPolicy int getDeliveryGroupPolicy() {
         return mDeliveryGroupPolicy;
     }
@@ -849,10 +832,7 @@
      * Clears any previously set delivery group policies using
      * {@link #setDeliveryGroupMatchingKey(String, String)} and resets the delivery group policy to
      * the default value ({@link #DELIVERY_GROUP_POLICY_ALL}).
-     *
-     * @hide
      */
-    @SystemApi
     public void clearDeliveryGroupPolicy() {
         mDeliveryGroupPolicy = DELIVERY_GROUP_POLICY_ALL;
     }
@@ -867,10 +847,7 @@
      * <p> If neither matching key using this API nor matching filter using
      * {@link #setDeliveryGroupMatchingFilter(IntentFilter)} is specified, then by default
      * {@link Intent#filterEquals(Intent)} will be used to identify the delivery group.
-     *
-     * @hide
      */
-    @SystemApi
     @NonNull
     public BroadcastOptions setDeliveryGroupMatchingKey(@NonNull String namespace,
             @NonNull String key) {
@@ -888,9 +865,7 @@
      *
      * @return the delivery group namespace and key that was previously set using
      *         {@link #setDeliveryGroupMatchingKey(String, String)}, concatenated with a {@code :}.
-     * @hide
      */
-    @SystemApi
     @Nullable
     public String getDeliveryGroupMatchingKey() {
         return mDeliveryGroupMatchingKey;
@@ -899,10 +874,7 @@
     /**
      * Clears the namespace and key that was previously set using
      * {@link #setDeliveryGroupMatchingKey(String, String)}.
-     *
-     * @hide
      */
-    @SystemApi
     public void clearDeliveryGroupMatchingKey() {
         mDeliveryGroupMatchingKey = null;
     }
@@ -917,10 +889,7 @@
      * <p> If neither matching key using {@link #setDeliveryGroupMatchingKey(String, String)} nor
      * matching filter using this API is specified, then by default
      * {@link Intent#filterEquals(Intent)} will be used to identify the delivery group.
-     *
-     * @hide
      */
-    @SystemApi
     @NonNull
     public BroadcastOptions setDeliveryGroupMatchingFilter(@NonNull IntentFilter matchingFilter) {
         mDeliveryGroupMatchingFilter = Objects.requireNonNull(matchingFilter);
@@ -933,9 +902,7 @@
      *
      * @return the {@link IntentFilter} object that was previously set using
      *         {@link #setDeliveryGroupMatchingFilter(IntentFilter)}.
-     * @hide
      */
-    @SystemApi
     @Nullable
     public IntentFilter getDeliveryGroupMatchingFilter() {
         return mDeliveryGroupMatchingFilter;
@@ -944,10 +911,7 @@
     /**
      * Clears the {@link IntentFilter} object that was previously set using
      * {@link #setDeliveryGroupMatchingFilter(IntentFilter)}.
-     *
-     * @hide
      */
-    @SystemApi
     public void clearDeliveryGroupMatchingFilter() {
         mDeliveryGroupMatchingFilter = null;
     }
@@ -990,6 +954,36 @@
     }
 
     /**
+     * Sets whether the broadcast should be considered as having originated from
+     * some direct interaction by the user such as a notification tap or button
+     * press. This signal is used internally to ensure the broadcast is
+     * delivered quickly with low latency.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.BROADCAST_OPTION_INTERACTIVE)
+    public @NonNull BroadcastOptions setInteractive(boolean interactive) {
+        if (interactive) {
+            mFlags |= FLAG_INTERACTIVE;
+        } else {
+            mFlags &= ~FLAG_INTERACTIVE;
+        }
+        return this;
+    }
+
+    /**
+     * Returns whether the broadcast should be considered as having originated
+     * from some direct interaction by the user such as a notification tap or
+     * button press.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.BROADCAST_OPTION_INTERACTIVE)
+    public boolean isInteractive() {
+        return (mFlags & FLAG_INTERACTIVE) != 0;
+    }
+
+    /**
      * Set PendingIntent activity is allowed to be started in the background if the caller
      * can start background activities.
      *
@@ -1092,9 +1086,6 @@
         if (mIdForResponseEvent != 0) {
             b.putLong(KEY_ID_FOR_RESPONSE_EVENT, mIdForResponseEvent);
         }
-        if (mRemoveMatchingFilter != null) {
-            b.putParcelable(KEY_REMOVE_MATCHING_FILTER, mRemoveMatchingFilter);
-        }
         if (mDeliveryGroupPolicy != DELIVERY_GROUP_POLICY_ALL) {
             b.putInt(KEY_DELIVERY_GROUP_POLICY, mDeliveryGroupPolicy);
         }
@@ -1113,11 +1104,22 @@
         if (mDeliveryGroupMatchingFilter != null) {
             b.putParcelable(KEY_DELIVERY_GROUP_MATCHING_FILTER, mDeliveryGroupMatchingFilter);
         }
-        return b.isEmpty() ? null : b;
+        if (mDeferralPolicy != DEFERRAL_POLICY_DEFAULT) {
+            b.putInt(KEY_DEFERRAL_POLICY, mDeferralPolicy);
+        }
+        return b;
     }
 
-    /** @hide */
-    public static @Nullable BroadcastOptions fromBundle(@Nullable Bundle options) {
+    /**
+     * Returns a {@link BroadcastOptions} parsed from the given {@link Bundle},
+     * typically generated from {@link #toBundle()}.
+     */
+    public static @NonNull BroadcastOptions fromBundle(@NonNull Bundle options) {
+        return new BroadcastOptions(options);
+    }
+
+    /** {@hide} */
+    public static @Nullable BroadcastOptions fromBundleNullable(@Nullable Bundle options) {
         return (options != null) ? new BroadcastOptions(options) : null;
     }
 }
diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java
index 6bb38e7..49fb794 100644
--- a/core/java/android/app/ClientTransactionHandler.java
+++ b/core/java/android/app/ClientTransactionHandler.java
@@ -188,7 +188,7 @@
 
     /** Perform activity launch. */
     public abstract Activity handleLaunchActivity(@NonNull ActivityClientRecord r,
-            PendingTransactionActions pendingActions, Intent customIntent);
+            PendingTransactionActions pendingActions, int deviceId, Intent customIntent);
 
     /** Perform activity start. */
     public abstract void handleStartActivity(@NonNull ActivityClientRecord r,
diff --git a/core/java/android/app/ComponentOptions.java b/core/java/android/app/ComponentOptions.java
index ceb9e90..e0e2855 100644
--- a/core/java/android/app/ComponentOptions.java
+++ b/core/java/android/app/ComponentOptions.java
@@ -19,7 +19,6 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
 import android.annotation.SuppressLint;
 import android.annotation.TestApi;
 import android.os.Bundle;
@@ -53,15 +52,8 @@
     public static final String KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED_BY_PERMISSION =
             "android.pendingIntent.backgroundActivityAllowedByPermission";
 
-    /**
-     * Corresponds to {@link #setInteractive(boolean)}
-     * @hide
-     */
-    private static final String KEY_INTERACTIVE = "android:component.isInteractive";
-
     private @Nullable Boolean mPendingIntentBalAllowed = null;
     private boolean mPendingIntentBalAllowedByPermission = false;
-    private boolean mIsInteractive = false;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
@@ -106,29 +98,6 @@
         setPendingIntentBackgroundActivityLaunchAllowedByPermission(
                 opts.getBoolean(
                         KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED_BY_PERMISSION, false));
-        mIsInteractive = opts.getBoolean(KEY_INTERACTIVE, false);
-    }
-
-    /**
-     * When set, a broadcast will be understood as having originated from
-     * some direct interaction by the user such as a notification tap or button
-     * press.  Only the OS itself may use this option.
-     * @hide
-     * @param interactive
-     * @see #isInteractive()
-     */
-    @RequiresPermission(android.Manifest.permission.COMPONENT_OPTION_INTERACTIVE)
-    public void setInteractive(boolean interactive) {
-        mIsInteractive = interactive;
-    }
-
-    /**
-     * Did this PendingIntent send originate with a direct user interaction?
-     * @return true if this is the result of an interaction, false otherwise
-     * @hide
-     */
-    public boolean isInteractive() {
-        return mIsInteractive;
     }
 
     /**
@@ -232,9 +201,6 @@
             b.putBoolean(KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED_BY_PERMISSION,
                     mPendingIntentBalAllowedByPermission);
         }
-        if (mIsInteractive) {
-            b.putBoolean(KEY_INTERACTIVE, true);
-        }
         return b;
     }
 
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index e3ec493..0cd42a3 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1299,7 +1299,7 @@
 
     @Override
     public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions,
-            String[] excludedPermissions, String[] excludedPackages) {
+            String[] excludedPermissions, String[] excludedPackages, BroadcastOptions options) {
         warnIfCallingFromSystemProcess();
         String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
         try {
@@ -1307,7 +1307,8 @@
             ActivityManager.getService().broadcastIntentWithFeature(
                     mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
                     null, Activity.RESULT_OK, null, null, receiverPermissions, excludedPermissions,
-                    excludedPackages, AppOpsManager.OP_NONE, null, false, false, getUserId());
+                    excludedPackages, AppOpsManager.OP_NONE,
+                    options == null ? null : options.toBundle(), false, false, getUserId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -2814,7 +2815,7 @@
     public @NonNull Context createDeviceContext(int deviceId) {
         if (deviceId != Context.DEVICE_ID_DEFAULT) {
             VirtualDeviceManager vdm = getSystemService(VirtualDeviceManager.class);
-            if (!vdm.isValidVirtualDeviceId(deviceId)) {
+            if (vdm == null || !vdm.isValidVirtualDeviceId(deviceId)) {
                 throw new IllegalArgumentException(
                         "Not a valid ID of the default device or any virtual device: " + deviceId);
             }
@@ -3460,7 +3461,9 @@
             @Nullable AttributionSource nextAttributionSource,
             @Nullable Set<String> renouncedPermissions) {
         AttributionSource attributionSource = new AttributionSource(Process.myUid(),
-                mOpPackageName, attributionTag, renouncedPermissions, nextAttributionSource);
+                Process.myPid(), mOpPackageName, attributionTag,
+                (renouncedPermissions != null) ? renouncedPermissions.toArray(new String[0]) : null,
+                nextAttributionSource);
         // If we want to access protected data on behalf of another app we need to
         // tell the OS that we opt in to participate in the attribution chain.
         if (nextAttributionSource != null) {
diff --git a/core/java/android/app/ForegroundServiceTypePolicy.java b/core/java/android/app/ForegroundServiceTypePolicy.java
index a7824a8..be012cf 100644
--- a/core/java/android/app/ForegroundServiceTypePolicy.java
+++ b/core/java/android/app/ForegroundServiceTypePolicy.java
@@ -59,6 +59,9 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.permission.PermissionCheckerManager;
+import android.provider.DeviceConfig;
+import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.SparseArray;
 
@@ -147,6 +150,108 @@
     public static final long FGS_TYPE_PERMISSION_CHANGE_ID = 254662522L;
 
     /**
+     * The prefix for the feature flags of the permission enforcement.
+     */
+    private static final String FGS_TYPE_PERM_ENFORCEMENT_FLAG_PREFIX =
+            "fgs_type_perm_enforcement_flag_";
+
+    /**
+     * The feature flag of the permission enforcement for
+     * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_DATA_SYNC},
+     * in the namespace of {@link DeviceConfig#NAMESPACE_ACTIVITY_MANAGER}.
+     */
+    private static final String FGS_TYPE_PERM_ENFORCEMENT_FLAG_DATA_SYNC =
+            FGS_TYPE_PERM_ENFORCEMENT_FLAG_PREFIX + "data_sync";
+
+    /**
+     * The feature flag of the permission enforcement for
+     * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK},
+     * in the namespace of {@link DeviceConfig#NAMESPACE_ACTIVITY_MANAGER}.
+     */
+    private static final String FGS_TYPE_PERM_ENFORCEMENT_FLAG_MEDIA_PLAYBACK =
+            FGS_TYPE_PERM_ENFORCEMENT_FLAG_PREFIX + "media_playback";
+
+    /**
+     * The feature flag of the permission enforcement for
+     * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_PHONE_CALL},
+     * in the namespace of {@link DeviceConfig#NAMESPACE_ACTIVITY_MANAGER}.
+     */
+    private static final String FGS_TYPE_PERM_ENFORCEMENT_FLAG_PHONE_CALL =
+            FGS_TYPE_PERM_ENFORCEMENT_FLAG_PREFIX + "phone_call";
+
+    /**
+     * The feature flag of the permission enforcement for
+     * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_LOCATION},
+     * in the namespace of {@link DeviceConfig#NAMESPACE_ACTIVITY_MANAGER}.
+     */
+    private static final String FGS_TYPE_PERM_ENFORCEMENT_FLAG_LOCATION =
+            FGS_TYPE_PERM_ENFORCEMENT_FLAG_PREFIX + "location";
+
+    /**
+     * The feature flag of the permission enforcement for
+     * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE},
+     * in the namespace of {@link DeviceConfig#NAMESPACE_ACTIVITY_MANAGER}.
+     */
+    private static final String FGS_TYPE_PERM_ENFORCEMENT_FLAG_CONNECTED_DEVICE =
+            FGS_TYPE_PERM_ENFORCEMENT_FLAG_PREFIX + "connected_device";
+
+    /**
+     * The feature flag of the permission enforcement for
+     * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION},
+     * in the namespace of {@link DeviceConfig#NAMESPACE_ACTIVITY_MANAGER}.
+     */
+    private static final String FGS_TYPE_PERM_ENFORCEMENT_FLAG_MEDIA_PROJECTION =
+            FGS_TYPE_PERM_ENFORCEMENT_FLAG_PREFIX + "media_projection";
+
+    /**
+     * The feature flag of the permission enforcement for
+     * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_CAMERA},
+     * in the namespace of {@link DeviceConfig#NAMESPACE_ACTIVITY_MANAGER}.
+     */
+    private static final String FGS_TYPE_PERM_ENFORCEMENT_FLAG_CAMERA =
+            FGS_TYPE_PERM_ENFORCEMENT_FLAG_PREFIX + "camera";
+
+    /**
+     * The feature flag of the permission enforcement for
+     * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_MICROPHONE},
+     * in the namespace of {@link DeviceConfig#NAMESPACE_ACTIVITY_MANAGER}.
+     */
+    private static final String FGS_TYPE_PERM_ENFORCEMENT_FLAG_MICROPHONE =
+            FGS_TYPE_PERM_ENFORCEMENT_FLAG_PREFIX + "microphone";
+
+    /**
+     * The feature flag of the permission enforcement for
+     * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_HEALTH},
+     * in the namespace of {@link DeviceConfig#NAMESPACE_ACTIVITY_MANAGER}.
+     */
+    private static final String FGS_TYPE_PERM_ENFORCEMENT_FLAG_HEALTH =
+            FGS_TYPE_PERM_ENFORCEMENT_FLAG_PREFIX + "health";
+
+    /**
+     * The feature flag of the permission enforcement for
+     * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_REMOTE_MESSAGING},
+     * in the namespace of {@link DeviceConfig#NAMESPACE_ACTIVITY_MANAGER}.
+     */
+    private static final String FGS_TYPE_PERM_ENFORCEMENT_FLAG_REMOTE_MESSAGING =
+            FGS_TYPE_PERM_ENFORCEMENT_FLAG_PREFIX + "remote_messaging";
+
+    /**
+     * The feature flag of the permission enforcement for
+     * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED},
+     * in the namespace of {@link DeviceConfig#NAMESPACE_ACTIVITY_MANAGER}.
+     */
+    private static final String FGS_TYPE_PERM_ENFORCEMENT_FLAG_SYSTEM_EXEMPTED =
+            FGS_TYPE_PERM_ENFORCEMENT_FLAG_PREFIX + "system_exempted";
+
+    /**
+     * The feature flag of the permission enforcement for
+     * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_SPECIAL_USE},
+     * in the namespace of {@link DeviceConfig#NAMESPACE_ACTIVITY_MANAGER}.
+     */
+    private static final String FGS_TYPE_PERM_ENFORCEMENT_FLAG_SPECIAL_USE =
+            FGS_TYPE_PERM_ENFORCEMENT_FLAG_PREFIX + "special_use";
+
+    /**
      * The policy for the {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_MANIFEST}.
      *
      * @hide
@@ -156,8 +261,10 @@
             FOREGROUND_SERVICE_TYPE_MANIFEST,
             FGS_TYPE_NONE_DEPRECATION_CHANGE_ID,
             FGS_TYPE_NONE_DISABLED_CHANGE_ID,
-            null,
-            null
+            null /* allOfPermissions */,
+            null /* anyOfPermissions */,
+            null /* permissionEnforcementFlag */,
+            false /* permissionEnforcementFlagDefaultValue */
     );
 
     /**
@@ -170,8 +277,10 @@
             FOREGROUND_SERVICE_TYPE_NONE,
             FGS_TYPE_NONE_DEPRECATION_CHANGE_ID,
             FGS_TYPE_NONE_DISABLED_CHANGE_ID,
-            null,
-            null
+            null /* allOfPermissions */,
+            null /* anyOfPermissions */,
+            null /* permissionEnforcementFlag */,
+            false /* permissionEnforcementFlagDefaultValue */
     );
 
     /**
@@ -187,7 +296,9 @@
             new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
                 new RegularPermission(Manifest.permission.FOREGROUND_SERVICE_DATA_SYNC)
             }, true),
-            null
+            null /* anyOfPermissions */,
+            FGS_TYPE_PERM_ENFORCEMENT_FLAG_DATA_SYNC /* permissionEnforcementFlag */,
+            true /* permissionEnforcementFlagDefaultValue */
     );
 
     /**
@@ -203,7 +314,9 @@
             new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
                 new RegularPermission(Manifest.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK)
             }, true),
-            null
+            null /* anyOfPermissions */,
+            FGS_TYPE_PERM_ENFORCEMENT_FLAG_MEDIA_PLAYBACK /* permissionEnforcementFlag */,
+            true /* permissionEnforcementFlagDefaultValue */
     );
 
     /**
@@ -221,7 +334,9 @@
             }, true),
             new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
                 new RegularPermission(Manifest.permission.MANAGE_OWN_CALLS)
-            }, false)
+            }, false),
+            FGS_TYPE_PERM_ENFORCEMENT_FLAG_PHONE_CALL /* permissionEnforcementFlag */,
+            true /* permissionEnforcementFlagDefaultValue */
     );
 
     /**
@@ -240,7 +355,9 @@
             new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
                 new RegularPermission(Manifest.permission.ACCESS_COARSE_LOCATION),
                 new RegularPermission(Manifest.permission.ACCESS_FINE_LOCATION),
-            }, false)
+            }, false),
+            FGS_TYPE_PERM_ENFORCEMENT_FLAG_LOCATION /* permissionEnforcementFlag */,
+            true /* permissionEnforcementFlagDefaultValue */
     );
 
     /**
@@ -268,7 +385,9 @@
                 new RegularPermission(Manifest.permission.UWB_RANGING),
                 new UsbDevicePermission(),
                 new UsbAccessoryPermission(),
-            }, false)
+            }, false),
+            FGS_TYPE_PERM_ENFORCEMENT_FLAG_CONNECTED_DEVICE /* permissionEnforcementFlag */,
+            true /* permissionEnforcementFlagDefaultValue */
     );
 
     /**
@@ -284,7 +403,12 @@
             new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
                 new RegularPermission(Manifest.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION)
             }, true),
-            null
+            new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
+                new RegularPermission(Manifest.permission.CAPTURE_VIDEO_OUTPUT),
+                new AppOpPermission(AppOpsManager.OP_PROJECT_MEDIA)
+            }, false),
+            FGS_TYPE_PERM_ENFORCEMENT_FLAG_MEDIA_PROJECTION /* permissionEnforcementFlag */,
+            true /* permissionEnforcementFlagDefaultValue */
     );
 
     /**
@@ -303,7 +427,9 @@
             new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
                 new RegularPermission(Manifest.permission.CAMERA),
                 new RegularPermission(Manifest.permission.SYSTEM_CAMERA),
-            }, false)
+            }, false),
+            FGS_TYPE_PERM_ENFORCEMENT_FLAG_CAMERA /* permissionEnforcementFlag */,
+            true /* permissionEnforcementFlagDefaultValue */
     );
 
     /**
@@ -326,7 +452,9 @@
                 new RegularPermission(Manifest.permission.CAPTURE_TUNER_AUDIO_INPUT),
                 new RegularPermission(Manifest.permission.CAPTURE_VOICE_COMMUNICATION_OUTPUT),
                 new RegularPermission(Manifest.permission.RECORD_AUDIO),
-            }, false)
+            }, false),
+            FGS_TYPE_PERM_ENFORCEMENT_FLAG_MICROPHONE /* permissionEnforcementFlag */,
+            true /* permissionEnforcementFlagDefaultValue */
     );
 
     /**
@@ -347,7 +475,9 @@
                 new RegularPermission(Manifest.permission.BODY_SENSORS),
                 new RegularPermission(Manifest.permission.BODY_SENSORS_WRIST_TEMPERATURE),
                 new RegularPermission(Manifest.permission.HIGH_SAMPLING_RATE_SENSORS),
-            }, false)
+            }, false),
+            FGS_TYPE_PERM_ENFORCEMENT_FLAG_HEALTH /* permissionEnforcementFlag */,
+            true /* permissionEnforcementFlagDefaultValue */
     );
 
     /**
@@ -363,7 +493,9 @@
             new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
                 new RegularPermission(Manifest.permission.FOREGROUND_SERVICE_REMOTE_MESSAGING)
             }, true),
-            null
+            null /* anyOfPermissions */,
+            FGS_TYPE_PERM_ENFORCEMENT_FLAG_REMOTE_MESSAGING /* permissionEnforcementFlag */,
+            true /* permissionEnforcementFlagDefaultValue */
     );
 
     /**
@@ -383,7 +515,9 @@
                 new RegularPermission(Manifest.permission.SCHEDULE_EXACT_ALARM),
                 new RegularPermission(Manifest.permission.USE_EXACT_ALARM),
                 new AppOpPermission(AppOpsManager.OP_ACTIVATE_VPN),
-            }, false)
+            }, false),
+            FGS_TYPE_PERM_ENFORCEMENT_FLAG_SYSTEM_EXEMPTED /* permissionEnforcementFlag */,
+            true /* permissionEnforcementFlagDefaultValue */
     );
 
     /**
@@ -396,7 +530,10 @@
             FOREGROUND_SERVICE_TYPE_SHORT_SERVICE,
             ForegroundServiceTypePolicyInfo.INVALID_CHANGE_ID,
             ForegroundServiceTypePolicyInfo.INVALID_CHANGE_ID,
-            null /* no type specific permissions */, null /* no type specific permissions */
+            null /* allOfPermissions */,
+            null /* anyOfPermissions */,
+            null /* permissionEnforcementFlag */,
+            false /* permissionEnforcementFlagDefaultValue */
     );
 
     /**
@@ -412,7 +549,9 @@
             new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
                 new RegularPermission(Manifest.permission.FOREGROUND_SERVICE_FILE_MANAGEMENT)
             }, true),
-            null
+            null /* anyOfPermissions */,
+            null /* permissionEnforcementFlag */,
+            false /* permissionEnforcementFlagDefaultValue */
     );
 
     /**
@@ -428,7 +567,9 @@
             new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
                 new RegularPermission(Manifest.permission.FOREGROUND_SERVICE_SPECIAL_USE)
             }, true),
-            null
+            null /* anyOfPermissions */,
+            FGS_TYPE_PERM_ENFORCEMENT_FLAG_SPECIAL_USE /* permissionEnforcementFlag */,
+            true /* permissionEnforcementFlagDefaultValue */
     );
 
     /**
@@ -512,6 +653,14 @@
             @NonNull String packageName, int callerUid, int callerPid, boolean allowWhileInUse,
             @NonNull ForegroundServiceTypePolicyInfo policy);
 
+    /**
+     * Run the given {@code policyFunctor} on the matching policy, if the flag is known
+     * to the policy.
+     *
+     * @hide
+     */
+    public abstract void updatePermissionEnforcementFlagIfNecessary(@NonNull String flag);
+
     @GuardedBy("sLock")
     private static ForegroundServiceTypePolicy sDefaultForegroundServiceTypePolicy = null;
 
@@ -575,11 +724,31 @@
         final @Nullable ForegroundServiceTypePermissions mAnyOfPermissions;
 
         /**
+         * A permission enforcement flag, unlike the {@link #FGS_TYPE_PERMISSION_CHANGE_ID},
+         * here it applies to all apps using this FGS type.
+         */
+        final @Nullable String mPermissionEnforcementFlag;
+
+        /**
+         * The default value to {@link #mPermissionEnforcementFlag}.
+         */
+        final boolean mPermissionEnforcementFlagDefaultValue;
+
+        /**
          * A customized check for the permissions.
          */
         @Nullable ForegroundServiceTypePermission mCustomPermission;
 
         /**
+         * The value of the permission enforcement flag, will be updated by the system.
+         * If the value is {@code false}, the FGS permission check will be ignored.
+         *
+         * <p>This value could be updated via the DeviceConfig flag specified
+         * in the {@link #mPermissionEnforcementFlag}.</p>
+         */
+        volatile boolean mPermissionEnforcementFlagValue;
+
+        /**
          * Not a real change id, but a place holder.
          */
         private static final long INVALID_CHANGE_ID = 0L;
@@ -599,12 +768,17 @@
         public ForegroundServiceTypePolicyInfo(@ForegroundServiceType int type,
                 long deprecationChangeId, long disabledChangeId,
                 @Nullable ForegroundServiceTypePermissions allOfPermissions,
-                @Nullable ForegroundServiceTypePermissions anyOfPermissions) {
+                @Nullable ForegroundServiceTypePermissions anyOfPermissions,
+                @Nullable String permissionEnforcementFlag,
+                boolean permissionEnforcementFlagDefaultValue) {
             mType = type;
             mDeprecationChangeId = deprecationChangeId;
             mDisabledChangeId = disabledChangeId;
             mAllOfPermissions = allOfPermissions;
             mAnyOfPermissions = anyOfPermissions;
+            mPermissionEnforcementFlag = permissionEnforcementFlag;
+            mPermissionEnforcementFlagDefaultValue = permissionEnforcementFlagDefaultValue;
+            mPermissionEnforcementFlagValue = permissionEnforcementFlagDefaultValue;
         }
 
         /**
@@ -650,6 +824,17 @@
             return sb;
         }
 
+        private void updatePermissionEnforcementFlagIfNecessary(@NonNull String flagName) {
+            if (mPermissionEnforcementFlag == null
+                    || !TextUtils.equals(flagName, mPermissionEnforcementFlag)) {
+                return;
+            }
+            mPermissionEnforcementFlagValue = DeviceConfig.getBoolean(
+                    DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                    mPermissionEnforcementFlag,
+                    mPermissionEnforcementFlagDefaultValue);
+        }
+
         /**
          * @hide
          */
@@ -745,6 +930,15 @@
                         ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
             platformCompat.clearOverrideForTest(changeId, packageName);
         }
+
+        /**
+         * For test only.
+         *
+         * @return The permission enforcement flag.
+         */
+        public @Nullable String getPermissionEnforcementFlagForTest() {
+            return mPermissionEnforcementFlag;
+        }
     }
 
     /**
@@ -991,6 +1185,12 @@
                 new SparseArray<>();
 
         /**
+         * The map between permission enforcement flag to its permission policy info.
+         */
+        private final ArrayMap<String, ForegroundServiceTypePolicyInfo>
+                mPermissionEnforcementToPolicyInfoMap = new ArrayMap<>();
+
+        /**
          * Constructor
          */
         public DefaultForegroundServiceTypePolicy() {
@@ -1022,10 +1222,15 @@
                     FGS_TYPE_POLICY_SYSTEM_EXEMPTED);
             mForegroundServiceTypePolicies.put(FOREGROUND_SERVICE_TYPE_SHORT_SERVICE,
                     FGS_TYPE_POLICY_SHORT_SERVICE);
-            mForegroundServiceTypePolicies.put(FOREGROUND_SERVICE_TYPE_FILE_MANAGEMENT,
-                    FGS_TYPE_POLICY_FILE_MANAGEMENT);
+            // TODO (b/271950506): revisit it in the next release.
+            // Hide the file management type for now. If anyone uses it, will default to "none".
             mForegroundServiceTypePolicies.put(FOREGROUND_SERVICE_TYPE_SPECIAL_USE,
                     FGS_TYPE_POLICY_SPECIAL_USE);
+            for (int i = 0, size = mForegroundServiceTypePolicies.size(); i < size; i++) {
+                final ForegroundServiceTypePolicyInfo info =
+                        mForegroundServiceTypePolicies.valueAt(i);
+                mPermissionEnforcementToPolicyInfoMap.put(info.mPermissionEnforcementFlag, info);
+            }
         }
 
         @Override
@@ -1078,8 +1283,8 @@
                 }
             }
             if (permissionResult != PERMISSION_GRANTED) {
-                return (CompatChanges.isChangeEnabled(
-                        FGS_TYPE_PERMISSION_CHANGE_ID, callerUid))
+                return policy.mPermissionEnforcementFlagValue
+                        && (CompatChanges.isChangeEnabled(FGS_TYPE_PERMISSION_CHANGE_ID, callerUid))
                         ? FGS_TYPE_POLICY_CHECK_PERMISSION_DENIED_ENFORCED
                         : FGS_TYPE_POLICY_CHECK_PERMISSION_DENIED_PERMISSIVE;
             }
@@ -1089,5 +1294,14 @@
             }
             return FGS_TYPE_POLICY_CHECK_OK;
         }
+
+        @Override
+        public void updatePermissionEnforcementFlagIfNecessary(@NonNull String flagName) {
+            final ForegroundServiceTypePolicyInfo info =
+                    mPermissionEnforcementToPolicyInfoMap.get(flagName);
+            if (info != null) {
+                info.updatePermissionEnforcementFlagIfNecessary(flagName);
+            }
+        }
     }
 }
diff --git a/core/java/android/app/IActivityClientController.aidl b/core/java/android/app/IActivityClientController.aidl
index 5136b20..a3c5e1c 100644
--- a/core/java/android/app/IActivityClientController.aidl
+++ b/core/java/android/app/IActivityClientController.aidl
@@ -181,4 +181,14 @@
      * that started the task.
      */
     void enableTaskLocaleOverride(in IBinder token);
+
+    /**
+     * Return {@code true} if the activity was explicitly requested to be launched in the
+     * TaskFragment.
+     *
+     * @param activityToken The token of the Activity.
+     * @param taskFragmentToken The token of the TaskFragment.
+     */
+    boolean isRequestedToLaunchInTaskFragment(in IBinder activityToken,
+            in IBinder taskFragmentToken);
 }
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index f653e13..62298a5 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -341,12 +341,6 @@
             in String message, boolean force, int exceptionTypeId);
     void crashApplicationWithTypeWithExtras(int uid, int initialPid, in String packageName,
             int userId, in String message, boolean force, int exceptionTypeId, in Bundle extras);
-    /** @deprecated -- use getProviderMimeTypeAsync */
-    @UnsupportedAppUsage(maxTargetSdk = 29, publicAlternatives =
-            "Use {@link android.content.ContentResolver#getType} public API instead.")
-    String getProviderMimeType(in Uri uri, int userId);
-
-    oneway void getProviderMimeTypeAsync(in Uri uri, int userId, in RemoteCallback resultCallback);
     oneway void getMimeTypeFilterAsync(in Uri uri, int userId, in RemoteCallback resultCallback);
     // Cause the specified process to dump the specified heap.
     boolean dumpHeap(in String process, int userId, boolean managed, boolean mallocInfo,
@@ -876,11 +870,11 @@
     boolean shouldServiceTimeOut(in ComponentName className, in IBinder token);
 
     /** Logs start of an API call to associate with an FGS, used for FGS Type Metrics */
-    oneway void logFgsApiBegin(int apiType, int appUid, int appPid);
+    void logFgsApiBegin(int apiType, int appUid, int appPid);
 
     /** Logs stop of an API call to associate with an FGS, used for FGS Type Metrics */
-    oneway void logFgsApiEnd(int apiType, int appUid, int appPid);
+    void logFgsApiEnd(int apiType, int appUid, int appPid);
 
     /** Logs API state change to associate with an FGS, used for FGS Type Metrics */
-    oneway void logFgsApiStateChanged(int apiType, int state, int appUid, int appPid);
+    void logFgsApiStateChanged(int apiType, int state, int appUid, int appPid);
 }
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index dad9b43..6b5f6b0 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -95,7 +95,7 @@
     void processInBackground();
     @UnsupportedAppUsage
     void scheduleBindService(IBinder token,
-            in Intent intent, boolean rebind, int processState);
+            in Intent intent, boolean rebind, int processState, long bindSeq);
     @UnsupportedAppUsage
     void scheduleUnbindService(IBinder token,
             in Intent intent);
@@ -172,4 +172,5 @@
             in TranslationSpec targetSpec, in List<AutofillId> viewIds,
             in UiTranslationSpec uiTranslationSpec);
     void scheduleTimeoutService(IBinder token, int startId);
+    void schedulePing(in RemoteCallback pong);
 }
diff --git a/core/java/android/app/IUiModeManager.aidl b/core/java/android/app/IUiModeManager.aidl
index 2242224b..2345c27 100644
--- a/core/java/android/app/IUiModeManager.aidl
+++ b/core/java/android/app/IUiModeManager.aidl
@@ -17,6 +17,7 @@
 package android.app;
 
 import android.app.IOnProjectionStateChangedListener;
+import android.app.IUiModeManagerCallback;
 
 /**
  * Interface used to control special UI modes.
@@ -24,6 +25,11 @@
  */
 interface IUiModeManager {
     /**
+     * @hide
+     */
+    void addCallback(IUiModeManagerCallback callback);
+
+    /**
      * Enables the car mode. Only the system can do this.
      * @hide
      */
@@ -173,4 +179,9 @@
     * Returns currently set projection types.
     */
     int getActiveProjectionTypes();
+
+    /**
+    * Returns the contrast for the current user
+    */
+    float getContrast();
 }
diff --git a/core/java/android/app/StartLockscreenValidationRequest.aidl b/core/java/android/app/IUiModeManagerCallback.aidl
similarity index 68%
copy from core/java/android/app/StartLockscreenValidationRequest.aidl
copy to core/java/android/app/IUiModeManagerCallback.aidl
index 367dfee..47c18a8 100644
--- a/core/java/android/app/StartLockscreenValidationRequest.aidl
+++ b/core/java/android/app/IUiModeManagerCallback.aidl
@@ -16,5 +16,12 @@
 
 package android.app;
 
-/** {@hide} */
-parcelable StartLockscreenValidationRequest;
+/**
+* Implemented by the UiModeManager client to receive information about changes from the service.
+* This is a oneway interface since the server should not block waiting for the client.
+*
+* @hide
+*/
+oneway interface IUiModeManagerCallback {
+  void notifyContrastChanged(float contrast);
+}
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 5cad1ae..ac92811 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -93,7 +93,7 @@
 
     private static final String TAG = "Instrumentation";
 
-    private static final long CONNECT_TIMEOUT_MILLIS = 5000;
+    private static final long CONNECT_TIMEOUT_MILLIS = 60_000;
 
     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
 
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index be0d1c9..0ef8e92 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -146,13 +146,13 @@
     public static final String EXTRA_CHECKBOX_LABEL = "android.app.extra.CHECKBOX_LABEL";
 
     /**
-     * A {@link StartLockscreenValidationRequest} extra to be sent along with
+     * A {@link RemoteLockscreenValidationSession} extra to be sent along with
      * {@link #ACTION_CONFIRM_REMOTE_DEVICE_CREDENTIAL} containing the data needed to prompt for
      * a remote device's lock screen.
      * @hide
      */
-    public static final String EXTRA_START_LOCKSCREEN_VALIDATION_REQUEST =
-            "android.app.extra.START_LOCKSCREEN_VALIDATION_REQUEST";
+    public static final String EXTRA_REMOTE_LOCKSCREEN_VALIDATION_SESSION =
+            "android.app.extra.REMOTE_LOCKSCREEN_VALIDATION_SESSION";
 
     /**
      * Result code returned by the activity started by
@@ -359,8 +359,7 @@
     /**
      * Get an Intent to launch an activity to prompt the user to confirm the
      * credentials (pin, pattern or password) of a remote device.
-     * @param startLockscreenValidationRequest contains information necessary to start remote device
-     *                                         credential validation.
+     * @param session contains information necessary to start remote device credential validation.
      * @param remoteLockscreenValidationServiceComponent
      *          the {@link ComponentName} of the implementation of
      *          {@link android.service.remotelockscreenvalidation.RemoteLockscreenValidationService}
@@ -376,15 +375,14 @@
     @RequiresPermission(Manifest.permission.CHECK_REMOTE_LOCKSCREEN)
     @NonNull
     public Intent createConfirmDeviceCredentialForRemoteValidationIntent(
-            @NonNull StartLockscreenValidationRequest startLockscreenValidationRequest,
+            @NonNull RemoteLockscreenValidationSession session,
             @NonNull ComponentName remoteLockscreenValidationServiceComponent,
             @Nullable CharSequence title,
             @Nullable CharSequence description,
             @Nullable CharSequence checkboxLabel,
             @Nullable CharSequence alternateButtonLabel) {
         Intent intent = new Intent(ACTION_CONFIRM_REMOTE_DEVICE_CREDENTIAL)
-                .putExtra(
-                        EXTRA_START_LOCKSCREEN_VALIDATION_REQUEST, startLockscreenValidationRequest)
+                .putExtra(EXTRA_REMOTE_LOCKSCREEN_VALIDATION_SESSION, session)
                 .putExtra(Intent.EXTRA_COMPONENT_NAME, remoteLockscreenValidationServiceComponent)
                 .putExtra(EXTRA_TITLE, title)
                 .putExtra(EXTRA_DESCRIPTION, description)
@@ -1157,7 +1155,7 @@
     @SystemApi
     @RequiresPermission(Manifest.permission.CHECK_REMOTE_LOCKSCREEN)
     @NonNull
-    public StartLockscreenValidationRequest startRemoteLockscreenValidation() {
+    public RemoteLockscreenValidationSession startRemoteLockscreenValidation() {
         return mLockPatternUtils.startRemoteLockscreenValidation();
     }
 
@@ -1165,11 +1163,10 @@
      * Verifies credentials guess from a remote device.
      *
      * <p>Secret must be encrypted using {@code SecureBox} library
-     * with public key from {@code StartLockscreenValidationRequest}
+     * with public key from {@code RemoteLockscreenValidationSession}
      * and header set to {@code "encrypted_remote_credentials"} in UTF-8 encoding.
      *
-     * @throws IllegalStateException if there is no active lock screen validation session or
-     * there was a decryption error.
+     * @throws IllegalStateException if there was a decryption error.
      *
      * @hide
      */
diff --git a/core/java/android/app/LocaleConfig.java b/core/java/android/app/LocaleConfig.java
index 69693fc..97cc706 100644
--- a/core/java/android/app/LocaleConfig.java
+++ b/core/java/android/app/LocaleConfig.java
@@ -38,7 +38,10 @@
 import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Locale;
 import java.util.Set;
 
@@ -55,10 +58,10 @@
  *
  * @attr ref android.R.styleable#LocaleConfig_Locale_name
  * @attr ref android.R.styleable#AndroidManifestApplication_localeConfig
- *
- * <p>For more information about the LocaleConfig overridden by the application, see
- * TODO(b/261528306): add link to guide
  */
+// Add following to last Note: when guide is written:
+// For more information about the LocaleConfig overridden by the application, see TODO(b/261528306):
+// add link to guide
 public class LocaleConfig implements Parcelable {
     private static final String TAG = "LocaleConfig";
     public static final String TAG_LOCALE_CONFIG = "locale-config";
@@ -263,6 +266,43 @@
             };
 
     /**
+     * Compare whether the LocaleConfig is the same.
+     *
+     * <p>If the elements of {@code mLocales} in LocaleConfig are the same but arranged in different
+     * positions, they are also considered to be the same LocaleConfig.
+     *
+     * @param other The {@link LocaleConfig} to compare for.
+     *
+     * @return true if the LocaleConfig is the same, false otherwise.
+     *
+     * @hide
+     */
+    public boolean isSameLocaleConfig(@Nullable LocaleConfig other) {
+        if (other == this) {
+            return true;
+        }
+
+        if (other != null) {
+            if (mStatus != other.mStatus) {
+                return false;
+            }
+            LocaleList otherLocales = other.mLocales;
+            if (mLocales == null && otherLocales == null) {
+                return true;
+            } else if (mLocales != null && otherLocales != null) {
+                List<String> hostStrList = Arrays.asList(mLocales.toLanguageTags().split(","));
+                List<String> targetStrList = Arrays.asList(
+                        otherLocales.toLanguageTags().split(","));
+                Collections.sort(hostStrList);
+                Collections.sort(targetStrList);
+                return hostStrList.equals(targetStrList);
+            }
+        }
+
+        return false;
+    }
+
+    /**
      * Compare whether the locale is existed in the {@code mLocales} of the LocaleConfig.
      *
      * @param locale The {@link Locale} to compare for.
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 91efa75..d2f2c3c 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -873,7 +873,7 @@
      * permission to your manifest, and use
      * {@link android.provider.Settings#ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT}.
      */
-    public boolean canSendFullScreenIntent() {
+    public boolean canUseFullScreenIntent() {
         final int result = PermissionChecker.checkPermissionForPreflight(mContext,
                 android.Manifest.permission.USE_FULL_SCREEN_INTENT,
                 mContext.getAttributionSource());
diff --git a/core/java/android/app/RemoteLockscreenValidationResult.java b/core/java/android/app/RemoteLockscreenValidationResult.java
index 0245f8c..bbb3567 100644
--- a/core/java/android/app/RemoteLockscreenValidationResult.java
+++ b/core/java/android/app/RemoteLockscreenValidationResult.java
@@ -55,10 +55,16 @@
      */
     public static final int RESULT_NO_REMAINING_ATTEMPTS = 4;
 
+    /**
+     * New lockscreen validation session is required to verify guess.
+     */
+    public static final int RESULT_SESSION_EXPIRED = 5;
+
     @IntDef({RESULT_GUESS_VALID,
             RESULT_GUESS_INVALID,
             RESULT_LOCKOUT,
-            RESULT_NO_REMAINING_ATTEMPTS})
+            RESULT_NO_REMAINING_ATTEMPTS,
+            RESULT_SESSION_EXPIRED})
     @Retention(RetentionPolicy.SOURCE)
     @interface ResultCode {}
 
diff --git a/core/java/android/app/StartLockscreenValidationRequest.aidl b/core/java/android/app/RemoteLockscreenValidationSession.aidl
similarity index 93%
rename from core/java/android/app/StartLockscreenValidationRequest.aidl
rename to core/java/android/app/RemoteLockscreenValidationSession.aidl
index 367dfee..edc8d56 100644
--- a/core/java/android/app/StartLockscreenValidationRequest.aidl
+++ b/core/java/android/app/RemoteLockscreenValidationSession.aidl
@@ -17,4 +17,4 @@
 package android.app;
 
 /** {@hide} */
-parcelable StartLockscreenValidationRequest;
+parcelable RemoteLockscreenValidationSession;
diff --git a/core/java/android/app/StartLockscreenValidationRequest.java b/core/java/android/app/RemoteLockscreenValidationSession.java
similarity index 69%
rename from core/java/android/app/StartLockscreenValidationRequest.java
rename to core/java/android/app/RemoteLockscreenValidationSession.java
index e818195..c6592e3 100644
--- a/core/java/android/app/StartLockscreenValidationRequest.java
+++ b/core/java/android/app/RemoteLockscreenValidationSession.java
@@ -30,44 +30,45 @@
  * @hide
  */
 @SystemApi
-public final class StartLockscreenValidationRequest implements Parcelable {
+public final class RemoteLockscreenValidationSession implements Parcelable {
 
     @LockTypes
-    private int mLockscreenUiType;
+    private int mLockType;
 
     private byte[] mSourcePublicKey;
 
     private int mRemainingAttempts;
 
-    public static final @NonNull Parcelable.Creator<StartLockscreenValidationRequest> CREATOR = new
-            Parcelable.Creator<StartLockscreenValidationRequest>() {
+    public static final @NonNull Parcelable.Creator<RemoteLockscreenValidationSession> CREATOR = new
+            Parcelable.Creator<RemoteLockscreenValidationSession>() {
         @Override
-        public StartLockscreenValidationRequest createFromParcel(Parcel source) {
-            return new StartLockscreenValidationRequest(source);
+        public RemoteLockscreenValidationSession createFromParcel(Parcel source) {
+            return new RemoteLockscreenValidationSession(source);
         }
 
         @Override
-        public StartLockscreenValidationRequest[] newArray(int size) {
-            return new StartLockscreenValidationRequest[size];
+        public RemoteLockscreenValidationSession[] newArray(int size) {
+            return new RemoteLockscreenValidationSession[size];
         }
     };
 
 
     /**
-     * Builder for {@code StartLockscreenValidationRequest}
+     * Builder for {@code RemoteLockscreenValidationSession}
      */
     public static final class Builder {
-        private StartLockscreenValidationRequest mInstance = new StartLockscreenValidationRequest();
+        private RemoteLockscreenValidationSession mInstance =
+                new RemoteLockscreenValidationSession();
 
         /**
          * Sets UI type.
          * Default value is {@code LockTypes.PASSWORD}
          *
-         * @param lockscreenUiType The UI format
+         * @param lockType The UI format
          * @return This builder.
          */
-        public @NonNull Builder setLockscreenUiType(@LockTypes int lockscreenUiType) {
-            mInstance.mLockscreenUiType = lockscreenUiType;
+        public @NonNull Builder setLockType(@LockTypes int lockType) {
+            mInstance.mLockType = lockType;
             return this;
         }
 
@@ -92,11 +93,11 @@
         }
 
         /**
-         * Creates {@code StartLockscreenValidationRequest}
+         * Creates {@code RemoteLockscreenValidationSession}
          *
          * @throws NullPointerException if required fields are not set.
          */
-        public @NonNull StartLockscreenValidationRequest build() {
+        public @NonNull RemoteLockscreenValidationSession build() {
             Objects.requireNonNull(mInstance.mSourcePublicKey);
             return mInstance;
         }
@@ -105,8 +106,8 @@
     /**
      * Specifies lock screen credential type.
      */
-    public @LockTypes int getLockscreenUiType() {
-        return mLockscreenUiType;
+    public @LockTypes int getLockType() {
+        return mLockType;
     }
 
     /**
@@ -127,16 +128,16 @@
 
     @Override
     public void writeToParcel(@NonNull Parcel out, int flags) {
-        out.writeInt(mLockscreenUiType);
+        out.writeInt(mLockType);
         out.writeByteArray(mSourcePublicKey);
         out.writeInt(mRemainingAttempts);
     }
 
-    private StartLockscreenValidationRequest() {
+    private RemoteLockscreenValidationSession() {
     }
 
-    private StartLockscreenValidationRequest(Parcel in) {
-        mLockscreenUiType = in.readInt();
+    private RemoteLockscreenValidationSession(Parcel in) {
+        mLockType = in.readInt();
         mSourcePublicKey = in.createByteArray();
         mRemainingAttempts = in.readInt();
     }
diff --git a/core/java/android/app/StartForegroundCalledOnStoppedServiceException.java b/core/java/android/app/StartForegroundCalledOnStoppedServiceException.java
new file mode 100644
index 0000000..55885a6
--- /dev/null
+++ b/core/java/android/app/StartForegroundCalledOnStoppedServiceException.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Exception thrown when {@link Service#startForeground} is called on a service that's not
+ * actually started.
+ */
+public final class StartForegroundCalledOnStoppedServiceException
+        extends IllegalStateException implements Parcelable {
+    /**
+     * Constructor.
+     */
+    public StartForegroundCalledOnStoppedServiceException(@NonNull String message) {
+        super(message);
+    }
+
+    StartForegroundCalledOnStoppedServiceException(@NonNull Parcel source) {
+        super(source.readString());
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString(getMessage());
+    }
+
+    public static final @NonNull Creator<StartForegroundCalledOnStoppedServiceException>
+            CREATOR = new Creator<StartForegroundCalledOnStoppedServiceException>() {
+                @NonNull
+                public StartForegroundCalledOnStoppedServiceException createFromParcel(
+                        Parcel source) {
+                    return new StartForegroundCalledOnStoppedServiceException(source);
+                }
+
+                @NonNull
+                public StartForegroundCalledOnStoppedServiceException[] newArray(int size) {
+                    return new StartForegroundCalledOnStoppedServiceException[size];
+                }
+            };
+}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 6d80a44..dbba0c6 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -509,7 +509,7 @@
                 new ServiceFetcher<InputManager>() {
             @Override
             public InputManager getService(ContextImpl ctx) {
-                return InputManager.getInstance(ctx);
+                return InputManager.getInstance(ctx.getOuterContext());
             }});
 
         registerService(Context.DISPLAY_SERVICE, DisplayManager.class,
@@ -877,6 +877,10 @@
             @Override
             public VirtualDeviceManager createService(ContextImpl ctx)
                     throws ServiceNotFoundException {
+                if (!ctx.getPackageManager().hasSystemFeature(
+                        PackageManager.FEATURE_COMPANION_DEVICE_SETUP)) {
+                    return null;
+                }
                 IVirtualDeviceManager service = IVirtualDeviceManager.Stub.asInterface(
                         ServiceManager.getServiceOrThrow(Context.VIRTUAL_DEVICE_SERVICE));
                 return new VirtualDeviceManager(service, ctx.getOuterContext());
@@ -1648,6 +1652,7 @@
                 case Context.ETHERNET_SERVICE:
                 case Context.CONTEXTHUB_SERVICE:
                 case Context.VIRTUALIZATION_SERVICE:
+                case Context.VIRTUAL_DEVICE_SERVICE:
                     return null;
             }
             Slog.wtf(TAG, "Manager wrapper not available: " + name);
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index 5a2f261..303ada0 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -453,6 +453,7 @@
                 && Objects.equals(shouldDockBigOverlays, that.shouldDockBigOverlays)
                 && Objects.equals(displayCutoutInsets, that.displayCutoutInsets)
                 && getWindowingMode() == that.getWindowingMode()
+                && configuration.uiMode == that.configuration.uiMode
                 && Objects.equals(taskDescription, that.taskDescription)
                 && isFocused == that.isFocused
                 && isVisible == that.isVisible
@@ -481,6 +482,7 @@
                     .equals(that.configuration.windowConfiguration.getBounds()))
                 && (!hasCompatUI() || configuration.getLayoutDirection()
                     == that.configuration.getLayoutDirection())
+                && (!hasCompatUI() || configuration.uiMode == that.configuration.uiMode)
                 && (!hasCompatUI() || isVisible == that.isVisible);
     }
 
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
index ecab37d..d90257a 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -17,6 +17,7 @@
 package android.app;
 
 import android.annotation.CallbackExecutor;
+import android.annotation.FloatRange;
 import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
@@ -34,6 +35,7 @@
 import android.os.ServiceManager.ServiceNotFoundException;
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.util.Log;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
@@ -43,10 +45,13 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
 import java.time.LocalTime;
+import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.Executor;
+import java.util.stream.Stream;
 
 /**
  * This class provides access to the system uimode services.  These services
@@ -72,6 +77,10 @@
  */
 @SystemService(Context.UI_MODE_SERVICE)
 public class UiModeManager {
+
+    private static final String TAG = "UiModeManager";
+
+
     /**
      * A listener with a single method that is invoked whenever the packages projecting using the
      * {@link ProjectionType}s for which it is registered change.
@@ -91,7 +100,20 @@
                 @NonNull Set<String> packageNames);
     }
 
-    private static final String TAG = "UiModeManager";
+    /**
+     * Listener for the UI contrast. To listen for changes to
+     * the UI contrast on the device, implement this interface and
+     * register it with the system by calling {@link #addContrastChangeListener}.
+     */
+    public interface ContrastChangeListener {
+
+        /**
+         * Called when the color contrast enabled state changes.
+         *
+         * @param contrast The color contrast as in {@link #getContrast}
+         */
+        void onContrastChanged(@FloatRange(from = -1.0f, to = 1.0f) float contrast);
+    }
 
     /**
      * Broadcast sent when the device's UI has switched to car mode, either
@@ -319,6 +341,95 @@
             mOnProjectionStateChangedListenerResourceManager =
             new OnProjectionStateChangedListenerResourceManager();
 
+    /**
+     * Define constants and conversions between {@link ContrastLevel}s and contrast values.
+     * <p>
+     * Contrast values are floats defined in [-1, 1], as defined in {@link #getContrast}.
+     * This is the official data type for contrast;
+     * all methods from the public API return contrast values.
+     * </p>
+     * <p>
+     * {@code ContrastLevel}, on the other hand, is an internal-only enumeration of contrasts that
+     * can be set from the system ui. Each {@code ContrastLevel} has an associated contrast value.
+     * </p>
+     * <p>
+     * Currently, a user chan chose from three contrast levels:
+     * <ul>
+     *     <li>{@link #CONTRAST_LEVEL_STANDARD}, corresponding to the default contrast value 0f</li>
+     *     <li>{@link #CONTRAST_LEVEL_MEDIUM}, corresponding to the contrast value 0.5f</li>
+     *     <li>{@link #CONTRAST_LEVEL_HIGH}, corresponding to the maximum contrast value 1f</li>
+     * </ul>
+     * </p>
+     *
+     * @hide
+     */
+    public static class ContrastUtils {
+
+        private static final float CONTRAST_MIN_VALUE = -1f;
+        private static final float CONTRAST_MAX_VALUE = 1f;
+        public static final float CONTRAST_DEFAULT_VALUE = 0f;
+
+        @IntDef(flag = true, prefix = { "CONTRAST_LEVEL_" }, value = {
+                CONTRAST_LEVEL_STANDARD,
+                CONTRAST_LEVEL_MEDIUM,
+                CONTRAST_LEVEL_HIGH
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface ContrastLevel {}
+
+        public static final int CONTRAST_LEVEL_STANDARD = 0;
+        public static final int CONTRAST_LEVEL_MEDIUM = 1;
+        public static final int CONTRAST_LEVEL_HIGH = 2;
+
+        private static Stream<Integer> allContrastLevels() {
+            return Stream.of(CONTRAST_LEVEL_STANDARD, CONTRAST_LEVEL_MEDIUM, CONTRAST_LEVEL_HIGH);
+        }
+
+        /**
+         * Convert a contrast value in [-1, 1] to its associated {@link ContrastLevel}
+         */
+        public static @ContrastLevel int toContrastLevel(float contrast) {
+            if (contrast < CONTRAST_MIN_VALUE || contrast > CONTRAST_MAX_VALUE) {
+                throw new IllegalArgumentException("contrast values should be in [-1, 1]");
+            }
+            return allContrastLevels().min(Comparator.comparingDouble(contrastLevel ->
+                    Math.abs(contrastLevel - 2 * contrast))).orElseThrow();
+        }
+
+        /**
+         * Convert a {@link ContrastLevel} to its associated contrast value in [-1, 1]
+         */
+        public static float fromContrastLevel(@ContrastLevel int contrastLevel) {
+            if (allContrastLevels().noneMatch(level -> level == contrastLevel)) {
+                throw new IllegalArgumentException("unrecognized contrast level: " + contrastLevel);
+            }
+            return contrastLevel / 2f;
+        }
+    }
+
+    /**
+     * Map that stores user provided {@link ContrastChangeListener} callbacks,
+     * and the executors on which these callbacks should be called.
+     */
+    private final ArrayMap<ContrastChangeListener, Executor>
+            mContrastChangeListeners = new ArrayMap<>();
+    private float mContrast;
+
+    private final IUiModeManagerCallback.Stub mCallback = new IUiModeManagerCallback.Stub() {
+        @Override
+        public void notifyContrastChanged(float contrast) {
+            final ArrayMap<ContrastChangeListener, Executor> listeners;
+            synchronized (mLock) {
+                // if value changed in the settings, update the cached value and notify listeners
+                if (Math.abs(mContrast - contrast) < 1e-10) return;
+                mContrast = contrast;
+                listeners = new ArrayMap<>(mContrastChangeListeners);
+            }
+            listeners.forEach((listener, executor) -> executor.execute(
+                    () -> listener.onContrastChanged(mContrast)));
+        }
+    };
+
     @UnsupportedAppUsage
     /*package*/ UiModeManager() throws ServiceNotFoundException {
         this(null /* context */);
@@ -328,6 +439,12 @@
         mService = IUiModeManager.Stub.asInterface(
                 ServiceManager.getServiceOrThrow(Context.UI_MODE_SERVICE));
         mContext = context;
+        try {
+            mService.addCallback(mCallback);
+            mContrast = mService.getContrast();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Setup failed: UiModeManagerService is dead", e);
+        }
     }
 
     /**
@@ -1067,4 +1184,56 @@
             return mExecutorMap.get(innerListener);
         }
     }
+
+    /**
+     * Returns the color contrast for the user.
+     * <p>
+     * <strong>Note:</strong> You need to query this only if your application is
+     * doing its own rendering and does not rely on the material rendering pipeline.
+     * </p>
+     * @return The color contrast, float in [-1, 1] where
+     * <ul>
+     *     <li> &nbsp; 0 corresponds to the default contrast </li>
+     *     <li>       -1 corresponds to the minimum contrast </li>
+     *     <li> &nbsp; 1 corresponds to the maximum contrast </li>
+     * </ul>
+     *
+     *
+     *
+     */
+    @FloatRange(from = -1.0f, to = 1.0f)
+    public float getContrast() {
+        synchronized (mLock) {
+            return mContrast;
+        }
+    }
+
+    /**
+     * Registers a {@link ContrastChangeListener} for the current user.
+     *
+     * @param executor The executor on which the listener should be called back.
+     * @param listener The listener.
+     */
+    public void addContrastChangeListener(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull ContrastChangeListener listener) {
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(listener);
+        synchronized (mLock) {
+            mContrastChangeListeners.put(listener, executor);
+        }
+    }
+
+    /**
+     * Unregisters a {@link ContrastChangeListener} for the current user.
+     * If the listener was not registered, does nothing and returns.
+     *
+     * @param listener The listener to unregister.
+     */
+    public void removeContrastChangeListener(@NonNull ContrastChangeListener listener) {
+        Objects.requireNonNull(listener);
+        synchronized (mLock) {
+            mContrastChangeListeners.remove(listener);
+        }
+    }
 }
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index 39d77c4..5b95503 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -875,15 +875,6 @@
     }
 
     /**
-     * Returns true if any visible windows belonging to apps with this window configuration should
-     * be kept on screen when the app is killed due to something like the low memory killer.
-     * @hide
-     */
-    public boolean keepVisibleDeadAppWindowOnScreen() {
-        return mWindowingMode != WINDOWING_MODE_PINNED;
-    }
-
-    /**
      * Returns true if the backdrop on the client side should match the frame of the window.
      * Returns false, if the backdrop should be fullscreen.
      * @hide
diff --git a/core/java/android/app/admin/DevicePolicyCache.java b/core/java/android/app/admin/DevicePolicyCache.java
index 3957732..b6e83c8 100644
--- a/core/java/android/app/admin/DevicePolicyCache.java
+++ b/core/java/android/app/admin/DevicePolicyCache.java
@@ -19,6 +19,9 @@
 
 import com.android.server.LocalServices;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Stores a copy of the set of device policies maintained by {@link DevicePolicyManager} that
  * can be accessed from any place without risking dead locks.
@@ -61,6 +64,12 @@
     public abstract boolean canAdminGrantSensorsPermissions();
 
     /**
+     * Returns a list of package names for which all launcher shortcuts should be modified to be
+     * launched in the managed profile and badged accordingly.
+     */
+    public abstract List<String> getLauncherShortcutOverrides();
+
+    /**
      * Empty implementation.
      */
     private static class EmptyDevicePolicyCache extends DevicePolicyCache {
@@ -85,5 +94,9 @@
         public boolean canAdminGrantSensorsPermissions() {
             return false;
         }
+        @Override
+        public List<String> getLauncherShortcutOverrides() {
+            return new ArrayList<>();
+        }
     }
 }
diff --git a/core/java/android/app/admin/PolicyUpdateReceiver.java b/core/java/android/app/admin/PolicyUpdateReceiver.java
index b5d9286..be13988 100644
--- a/core/java/android/app/admin/PolicyUpdateReceiver.java
+++ b/core/java/android/app/admin/PolicyUpdateReceiver.java
@@ -238,7 +238,7 @@
      *                               needed.
      * @param targetUser The {@link TargetUser} which this policy relates to.
      * @param policyUpdateResult Indicates whether the policy has been set successfully
-     *                           ({@link PolicyUpdateResult#RESULT_SUCCESS}) or the reason it
+     *                           ({@link PolicyUpdateResult#RESULT_POLICY_SET}) or the reason it
      *                           failed to apply (e.g.
      *                           {@link PolicyUpdateResult#RESULT_FAILURE_CONFLICTING_ADMIN_POLICY},
      *                           etc).
@@ -271,8 +271,8 @@
      *                               needed.
      * @param targetUser The {@link TargetUser} which this policy relates to.
      * @param policyUpdateResult Indicates the reason the policy value has changed
-     *                           (e.g. {@link PolicyUpdateResult#RESULT_SUCCESS} if the policy has
-     *                           changed to the value set by the admin,
+     *                           (e.g. {@link PolicyUpdateResult#RESULT_POLICY_SET} if the policy
+     *                           has changed to the value set by the admin,
      *                           {@link PolicyUpdateResult#RESULT_FAILURE_CONFLICTING_ADMIN_POLICY}
      *                           if the policy has changed because another admin has set a
      *                           conflicting policy, etc)
diff --git a/core/java/android/app/admin/PolicyUpdateResult.java b/core/java/android/app/admin/PolicyUpdateResult.java
index 7d7d91a..414c6ed 100644
--- a/core/java/android/app/admin/PolicyUpdateResult.java
+++ b/core/java/android/app/admin/PolicyUpdateResult.java
@@ -39,7 +39,7 @@
      * Result code to indicate that the policy has been changed to the desired value set by
      * the admin.
      */
-    public static final int RESULT_SUCCESS = 0;
+    public static final int RESULT_POLICY_SET = 0;
 
     /**
      * Result code to indicate that the policy has not been enforced or has changed because another
@@ -82,7 +82,7 @@
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = { "RESULT_" }, value = {
             RESULT_FAILURE_UNKNOWN,
-            RESULT_SUCCESS,
+            RESULT_POLICY_SET,
             RESULT_FAILURE_CONFLICTING_ADMIN_POLICY,
             RESULT_POLICY_CLEARED,
             RESULT_FAILURE_STORAGE_LIMIT_REACHED,
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index e750f49..5848521 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -1091,7 +1091,6 @@
      *
      * @hide
      */
-    @NonNull
     @SystemApi
     public void reportDelayedRestoreResult(@NonNull BackupRestoreEventLogger logger) {
         checkServiceBinder();
diff --git a/core/java/android/app/backup/BackupRestoreEventLogger.java b/core/java/android/app/backup/BackupRestoreEventLogger.java
index c4ff892..ea31ef3 100644
--- a/core/java/android/app/backup/BackupRestoreEventLogger.java
+++ b/core/java/android/app/backup/BackupRestoreEventLogger.java
@@ -47,7 +47,7 @@
  * @hide
  */
 @SystemApi
-public class BackupRestoreEventLogger {
+public final class BackupRestoreEventLogger {
     private static final String TAG = "BackupRestoreEventLogger";
 
     /**
@@ -61,6 +61,8 @@
     /**
      * Denotes that the annotated element identifies a data type as required by the logging methods
      * of {@code BackupRestoreEventLogger}
+     *
+     * @hide
      */
     @Retention(RetentionPolicy.SOURCE)
     public @interface BackupRestoreDataType {}
@@ -68,6 +70,8 @@
     /**
      * Denotes that the annotated element identifies an error type as required by the logging
      * methods of {@code BackupRestoreEventLogger}
+     *
+     * @hide
      */
     @Retention(RetentionPolicy.SOURCE)
     public @interface BackupRestoreError {}
@@ -144,7 +148,7 @@
      * @param dataType the type of data being backed up.
      * @param metaData the metadata associated with the data type.
      */
-    public void logBackupMetaData(@NonNull @BackupRestoreDataType String dataType,
+    public void logBackupMetadata(@NonNull @BackupRestoreDataType String dataType,
             @NonNull String metaData) {
         logMetaData(OperationType.BACKUP, dataType, metaData);
     }
diff --git a/core/java/android/app/backup/BackupTransport.java b/core/java/android/app/backup/BackupTransport.java
index f56c8c3..dcac59c 100644
--- a/core/java/android/app/backup/BackupTransport.java
+++ b/core/java/android/app/backup/BackupTransport.java
@@ -656,11 +656,14 @@
     }
 
     /**
-     * Ask the transport for a {@link IBackupManagerMonitor} instance which will be used by the
+     * Ask the transport for a {@link BackupManagerMonitor} instance which will be used by the
      * framework to report logging events back to the transport.
      *
      * <p>Backups requested from outside the framework may pass in a monitor with the request,
      * however backups initiated by the framework will call this method to retrieve one.
+     *
+     * @return {@link BackupManagerMonitor} or {@code null} if the transport implementation does not
+     *         wish to receive the logging events.
      */
     @Nullable
     public BackupManagerMonitor getBackupManagerMonitor() {
diff --git a/core/java/android/app/search/SearchTargetEvent.java b/core/java/android/app/search/SearchTargetEvent.java
index d4915af..e8ef922 100644
--- a/core/java/android/app/search/SearchTargetEvent.java
+++ b/core/java/android/app/search/SearchTargetEvent.java
@@ -50,7 +50,9 @@
             ACTION_LAUNCH_TOUCH,
             ACTION_LAUNCH_KEYBOARD_FOCUS,
             ACTION_DRAGNDROP,
-            ACTION_SURFACE_INVISIBLE
+            ACTION_SURFACE_INVISIBLE,
+            ACTION_DELETE,
+            ACTION_DISMISS
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ActionType {}
@@ -114,6 +116,16 @@
      */
     public static final int ACTION_SURFACE_INVISIBLE = 8;
 
+     /**
+     * Constant that defines user deleted a target.
+     */
+    public static final int ACTION_DELETE = 9;
+
+    /**
+     * Constant that defines user dismissed a target.
+     */
+    public static final int ACTION_DISMISS = 10;
+
     private SearchTargetEvent(@NonNull List<String> targetIds,
             @Nullable String location,
             @ActionType int actionType,
diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java
index 3d0aa25..5833f1b 100644
--- a/core/java/android/app/servertransaction/LaunchActivityItem.java
+++ b/core/java/android/app/servertransaction/LaunchActivityItem.java
@@ -96,11 +96,11 @@
             PendingTransactionActions pendingActions) {
         Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
         ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
-                mOverrideConfig, mDeviceId, mReferrer, mVoiceInteractor, mState, mPersistentState,
+                mOverrideConfig, mReferrer, mVoiceInteractor, mState, mPersistentState,
                 mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
                 client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble,
                 mTaskFragmentToken);
-        client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
+        client.handleLaunchActivity(r, pendingActions, mDeviceId, null /* customIntent */);
         Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
     }
 
diff --git a/core/java/android/app/servertransaction/TransactionExecutor.java b/core/java/android/app/servertransaction/TransactionExecutor.java
index c8f7d10..bfab61f 100644
--- a/core/java/android/app/servertransaction/TransactionExecutor.java
+++ b/core/java/android/app/servertransaction/TransactionExecutor.java
@@ -32,6 +32,7 @@
 
 import android.app.ActivityThread.ActivityClientRecord;
 import android.app.ClientTransactionHandler;
+import android.content.Context;
 import android.os.IBinder;
 import android.util.IntArray;
 import android.util.Slog;
@@ -218,7 +219,7 @@
             switch (state) {
                 case ON_CREATE:
                     mTransactionHandler.handleLaunchActivity(r, mPendingActions,
-                            null /* customIntent */);
+                            Context.DEVICE_ID_INVALID, null /* customIntent */);
                     break;
                 case ON_START:
                     mTransactionHandler.handleStartActivity(r, mPendingActions,
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index de4f619..a522cc0 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -801,6 +801,119 @@
     }
 
     /**
+     * Listener for any changes to {@link com.android.server.companion.transport.Transport}.
+     *
+     * @hide
+     */
+    public interface OnTransportsChangedListener {
+        /**
+         * Invoked when a change occurs to any of the transports
+         *
+         * @param associations all the associations which have connected transports
+         */
+        void onTransportsChanged(@NonNull List<AssociationInfo> associations);
+    }
+
+    /**
+     * Register a listener for any changes to
+     * {@link com.android.server.companion.transport.Transport}. Your app will receive a callback to
+     * {@link OnTransportsChangedListener} immediately with all the existing transports.
+     *
+     * @hide
+     */
+    public void addOnTransportsChangedListener(
+            @NonNull Executor executor, @NonNull OnTransportsChangedListener listener) {
+        final OnTransportsChangedListenerProxy proxy = new OnTransportsChangedListenerProxy(
+                executor, listener);
+        try {
+            mService.addOnTransportsChangedListener(proxy);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Unregister a listener to stop receiving any changes to
+     * {@link com.android.server.companion.transport.Transport}.
+     *
+     * @hide
+     */
+    public void removeOnTransportsChangedListener(
+            @NonNull OnTransportsChangedListener listener) {
+        final OnTransportsChangedListenerProxy proxy = new OnTransportsChangedListenerProxy(
+                null, listener);
+        try {
+            mService.removeOnTransportsChangedListener(proxy);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Send a message to remote devices
+     *
+     * @hide
+     */
+    public void sendMessage(int messageType, byte[] data, int[] associationIds) {
+        try {
+            mService.sendMessage(messageType, data, associationIds);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Listener when a message is received for the registered message type
+     *
+     * @see #addOnMessageReceivedListener(Executor, int, OnMessageReceivedListener)
+     *
+     * @hide
+     */
+    public interface OnMessageReceivedListener {
+        /**
+         * Called when a message is received
+         */
+        void onMessageReceived(int associationId, byte[] data);
+    }
+
+    /**
+     * Register a listener to receive callbacks when a message is received by the given type
+     *
+     * @see com.android.server.companion.transport.Transport for supported message types
+     *
+     * @hide
+     */
+    public void addOnMessageReceivedListener(@NonNull Executor executor, int messageType,
+            OnMessageReceivedListener listener) {
+        final OnMessageReceivedListenerProxy proxy = new OnMessageReceivedListenerProxy(
+                executor, listener);
+        try {
+            mService.addOnMessageReceivedListener(messageType, proxy);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Unregister a listener to stop receiving callbacks when a message is received by the given
+     * type
+     *
+     * @see com.android.server.companion.transport.Transport for supported message types
+     *
+     * @hide
+     */
+    public void removeOnMessageReceivedListener(int messageType,
+            OnMessageReceivedListener listener) {
+        final OnMessageReceivedListenerProxy proxy = new OnMessageReceivedListenerProxy(
+                null, listener);
+        try {
+            mService.removeOnMessageReceivedListener(messageType, proxy);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Checks whether the bluetooth device represented by the mac address was recently associated
      * with the companion app. This allows these devices to skip the Bluetooth pairing dialog if
      * their pairing variant is {@link BluetoothDevice#PAIRING_VARIANT_CONSENT}.
@@ -1277,6 +1390,40 @@
         }
     }
 
+    private static class OnTransportsChangedListenerProxy
+            extends IOnTransportsChangedListener.Stub {
+        private final Executor mExecutor;
+        private final OnTransportsChangedListener mListener;
+
+        private OnTransportsChangedListenerProxy(Executor executor,
+                OnTransportsChangedListener listener) {
+            mExecutor = executor;
+            mListener = listener;
+        }
+
+        @Override
+        public void onTransportsChanged(@NonNull List<AssociationInfo> associations) {
+            mExecutor.execute(() -> mListener.onTransportsChanged(associations));
+        }
+    }
+
+    private static class OnMessageReceivedListenerProxy
+            extends IOnMessageReceivedListener.Stub {
+        private final Executor mExecutor;
+        private final OnMessageReceivedListener mListener;
+
+        private OnMessageReceivedListenerProxy(Executor executor,
+                OnMessageReceivedListener listener) {
+            mExecutor = executor;
+            mListener = listener;
+        }
+
+        @Override
+        public void onMessageReceived(int associationId, byte[] data) {
+            mExecutor.execute(() -> mListener.onMessageReceived(associationId, data));
+        }
+    }
+
     private static class SystemDataTransferCallbackProxy extends ISystemDataTransferCallback.Stub {
         private final Executor mExecutor;
         private final OutcomeReceiver<Void, CompanionException> mCallback;
diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl
index cb4baca..b5e2670 100644
--- a/core/java/android/companion/ICompanionDeviceManager.aidl
+++ b/core/java/android/companion/ICompanionDeviceManager.aidl
@@ -19,6 +19,8 @@
 import android.app.PendingIntent;
 import android.companion.IAssociationRequestCallback;
 import android.companion.IOnAssociationsChangedListener;
+import android.companion.IOnMessageReceivedListener;
+import android.companion.IOnTransportsChangedListener;
 import android.companion.ISystemDataTransferCallback;
 import android.companion.AssociationInfo;
 import android.companion.AssociationRequest;
@@ -67,6 +69,16 @@
 
     void removeOnAssociationsChangedListener(IOnAssociationsChangedListener listener, int userId);
 
+    void addOnTransportsChangedListener(IOnTransportsChangedListener listener);
+
+    void removeOnTransportsChangedListener(IOnTransportsChangedListener listener);
+
+    void sendMessage(int messageType, in byte[] data, in int[] associationIds);
+
+    void addOnMessageReceivedListener(int messageType, IOnMessageReceivedListener listener);
+
+    void removeOnMessageReceivedListener(int messageType, IOnMessageReceivedListener listener);
+
     void notifyDeviceAppeared(int associationId);
 
     void notifyDeviceDisappeared(int associationId);
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl b/core/java/android/companion/IOnMessageReceivedListener.aidl
similarity index 70%
copy from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
copy to core/java/android/companion/IOnMessageReceivedListener.aidl
index 35d5c15..17f03f8 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
+++ b/core/java/android/companion/IOnMessageReceivedListener.aidl
@@ -10,10 +10,14 @@
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
+ * See the License for the specific language governing per  missions and
  * limitations under the License.
  */
 
-package android.net.wifi.sharedconnectivity.app;
+package android.companion;
 
-parcelable DeviceInfo;
\ No newline at end of file
+/** @hide */
+interface IOnMessageReceivedListener {
+
+    oneway void onMessageReceived(int associationId, in byte[] data);
+}
\ No newline at end of file
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl b/core/java/android/companion/IOnTransportsChangedListener.aidl
similarity index 66%
copy from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
copy to core/java/android/companion/IOnTransportsChangedListener.aidl
index 35d5c15..a101476 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
+++ b/core/java/android/companion/IOnTransportsChangedListener.aidl
@@ -10,10 +10,16 @@
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
+ * See the License for the specific language governing per  missions and
  * limitations under the License.
  */
 
-package android.net.wifi.sharedconnectivity.app;
+package android.companion;
 
-parcelable DeviceInfo;
\ No newline at end of file
+import android.companion.AssociationInfo;
+
+/** @hide */
+interface IOnTransportsChangedListener {
+
+    oneway void onTransportsChanged(in List<AssociationInfo> associations);
+}
\ No newline at end of file
diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java
index 4d2c7cb..90681cb 100644
--- a/core/java/android/companion/virtual/VirtualDeviceManager.java
+++ b/core/java/android/companion/virtual/VirtualDeviceManager.java
@@ -89,14 +89,6 @@
 
     private static final String TAG = "VirtualDeviceManager";
 
-    private static final int DEFAULT_VIRTUAL_DISPLAY_FLAGS =
-            DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC
-                    | DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT
-                    | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY
-                    | DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL
-                    | DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH
-                    | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_FOCUS;
-
     /**
      * Broadcast Action: A Virtual Device was removed.
      *
@@ -539,7 +531,11 @@
          * not create the virtual display.
          *
          * @see DisplayManager#createVirtualDisplay
+         *
+         * @deprecated use {@link #createVirtualDisplay(VirtualDisplayConfig, Executor,
+         * VirtualDisplay.Callback)}
          */
+        @Deprecated
         @Nullable
         public VirtualDisplay createVirtualDisplay(
                 @IntRange(from = 1) int width,
@@ -549,33 +545,20 @@
                 @VirtualDisplayFlag int flags,
                 @Nullable @CallbackExecutor Executor executor,
                 @Nullable VirtualDisplay.Callback callback) {
-            VirtualDisplayConfig config = new VirtualDisplayConfig.Builder(
+            VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
                     getVirtualDisplayName(), width, height, densityDpi)
-                    .setSurface(surface)
-                    .setFlags(getVirtualDisplayFlags(flags))
-                    .build();
-            return createVirtualDisplayInternal(config, executor, callback);
+                    .setFlags(flags);
+            if (surface != null) {
+                builder.setSurface(surface);
+            }
+            return createVirtualDisplay(builder.build(), executor, callback);
         }
 
         /**
          * Creates a virtual display for this virtual device. All displays created on the same
          * device belongs to the same display group.
          *
-         * @param width The width of the virtual display in pixels, must be greater than 0.
-         * @param height The height of the virtual display in pixels, must be greater than 0.
-         * @param densityDpi The density of the virtual display in dpi, must be greater than 0.
-         * @param displayCategories The categories of the virtual display, indicating the type of
-         * activities allowed to run on the display. Activities can declare their type using
-         * {@link android.content.pm.ActivityInfo#requiredDisplayCategory}.
-         * @param surface The surface to which the content of the virtual display should
-         * be rendered, or null if there is none initially. The surface can also be set later using
-         * {@link VirtualDisplay#setSurface(Surface)}.
-         * @param flags A combination of virtual display flags accepted by
-         * {@link DisplayManager#createVirtualDisplay}. In addition, the following flags are
-         * automatically set for all virtual devices:
-         * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PUBLIC VIRTUAL_DISPLAY_FLAG_PUBLIC} and
-         * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY
-         * VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY}.
+         * @param config The configuration of the display.
          * @param executor The executor on which {@code callback} will be invoked. This is ignored
          * if {@code callback} is {@code null}. If {@code callback} is specified, this executor must
          * not be null.
@@ -587,28 +570,6 @@
          */
         @Nullable
         public VirtualDisplay createVirtualDisplay(
-                @IntRange(from = 1) int width,
-                @IntRange(from = 1) int height,
-                @IntRange(from = 1) int densityDpi,
-                @NonNull List<String> displayCategories,
-                @Nullable Surface surface,
-                @VirtualDisplayFlag int flags,
-                @Nullable @CallbackExecutor Executor executor,
-                @Nullable VirtualDisplay.Callback callback) {
-            VirtualDisplayConfig config = new VirtualDisplayConfig.Builder(
-                    getVirtualDisplayName(), width, height, densityDpi)
-                    .setDisplayCategories(displayCategories)
-                    .setSurface(surface)
-                    .setFlags(getVirtualDisplayFlags(flags))
-                    .build();
-            return createVirtualDisplayInternal(config, executor, callback);
-        }
-
-        /**
-         * @hide
-         */
-        @Nullable
-        private VirtualDisplay createVirtualDisplayInternal(
                 @NonNull VirtualDisplayConfig config,
                 @Nullable @CallbackExecutor Executor executor,
                 @Nullable VirtualDisplay.Callback callback) {
@@ -897,16 +858,6 @@
             }
         }
 
-        /**
-         * Returns the display flags that should be added to a particular virtual display.
-         * Additional device-level flags from {@link
-         * com.android.server.companion.virtual.VirtualDeviceImpl#getBaseVirtualDisplayFlags()} will
-         * be added by DisplayManagerService.
-         */
-        private int getVirtualDisplayFlags(int flags) {
-            return DEFAULT_VIRTUAL_DISPLAY_FLAGS | flags;
-        }
-
         private String getVirtualDisplayName() {
             try {
                 // Currently this just use the device ID, which means all of the virtual displays
diff --git a/core/java/android/companion/virtual/VirtualDeviceParams.java b/core/java/android/companion/virtual/VirtualDeviceParams.java
index d8076b5..3a60a69 100644
--- a/core/java/android/companion/virtual/VirtualDeviceParams.java
+++ b/core/java/android/companion/virtual/VirtualDeviceParams.java
@@ -35,6 +35,7 @@
 import android.content.ComponentName;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.SharedMemory;
 import android.os.UserHandle;
 import android.util.ArraySet;
 import android.util.SparseArray;
@@ -139,7 +140,8 @@
      * a given policy type.
      * @hide
      */
-    @IntDef(prefix = "POLICY_TYPE_",  value = {POLICY_TYPE_SENSORS, POLICY_TYPE_AUDIO})
+    @IntDef(prefix = "POLICY_TYPE_", value = {POLICY_TYPE_SENSORS, POLICY_TYPE_AUDIO,
+            POLICY_TYPE_RECENTS})
     @Retention(RetentionPolicy.SOURCE)
     @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
     public @interface PolicyType {}
@@ -168,22 +170,21 @@
      *     <li>{@link #DEVICE_POLICY_CUSTOM}: audio framework will assign device specific session
      *     ids to players and recorders constructed within device context. The session ids are
      *     used to re-route corresponding audio streams to VirtualAudioDevice.
-     * <ul/>
+     * </ul>
      */
     public static final int POLICY_TYPE_AUDIO = 1;
 
-    /** @hide */
-    @IntDef(flag = true, prefix = "RECENTS_POLICY_",
-            value = {RECENTS_POLICY_ALLOW_IN_HOST_DEVICE_RECENTS})
-    @Retention(RetentionPolicy.SOURCE)
-    @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
-    public @interface RecentsPolicy {}
-
     /**
-     * If set, activities launched on this virtual device are allowed to appear in the host device
-     * of the recently launched activities list.
+     * Tells the activity manager how to handle recents entries for activities run on this device.
+     *
+     * <ul>
+     *     <li>{@link #DEVICE_POLICY_DEFAULT}: Activities launched on VirtualDisplays owned by this
+     *     device will appear in the host device recents.
+     *     <li>{@link #DEVICE_POLICY_CUSTOM}: Activities launched on VirtualDisplays owned by this
+     *      *     device will not appear in recents.
+     * </ul>
      */
-    public static final int RECENTS_POLICY_ALLOW_IN_HOST_DEVICE_RECENTS = 1 << 0;
+    public static final int POLICY_TYPE_RECENTS = 2;
 
     private final int mLockState;
     @NonNull private final ArraySet<UserHandle> mUsersWithMatchingAccounts;
@@ -200,8 +201,6 @@
     @NonNull private final SparseIntArray mDevicePolicies;
     @NonNull private final List<VirtualSensorConfig> mVirtualSensorConfigs;
     @Nullable private final IVirtualSensorCallback mVirtualSensorCallback;
-    @RecentsPolicy
-    private final int mDefaultRecentsPolicy;
     private final int mAudioPlaybackSessionId;
     private final int mAudioRecordingSessionId;
 
@@ -218,7 +217,6 @@
             @NonNull SparseIntArray devicePolicies,
             @NonNull List<VirtualSensorConfig> virtualSensorConfigs,
             @Nullable IVirtualSensorCallback virtualSensorCallback,
-            @RecentsPolicy int defaultRecentsPolicy,
             int audioPlaybackSessionId,
             int audioRecordingSessionId) {
         mLockState = lockState;
@@ -236,10 +234,8 @@
         mDevicePolicies = Objects.requireNonNull(devicePolicies);
         mVirtualSensorConfigs = Objects.requireNonNull(virtualSensorConfigs);
         mVirtualSensorCallback = virtualSensorCallback;
-        mDefaultRecentsPolicy = defaultRecentsPolicy;
         mAudioPlaybackSessionId = audioPlaybackSessionId;
         mAudioRecordingSessionId = audioRecordingSessionId;
-
     }
 
     @SuppressWarnings("unchecked")
@@ -258,7 +254,6 @@
         parcel.readTypedList(mVirtualSensorConfigs, VirtualSensorConfig.CREATOR);
         mVirtualSensorCallback =
                 IVirtualSensorCallback.Stub.asInterface(parcel.readStrongBinder());
-        mDefaultRecentsPolicy = parcel.readInt();
         mAudioPlaybackSessionId = parcel.readInt();
         mAudioRecordingSessionId = parcel.readInt();
     }
@@ -395,16 +390,6 @@
     }
 
     /**
-     * Returns the policy of how to handle activities in recents.
-     *
-     * @see RecentsPolicy
-     */
-    @RecentsPolicy
-    public int getDefaultRecentsPolicy() {
-        return mDefaultRecentsPolicy;
-    }
-
-    /**
      * Returns device-specific audio session id for playback.
      *
      * @see Builder#setAudioPlaybackSessionId(int)
@@ -442,7 +427,6 @@
         dest.writeTypedList(mVirtualSensorConfigs);
         dest.writeStrongBinder(
                 mVirtualSensorCallback != null ? mVirtualSensorCallback.asBinder() : null);
-        dest.writeInt(mDefaultRecentsPolicy);
         dest.writeInt(mAudioPlaybackSessionId);
         dest.writeInt(mAudioRecordingSessionId);
     }
@@ -477,7 +461,6 @@
                 && Objects.equals(mBlockedActivities, that.mBlockedActivities)
                 && mDefaultActivityPolicy == that.mDefaultActivityPolicy
                 && Objects.equals(mName, that.mName)
-                && mDefaultRecentsPolicy == that.mDefaultRecentsPolicy
                 && mAudioPlaybackSessionId == that.mAudioPlaybackSessionId
                 && mAudioRecordingSessionId == that.mAudioRecordingSessionId;
     }
@@ -488,7 +471,7 @@
                 mLockState, mUsersWithMatchingAccounts, mAllowedCrossTaskNavigations,
                 mBlockedCrossTaskNavigations, mDefaultNavigationPolicy, mAllowedActivities,
                 mBlockedActivities, mDefaultActivityPolicy, mName, mDevicePolicies,
-                mDefaultRecentsPolicy, mAudioPlaybackSessionId, mAudioRecordingSessionId);
+                mAudioPlaybackSessionId, mAudioRecordingSessionId);
         for (int i = 0; i < mDevicePolicies.size(); i++) {
             hashCode = 31 * hashCode + mDevicePolicies.keyAt(i);
             hashCode = 31 * hashCode + mDevicePolicies.valueAt(i);
@@ -510,7 +493,6 @@
                 + " mDefaultActivityPolicy=" + mDefaultActivityPolicy
                 + " mName=" + mName
                 + " mDevicePolicies=" + mDevicePolicies
-                + " mDefaultRecentsPolicy=" + mDefaultRecentsPolicy
                 + " mAudioPlaybackSessionId=" + mAudioPlaybackSessionId
                 + " mAudioRecordingSessionId=" + mAudioRecordingSessionId
                 + ")";
@@ -547,7 +529,6 @@
         private boolean mDefaultActivityPolicyConfigured = false;
         @Nullable private String mName;
         @NonNull private SparseIntArray mDevicePolicies = new SparseIntArray();
-        private int mDefaultRecentsPolicy;
         private int mAudioPlaybackSessionId = AUDIO_SESSION_ID_GENERATE;
         private int mAudioRecordingSessionId = AUDIO_SESSION_ID_GENERATE;
 
@@ -577,6 +558,25 @@
                 mExecutor.execute(() -> mCallback.onConfigurationChanged(
                         sensor, enabled, samplingPeriod, batchReportingLatency));
             }
+
+            @Override
+            public void onDirectChannelCreated(int channelHandle,
+                    @NonNull SharedMemory sharedMemory) {
+                mExecutor.execute(
+                        () -> mCallback.onDirectChannelCreated(channelHandle, sharedMemory));
+            }
+
+            @Override
+            public void onDirectChannelDestroyed(int channelHandle) {
+                mExecutor.execute(() -> mCallback.onDirectChannelDestroyed(channelHandle));
+            }
+
+            @Override
+            public void onDirectChannelConfigured(int channelHandle, @NonNull VirtualSensor sensor,
+                    int rateLevel, int reportToken) {
+                mExecutor.execute(() -> mCallback.onDirectChannelConfigured(
+                        channelHandle, sensor, rateLevel, reportToken));
+            }
         }
 
         /**
@@ -801,17 +801,6 @@
         }
 
         /**
-         * Sets the policy to indicate how activities are handled in recents.
-         *
-         * @param defaultRecentsPolicy A policy specifying how to handle activities in recents.
-         */
-        @NonNull
-        public Builder setDefaultRecentsPolicy(@RecentsPolicy int defaultRecentsPolicy) {
-            mDefaultRecentsPolicy = defaultRecentsPolicy;
-            return this;
-        }
-
-        /**
          * Sets audio playback session id specific for this virtual device.
          *
          * <p>Audio players constructed within context associated with this virtual device
@@ -913,7 +902,6 @@
                     mDevicePolicies,
                     mVirtualSensorConfigs,
                     mVirtualSensorCallback,
-                    mDefaultRecentsPolicy,
                     mAudioPlaybackSessionId,
                     mAudioRecordingSessionId);
         }
diff --git a/core/java/android/companion/virtual/sensor/IVirtualSensorCallback.aidl b/core/java/android/companion/virtual/sensor/IVirtualSensorCallback.aidl
index 7da9c32..3cb0572 100644
--- a/core/java/android/companion/virtual/sensor/IVirtualSensorCallback.aidl
+++ b/core/java/android/companion/virtual/sensor/IVirtualSensorCallback.aidl
@@ -17,6 +17,7 @@
 package android.companion.virtual.sensor;
 
 import android.companion.virtual.sensor.VirtualSensor;
+import android.os.SharedMemory;
 
 /**
  * Interface for notifying the sensor owner about whether and how sensor events should be injected.
@@ -36,4 +37,31 @@
      */
     void onConfigurationChanged(in VirtualSensor sensor, boolean enabled, int samplingPeriodMicros,
             int batchReportLatencyMicros);
+
+    /**
+     * Called when a sensor direct channel is created.
+     *
+     * @param channelHandle Identifier of the channel that was created.
+     * @param sharedMemory The shared memory region for the direct sensor channel.
+     */
+    void onDirectChannelCreated(int channelHandle, in SharedMemory sharedMemory);
+
+    /**
+     * Called when a sensor direct channel is destroyed.
+     *
+     * @param channelHandle Identifier of the channel that was destroyed.
+     */
+    void onDirectChannelDestroyed(int channelHandle);
+
+    /**
+     * Called when a sensor direct channel is configured.
+     *
+     * @param channelHandle Identifier of the channel that was configured.
+     * @param sensor The sensor, for which the channel was configured.
+     * @param rateLevel The rate level used to configure the direct sensor channel.
+     * @param reportToken A positive sensor report token, used to differentiate between events from
+     * different sensors within the same channel.
+     */
+    void onDirectChannelConfigured(int channelHandle, in VirtualSensor sensor, int rateLevel,
+            int reportToken);
 }
diff --git a/core/java/android/companion/virtual/sensor/VirtualSensorCallback.java b/core/java/android/companion/virtual/sensor/VirtualSensorCallback.java
index e097189..f7af283 100644
--- a/core/java/android/companion/virtual/sensor/VirtualSensorCallback.java
+++ b/core/java/android/companion/virtual/sensor/VirtualSensorCallback.java
@@ -17,8 +17,13 @@
 package android.companion.virtual.sensor;
 
 
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.hardware.Sensor;
+import android.hardware.SensorDirectChannel;
+import android.os.MemoryFile;
+import android.os.SharedMemory;
 
 import java.time.Duration;
 
@@ -50,4 +55,74 @@
      */
     void onConfigurationChanged(@NonNull VirtualSensor sensor, boolean enabled,
             @NonNull Duration samplingPeriod, @NonNull Duration batchReportLatency);
+
+    /**
+     * Called when a {@link android.hardware.SensorDirectChannel} is created.
+     *
+     * <p>The {@link android.hardware.SensorManager} instance used to create the direct channel must
+     * be associated with the virtual device.
+     *
+     * <p>A typical order of callback invocations is:
+     * <ul>
+     *     <li>{@code onDirectChannelCreated} - the channel handle and the associated shared memory
+     *     should be stored by the virtual device</li>
+     *     <li>{@code onDirectChannelConfigured} with a positive {@code rateLevel} - the virtual
+     *     device should start writing to the shared memory for the associated channel with the
+     *     requested parameters.</li>
+     *     <li>{@code onDirectChannelConfigured} with a {@code rateLevel = RATE_STOP} - the virtual
+     *     device should stop writing to the shared memory for the associated channel.</li>
+     *     <li>{@code onDirectChannelDestroyed} - the shared memory associated with the channel
+     *     handle should be closed.</li>
+     * </ul>
+     *
+     * @param channelHandle Identifier of the newly created channel.
+     * @param sharedMemory writable shared memory region.
+     *
+     * @see android.hardware.SensorManager#createDirectChannel(MemoryFile)
+     * @see #onDirectChannelConfigured
+     * @see #onDirectChannelDestroyed
+     */
+    default void onDirectChannelCreated(@IntRange(from = 1) int channelHandle,
+            @NonNull SharedMemory sharedMemory) {}
+
+    /**
+     * Called when a {@link android.hardware.SensorDirectChannel} is destroyed.
+     *
+     * <p>The virtual device must perform any clean-up and close the shared memory that was
+     * received with the {@link #onDirectChannelCreated} callback and the corresponding
+     * {@code channelHandle}.
+     *
+     * @param channelHandle Identifier of the channel that was destroyed.
+     *
+     * @see SensorDirectChannel#close()
+     */
+    default void onDirectChannelDestroyed(@IntRange(from = 1) int channelHandle) {}
+
+    /**
+     * Called when a {@link android.hardware.SensorDirectChannel} is configured.
+     *
+     * <p>Sensor events for the corresponding sensor should be written at the indicated rate to the
+     * shared memory region that was received with the {@link #onDirectChannelCreated} callback and
+     * the corresponding {@code channelHandle}. The events should be written in the correct format
+     * and with the provided {@code reportToken} until the channel is reconfigured with
+     * {@link SensorDirectChannel#RATE_STOP}.
+     *
+     * <p>The sensor must support direct channel in order for this callback to be invoked. Only
+     * {@link MemoryFile} sensor direct channels are supported for virtual sensors.
+     *
+     * @param channelHandle Identifier of the channel that was configured.
+     * @param sensor The sensor, for which the channel was configured.
+     * @param rateLevel The rate level used to configure the direct sensor channel.
+     * @param reportToken A positive sensor report token, used to differentiate between events from
+     * different sensors within the same channel.
+     *
+     * @see VirtualSensorConfig.Builder#setHighestDirectReportRateLevel(int)
+     * @see VirtualSensorConfig.Builder#setDirectChannelTypesSupported(int)
+     * @see android.hardware.SensorManager#createDirectChannel(MemoryFile)
+     * @see #onDirectChannelCreated
+     * @see SensorDirectChannel#configure(Sensor, int)
+     */
+    default void onDirectChannelConfigured(@IntRange(from = 1) int channelHandle,
+            @NonNull VirtualSensor sensor, @SensorDirectChannel.RateLevel int rateLevel,
+            @IntRange(from = 1) int reportToken) {}
 }
diff --git a/core/java/android/companion/virtual/sensor/VirtualSensorConfig.java b/core/java/android/companion/virtual/sensor/VirtualSensorConfig.java
index 6d45365..401e754 100644
--- a/core/java/android/companion/virtual/sensor/VirtualSensorConfig.java
+++ b/core/java/android/companion/virtual/sensor/VirtualSensorConfig.java
@@ -17,15 +17,18 @@
 package android.companion.virtual.sensor;
 
 
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.hardware.Sensor;
+import android.hardware.SensorDirectChannel;
 import android.os.Parcel;
 import android.os.Parcelable;
 
 import java.util.Objects;
 
+
 /**
  * Configuration for creation of a virtual sensor.
  * @see VirtualSensor
@@ -33,6 +36,14 @@
  */
 @SystemApi
 public final class VirtualSensorConfig implements Parcelable {
+    private static final String TAG = "VirtualSensorConfig";
+
+    // Mask for direct mode highest rate level, bit 7, 8, 9.
+    private static final int DIRECT_REPORT_MASK = 0x380;
+    private static final int DIRECT_REPORT_SHIFT = 7;
+
+    // Mask for supported direct channel, bit 10, 11
+    private static final int DIRECT_CHANNEL_SHIFT = 10;
 
     private final int mType;
     @NonNull
@@ -40,16 +51,21 @@
     @Nullable
     private final String mVendor;
 
-    private VirtualSensorConfig(int type, @NonNull String name, @Nullable String vendor) {
+    private final int mFlags;
+
+    private VirtualSensorConfig(int type, @NonNull String name, @Nullable String vendor,
+            int flags) {
         mType = type;
         mName = name;
         mVendor = vendor;
+        mFlags = flags;
     }
 
     private VirtualSensorConfig(@NonNull Parcel parcel) {
         mType = parcel.readInt();
         mName = parcel.readString8();
         mVendor = parcel.readString8();
+        mFlags = parcel.readInt();
     }
 
     @Override
@@ -62,6 +78,7 @@
         parcel.writeInt(mType);
         parcel.writeString8(mName);
         parcel.writeString8(mVendor);
+        parcel.writeInt(mFlags);
     }
 
     /**
@@ -92,24 +109,69 @@
     }
 
     /**
+     * Returns the highest supported direct report mode rate level of the sensor.
+     *
+     * @see Sensor#getHighestDirectReportRateLevel()
+     */
+    @SensorDirectChannel.RateLevel
+    public int getHighestDirectReportRateLevel() {
+        int rateLevel = ((mFlags & DIRECT_REPORT_MASK) >> DIRECT_REPORT_SHIFT);
+        return rateLevel <= SensorDirectChannel.RATE_VERY_FAST
+                ? rateLevel : SensorDirectChannel.RATE_VERY_FAST;
+    }
+
+    /**
+     * Returns a combination of all supported direct channel types.
+     *
+     * @see Builder#setDirectChannelTypesSupported(int)
+     * @see Sensor#isDirectChannelTypeSupported(int)
+     */
+    public @SensorDirectChannel.MemoryType int getDirectChannelTypesSupported() {
+        int memoryTypes = 0;
+        if ((mFlags & (1 << DIRECT_CHANNEL_SHIFT)) > 0) {
+            memoryTypes |= SensorDirectChannel.TYPE_MEMORY_FILE;
+        }
+        if ((mFlags & (1 << (DIRECT_CHANNEL_SHIFT + 1))) > 0) {
+            memoryTypes |= SensorDirectChannel.TYPE_HARDWARE_BUFFER;
+        }
+        return memoryTypes;
+    }
+
+    /**
+     * Returns the sensor flags.
+     * @hide
+     */
+    public int getFlags() {
+        return mFlags;
+    }
+
+    /**
      * Builder for {@link VirtualSensorConfig}.
      */
     public static final class Builder {
 
+        private static final int FLAG_MEMORY_FILE_DIRECT_CHANNEL_SUPPORTED =
+                1 << DIRECT_CHANNEL_SHIFT;
         private final int mType;
         @NonNull
         private final String mName;
         @Nullable
         private String mVendor;
+        private int mFlags;
+        @SensorDirectChannel.RateLevel
+        int mHighestDirectReportRateLevel;
 
         /**
          * Creates a new builder.
          *
          * @param type The type of the sensor, matching {@link Sensor#getType}.
          * @param name The name of the sensor. Must be unique among all sensors with the same type
-         * that belong to the same virtual device.
+         *             that belong to the same virtual device.
          */
-        public Builder(int type, @NonNull String name) {
+        public Builder(@IntRange(from = 1) int type, @NonNull String name) {
+            if (type <= 0) {
+                throw new IllegalArgumentException("Virtual sensor type must be positive");
+            }
             mType = type;
             mName = Objects.requireNonNull(name);
         }
@@ -119,7 +181,19 @@
          */
         @NonNull
         public VirtualSensorConfig build() {
-            return new VirtualSensorConfig(mType, mName, mVendor);
+            if (mHighestDirectReportRateLevel > 0) {
+                if ((mFlags & FLAG_MEMORY_FILE_DIRECT_CHANNEL_SUPPORTED) == 0) {
+                    throw new IllegalArgumentException("Setting direct channel type is required "
+                            + "for sensors with direct channel support.");
+                }
+                mFlags |= mHighestDirectReportRateLevel << DIRECT_REPORT_SHIFT;
+            }
+            if ((mFlags & FLAG_MEMORY_FILE_DIRECT_CHANNEL_SUPPORTED) > 0
+                    && mHighestDirectReportRateLevel == 0) {
+                throw new IllegalArgumentException("Highest direct report rate level is "
+                        + "required for sensors with direct channel support.");
+            }
+            return new VirtualSensorConfig(mType, mName, mVendor, mFlags);
         }
 
         /**
@@ -130,6 +204,44 @@
             mVendor = vendor;
             return this;
         }
+
+        /**
+         * Sets the highest supported rate level for direct sensor report.
+         *
+         * @see VirtualSensorConfig#getHighestDirectReportRateLevel()
+         */
+        @NonNull
+        public VirtualSensorConfig.Builder setHighestDirectReportRateLevel(
+                @SensorDirectChannel.RateLevel int rateLevel) {
+            mHighestDirectReportRateLevel = rateLevel;
+            return this;
+        }
+
+        /**
+         * Sets whether direct sensor channel of the given types is supported.
+         *
+         * @param memoryTypes A combination of {@link SensorDirectChannel.MemoryType} flags
+         * indicating the types of shared memory supported for creating direct channels. Only
+         * {@link SensorDirectChannel#TYPE_MEMORY_FILE} direct channels may be supported for virtual
+         * sensors.
+         * @throws IllegalArgumentException if {@link SensorDirectChannel#TYPE_HARDWARE_BUFFER} is
+         * set to be supported.
+         */
+        @NonNull
+        public VirtualSensorConfig.Builder setDirectChannelTypesSupported(
+                @SensorDirectChannel.MemoryType int memoryTypes) {
+            if ((memoryTypes & SensorDirectChannel.TYPE_MEMORY_FILE) > 0) {
+                mFlags |= FLAG_MEMORY_FILE_DIRECT_CHANNEL_SUPPORTED;
+            } else {
+                mFlags &= ~FLAG_MEMORY_FILE_DIRECT_CHANNEL_SUPPORTED;
+            }
+            if ((memoryTypes & ~SensorDirectChannel.TYPE_MEMORY_FILE) > 0) {
+                throw new IllegalArgumentException(
+                        "Only TYPE_MEMORY_FILE direct channels can be supported for virtual "
+                                + "sensors.");
+            }
+            return this;
+        }
     }
 
     @NonNull
diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java
index 2b400c1f..cd45f4d 100644
--- a/core/java/android/content/AttributionSource.java
+++ b/core/java/android/content/AttributionSource.java
@@ -101,22 +101,28 @@
     @TestApi
     public AttributionSource(int uid, @Nullable String packageName,
             @Nullable String attributionTag) {
-        this(uid, packageName, attributionTag, sDefaultToken);
+        this(uid, Process.INVALID_PID, packageName, attributionTag, sDefaultToken);
+    }
+
+    /** @hide */
+    public AttributionSource(int uid, int pid, @Nullable String packageName,
+            @Nullable String attributionTag) {
+        this(uid, pid, packageName, attributionTag, sDefaultToken);
     }
 
     /** @hide */
     @TestApi
     public AttributionSource(int uid, @Nullable String packageName,
             @Nullable String attributionTag, @NonNull IBinder token) {
-        this(uid, packageName, attributionTag, token, /*renouncedPermissions*/ null,
-                /*next*/ null);
+        this(uid, Process.INVALID_PID, packageName, attributionTag, token,
+                /*renouncedPermissions*/ null, /*next*/ null);
     }
 
     /** @hide */
-    public AttributionSource(int uid, @Nullable String packageName,
-            @Nullable String attributionTag, @NonNull IBinder token,
-            @Nullable AttributionSource next) {
-        this(uid, packageName, attributionTag, token, /*renouncedPermissions*/ null, next);
+    public AttributionSource(int uid, int pid, @Nullable String packageName,
+            @Nullable String attributionTag, @NonNull IBinder token) {
+        this(uid, pid, packageName, attributionTag, token, /*renouncedPermissions*/ null,
+                /*next*/ null);
     }
 
     /** @hide */
@@ -124,26 +130,33 @@
     public AttributionSource(int uid, @Nullable String packageName,
             @Nullable String attributionTag, @Nullable Set<String> renouncedPermissions,
             @Nullable AttributionSource next) {
-        this(uid, packageName, attributionTag, (renouncedPermissions != null)
-                ? renouncedPermissions.toArray(new String[0]) : null, next);
+        this(uid, Process.INVALID_PID, packageName, attributionTag, sDefaultToken,
+                (renouncedPermissions != null)
+                ? renouncedPermissions.toArray(new String[0]) : null, /*next*/ next);
     }
 
     /** @hide */
     public AttributionSource(@NonNull AttributionSource current, @Nullable AttributionSource next) {
-        this(current.getUid(), current.getPackageName(), current.getAttributionTag(),
-                current.getToken(), current.mAttributionSourceState.renouncedPermissions, next);
+        this(current.getUid(), current.getPid(), current.getPackageName(),
+                current.getAttributionTag(), current.getToken(),
+                current.mAttributionSourceState.renouncedPermissions, next);
     }
 
-    AttributionSource(int uid, @Nullable String packageName, @Nullable String attributionTag,
-            @Nullable String[] renouncedPermissions, @Nullable AttributionSource next) {
-        this(uid, packageName, attributionTag, sDefaultToken, renouncedPermissions, next);
+    /** @hide */
+    public AttributionSource(int uid, int pid, @Nullable String packageName,
+            @Nullable String attributionTag, @Nullable String[] renouncedPermissions,
+            @Nullable AttributionSource next) {
+        this(uid, pid, packageName, attributionTag, sDefaultToken, renouncedPermissions, next);
     }
 
-    AttributionSource(int uid, @Nullable String packageName, @Nullable String attributionTag,
-            @NonNull IBinder token, @Nullable String[] renouncedPermissions,
+    /** @hide */
+    public AttributionSource(int uid, int pid, @Nullable String packageName,
+            @Nullable String attributionTag, @NonNull IBinder token,
+            @Nullable String[] renouncedPermissions,
             @Nullable AttributionSource next) {
         mAttributionSourceState = new AttributionSourceState();
         mAttributionSourceState.uid = uid;
+        mAttributionSourceState.pid = pid;
         mAttributionSourceState.token = token;
         mAttributionSourceState.packageName = packageName;
         mAttributionSourceState.attributionTag = attributionTag;
@@ -162,7 +175,17 @@
 
         // Since we just unpacked this object as part of it transiting a Binder
         // call, this is the perfect time to enforce that its UID and PID can be trusted
-        enforceCallingUidAndPid();
+        enforceCallingUid();
+
+        // If this object is being constructed as part of a oneway Binder call, getCallingPid will
+        // return 0 instead of the true PID. In that case, invalidate the PID by setting it to
+        // INVALID_PID (-1).
+        final int callingPid = Binder.getCallingPid();
+        if (callingPid == 0) {
+            mAttributionSourceState.pid = Process.INVALID_PID;
+        }
+
+        enforceCallingPid();
     }
 
     /** @hide */
@@ -172,23 +195,29 @@
 
     /** @hide */
     public AttributionSource withNextAttributionSource(@Nullable AttributionSource next) {
-        return new AttributionSource(getUid(), getPackageName(), getAttributionTag(),
-                mAttributionSourceState.renouncedPermissions, next);
+        return new AttributionSource(getUid(), getPid(), getPackageName(), getAttributionTag(),
+                getToken(), mAttributionSourceState.renouncedPermissions, next);
     }
 
     /** @hide */
     public AttributionSource withPackageName(@Nullable String packageName) {
-        return new AttributionSource(getUid(), packageName, getAttributionTag(),
-                mAttributionSourceState.renouncedPermissions, getNext());
+        return new AttributionSource(getUid(), getPid(), packageName, getAttributionTag(),
+               getToken(), mAttributionSourceState.renouncedPermissions, getNext());
     }
 
     /** @hide */
     public AttributionSource withToken(@NonNull Binder token) {
-        return new AttributionSource(getUid(), getPackageName(), getAttributionTag(),
+        return new AttributionSource(getUid(), getPid(), getPackageName(), getAttributionTag(),
                 token, mAttributionSourceState.renouncedPermissions, getNext());
     }
 
     /** @hide */
+    public AttributionSource withPid(int pid) {
+        return new AttributionSource(getUid(), pid, getPackageName(), getAttributionTag(),
+                getToken(), mAttributionSourceState.renouncedPermissions, getNext());
+    }
+
+    /** @hide */
     public @NonNull AttributionSourceState asState() {
         return mAttributionSourceState;
     }
@@ -228,6 +257,7 @@
         }
         try {
             return new AttributionSource.Builder(uid)
+                .setPid(Process.myPid())
                 .setPackageName(AppGlobals.getPackageManager().getPackagesForUid(uid)[0])
                 .build();
         } catch (Exception ignored) {
@@ -265,18 +295,6 @@
     }
 
     /**
-     * If you are handling an IPC and you don't trust the caller you need to validate whether the
-     * attribution source is one for the calling app to prevent the caller to pass you a source from
-     * another app without including themselves in the attribution chain.
-     *
-     * @throws SecurityException if the attribution source cannot be trusted to be from the caller.
-     */
-    private void enforceCallingUidAndPid() {
-        enforceCallingUid();
-        enforceCallingPid();
-    }
-
-    /**
      * If you are handling an IPC and you don't trust the caller you need to validate
      * whether the attribution source is one for the calling app to prevent the caller
      * to pass you a source from another app without including themselves in the
@@ -312,7 +330,10 @@
     }
 
     /**
-     * Validate that the pid being claimed for the calling app is not spoofed
+     * Validate that the pid being claimed for the calling app is not spoofed.
+     *
+     * Note that the PID may be unavailable, for example if we're in a oneway Binder call. In this
+     * case, calling enforceCallingPid is guaranteed to fail. The caller should anticipate this.
      *
      * @throws SecurityException if the attribution source cannot be trusted to be from the caller.
      * @hide
@@ -320,8 +341,12 @@
     @TestApi
     public void enforceCallingPid() {
         if (!checkCallingPid()) {
-            throw new SecurityException("Calling pid: " + Binder.getCallingPid()
-                    + " doesn't match source pid: " + mAttributionSourceState.pid);
+            if (Binder.getCallingPid() == 0) {
+                throw new SecurityException("Calling pid unavailable due to oneway Binder call.");
+            } else {
+                throw new SecurityException("Calling pid: " + Binder.getCallingPid()
+                        + " doesn't match source pid: " + mAttributionSourceState.pid);
+            }
         }
     }
 
@@ -332,7 +357,8 @@
      */
     private boolean checkCallingPid() {
         final int callingPid = Binder.getCallingPid();
-        if (mAttributionSourceState.pid != -1 && callingPid != mAttributionSourceState.pid) {
+        if (mAttributionSourceState.pid != Process.INVALID_PID
+                && callingPid != mAttributionSourceState.pid) {
             return false;
         }
         return true;
@@ -449,6 +475,13 @@
     }
 
     /**
+     * The PID that is accessing the permission protected data.
+     */
+    public int getPid() {
+        return mAttributionSourceState.pid;
+    }
+
+    /**
      * The package that is accessing the permission protected data.
      */
     public @Nullable String getPackageName() {
@@ -551,6 +584,7 @@
                 throw new IllegalArgumentException("current AttributionSource can not be null");
             }
             mAttributionSourceState.uid = current.getUid();
+            mAttributionSourceState.pid = current.getPid();
             mAttributionSourceState.packageName = current.getPackageName();
             mAttributionSourceState.attributionTag = current.getAttributionTag();
             mAttributionSourceState.token = current.getToken();
@@ -559,11 +593,25 @@
         }
 
         /**
+         * The PID of the process that is accessing the permission protected data.
+         *
+         * If not called, pid will default to {@link Process@INVALID_PID} (-1). This indicates that
+         * the PID data is missing. Supplying a PID is not required, but recommended when
+         * accessible.
+         */
+        public @NonNull Builder setPid(int value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x2;
+            mAttributionSourceState.pid = value;
+            return this;
+        }
+
+        /**
          * The package that is accessing the permission protected data.
          */
         public @NonNull Builder setPackageName(@Nullable String value) {
             checkNotUsed();
-            mBuilderFieldsSet |= 0x2;
+            mBuilderFieldsSet |= 0x4;
             mAttributionSourceState.packageName = value;
             return this;
         }
@@ -573,7 +621,7 @@
          */
         public @NonNull Builder setAttributionTag(@Nullable String value) {
             checkNotUsed();
-            mBuilderFieldsSet |= 0x4;
+            mBuilderFieldsSet |= 0x8;
             mAttributionSourceState.attributionTag = value;
             return this;
         }
@@ -606,7 +654,7 @@
         @RequiresPermission(android.Manifest.permission.RENOUNCE_PERMISSIONS)
         public @NonNull Builder setRenouncedPermissions(@Nullable Set<String> value) {
             checkNotUsed();
-            mBuilderFieldsSet |= 0x8;
+            mBuilderFieldsSet |= 0x10;
             mAttributionSourceState.renouncedPermissions = (value != null)
                     ? value.toArray(new String[0]) : null;
             return this;
@@ -617,7 +665,7 @@
          */
         public @NonNull Builder setNext(@Nullable AttributionSource value) {
             checkNotUsed();
-            mBuilderFieldsSet |= 0x10;
+            mBuilderFieldsSet |= 0x20;
             mAttributionSourceState.next = (value != null) ? new AttributionSourceState[]
                     {value.mAttributionSourceState} : mAttributionSourceState.next;
             return this;
@@ -629,15 +677,18 @@
             mBuilderFieldsSet |= 0x40; // Mark builder used
 
             if ((mBuilderFieldsSet & 0x2) == 0) {
-                mAttributionSourceState.packageName = null;
+                mAttributionSourceState.pid = Process.INVALID_PID;
             }
             if ((mBuilderFieldsSet & 0x4) == 0) {
-                mAttributionSourceState.attributionTag = null;
+                mAttributionSourceState.packageName = null;
             }
             if ((mBuilderFieldsSet & 0x8) == 0) {
-                mAttributionSourceState.renouncedPermissions = null;
+                mAttributionSourceState.attributionTag = null;
             }
             if ((mBuilderFieldsSet & 0x10) == 0) {
+                mAttributionSourceState.renouncedPermissions = null;
+            }
+            if ((mBuilderFieldsSet & 0x20) == 0) {
                 mAttributionSourceState.next = null;
             }
 
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 795c77f..d3502c5 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -389,6 +389,8 @@
 
         @Override
         public void getTypeAnonymousAsync(Uri uri, RemoteCallback callback) {
+            uri = validateIncomingUri(uri);
+            uri = maybeGetUriWithoutUserId(uri);
             final Bundle result = new Bundle();
             try {
                 result.putString(ContentResolver.REMOTE_CALLBACK_RESULT, getTypeAnonymous(uri));
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 658702f..fc75323 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -316,10 +316,12 @@
             BIND_ALLOW_ACTIVITY_STARTS,
             BIND_INCLUDE_CAPABILITIES,
             BIND_SHARED_ISOLATED_PROCESS,
-            // Intentionally not included, because it'd cause sign-extension.
+            // Intentionally not include BIND_EXTERNAL_SERVICE, because it'd cause sign-extension.
             // This would allow Android Studio to show a warning, if someone tries to use
             // BIND_EXTERNAL_SERVICE BindServiceFlags.
-            BIND_EXTERNAL_SERVICE_LONG
+            BIND_EXTERNAL_SERVICE_LONG,
+            // Make sure no flag uses the sign bit (most significant bit) of the long integer,
+            // to avoid future confusion.
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface BindServiceFlagsLongBits {}
@@ -338,6 +340,7 @@
 
         /**
          * @return Return flags in 64 bits long integer.
+         * @hide
          */
         public long getValue() {
             return mValue;
@@ -528,7 +531,7 @@
 
     /**
      * Flag for {@link #bindService}: allow the process hosting the target service to gain
-     * {@link ActivityManager#PROCESS_CAPABILITY_NETWORK}, which allows it be able
+     * {@link ActivityManager#PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK}, which allows it be able
      * to access network regardless of any power saving restrictions.
      *
      * @hide
@@ -678,13 +681,11 @@
      */
     public static final int BIND_EXTERNAL_SERVICE = 0x80000000;
 
-
     /**
      * Works in the same way as {@link #BIND_EXTERNAL_SERVICE}, but it's defined as a (@code long)
      * value that is compatible to {@link BindServiceFlags}.
      */
-    public static final long BIND_EXTERNAL_SERVICE_LONG = 0x8000_0000_0000_0000L;
-
+    public static final long BIND_EXTERNAL_SERVICE_LONG = 1L << 62;
 
     /**
      * These bind flags reduce the strength of the binding such that we shouldn't
@@ -2398,7 +2399,6 @@
         sendBroadcastMultiplePermissions(intent, receiverPermissions, excludedPermissions, null);
     }
 
-
     /**
      * Like {@link #sendBroadcastMultiplePermissions(Intent, String[], String[])}, but also allows
      * specification of a list of excluded packages.
@@ -2408,6 +2408,19 @@
     public void sendBroadcastMultiplePermissions(@NonNull Intent intent,
             @NonNull String[] receiverPermissions, @Nullable String[] excludedPermissions,
             @Nullable String[] excludedPackages) {
+        sendBroadcastMultiplePermissions(intent, receiverPermissions, excludedPermissions,
+                excludedPackages, null);
+    }
+
+    /**
+     * Like {@link #sendBroadcastMultiplePermissions(Intent, String[], String[], String[])}, but
+     * also allows specification of options generated from {@link android.app.BroadcastOptions}.
+     *
+     * @hide
+     */
+    public void sendBroadcastMultiplePermissions(@NonNull Intent intent,
+            @NonNull String[] receiverPermissions, @Nullable String[] excludedPermissions,
+            @Nullable String[] excludedPackages, @Nullable BroadcastOptions options) {
         throw new RuntimeException("Not implemented. Must override in a subclass.");
     }
 
@@ -5703,6 +5716,9 @@
      * Use with {@link #getSystemService(String)} to retrieve a
      * {@link android.companion.virtual.VirtualDeviceManager} for managing virtual devices.
      *
+     * On devices without {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP}
+     * system feature the {@link #getSystemService(String)} will return {@code null}.
+     *
      * @see #getSystemService(String)
      * @see android.companion.virtual.VirtualDeviceManager
      */
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 1775bf7..21de5cf 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -24,6 +24,7 @@
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.annotation.UiContext;
+import android.app.BroadcastOptions;
 import android.app.IApplicationThread;
 import android.app.IServiceConnection;
 import android.app.compat.CompatChanges;
@@ -519,9 +520,9 @@
     @Override
     public void sendBroadcastMultiplePermissions(@NonNull Intent intent,
             @NonNull String[] receiverPermissions, @Nullable String[] excludedPermissions,
-            @Nullable String[] excludedPackages) {
+            @Nullable String[] excludedPackages, @Nullable BroadcastOptions options) {
         mBase.sendBroadcastMultiplePermissions(intent, receiverPermissions, excludedPermissions,
-                excludedPackages);
+                excludedPackages, options);
     }
 
     /** @hide */
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index bd3cf5f..5928a50 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -20,9 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.app.compat.CompatChanges;
-import android.compat.annotation.ChangeId;
-import android.compat.annotation.EnabledAfter;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.net.Uri;
 import android.os.Build;
@@ -185,28 +182,6 @@
     private static final boolean[] EMPTY_BOOLEAN_ARRAY = new boolean[0];
 
     /**
-     * An intent with action set as null used to always pass the action test during intent
-     * filter matching. This causes a lot of confusion and unexpected intent matches.
-     * Null action intents should be blocked when either the intent sender or receiver
-     * application targets U or higher.
-     *
-     * mBlockNullAction indicates whether the intent filter owner (intent receiver) is
-     * targeting U+. This value will be properly set by package manager when IntentFilters are
-     * passed to an application, so that when an application is trying to perform intent filter
-     * matching locally, the correct matching algorithm will be chosen.
-     *
-     * When an IntentFilter is sent to system server (e.g. for registering runtime receivers),
-     * the value set in mBlockNullAction will be ignored and overwritten with the correct
-     * value evaluated based on the Binder calling identity. This makes sure that the
-     * security enforcement cannot be bypassed by crafting a malicious IntentFilter.
-     *
-     * @hide
-     */
-    @ChangeId
-    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
-    public static final long BLOCK_NULL_ACTION_INTENTS = 264497795;
-
-    /**
      * The filter {@link #setPriority} value at which system high-priority
      * receivers are placed; that is, receivers that should execute before
      * application code. Applications should never use filters with this or
@@ -2229,9 +2204,7 @@
      * <p> Subsequent calls to this method  will override any previously set extras.
      *
      * @param extras The intent extras to match against.
-     * @hide
      */
-    @SystemApi
     public final void setExtras(@NonNull PersistableBundle extras) {
         mExtras = extras;
     }
@@ -2241,11 +2214,8 @@
      *
      * @return the extras that were previously set using {@link #setExtras(PersistableBundle)} or
      *         an empty {@link PersistableBundle} object if no extras were set.
-     * @hide
      */
-    @SystemApi
-    @NonNull
-    public final PersistableBundle getExtras() {
+    public final @NonNull PersistableBundle getExtras() {
         return mExtras == null ? new PersistableBundle() : mExtras;
     }
 
@@ -2301,7 +2271,6 @@
         String type = resolve ? intent.resolveType(resolver) : intent.getType();
         return match(intent.getAction(), type, intent.getScheme(),
                      intent.getData(), intent.getCategories(), logTag,
-                     CompatChanges.isChangeEnabled(BLOCK_NULL_ACTION_INTENTS),
                      false /* supportWildcards */, null /* ignoreActions */,
                      intent.getExtras());
     }
@@ -2354,7 +2323,6 @@
             Uri data, Set<String> categories, String logTag, boolean supportWildcards,
             @Nullable Collection<String> ignoreActions) {
         return match(action, type, scheme, data, categories, logTag, supportWildcards,
-                CompatChanges.isChangeEnabled(BLOCK_NULL_ACTION_INTENTS),
                 ignoreActions, null /* extras */);
     }
 
@@ -2366,10 +2334,8 @@
      */
     public final int match(String action, String type, String scheme,
             Uri data, Set<String> categories, String logTag, boolean supportWildcards,
-            boolean blockNullAction, @Nullable Collection<String> ignoreActions,
-            @Nullable Bundle extras) {
-        if ((action == null && blockNullAction)
-                || !matchAction(action, supportWildcards, ignoreActions)) {
+            @Nullable Collection<String> ignoreActions, @Nullable Bundle extras) {
+        if (action != null && !matchAction(action, supportWildcards, ignoreActions)) {
             if (false) Log.v(
                 logTag, "No matching action " + action + " for " + this);
             return NO_MATCH_ACTION;
diff --git a/core/java/android/content/PermissionChecker.java b/core/java/android/content/PermissionChecker.java
index 8d3452e..0e3217d 100644
--- a/core/java/android/content/PermissionChecker.java
+++ b/core/java/android/content/PermissionChecker.java
@@ -152,7 +152,7 @@
             @NonNull String permission, int pid, int uid, @Nullable String packageName,
             @Nullable String attributionTag, @Nullable String message, boolean startDataDelivery) {
         return checkPermissionForDataDelivery(context, permission, pid, new AttributionSource(uid,
-                packageName, attributionTag), message, startDataDelivery);
+                pid, packageName, attributionTag), message, startDataDelivery);
     }
 
     /**
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index f8f2663..eb14cc4 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -1156,6 +1156,34 @@
             264301586L; // buganizer id
 
     /**
+     * This change id forces the packages it is applied to sandbox {@link android.view.View} API to
+     * an activity bounds for:
+     *
+     * <p>{@link android.view.View#getLocationOnScreen},
+     * {@link android.view.View#getWindowVisibleDisplayFrame},
+     * {@link android.view.View}#getWindowDisplayFrame,
+     * {@link android.view.View}#getBoundsOnScreen.
+     *
+     * <p>For {@link android.view.View#getWindowVisibleDisplayFrame} and
+     * {@link android.view.View}#getWindowDisplayFrame this sandboxing is happening indirectly
+     * through
+     * {@link android.view.ViewRootImpl}#getWindowVisibleDisplayFrame,
+     * {@link android.view.ViewRootImpl}#getDisplayFrame respectively.
+     *
+     * <p>Some applications assume that they occupy the whole screen and therefore use the display
+     * coordinates in their calculations as if an activity is  positioned in the top-left corner of
+     * the screen, with left coordinate equal to 0. This may not be the case of applications in
+     * multi-window and in letterbox modes. This can lead to shifted or out of bounds UI elements in
+     * case the activity is Letterboxed or is in multi-window mode.
+     * @hide
+     */
+    @ChangeId
+    @Overridable
+    @Disabled
+    @TestApi
+    public static final long OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS = 237531167L; // buganizer id
+
+    /**
      * This change id is the gatekeeper for all treatments that force a given min aspect ratio.
      * Enabling this change will allow the following min aspect ratio treatments to be applied:
      * OVERRIDE_MIN_ASPECT_RATIO_MEDIUM
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index 08cfbf7..96a42e2 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -33,6 +33,7 @@
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ShortcutInfo;
+import android.content.pm.LauncherActivityInfoInternal;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.UserHandle;
@@ -114,4 +115,5 @@
 
     String getShortcutIconUri(String callingPackage, String packageName, String shortcutId,
             int userId);
+    Map<String, LauncherActivityInfoInternal> getActivityOverrides(String callingPackage, int userId);
 }
diff --git a/core/java/android/content/pm/LauncherActivityInfo.java b/core/java/android/content/pm/LauncherActivityInfo.java
index 16e720e..a4d5327 100644
--- a/core/java/android/content/pm/LauncherActivityInfo.java
+++ b/core/java/android/content/pm/LauncherActivityInfo.java
@@ -34,7 +34,6 @@
  */
 public class LauncherActivityInfo {
     private final PackageManager mPm;
-    private UserHandle mUser;
     private final LauncherActivityInfoInternal mInternal;
 
     /**
@@ -43,9 +42,8 @@
      * @param context The context for fetching resources.
 
      */
-    LauncherActivityInfo(Context context, UserHandle user, LauncherActivityInfoInternal internal) {
+    LauncherActivityInfo(Context context, LauncherActivityInfoInternal internal) {
         mPm = context.getPackageManager();
-        mUser = user;
         mInternal = internal;
     }
 
@@ -70,7 +68,7 @@
      * @return The UserHandle of the profile.
      */
     public UserHandle getUser() {
-        return mUser;
+        return mInternal.getUser();
     }
 
     /**
@@ -180,6 +178,6 @@
     public Drawable getBadgedIcon(int density) {
         Drawable originalIcon = getIcon(density);
 
-        return mPm.getUserBadgedIcon(originalIcon, mUser);
+        return mPm.getUserBadgedIcon(originalIcon, mInternal.getUser());
     }
 }
diff --git a/core/java/android/content/pm/LauncherActivityInfoInternal.java b/core/java/android/content/pm/LauncherActivityInfoInternal.java
index 46c415d..5aac97d 100644
--- a/core/java/android/content/pm/LauncherActivityInfoInternal.java
+++ b/core/java/android/content/pm/LauncherActivityInfoInternal.java
@@ -21,6 +21,7 @@
 import android.content.ComponentName;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.UserHandle;
 
 /**
  * @hide
@@ -30,23 +31,27 @@
     @NonNull private ActivityInfo mActivityInfo;
     @NonNull private ComponentName mComponentName;
     @NonNull private IncrementalStatesInfo mIncrementalStatesInfo;
+    @NonNull private UserHandle mUser;
 
     /**
      * @param info ActivityInfo from which to create the LauncherActivityInfo.
      * @param incrementalStatesInfo The package's states.
+     * @param user The user the activity info belongs to.
      */
     public LauncherActivityInfoInternal(@NonNull ActivityInfo info,
-            @NonNull IncrementalStatesInfo incrementalStatesInfo) {
+            @NonNull IncrementalStatesInfo incrementalStatesInfo,
+            @NonNull UserHandle user) {
         mActivityInfo = info;
         mComponentName = new ComponentName(info.packageName, info.name);
         mIncrementalStatesInfo = incrementalStatesInfo;
+        mUser = user;
     }
 
     public LauncherActivityInfoInternal(Parcel source) {
-        mActivityInfo = source.readParcelable(ActivityInfo.class.getClassLoader(), android.content.pm.ActivityInfo.class);
+        mActivityInfo = source.readTypedObject(ActivityInfo.CREATOR);
         mComponentName = new ComponentName(mActivityInfo.packageName, mActivityInfo.name);
-        mIncrementalStatesInfo = source.readParcelable(
-                IncrementalStatesInfo.class.getClassLoader(), android.content.pm.IncrementalStatesInfo.class);
+        mIncrementalStatesInfo = source.readTypedObject(IncrementalStatesInfo.CREATOR);
+        mUser = source.readTypedObject(UserHandle.CREATOR);
     }
 
     public ComponentName getComponentName() {
@@ -57,6 +62,10 @@
         return mActivityInfo;
     }
 
+    public UserHandle getUser() {
+        return mUser;
+    }
+
     public IncrementalStatesInfo getIncrementalStatesInfo() {
         return mIncrementalStatesInfo;
     }
@@ -68,8 +77,9 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeParcelable(mActivityInfo, 0);
-        dest.writeParcelable(mIncrementalStatesInfo, 0);
+        dest.writeTypedObject(mActivityInfo, flags);
+        dest.writeTypedObject(mIncrementalStatesInfo, flags);
+        dest.writeTypedObject(mUser, flags);
     }
 
     public static final @android.annotation.NonNull Creator<LauncherActivityInfoInternal> CREATOR =
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index f8c4974..8989006 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -64,6 +64,7 @@
 import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.util.ArrayMap;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.Pair;
@@ -793,13 +794,45 @@
             if (ai == null) {
                 return null;
             }
-            return new LauncherActivityInfo(mContext, user, ai);
+            return new LauncherActivityInfo(mContext, ai);
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
     }
 
     /**
+     * Returns overrides for the activities that should be launched for the shortcuts of certain
+     * package names.
+     *
+     * @return {@link Map} whose keys are package names and whose values are the
+     * {@link LauncherActivityInfo}s that should be used for those packages' shortcuts. If there are
+     * no activity overrides, an empty {@link Map} will be returned.
+     *
+     * @hide
+     */
+    @NonNull
+    public Map<String, LauncherActivityInfo> getActivityOverrides() {
+        Map<String, LauncherActivityInfo> activityOverrides = new ArrayMap<>();
+        try {
+            Map<String, LauncherActivityInfoInternal> activityOverridesInternal =
+                    mService.getActivityOverrides(mContext.getPackageName(), mContext.getUserId());
+            for (Map.Entry<String, LauncherActivityInfoInternal> packageToOverride :
+                    activityOverridesInternal.entrySet()) {
+                activityOverrides.put(
+                        packageToOverride.getKey(),
+                        new LauncherActivityInfo(
+                                mContext,
+                                packageToOverride.getValue()
+                        )
+                );
+            }
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+        return activityOverrides;
+    }
+
+    /**
      * Starts a Main activity in the specified profile.
      *
      * @param component The ComponentName of the activity to launch
@@ -916,7 +949,7 @@
         }
         ArrayList<LauncherActivityInfo> lais = new ArrayList<>();
         for (LauncherActivityInfoInternal internal : internals.getList()) {
-            LauncherActivityInfo lai = new LauncherActivityInfo(mContext, user, internal);
+            LauncherActivityInfo lai = new LauncherActivityInfo(mContext, internal);
             if (DEBUG) {
                 Log.v(TAG, "Returning activity for profile " + user + " : "
                         + lai.getComponentName());
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index a6a6215..cb988df 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -2935,13 +2935,14 @@
          *             <li>The {@link InstallSourceInfo#getUpdateOwnerPackageName() update owner}
          *             of an existing version of the app (in other words, this install session is
          *             an app update) if the update ownership enforcement is enabled.</li>
-         *             <li>The {@link InstallSourceInfo#getInstallingPackageName() installer of
-         *             record} of an existing version of the app (in other words, this install
+         *             <li>The
+         *             {@link InstallSourceInfo#getInstallingPackageName() installer of record}
+         *             of an existing version of the app (in other words, this install
          *             session is an app update) if the update ownership enforcement isn't
          *             enabled.</li>
          *             <li>Updating itself.</li>
          *         </ul>
-         *     </li>>
+         *     </li>
          *     <li>The installer declares the
          *     {@link android.Manifest.permission#UPDATE_PACKAGES_WITHOUT_USER_ACTION
          *     UPDATE_PACKAGES_WITHOUT_USER_ACTION} permission.</li>
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index d927c5e..328b0ae 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -204,6 +204,36 @@
             "android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE";
 
     /**
+     * Application level {@link android.content.pm.PackageManager.Property PackageManager
+     * .Property} for an app to inform the system that the app can be opted-in or opted-out
+     * from the compatibility treatment that rotates camera output by 90 degrees on landscape
+     * sensors on devices known to have compatibility issues.
+     *
+     * <p>The treatment is disabled by default but device manufacturers can enable the treatment
+     * using their discretion to improve camera compatibility. With this property set to
+     * {@code false}, the rotation will not be applied. A value of {@code true}
+     * will ensure that rotation is applied, provided it is enabled for the device. In most cases,
+     * if rotation is the desired behavior this property need not be set. However, if your app
+     * experiences stretching or incorrect rotation on these devices, explicitly setting this to
+     * {@code true} may resolve that behavior. Apps should set this to {@code false} if there
+     * is confidence that the app handles
+     * {@link android.hardware.camera2.CameraCharacteristics#SENSOR_ORIENTATION} correctly.
+     * See <a href="https://developer.android.com/training/camera2/camera-preview"> the
+     * documentation for best practice.</a>
+     *
+     * <p><b>Syntax:</b>
+     * <pre>
+     * &lt;application&gt;
+     *   &lt;property
+     *     android:name="android.camera.PROPERTY_COMPAT_OVERRIDE_LANDSCAPE_TO_PORTRAIT"
+     *     android:value="true|false"/&gt;
+     * &lt;/application&gt;
+     * </pre>
+     */
+    public static final String PROPERTY_COMPAT_OVERRIDE_LANDSCAPE_TO_PORTRAIT =
+            "android.camera.PROPERTY_COMPAT_OVERRIDE_LANDSCAPE_TO_PORTRAIT";
+
+    /**
      * A property value set within the manifest.
      * <p>
      * The value of a property will only have a single type, as defined by
@@ -4353,19 +4383,26 @@
     public static final String FEATURE_CREDENTIALS = "android.software.credentials";
 
     /**
-     * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
-     * The device supports locking (for example, by a financing provider in case of a missed
-     * payment).
+     * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device
+     * supports locking (for example, by a financing provider in case of a missed payment).
      */
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_DEVICE_LOCK = "android.software.device_lock";
 
+    /**
+     * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device
+     * supports showing location-based suggestions for wallet cards provided by the default payment
+     * app.
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_WALLET_LOCATION_BASED_SUGGESTIONS =
+            "android.software.wallet_location_based_suggestions";
+
     /** @hide */
     public static final boolean APP_ENUMERATION_ENABLED_BY_DEFAULT = true;
 
     /**
-     * Extra field name for the URI to a verification file. Passed to a package
-     * verifier.
+     * Extra field name for the URI to a verification file. Passed to a package verifier.
      *
      * @hide
      */
@@ -5720,17 +5757,6 @@
     }
 
     /**
-     * @hide
-     */
-    @NonNull
-    public ActivityInfo getActivityInfoAsUser(@NonNull ComponentName component,
-            @NonNull ComponentInfoFlags flags, @UserIdInt int userId)
-            throws NameNotFoundException {
-        throw new UnsupportedOperationException(
-                "getActivityInfoAsUser not implemented in subclass");
-    }
-
-    /**
      * Retrieve all of the information we know about a particular receiver
      * class.
      *
diff --git a/core/java/android/content/pm/TEST_MAPPING b/core/java/android/content/pm/TEST_MAPPING
index 45e0efb..b601275 100644
--- a/core/java/android/content/pm/TEST_MAPPING
+++ b/core/java/android/content/pm/TEST_MAPPING
@@ -28,7 +28,13 @@
       "path": "cts/hostsidetests/os/test_mappings/packagemanager"
     },
     {
+      "path": "cts/hostsidetests/appsearch"
+    },
+    {
       "path": "system/apex/tests"
+    },
+    {
+      "path": "cts/tests/tests/content/pm/SecureFrp"
     }
   ],
   "presubmit": [
@@ -43,6 +49,12 @@
       "name": "ApkVerityTest"
     },
     {
+      "name": "CtsSilentUpdateHostTestCases"
+    },
+    {
+      "name": "CtsSuspendAppsTestCases"
+    },
+    {
       "name": "CtsAppFgsTestCases",
       "file_patterns": ["(/|^)ServiceInfo[^/]*"],
       "options": [
@@ -108,50 +120,6 @@
       ]
     },
     {
-      "name": "CtsAppSearchHostTestCases",
-      "options": [
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        },
-        {
-          "exclude-annotation": "org.junit.Ignore"
-        }
-      ]
-    },
-    {
-      "name": "CtsSilentUpdateHostTestCases",
-      "options": [
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        },
-        {
-          "exclude-annotation": "org.junit.Ignore"
-        }
-      ]
-    },
-    {
-      "name": "CtsSuspendAppsTestCases",
-      "options": [
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        },
-        {
-          "exclude-annotation": "org.junit.Ignore"
-        }
-      ]
-    },
-    {
-      "name": "CtsSecureFrpInstallTestCases",
-      "options": [
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        },
-        {
-          "exclude-annotation": "org.junit.Ignore"
-        }
-      ]
-    },
-    {
       "name": "CtsSuspendAppsPermissionTestCases",
       "options": [
         {
diff --git a/core/java/android/content/pm/UserPackage.java b/core/java/android/content/pm/UserPackage.java
index 7ca92c3..c35e678 100644
--- a/core/java/android/content/pm/UserPackage.java
+++ b/core/java/android/content/pm/UserPackage.java
@@ -18,14 +18,16 @@
 
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
-import android.os.Process;
-import android.os.UserHandle;
 import android.util.SparseArrayMap;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 
+import libcore.util.EmptyArray;
+
 import java.util.Objects;
+import java.util.Random;
 
 /**
  * POJO to represent a package for a specific user ID.
@@ -34,6 +36,16 @@
  */
 public final class UserPackage {
     private static final boolean ENABLE_CACHING = true;
+    /**
+     * The maximum number of entries to keep in the cache per user ID.
+     * The value should ideally be high enough to cover all packages on an end-user device,
+     * but low enough that stale or invalid packages would eventually (probably) get removed.
+     * This should benefit components that loop through all packages on a device and use this class,
+     * since being able to cache the objects for all packages on the device
+     * means we don't have to keep recreating the objects.
+     */
+    @VisibleForTesting
+    static final int MAX_NUM_CACHED_ENTRIES_PER_USER = 1000;
 
     @UserIdInt
     public final int userId;
@@ -43,11 +55,13 @@
     @GuardedBy("sCacheLock")
     private static final SparseArrayMap<String, UserPackage> sCache = new SparseArrayMap<>();
 
-    private static final class NoPreloadHolder {
-        /** Set of userIDs to cache objects for. */
-        @GuardedBy("sCacheLock")
-        private static int[] sUserIds = new int[]{UserHandle.getUserId(Process.myUid())};
-    }
+    /**
+     * Set of userIDs to cache objects for. We start off with an empty set, so there's no caching
+     * by default. The system will override with a valid set of userIDs in its process so that
+     * caching becomes active in the system process.
+     */
+    @GuardedBy("sCacheLock")
+    private static int[] sUserIds = EmptyArray.INT;
 
     private UserPackage(int userId, String packageName) {
         this.userId = userId;
@@ -87,13 +101,14 @@
         }
 
         synchronized (sCacheLock) {
-            if (!ArrayUtils.contains(NoPreloadHolder.sUserIds, userId)) {
+            if (!ArrayUtils.contains(sUserIds, userId)) {
                 // Don't cache objects for invalid userIds.
                 return new UserPackage(userId, packageName);
             }
 
             UserPackage up = sCache.get(userId, packageName);
             if (up == null) {
+                maybePurgeRandomEntriesLocked(userId);
                 packageName = packageName.intern();
                 up = new UserPackage(userId, packageName);
                 sCache.add(userId, packageName, up);
@@ -121,7 +136,7 @@
 
         userIds = userIds.clone();
         synchronized (sCacheLock) {
-            NoPreloadHolder.sUserIds = userIds;
+            sUserIds = userIds;
 
             for (int u = sCache.numMaps() - 1; u >= 0; --u) {
                 final int userId = sCache.keyAt(u);
@@ -131,4 +146,35 @@
             }
         }
     }
+
+    @VisibleForTesting
+    public static int numEntriesForUser(int userId) {
+        synchronized (sCacheLock) {
+            return sCache.numElementsForKey(userId);
+        }
+    }
+
+    /** Purge a random set of entries if the cache size is too large. */
+    @GuardedBy("sCacheLock")
+    private static void maybePurgeRandomEntriesLocked(int userId) {
+        final int uIdx = sCache.indexOfKey(userId);
+        if (uIdx < 0) {
+            return;
+        }
+        int numCached = sCache.numElementsForKeyAt(uIdx);
+        if (numCached < MAX_NUM_CACHED_ENTRIES_PER_USER) {
+            return;
+        }
+        // Purge a random set of 1% of cached elements for the userId. We don't want to use a
+        // deterministic system of purging because that may cause us to repeatedly remove elements
+        // that are frequently added and queried more than others. Choosing a random set
+        // means we will probably eventually remove less useful elements.
+        // An LRU cache is too expensive for this commonly used utility class.
+        final Random rand = new Random();
+        final int numToPurge = Math.max(1, MAX_NUM_CACHED_ENTRIES_PER_USER / 100);
+        for (int i = 0; i < numToPurge && numCached > 0; ++i) {
+            final int removeIdx = rand.nextInt(numCached--);
+            sCache.deleteAt(uIdx, removeIdx);
+        }
+    }
 }
diff --git a/core/java/android/content/res/FontScaleConverterFactory.java b/core/java/android/content/res/FontScaleConverterFactory.java
index ffdc7b38..6b09c30 100644
--- a/core/java/android/content/res/FontScaleConverterFactory.java
+++ b/core/java/android/content/res/FontScaleConverterFactory.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.util.MathUtils;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -98,22 +99,81 @@
     public static FontScaleConverter forScale(float fontScale) {
         if (fontScale <= 1) {
             // We don't need non-linear curves for shrinking text or for 100%.
-            // Also, fontScale==0 should not have a curve either
+            // Also, fontScale==0 should not have a curve either.
+            // And ignore negative font scales; that's just silly.
             return null;
         }
 
         FontScaleConverter lookupTable = get(fontScale);
-        // TODO(b/247861716): interpolate between two tables when null
+        if (lookupTable != null) {
+            return lookupTable;
+        }
 
-        return lookupTable;
+        // Didn't find an exact match: interpolate between two existing tables
+        final int index = LOOKUP_TABLES.indexOfKey(getKey(fontScale));
+        if (index >= 0) {
+            // This should never happen, should have been covered by get() above.
+            return LOOKUP_TABLES.valueAt(index);
+        }
+        // Didn't find an exact match: interpolate between two existing tables
+        final int lowerIndex = -(index + 1) - 1;
+        final int higherIndex = lowerIndex + 1;
+        if (lowerIndex < 0 || higherIndex >= LOOKUP_TABLES.size()) {
+            // We have gone beyond our bounds and have nothing to interpolate between. Just give
+            // them a straight linear table instead.
+            // This works because when FontScaleConverter encounters a size beyond its bounds, it
+            // calculates a linear fontScale factor using the ratio of the last element pair.
+            return new FontScaleConverter(new float[] {1f}, new float[] {fontScale});
+        } else {
+            float startScale = getScaleFromKey(LOOKUP_TABLES.keyAt(lowerIndex));
+            float endScale = getScaleFromKey(LOOKUP_TABLES.keyAt(higherIndex));
+            float interpolationPoint = MathUtils.constrainedMap(
+                    /* rangeMin= */ 0f,
+                    /* rangeMax= */ 1f,
+                    startScale,
+                    endScale,
+                    fontScale
+            );
+            return createInterpolatedTableBetween(
+                    LOOKUP_TABLES.valueAt(lowerIndex),
+                    LOOKUP_TABLES.valueAt(higherIndex),
+                    interpolationPoint);
+        }
+    }
+
+    @NonNull
+    private static FontScaleConverter createInterpolatedTableBetween(
+            FontScaleConverter start,
+            FontScaleConverter end,
+            float interpolationPoint
+    ) {
+        float[] commonSpSizes = new float[] { 8f, 10f, 12f, 14f, 18f, 20f, 24f, 30f, 100f};
+        float[] dpInterpolated = new float[commonSpSizes.length];
+
+        for (int i = 0; i < commonSpSizes.length; i++) {
+            float sp = commonSpSizes[i];
+            float startDp = start.convertSpToDp(sp);
+            float endDp = end.convertSpToDp(sp);
+            dpInterpolated[i] = MathUtils.lerp(startDp, endDp, interpolationPoint);
+        }
+
+        return new FontScaleConverter(commonSpSizes, dpInterpolated);
+    }
+
+    private static int getKey(float fontScale) {
+        return (int) (fontScale * SCALE_KEY_MULTIPLIER);
+    }
+
+    private static float getScaleFromKey(int key) {
+        return (float) key / SCALE_KEY_MULTIPLIER;
     }
 
     private static void put(float scaleKey, @NonNull FontScaleConverter fontScaleConverter) {
-        LOOKUP_TABLES.put((int) (scaleKey * SCALE_KEY_MULTIPLIER), fontScaleConverter);
+        LOOKUP_TABLES.put(getKey(scaleKey), fontScaleConverter);
     }
 
     @Nullable
     private static FontScaleConverter get(float scaleKey) {
-        return LOOKUP_TABLES.get((int) (scaleKey * SCALE_KEY_MULTIPLIER));
+        return LOOKUP_TABLES.get(getKey(scaleKey));
     }
 }
diff --git a/core/java/android/credentials/CreateCredentialRequest.java b/core/java/android/credentials/CreateCredentialRequest.java
index b756a43..fc3dc79 100644
--- a/core/java/android/credentials/CreateCredentialRequest.java
+++ b/core/java/android/credentials/CreateCredentialRequest.java
@@ -244,7 +244,7 @@
     /** A builder for {@link CreateCredentialRequest}. */
     public static final class Builder {
 
-        private boolean mAlwaysSendAppInfoToProvider;
+        private boolean mAlwaysSendAppInfoToProvider = true;
 
         @NonNull
         private String mType;
@@ -260,11 +260,17 @@
         private String mOrigin;
 
         /**
+         * @param type the type of the credential to be stored
          * @param credentialData the full credential creation request data
          * @param candidateQueryData the partial request data that will be sent to the provider
          *                           during the initial creation candidate query stage
          */
-        public Builder(@NonNull Bundle credentialData, @NonNull Bundle candidateQueryData) {
+        public Builder(
+                @NonNull String type,
+                @NonNull Bundle credentialData,
+                @NonNull Bundle candidateQueryData) {
+            mType = Preconditions.checkStringNotEmpty(type,
+                    "type must not be null or empty");
             mCredentialData = requireNonNull(credentialData,
                     "credentialData must not be null");
             mCandidateQueryData = requireNonNull(candidateQueryData,
@@ -291,16 +297,6 @@
         }
 
         /**
-         * Sets the requested credential type.
-         */
-        @SuppressLint("MissingGetterMatchingBuilder")
-        @NonNull
-        public CreateCredentialRequest.Builder setType(@NonNull String type) {
-            mType = type;
-            return this;
-        }
-
-        /**
          * Sets whether the request must only be fulfilled by a system provider.
          * This defaults to false
          */
diff --git a/core/java/android/credentials/CredentialManager.java b/core/java/android/credentials/CredentialManager.java
index f0230e7..493a4ff 100644
--- a/core/java/android/credentials/CredentialManager.java
+++ b/core/java/android/credentials/CredentialManager.java
@@ -26,12 +26,12 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemService;
+import android.annotation.TestApi;
 import android.app.Activity;
 import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.IntentSender;
-import android.content.pm.ServiceInfo;
 import android.os.CancellationSignal;
 import android.os.ICancellationSignal;
 import android.os.OutcomeReceiver;
@@ -75,21 +75,21 @@
      *
      * @hide
      */
-    public static final int PROVIDER_FILTER_ALL_PROVIDERS = 0;
+    @TestApi public static final int PROVIDER_FILTER_ALL_PROVIDERS = 0;
 
     /**
      * Returns system credential providers only.
      *
      * @hide
      */
-    public static final int PROVIDER_FILTER_SYSTEM_PROVIDERS_ONLY = 1;
+    @TestApi public static final int PROVIDER_FILTER_SYSTEM_PROVIDERS_ONLY = 1;
 
     /**
      * Returns user credential providers only.
      *
      * @hide
      */
-    public static final int PROVIDER_FILTER_USER_PROVIDERS_ONLY = 2;
+    @TestApi public static final int PROVIDER_FILTER_USER_PROVIDERS_ONLY = 2;
 
     private final Context mContext;
     private final ICredentialManager mService;
@@ -167,6 +167,48 @@
     }
 
     /**
+     * Gets a {@link GetPendingCredentialResponse} that can launch the credential retrieval UI flow
+     * to request a user credential for your app.
+     *
+     * @param request            the request specifying type(s) of credentials to get from the user
+     * @param cancellationSignal an optional signal that allows for cancelling this call
+     * @param executor           the callback will take place on this {@link Executor}
+     * @param callback           the callback invoked when the request succeeds or fails
+     *
+     * @hide
+     */
+    public void getPendingCredential(
+            @NonNull GetCredentialRequest request,
+            @Nullable CancellationSignal cancellationSignal,
+            @CallbackExecutor @NonNull Executor executor,
+            @NonNull OutcomeReceiver<
+                    GetPendingCredentialResponse, GetCredentialException> callback) {
+        requireNonNull(request, "request must not be null");
+        requireNonNull(executor, "executor must not be null");
+        requireNonNull(callback, "callback must not be null");
+
+        if (cancellationSignal != null && cancellationSignal.isCanceled()) {
+            Log.w(TAG, "getPendingCredential already canceled");
+            return;
+        }
+
+        ICancellationSignal cancelRemote = null;
+        try {
+            cancelRemote =
+                    mService.executeGetPendingCredential(
+                            request,
+                            new GetPendingCredentialTransport(executor, callback),
+                            mContext.getOpPackageName());
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+
+        if (cancellationSignal != null && cancelRemote != null) {
+            cancellationSignal.setRemote(cancelRemote);
+        }
+    }
+
+    /**
      * Launches the necessary flows to register an app credential for the user.
      *
      * <p>The execution can potentially launch UI flows to collect user consent to creating or
@@ -263,44 +305,6 @@
     }
 
     /**
-     * Gets a list of all user configurable credential providers registered on the system. This API
-     * is intended for browsers and settings apps.
-     *
-     * @param cancellationSignal an optional signal that allows for cancelling this call
-     * @param executor the callback will take place on this {@link Executor}
-     * @param callback the callback invoked when the request succeeds or fails
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public void listEnabledProviders(
-            @Nullable CancellationSignal cancellationSignal,
-            @CallbackExecutor @NonNull Executor executor,
-            @NonNull
-                    OutcomeReceiver<ListEnabledProvidersResponse, ListEnabledProvidersException>
-                            callback) {
-        requireNonNull(executor, "executor must not be null");
-        requireNonNull(callback, "callback must not be null");
-
-        if (cancellationSignal != null && cancellationSignal.isCanceled()) {
-            Log.w(TAG, "listEnabledProviders already canceled");
-            return;
-        }
-
-        ICancellationSignal cancelRemote = null;
-        try {
-            cancelRemote =
-                    mService.listEnabledProviders(
-                            new ListEnabledProvidersTransport(executor, callback));
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-
-        if (cancellationSignal != null && cancelRemote != null) {
-            cancellationSignal.setRemote(cancelRemote);
-        }
-    }
-
-    /**
      * Sets a list of all user configurable credential providers registered on the system. This API
      * is intended for settings apps.
      *
@@ -348,36 +352,43 @@
     }
 
     /**
-     * Returns the list of ServiceInfo for all discovered credential providers on this device.
+     * Returns the list of CredentialProviderInfo for all discovered credential providers on this
+     * device but will include test system providers as well.
      *
      * @hide
      */
     @NonNull
-    @RequiresPermission(android.Manifest.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS)
-    public List<ServiceInfo> getCredentialProviderServicesForTesting(
-            @ProviderFilter int providerFilter) {
+    @TestApi
+    @RequiresPermission(
+      anyOf = {
+        android.Manifest.permission.QUERY_ALL_PACKAGES,
+        android.Manifest.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS
+      })
+    public List<CredentialProviderInfo> getCredentialProviderServicesForTesting(
+             @ProviderFilter int providerFilter) {
         try {
-            return mService.getCredentialProviderServices(
-                    mContext.getUserId(),
-                    /* disableSystemAppVerificationForTests= */ true,
-                    providerFilter);
+            return mService.getCredentialProviderServicesForTesting(providerFilter);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
     /**
-     * Returns the list of ServiceInfo for all discovered credential providers on this device.
+     * Returns the list of CredentialProviderInfo for all discovered credential providers on this
+     * device.
      *
      * @hide
      */
     @NonNull
-    @RequiresPermission(android.Manifest.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS)
-    public List<ServiceInfo> getCredentialProviderServices(
+    @RequiresPermission(
+      anyOf = {
+        android.Manifest.permission.QUERY_ALL_PACKAGES,
+        android.Manifest.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS
+      })
+    public List<CredentialProviderInfo> getCredentialProviderServices(
             int userId, @ProviderFilter int providerFilter) {
         try {
-            return mService.getCredentialProviderServices(
-                    userId, /* disableSystemAppVerificationForTests= */ false, providerFilter);
+            return mService.getCredentialProviderServices(userId, providerFilter);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -388,7 +399,9 @@
      *
      * @hide
      */
-    public static boolean isServiceEnabled(Context context) {
+    @TestApi
+    public static boolean isServiceEnabled(@NonNull Context context) {
+        requireNonNull(context, "context must not be null");
         if (context == null) {
             return false;
         }
@@ -471,6 +484,32 @@
         }
     }
 
+    private static class GetPendingCredentialTransport extends IGetPendingCredentialCallback.Stub {
+        // TODO: listen for cancellation to release callback.
+
+        private final Executor mExecutor;
+        private final OutcomeReceiver<
+                GetPendingCredentialResponse, GetCredentialException> mCallback;
+
+        private GetPendingCredentialTransport(
+                Executor executor,
+                OutcomeReceiver<GetPendingCredentialResponse, GetCredentialException> callback) {
+            mExecutor = executor;
+            mCallback = callback;
+        }
+
+        @Override
+        public void onResponse(GetPendingCredentialResponse response) {
+            mExecutor.execute(() -> mCallback.onResult(response));
+        }
+
+        @Override
+        public void onError(String errorType, String message) {
+            mExecutor.execute(
+                    () -> mCallback.onError(new GetCredentialException(errorType, message)));
+        }
+    }
+
     private static class GetCredentialTransport extends IGetCredentialCallback.Stub {
         // TODO: listen for cancellation to release callback.
 
@@ -578,33 +617,6 @@
         }
     }
 
-    private static class ListEnabledProvidersTransport extends IListEnabledProvidersCallback.Stub {
-        // TODO: listen for cancellation to release callback.
-
-        private final Executor mExecutor;
-        private final OutcomeReceiver<ListEnabledProvidersResponse, ListEnabledProvidersException>
-                mCallback;
-
-        private ListEnabledProvidersTransport(
-                Executor executor,
-                OutcomeReceiver<ListEnabledProvidersResponse, ListEnabledProvidersException>
-                        callback) {
-            mExecutor = executor;
-            mCallback = callback;
-        }
-
-        @Override
-        public void onResponse(ListEnabledProvidersResponse response) {
-            mExecutor.execute(() -> mCallback.onResult(response));
-        }
-
-        @Override
-        public void onError(String errorType, String message) {
-            mExecutor.execute(
-                    () -> mCallback.onError(new ListEnabledProvidersException(errorType, message)));
-        }
-    }
-
     private static class SetEnabledProvidersTransport extends ISetEnabledProvidersCallback.Stub {
         // TODO: listen for cancellation to release callback.
 
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl b/core/java/android/credentials/CredentialProviderInfo.aidl
similarity index 81%
copy from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
copy to core/java/android/credentials/CredentialProviderInfo.aidl
index 35d5c15..30b7742 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
+++ b/core/java/android/credentials/CredentialProviderInfo.aidl
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.net.wifi.sharedconnectivity.app;
+package android.credentials;
 
-parcelable DeviceInfo;
\ No newline at end of file
+parcelable CredentialProviderInfo;
\ No newline at end of file
diff --git a/core/java/android/credentials/CredentialProviderInfo.java b/core/java/android/credentials/CredentialProviderInfo.java
new file mode 100644
index 0000000..7276770
--- /dev/null
+++ b/core/java/android/credentials/CredentialProviderInfo.java
@@ -0,0 +1,215 @@
+/*
+ * 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.credentials;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.TestApi;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ServiceInfo;
+import android.graphics.drawable.Drawable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * {@link ServiceInfo} and meta-data about a credential provider.
+ *
+ * @hide
+ */
+@TestApi
+public final class CredentialProviderInfo implements Parcelable {
+    @NonNull private final ServiceInfo mServiceInfo;
+    @NonNull private final List<String> mCapabilities = new ArrayList<>();
+    @Nullable private final CharSequence mOverrideLabel;
+    private final boolean mIsSystemProvider;
+    private final boolean mIsEnabled;
+
+    /**
+     * Constructs an information instance of the credential provider.
+     *
+     * @param builder the builder object.
+     */
+    private CredentialProviderInfo(@NonNull Builder builder) {
+        mServiceInfo = builder.mServiceInfo;
+        mCapabilities.addAll(builder.mCapabilities);
+        mIsSystemProvider = builder.mIsSystemProvider;
+        mIsEnabled = builder.mIsEnabled;
+        mOverrideLabel = builder.mOverrideLabel;
+    }
+
+    /** Returns true if the service supports the given {@code credentialType}, false otherwise. */
+    @NonNull
+    public boolean hasCapability(@NonNull String credentialType) {
+        return mCapabilities.contains(credentialType);
+    }
+
+    /** Returns the service info. */
+    @NonNull
+    public ServiceInfo getServiceInfo() {
+        return mServiceInfo;
+    }
+
+    /** Returns whether it is a system provider. */
+    public boolean isSystemProvider() {
+        return mIsSystemProvider;
+    }
+
+    /** Returns the service icon. */
+    @Nullable
+    public Drawable getServiceIcon(@NonNull Context context) {
+        return mServiceInfo.loadIcon(context.getPackageManager());
+    }
+
+    /** Returns the service label. */
+    @Nullable
+    public CharSequence getLabel(@NonNull Context context) {
+        if (mOverrideLabel != null) {
+            return mOverrideLabel;
+        }
+        return mServiceInfo.loadSafeLabel(context.getPackageManager());
+    }
+
+    /** Returns a list of capabilities this provider service can support. */
+    @NonNull
+    public List<String> getCapabilities() {
+        return Collections.unmodifiableList(mCapabilities);
+    }
+
+    /** Returns whether the provider is enabled by the user. */
+    public boolean isEnabled() {
+        return mIsEnabled;
+    }
+
+    /** Returns the component name for the service. */
+    @NonNull
+    public ComponentName getComponentName() {
+        return mServiceInfo.getComponentName();
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeTypedObject(mServiceInfo, flags);
+        dest.writeBoolean(mIsSystemProvider);
+        dest.writeStringList(mCapabilities);
+        dest.writeBoolean(mIsEnabled);
+        TextUtils.writeToParcel(mOverrideLabel, dest, flags);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public String toString() {
+        return "CredentialProviderInfo {"
+                + "serviceInfo="
+                + mServiceInfo
+                + ", "
+                + "isSystemProvider="
+                + mIsSystemProvider
+                + ", "
+                + "isEnabled="
+                + mIsEnabled
+                + ", "
+                + "overrideLabel="
+                + mOverrideLabel
+                + ", "
+                + "capabilities="
+                + String.join(",", mCapabilities)
+                + "}";
+    }
+
+    private CredentialProviderInfo(@NonNull Parcel in) {
+        mServiceInfo = in.readTypedObject(ServiceInfo.CREATOR);
+        mIsSystemProvider = in.readBoolean();
+        in.readStringList(mCapabilities);
+        mIsEnabled = in.readBoolean();
+        mOverrideLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+    }
+
+    public static final @NonNull Parcelable.Creator<CredentialProviderInfo> CREATOR =
+            new Parcelable.Creator<CredentialProviderInfo>() {
+                @Override
+                public CredentialProviderInfo[] newArray(int size) {
+                    return new CredentialProviderInfo[size];
+                }
+
+                @Override
+                public CredentialProviderInfo createFromParcel(@NonNull Parcel in) {
+                    return new CredentialProviderInfo(in);
+                }
+            };
+
+    /** A builder for {@link CredentialProviderInfo} objects. */
+    public static final class Builder {
+
+        @NonNull private ServiceInfo mServiceInfo;
+        @NonNull private List<String> mCapabilities = new ArrayList<>();
+        private boolean mIsSystemProvider = false;
+        private boolean mIsEnabled = false;
+        @Nullable private CharSequence mOverrideLabel = null;
+
+        /**
+         * Creates a new builder.
+         *
+         * @param serviceInfo the service info of the credential provider service.
+         */
+        public Builder(@NonNull ServiceInfo serviceInfo) {
+            mServiceInfo = serviceInfo;
+        }
+
+        /** Sets whether it is a system provider. */
+        public @NonNull Builder setSystemProvider(boolean isSystemProvider) {
+            mIsSystemProvider = isSystemProvider;
+            return this;
+        }
+
+        /**
+         * Sets the label to be used instead of getting from the system (for unit tests).
+         *
+         * @hide
+         */
+        public @NonNull Builder setOverrideLabel(@NonNull CharSequence overrideLabel) {
+            mOverrideLabel = overrideLabel;
+            return this;
+        }
+
+        /** Sets a list of capabilities this provider service can support. */
+        public @NonNull Builder addCapabilities(@NonNull List<String> capabilities) {
+            mCapabilities.addAll(capabilities);
+            return this;
+        }
+
+        /** Sets whether it is enabled by the user. */
+        public @NonNull Builder setEnabled(boolean isEnabled) {
+            mIsEnabled = isEnabled;
+            return this;
+        }
+
+        /** Builds a new {@link CredentialProviderInfo} instance. */
+        public @NonNull CredentialProviderInfo build() {
+            return new CredentialProviderInfo(this);
+        }
+    }
+}
diff --git a/core/java/android/credentials/GetCredentialRequest.java b/core/java/android/credentials/GetCredentialRequest.java
index 951cbe4..c58d2dc 100644
--- a/core/java/android/credentials/GetCredentialRequest.java
+++ b/core/java/android/credentials/GetCredentialRequest.java
@@ -149,7 +149,6 @@
         mCredentialOptions = credentialOptions;
         AnnotationValidations.validate(NonNull.class, null, mCredentialOptions);
 
-
         Bundle data = in.readBundle();
         mData = data;
         AnnotationValidations.validate(NonNull.class, null, mData);
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl b/core/java/android/credentials/GetPendingCredentialResponse.aidl
similarity index 81%
copy from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
copy to core/java/android/credentials/GetPendingCredentialResponse.aidl
index 35d5c15..1cdd637 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
+++ b/core/java/android/credentials/GetPendingCredentialResponse.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright 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.
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.net.wifi.sharedconnectivity.app;
+package android.credentials;
 
-parcelable DeviceInfo;
\ No newline at end of file
+parcelable GetPendingCredentialResponse;
\ No newline at end of file
diff --git a/core/java/android/credentials/GetPendingCredentialResponse.java b/core/java/android/credentials/GetPendingCredentialResponse.java
new file mode 100644
index 0000000..9005d9d
--- /dev/null
+++ b/core/java/android/credentials/GetPendingCredentialResponse.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.credentials;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.os.CancellationSignal;
+import android.os.OutcomeReceiver;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.concurrent.Executor;
+
+
+/**
+ * A response object that prefetches user app credentials and provides metadata about them. It can
+ * then be used to issue the full credential retrieval flow via the
+ * {@link #show(Activity, CancellationSignal, Executor, OutcomeReceiver)} method to perform the
+ * necessary flows such as consent collection and officially retrieve a credential.
+ *
+ * @hide
+ */
+public final class GetPendingCredentialResponse implements Parcelable {
+    private final boolean mHasCredentialResults;
+    private final boolean mHasAuthenticationResults;
+    private final boolean mHasRemoteResults;
+
+    /** Returns true if the user has any candidate credentials, and false otherwise. */
+    public boolean hasCredentialResults() {
+        return mHasCredentialResults;
+    }
+
+    /**
+     * Returns true if the user has any candidate authentication actions (locked credential
+     * supplier), and false otherwise.
+     */
+    public boolean hasAuthenticationResults() {
+        return mHasAuthenticationResults;
+    }
+
+    /**
+     * Returns true if the user has any candidate remote credential results, and false otherwise.
+     */
+    public boolean hasRemoteResults() {
+        return mHasRemoteResults;
+    }
+
+    /**
+     * Launches the necessary flows such as consent collection and credential selection to
+     * officially retrieve a credential among the pending credential candidates.
+     *
+     * @param activity           the activity used to launch any UI needed
+     * @param cancellationSignal an optional signal that allows for cancelling this call
+     * @param executor           the callback will take place on this {@link Executor}
+     * @param callback           the callback invoked when the request succeeds or fails
+     */
+    public void show(@NonNull Activity activity, @Nullable CancellationSignal cancellationSignal,
+            @CallbackExecutor @NonNull Executor executor,
+            @NonNull OutcomeReceiver<GetCredentialResponse, GetCredentialException> callback) {
+        // TODO(b/273308895): implement
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeBoolean(mHasCredentialResults);
+        dest.writeBoolean(mHasAuthenticationResults);
+        dest.writeBoolean(mHasRemoteResults);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public String toString() {
+        return "GetCredentialResponse {" + "credential=" + mHasCredentialResults + "}";
+    }
+
+    /**
+     * Constructs a {@link GetPendingCredentialResponse}.
+     *
+     * @param hasCredentialResults whether the user has any candidate credentials
+     * @param hasAuthenticationResults whether the user has any candidate authentication actions
+     * @param hasRemoteResults whether the user has any candidate remote options
+     */
+    public GetPendingCredentialResponse(boolean hasCredentialResults,
+            boolean hasAuthenticationResults, boolean hasRemoteResults) {
+        mHasCredentialResults = hasCredentialResults;
+        mHasAuthenticationResults = hasAuthenticationResults;
+        mHasRemoteResults = hasRemoteResults;
+    }
+
+    private GetPendingCredentialResponse(@NonNull Parcel in) {
+        mHasCredentialResults = in.readBoolean();
+        mHasAuthenticationResults = in.readBoolean();
+        mHasRemoteResults = in.readBoolean();
+    }
+
+    public static final @NonNull Creator<GetPendingCredentialResponse> CREATOR = new Creator<>() {
+        @Override
+        public GetPendingCredentialResponse[] newArray(int size) {
+            return new GetPendingCredentialResponse[size];
+        }
+
+        @Override
+        public GetPendingCredentialResponse createFromParcel(@NonNull Parcel in) {
+            return new GetPendingCredentialResponse(in);
+        }
+    };
+}
diff --git a/core/java/android/credentials/ICredentialManager.aidl b/core/java/android/credentials/ICredentialManager.aidl
index 625fc8a..af8e7b4 100644
--- a/core/java/android/credentials/ICredentialManager.aidl
+++ b/core/java/android/credentials/ICredentialManager.aidl
@@ -18,7 +18,7 @@
 
 import java.util.List;
 
-import android.content.pm.ServiceInfo;
+import android.credentials.CredentialProviderInfo;
 import android.credentials.ClearCredentialStateRequest;
 import android.credentials.CreateCredentialRequest;
 import android.credentials.GetCredentialRequest;
@@ -27,7 +27,7 @@
 import android.credentials.IClearCredentialStateCallback;
 import android.credentials.ICreateCredentialCallback;
 import android.credentials.IGetCredentialCallback;
-import android.credentials.IListEnabledProvidersCallback;
+import android.credentials.IGetPendingCredentialCallback;
 import android.credentials.ISetEnabledProvidersCallback;
 import android.content.ComponentName;
 import android.os.ICancellationSignal;
@@ -41,12 +41,12 @@
 
     @nullable ICancellationSignal executeGetCredential(in GetCredentialRequest request, in IGetCredentialCallback callback, String callingPackage);
 
+    @nullable ICancellationSignal executeGetPendingCredential(in GetCredentialRequest request, in IGetPendingCredentialCallback callback, String callingPackage);
+
     @nullable ICancellationSignal executeCreateCredential(in CreateCredentialRequest request, in ICreateCredentialCallback callback, String callingPackage);
 
     @nullable ICancellationSignal clearCredentialState(in ClearCredentialStateRequest request, in IClearCredentialStateCallback callback, String callingPackage);
 
-    @nullable ICancellationSignal listEnabledProviders(in IListEnabledProvidersCallback callback);
-
     void setEnabledProviders(in List<String> providers, in int userId, in ISetEnabledProvidersCallback callback);
 
     void registerCredentialDescription(in RegisterCredentialDescriptionRequest request, String callingPackage);
@@ -55,6 +55,8 @@
 
     boolean isEnabledCredentialProviderService(in ComponentName componentName, String callingPackage);
 
-    List<ServiceInfo> getCredentialProviderServices(in int userId, in boolean disableSystemAppVerificationForTests, in int providerFilter);
+    List<CredentialProviderInfo> getCredentialProviderServices(in int userId, in int providerFilter);
+
+    List<CredentialProviderInfo> getCredentialProviderServicesForTesting(in int providerFilter);
 }
 
diff --git a/core/java/android/credentials/IListEnabledProvidersCallback.aidl b/core/java/android/credentials/IGetPendingCredentialCallback.aidl
similarity index 74%
rename from core/java/android/credentials/IListEnabledProvidersCallback.aidl
rename to core/java/android/credentials/IGetPendingCredentialCallback.aidl
index 3a8e25ed..4ab0f99 100644
--- a/core/java/android/credentials/IListEnabledProvidersCallback.aidl
+++ b/core/java/android/credentials/IGetPendingCredentialCallback.aidl
@@ -16,14 +16,15 @@
 
 package android.credentials;
 
-import android.credentials.ListEnabledProvidersResponse;
+import android.app.PendingIntent;
+import android.credentials.GetPendingCredentialResponse;
 
 /**
- * Listener for an listEnabledProviders request.
+ * Listener for a executeGetPendingCredential request.
  *
  * @hide
  */
-interface IListEnabledProvidersCallback {
-    oneway void onResponse(in ListEnabledProvidersResponse response);
+interface IGetPendingCredentialCallback {
+    oneway void onResponse(in GetPendingCredentialResponse response);
     oneway void onError(String errorType, String message);
 }
\ No newline at end of file
diff --git a/core/java/android/credentials/ui/Entry.java b/core/java/android/credentials/ui/Entry.java
index 12665ba..55f2a3e 100644
--- a/core/java/android/credentials/ui/Entry.java
+++ b/core/java/android/credentials/ui/Entry.java
@@ -70,17 +70,6 @@
     /** Constructor to be used for an entry that requires a pending intent to be invoked
      * when clicked.
      */
-    // TODO: Remove this constructor as it is no longer used
-    public Entry(@NonNull String key, @NonNull String subkey, @NonNull Slice slice,
-            @NonNull PendingIntent pendingIntent, @NonNull Intent intent) {
-        this(key, subkey, slice);
-        mPendingIntent = pendingIntent;
-        mFrameworkExtrasIntent = intent;
-    }
-
-    /** Constructor to be used for an entry that requires a pending intent to be invoked
-     * when clicked.
-     */
     public Entry(@NonNull String key, @NonNull String subkey, @NonNull Slice slice,
             @NonNull Intent intent) {
         this(key, subkey, slice);
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 1a3e0b0..73157e6 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -92,7 +92,8 @@
     private static native boolean nativeIsDataInjectionEnabled(long nativeInstance);
 
     private static native int nativeCreateDirectChannel(
-            long nativeInstance, long size, int channelType, int fd, HardwareBuffer buffer);
+            long nativeInstance, int deviceId, long size, int channelType, int fd,
+            HardwareBuffer buffer);
     private static native void nativeDestroyDirectChannel(
             long nativeInstance, int channelHandle);
     private static native int nativeConfigDirectChannel(
@@ -695,6 +696,10 @@
     /** @hide */
     protected SensorDirectChannel createDirectChannelImpl(
             MemoryFile memoryFile, HardwareBuffer hardwareBuffer) {
+        int deviceId = mContext.getDeviceId();
+        if (isDeviceSensorPolicyDefault(deviceId)) {
+            deviceId = DEVICE_ID_DEFAULT;
+        }
         int id;
         int type;
         long size;
@@ -713,8 +718,8 @@
             }
 
             size = memoryFile.length();
-            id = nativeCreateDirectChannel(
-                    mNativeInstance, size, SensorDirectChannel.TYPE_MEMORY_FILE, fd, null);
+            id = nativeCreateDirectChannel(mNativeInstance, deviceId, size,
+                    SensorDirectChannel.TYPE_MEMORY_FILE, fd, null);
             if (id <= 0) {
                 throw new UncheckedIOException(
                         new IOException("create MemoryFile direct channel failed " + id));
@@ -738,7 +743,7 @@
             }
             size = hardwareBuffer.getWidth();
             id = nativeCreateDirectChannel(
-                    mNativeInstance, size, SensorDirectChannel.TYPE_HARDWARE_BUFFER,
+                    mNativeInstance, deviceId, size, SensorDirectChannel.TYPE_HARDWARE_BUFFER,
                     -1, hardwareBuffer);
             if (id <= 0) {
                 throw new UncheckedIOException(
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index fbc0184..722dd08 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -118,13 +118,6 @@
     public static final long OVERRIDE_CAMERA_LANDSCAPE_TO_PORTRAIT = 250678880L;
 
     /**
-     * Package-level opt in/out for the above.
-     * @hide
-     */
-    public static final String PROPERTY_COMPAT_OVERRIDE_LANDSCAPE_TO_PORTRAIT =
-            "android.camera.PROPERTY_COMPAT_OVERRIDE_LANDSCAPE_TO_PORTRAIT";
-
-    /**
      * System property for allowing the above
      * @hide
      */
@@ -1189,8 +1182,9 @@
             PackageManager packageManager = context.getPackageManager();
 
             try {
-                return packageManager.getProperty(context.getOpPackageName(),
-                            PROPERTY_COMPAT_OVERRIDE_LANDSCAPE_TO_PORTRAIT).getBoolean();
+                return packageManager.getProperty(
+                        PackageManager.PROPERTY_COMPAT_OVERRIDE_LANDSCAPE_TO_PORTRAIT,
+                        context.getOpPackageName()).getBoolean();
             } catch (PackageManager.NameNotFoundException e) {
                 // No such property
             }
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 9640b0e..631df01 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -1132,6 +1132,12 @@
 
     private boolean setGpsLocation(Location l) {
         if (l == null) {
+            // If Location value being set is null, remove corresponding keys.
+            // This is safe because api1/client2/CameraParameters.cpp already erases
+            // the keys for JPEG_GPS_LOCATION for certain cases.
+            setBase(CaptureRequest.JPEG_GPS_TIMESTAMP, null);
+            setBase(CaptureRequest.JPEG_GPS_COORDINATES, null);
+            setBase(CaptureRequest.JPEG_GPS_PROCESSING_METHOD, null);
             return false;
         }
 
diff --git a/core/java/android/hardware/camera2/params/DynamicRangeProfiles.java b/core/java/android/hardware/camera2/params/DynamicRangeProfiles.java
index 34c8336..7cd627d 100644
--- a/core/java/android/hardware/camera2/params/DynamicRangeProfiles.java
+++ b/core/java/android/hardware/camera2/params/DynamicRangeProfiles.java
@@ -181,13 +181,15 @@
      * for a given camera id in order to retrieve the device capabilities.</p>
      *
      * @param elements
-     *          An array of elements describing the map. It contains two elements per entry which
-     *          describe the supported dynamic range profile value in the first element and in the
-     *          second element a bitmap of concurrently supported dynamic range profiles within the
-     *          same capture request. Bitmap values of 0 indicate that there are no constraints.
+     *          An array of elements describing the map. It contains three elements per entry. The
+     *          first element describes the supported dynamic range profile value. The
+     *          second element contains a bitmap of concurrently supported dynamic range profiles
+     *          within the same capture request. The third element contains a hint about
+     *          extra latency associated with the corresponding dynamic range. Bitmap values of 0
+     *          indicate that there are no constraints.
      *
      * @throws IllegalArgumentException
-     *            if the {@code elements} array length is invalid, not divisible by 2 or contains
+     *            if the {@code elements} array length is invalid, not divisible by 3 or contains
      *            invalid element values
      * @throws NullPointerException
      *            if {@code elements} is {@code null}
diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
index cb678b9..5a48176 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -26,7 +26,6 @@
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.utils.HashCodeHelpers;
 import android.hardware.camera2.utils.SurfaceUtils;
-import android.util.Log;
 import android.util.Range;
 import android.util.Size;
 import android.util.SparseIntArray;
@@ -2019,7 +2018,7 @@
     /**
      * @hide
      */
-    public static final int HAL_DATASPACE_HEIF = 0x1003;
+    public static final int HAL_DATASPACE_HEIF = 0x1004;
     /**
      * @hide
      */
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index b766cd1..6ae71d2 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -989,24 +989,6 @@
 
     /**
      * Creates a virtual display.
-     *
-     * @see #createVirtualDisplay(String, int, int, int, float, Surface, int,
-     * Handler, VirtualDisplay.Callback)
-     */
-    @Nullable
-    public VirtualDisplay createVirtualDisplay(@NonNull String name,
-            @IntRange(from = 1) int width,
-            @IntRange(from = 1) int height,
-            @IntRange(from = 1) int densityDpi,
-            float requestedRefreshRate,
-            @Nullable Surface surface,
-            @VirtualDisplayFlag int flags) {
-        return createVirtualDisplay(name, width, height, densityDpi, requestedRefreshRate,
-                surface, flags, null, null);
-    }
-
-    /**
-     * Creates a virtual display.
      * <p>
      * The content of a virtual display is rendered to a {@link Surface} provided
      * by the application.
@@ -1056,8 +1038,23 @@
             @VirtualDisplayFlag int flags,
             @Nullable VirtualDisplay.Callback callback,
             @Nullable Handler handler) {
-        return createVirtualDisplay(name, width, height, densityDpi, 0.0f, surface,
-                flags, handler, callback);
+        final VirtualDisplayConfig.Builder builder =
+                new VirtualDisplayConfig.Builder(name, width, height, densityDpi);
+        builder.setFlags(flags);
+        if (surface != null) {
+            builder.setSurface(surface);
+        }
+        return createVirtualDisplay(builder.build(), handler, callback);
+    }
+
+    /**
+     * Creates a virtual display.
+     *
+     * @see #createVirtualDisplay(VirtualDisplayConfig, Handler, VirtualDisplay.Callback)
+     */
+    @Nullable
+    public VirtualDisplay createVirtualDisplay(@NonNull VirtualDisplayConfig config) {
+        return createVirtualDisplay(config, /*handler=*/null, /*callback=*/null);
     }
 
     /**
@@ -1084,21 +1081,7 @@
      * turning off the screen.
      * </p>
      *
-     * @param name The name of the virtual display, must be non-empty.
-     * @param width The width of the virtual display in pixels, must be greater than 0.
-     * @param height The height of the virtual display in pixels, must be greater than 0.
-     * @param densityDpi The density of the virtual display in dpi, must be greater than 0.
-     * @param requestedRefreshRate The requested refresh rate in frames per second.
-     * For best results, specify a divisor of the physical refresh rate, e.g., 30 or 60 on
-     * 120hz display. If an arbitrary refresh rate is specified, the rate will be rounded
-     * up or down to a divisor of the physical display. If 0 is specified, the virtual
-     * display is refreshed at the physical display refresh rate.
-     * @param surface The surface to which the content of the virtual display should
-     * be rendered, or null if there is none initially.
-     * @param flags A combination of virtual display flags:
-     * {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}, {@link #VIRTUAL_DISPLAY_FLAG_PRESENTATION},
-     * {@link #VIRTUAL_DISPLAY_FLAG_SECURE}, {@link #VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY},
-     * or {@link #VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}.
+     * @param config The configuration of the virtual display, must be non-null.
      * @param handler The handler on which the listener should be invoked, or null
      * if the listener should be invoked on the calling thread's looper.
      * @param callback Callback to call when the state of the {@link VirtualDisplay} changes
@@ -1106,33 +1089,14 @@
      * not create the virtual display.
      *
      * @throws SecurityException if the caller does not have permission to create
-     * a virtual display with the specified flags.
+     * a virtual display with flags specified in the configuration.
      */
     @Nullable
-    public VirtualDisplay createVirtualDisplay(@NonNull String name,
-            @IntRange(from = 1) int width,
-            @IntRange(from = 1) int height,
-            @IntRange(from = 1) int densityDpi,
-            float requestedRefreshRate,
-            @Nullable Surface surface,
-            @VirtualDisplayFlag int flags,
+    public VirtualDisplay createVirtualDisplay(
+            @NonNull VirtualDisplayConfig config,
             @Nullable Handler handler,
             @Nullable VirtualDisplay.Callback callback) {
-        if (!ENABLE_VIRTUAL_DISPLAY_REFRESH_RATE && requestedRefreshRate != 0.0f) {
-            Slog.e(TAG, "Please turn on ENABLE_VIRTUAL_DISPLAY_REFRESH_RATE to use the new api");
-            return null;
-        }
-
-        final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width,
-                height, densityDpi);
-        builder.setFlags(flags);
-        if (surface != null) {
-            builder.setSurface(surface);
-        }
-        if (requestedRefreshRate != 0.0f) {
-            builder.setRequestedRefreshRate(requestedRefreshRate);
-        }
-        return createVirtualDisplay(null /* projection */, builder.build(), callback, handler,
+        return createVirtualDisplay(null /* projection */, config, callback, handler,
                 null /* windowContext */);
     }
 
@@ -1445,9 +1409,10 @@
      * @param hdrConversionMode The {@link HdrConversionMode} to set.
      * Note, {@code HdrConversionMode.preferredHdrOutputType} is only applicable when
      * {@code HdrConversionMode.conversionMode} is {@link HdrConversionMode#HDR_CONVERSION_FORCE}.
+     * If {@code HdrConversionMode.preferredHdrOutputType} is not set in case when
+     * {@code HdrConversionMode.conversionMode} is {@link HdrConversionMode#HDR_CONVERSION_FORCE},
+     * it means that preferred output type is SDR.
      *
-     * @throws IllegalArgumentException if hdrConversionMode.preferredHdrOutputType is not set
-     * when hdrConversionMode.conversionMode is {@link HdrConversionMode#HDR_CONVERSION_FORCE}.
      * @throws IllegalArgumentException if hdrConversionMode.preferredHdrOutputType is set but
      * hdrConversionMode.conversionMode is not {@link HdrConversionMode#HDR_CONVERSION_FORCE}.
      *
diff --git a/core/java/android/hardware/display/VirtualDisplayConfig.java b/core/java/android/hardware/display/VirtualDisplayConfig.java
index f6a2e33..490e55b 100644
--- a/core/java/android/hardware/display/VirtualDisplayConfig.java
+++ b/core/java/android/hardware/display/VirtualDisplayConfig.java
@@ -18,121 +18,47 @@
 
 import static android.view.Display.DEFAULT_DISPLAY;
 
+import android.annotation.FloatRange;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.hardware.display.DisplayManager.VirtualDisplayFlag;
 import android.media.projection.MediaProjection;
+import android.os.Handler;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.ArraySet;
+import android.view.ContentRecordingSession;
+import android.view.Display;
 import android.view.Surface;
 
-import com.android.internal.util.DataClass;
-
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.Set;
 
 /**
- * Holds configuration used to create {@link VirtualDisplay} instances. See
- * {@link MediaProjection#createVirtualDisplay} and
- * {@link android.companion.virtual.VirtualDeviceManager.VirtualDevice#createVirtualDisplay}.
+ * Holds configuration used to create {@link VirtualDisplay} instances.
  *
- * @hide
+ * @see DisplayManager#createVirtualDisplay(VirtualDisplayConfig, Handler, VirtualDisplay.Callback)
+ * @see MediaProjection#createVirtualDisplay
  */
-@DataClass(genParcelable = true, genAidl = true, genBuilder = true)
 public final class VirtualDisplayConfig implements Parcelable {
-    /**
-     * The name of the virtual display, must be non-empty.
-     */
-    @NonNull
-    private String mName;
 
-    /**
-     * The width of the virtual display in pixels. Must be greater than 0.
-     */
-    @IntRange(from = 1)
-    private int mWidth;
-
-    /**
-     * The height of the virtual display in pixels. Must be greater than 0.
-     */
-    @IntRange(from = 1)
-    private int mHeight;
-
-    /**
-     * The density of the virtual display in dpi. Must be greater than 0.
-     */
-    @IntRange(from = 1)
-    private int mDensityDpi;
-
-    /**
-     * A combination of virtual display flags.
-     * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PUBLIC},
-     * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PRESENTATION},
-     * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_SECURE},
-     * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY},
-     * or {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}.
-     */
-    @VirtualDisplayFlag
-    private int mFlags = 0;
-
-    /**
-     * The surface to which the content of the virtual display should be rendered, or null if
-     * there is none initially.
-     */
+    private final String mName;
+    private final int mWidth;
+    private final int mHeight;
+    private final int mDensityDpi;
+    private final int mFlags;
+    private final Surface mSurface;
+    private final String mUniqueId;
+    private final int mDisplayIdToMirror;
+    private final boolean mWindowManagerMirroringEnabled;
+    private ArraySet<String> mDisplayCategories = null;
     @Nullable
-    private Surface mSurface = null;
+    private ContentRecordingSession mContentRecordingSession;
+    private final float mRequestedRefreshRate;
 
-    /**
-     * The unique identifier for the display. Shouldn't be displayed to the user.
-     * @hide
-     */
-    @Nullable
-    private String mUniqueId = null;
-
-    /**
-     * The id of the display that the virtual display should mirror, or
-     * {@link android.view.Display#DEFAULT_DISPLAY} if there is none initially.
-     */
-    private int mDisplayIdToMirror = DEFAULT_DISPLAY;
-
-    /**
-     * Indicates if WindowManager is responsible for mirroring content to this VirtualDisplay, or
-     * if DisplayManager should record contents instead.
-     */
-    private boolean mWindowManagerMirroring = false;
-
-    /**
-     * The display categories. If set, only corresponding activities from the same category can be
-     * shown on the display.
-     */
-    @DataClass.PluralOf("displayCategory")
-    @NonNull private List<String> mDisplayCategories = new ArrayList<>();
-
-    /**
-     * The refresh rate of a virtual display in frames per second.
-     * If this value is non-zero, this is the requested refresh rate to set.
-     * If this value is zero, the system chooses a default refresh rate.
-     */
-    private float mRequestedRefreshRate = 0.0f;
-
-
-
-    // Code below generated by codegen v1.0.23.
-    //
-    // DO NOT MODIFY!
-    // CHECKSTYLE:OFF Generated code
-    //
-    // To regenerate run:
-    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/hardware/display/VirtualDisplayConfig.java
-    //
-    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
-    //   Settings > Editor > Code Style > Formatter Control
-    //@formatter:off
-
-
-    @DataClass.Generated.Member
-    /* package-private */ VirtualDisplayConfig(
+    private VirtualDisplayConfig(
             @NonNull String name,
             @IntRange(from = 1) int width,
             @IntRange(from = 1) int height,
@@ -141,220 +67,217 @@
             @Nullable Surface surface,
             @Nullable String uniqueId,
             int displayIdToMirror,
-            boolean windowManagerMirroring,
-            @NonNull List<String> displayCategories,
+            boolean windowManagerMirroringEnabled,
+            ContentRecordingSession session,
+            @NonNull ArraySet<String> displayCategories,
             float requestedRefreshRate) {
-        this.mName = name;
-        com.android.internal.util.AnnotationValidations.validate(
-                NonNull.class, null, mName);
-        this.mWidth = width;
-        com.android.internal.util.AnnotationValidations.validate(
-                IntRange.class, null, mWidth,
-                "from", 1);
-        this.mHeight = height;
-        com.android.internal.util.AnnotationValidations.validate(
-                IntRange.class, null, mHeight,
-                "from", 1);
-        this.mDensityDpi = densityDpi;
-        com.android.internal.util.AnnotationValidations.validate(
-                IntRange.class, null, mDensityDpi,
-                "from", 1);
-        this.mFlags = flags;
-        com.android.internal.util.AnnotationValidations.validate(
-                VirtualDisplayFlag.class, null, mFlags);
-        this.mSurface = surface;
-        this.mUniqueId = uniqueId;
-        this.mDisplayIdToMirror = displayIdToMirror;
-        this.mWindowManagerMirroring = windowManagerMirroring;
-        this.mDisplayCategories = displayCategories;
-        com.android.internal.util.AnnotationValidations.validate(
-                NonNull.class, null, mDisplayCategories);
-        this.mRequestedRefreshRate = requestedRefreshRate;
-
-        // onConstructed(); // You can define this method to get a callback
+        mName = name;
+        mWidth = width;
+        mHeight = height;
+        mDensityDpi = densityDpi;
+        mFlags = flags;
+        mSurface = surface;
+        mUniqueId = uniqueId;
+        mDisplayIdToMirror = displayIdToMirror;
+        mWindowManagerMirroringEnabled = windowManagerMirroringEnabled;
+        mContentRecordingSession = session;
+        mDisplayCategories = displayCategories;
+        mRequestedRefreshRate = requestedRefreshRate;
     }
 
     /**
-     * The name of the virtual display, must be non-empty.
+     * Returns the name of the virtual display.
      */
-    @DataClass.Generated.Member
-    public @NonNull String getName() {
+    @NonNull
+    public String getName() {
         return mName;
     }
 
     /**
-     * The width of the virtual display in pixels. Must be greater than 0.
+     * Returns the width of the virtual display in pixels.
      */
-    @DataClass.Generated.Member
-    public @IntRange(from = 1) int getWidth() {
+    public int getWidth() {
         return mWidth;
     }
 
     /**
-     * The height of the virtual display in pixels. Must be greater than 0.
+     * Returns the height of the virtual display in pixels.
      */
-    @DataClass.Generated.Member
-    public @IntRange(from = 1) int getHeight() {
+    public int getHeight() {
         return mHeight;
     }
 
     /**
-     * The density of the virtual display in dpi. Must be greater than 0.
+     * Returns the density of the virtual display in dpi.
      */
-    @DataClass.Generated.Member
-    public @IntRange(from = 1) int getDensityDpi() {
+    public int getDensityDpi() {
         return mDensityDpi;
     }
 
     /**
-     * A combination of virtual display flags.
-     * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PUBLIC},
-     * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PRESENTATION},
-     * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_SECURE},
-     * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY},
-     * or {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}.
+     * Returns the virtual display flags.
+     *
+     * @see Builder#setFlags
      */
-    @DataClass.Generated.Member
-    public @VirtualDisplayFlag int getFlags() {
+    public int getFlags() {
         return mFlags;
     }
 
     /**
-     * The surface to which the content of the virtual display should be rendered, or null if
-     * there is none initially.
+     * Returns the surface to which the content of the virtual display should be rendered, if any.
+     *
+     * @see Builder#setSurface
      */
-    @DataClass.Generated.Member
-    public @Nullable Surface getSurface() {
+    @Nullable
+    public Surface getSurface() {
         return mSurface;
     }
 
     /**
-     * The unique identifier for the display. Shouldn't be displayed to the user.
-     *
+     * Returns the unique identifier for the display. Shouldn't be displayed to the user.
      * @hide
      */
-    @DataClass.Generated.Member
-    public @Nullable String getUniqueId() {
+    @Nullable
+    public String getUniqueId() {
         return mUniqueId;
     }
 
     /**
-     * The id of the display that the virtual display should mirror, or
-     * {@link android.view.Display#DEFAULT_DISPLAY} if there is none initially.
+     * Returns the id of the display that the virtual display should mirror, or
+     * {@link android.view.Display#DEFAULT_DISPLAY} if there is none.
+     * @hide
      */
-    @DataClass.Generated.Member
     public int getDisplayIdToMirror() {
         return mDisplayIdToMirror;
     }
 
     /**
-     * Indicates if WindowManager is responsible for mirroring content to this VirtualDisplay, or
+     * Whether if WindowManager is responsible for mirroring content to this VirtualDisplay, or
      * if DisplayManager should record contents instead.
+     * @hide
      */
-    @DataClass.Generated.Member
-    public boolean isWindowManagerMirroring() {
-        return mWindowManagerMirroring;
+    public boolean isWindowManagerMirroringEnabled() {
+        return mWindowManagerMirroringEnabled;
     }
 
     /**
-     * The display categories. If set, only corresponding activities from the same category can be
-     * shown on the display.
+     * Returns the recording session associated with this VirtualDisplay. Only used for
+     * recording via {@link MediaProjection}.
+     *
+     * @hide
      */
-    @DataClass.Generated.Member
-    public @NonNull List<String> getDisplayCategories() {
-        return mDisplayCategories;
+    @Nullable
+    public ContentRecordingSession getContentRecordingSession() {
+        return mContentRecordingSession;
     }
 
     /**
-     * The refresh rate of a virtual display in frames per second.
-     * If this value is none zero, this is the requested refresh rate to set.
-     * If this value is zero, the system chooses a default refresh rate.
+     * Returns the display categories.
+     *
+     * @see Builder#setDisplayCategories
      */
-    @DataClass.Generated.Member
+    @NonNull
+    public Set<String> getDisplayCategories() {
+        return Collections.unmodifiableSet(mDisplayCategories);
+    }
+
+    /**
+     * Returns the refresh rate of a virtual display in frames per second, or zero if it is using a
+     * default refresh rate chosen by the system.
+     *
+     * @see Builder#setRequestedRefreshRate
+     */
     public float getRequestedRefreshRate() {
         return mRequestedRefreshRate;
     }
 
     @Override
-    @DataClass.Generated.Member
     public void writeToParcel(@NonNull Parcel dest, int flags) {
-        // You can override field parcelling by defining methods like:
-        // void parcelFieldName(Parcel dest, int flags) { ... }
-
-        int flg = 0;
-        if (mWindowManagerMirroring) flg |= 0x100;
-        if (mSurface != null) flg |= 0x20;
-        if (mUniqueId != null) flg |= 0x40;
-        dest.writeInt(flg);
-        dest.writeString(mName);
+        dest.writeString8(mName);
         dest.writeInt(mWidth);
         dest.writeInt(mHeight);
         dest.writeInt(mDensityDpi);
         dest.writeInt(mFlags);
-        if (mSurface != null) dest.writeTypedObject(mSurface, flags);
-        if (mUniqueId != null) dest.writeString(mUniqueId);
+        dest.writeTypedObject(mSurface, flags);
+        dest.writeString8(mUniqueId);
         dest.writeInt(mDisplayIdToMirror);
-        dest.writeStringList(mDisplayCategories);
+        dest.writeBoolean(mWindowManagerMirroringEnabled);
+        dest.writeTypedObject(mContentRecordingSession, flags);
+        dest.writeArraySet(mDisplayCategories);
         dest.writeFloat(mRequestedRefreshRate);
     }
 
     @Override
-    @DataClass.Generated.Member
     public int describeContents() { return 0; }
 
-    /** @hide */
-    @SuppressWarnings({"unchecked", "RedundantCast"})
-    @DataClass.Generated.Member
-    /* package-private */ VirtualDisplayConfig(@NonNull Parcel in) {
-        // You can override field unparcelling by defining methods like:
-        // static FieldType unparcelFieldName(Parcel in) { ... }
-
-        int flg = in.readInt();
-        boolean windowManagerMirroring = (flg & 0x100) != 0;
-        String name = in.readString();
-        int width = in.readInt();
-        int height = in.readInt();
-        int densityDpi = in.readInt();
-        int flags = in.readInt();
-        Surface surface = (flg & 0x20) == 0 ? null : (Surface) in.readTypedObject(Surface.CREATOR);
-        String uniqueId = (flg & 0x40) == 0 ? null : in.readString();
-        int displayIdToMirror = in.readInt();
-        List<String> displayCategories = new ArrayList<>();
-        in.readStringList(displayCategories);
-        float requestedRefreshRate = in.readFloat();
-
-        this.mName = name;
-        com.android.internal.util.AnnotationValidations.validate(
-                NonNull.class, null, mName);
-        this.mWidth = width;
-        com.android.internal.util.AnnotationValidations.validate(
-                IntRange.class, null, mWidth,
-                "from", 1);
-        this.mHeight = height;
-        com.android.internal.util.AnnotationValidations.validate(
-                IntRange.class, null, mHeight,
-                "from", 1);
-        this.mDensityDpi = densityDpi;
-        com.android.internal.util.AnnotationValidations.validate(
-                IntRange.class, null, mDensityDpi,
-                "from", 1);
-        this.mFlags = flags;
-        com.android.internal.util.AnnotationValidations.validate(
-                VirtualDisplayFlag.class, null, mFlags);
-        this.mSurface = surface;
-        this.mUniqueId = uniqueId;
-        this.mDisplayIdToMirror = displayIdToMirror;
-        this.mWindowManagerMirroring = windowManagerMirroring;
-        this.mDisplayCategories = displayCategories;
-        com.android.internal.util.AnnotationValidations.validate(
-                NonNull.class, null, mDisplayCategories);
-        this.mRequestedRefreshRate = requestedRefreshRate;
-
-        // onConstructed(); // You can define this method to get a callback
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof VirtualDisplayConfig)) {
+            return false;
+        }
+        VirtualDisplayConfig that = (VirtualDisplayConfig) o;
+        return Objects.equals(mName, that.mName)
+                && mWidth == that.mWidth
+                && mHeight == that.mHeight
+                && mDensityDpi == that.mDensityDpi
+                && mFlags == that.mFlags
+                && Objects.equals(mSurface, that.mSurface)
+                && Objects.equals(mUniqueId, that.mUniqueId)
+                && mDisplayIdToMirror == that.mDisplayIdToMirror
+                && mWindowManagerMirroringEnabled == that.mWindowManagerMirroringEnabled
+                && Objects.equals(mContentRecordingSession, that.mContentRecordingSession)
+                && Objects.equals(mDisplayCategories, that.mDisplayCategories)
+                && mRequestedRefreshRate == that.mRequestedRefreshRate;
     }
 
-    @DataClass.Generated.Member
-    public static final @NonNull Parcelable.Creator<VirtualDisplayConfig> CREATOR
+    @Override
+    public int hashCode() {
+        int hashCode = Objects.hash(
+                mName, mWidth, mHeight, mDensityDpi, mFlags, mSurface, mUniqueId,
+                mDisplayIdToMirror, mWindowManagerMirroringEnabled, mContentRecordingSession,
+                mDisplayCategories, mRequestedRefreshRate);
+        return hashCode;
+    }
+
+    @Override
+    @NonNull
+    public String toString() {
+        return "VirtualDisplayConfig("
+                + " mName=" + mName
+                + " mHeight=" + mHeight
+                + " mWidth=" + mWidth
+                + " mDensityDpi=" + mDensityDpi
+                + " mFlags=" + mFlags
+                + " mSurface=" + mSurface
+                + " mUniqueId=" + mUniqueId
+                + " mDisplayIdToMirror=" + mDisplayIdToMirror
+                + " mWindowManagerMirroringEnabled=" + mWindowManagerMirroringEnabled
+                + " mContentRecordingSession=" + mContentRecordingSession
+                + " mDisplayCategories=" + mDisplayCategories
+                + " mRequestedRefreshRate=" + mRequestedRefreshRate
+                + ")";
+    }
+
+    private VirtualDisplayConfig(@NonNull Parcel in) {
+        mName = in.readString8();
+        mWidth = in.readInt();
+        mHeight = in.readInt();
+        mDensityDpi = in.readInt();
+        mFlags = in.readInt();
+        mSurface = in.readTypedObject(Surface.CREATOR);
+        mUniqueId = in.readString8();
+        mDisplayIdToMirror = in.readInt();
+        mWindowManagerMirroringEnabled = in.readBoolean();
+        mContentRecordingSession = in.readTypedObject(ContentRecordingSession.CREATOR);
+        mDisplayCategories = (ArraySet<String>) in.readArraySet(null);
+        mRequestedRefreshRate = in.readFloat();
+    }
+
+    @NonNull
+    public static final Parcelable.Creator<VirtualDisplayConfig> CREATOR
             = new Parcelable.Creator<VirtualDisplayConfig>() {
         @Override
         public VirtualDisplayConfig[] newArray(int size) {
@@ -368,229 +291,175 @@
     };
 
     /**
-     * A builder for {@link VirtualDisplayConfig}
+     * A builder for {@link VirtualDisplayConfig}.
      */
-    @SuppressWarnings("WeakerAccess")
-    @DataClass.Generated.Member
     public static final class Builder {
-
-        private @NonNull String mName;
-        private @IntRange(from = 1) int mWidth;
-        private @IntRange(from = 1) int mHeight;
-        private @IntRange(from = 1) int mDensityDpi;
-        private @VirtualDisplayFlag int mFlags;
-        private @Nullable Surface mSurface;
-        private @Nullable String mUniqueId;
-        private int mDisplayIdToMirror;
-        private boolean mWindowManagerMirroring;
-        private @NonNull List<String> mDisplayCategories;
-        private float mRequestedRefreshRate;
-
-        private long mBuilderFieldsSet = 0L;
+        private final String mName;
+        private final int mWidth;
+        private final int mHeight;
+        private final int mDensityDpi;
+        private int mFlags = 0;
+        private Surface mSurface = null;
+        private String mUniqueId = null;
+        private int mDisplayIdToMirror = DEFAULT_DISPLAY;
+        private boolean mWindowManagerMirroringEnabled = false;
+        @Nullable
+        private ContentRecordingSession mContentRecordingSession;
+        private ArraySet<String> mDisplayCategories = new ArraySet<>();
+        private float mRequestedRefreshRate = 0.0f;
 
         /**
          * Creates a new Builder.
          *
-         * @param name
-         *   The name of the virtual display, must be non-empty.
-         * @param width
-         *   The width of the virtual display in pixels. Must be greater than 0.
-         * @param height
-         *   The height of the virtual display in pixels. Must be greater than 0.
-         * @param densityDpi
-         *   The density of the virtual display in dpi. Must be greater than 0.
+         * @param name The name of the virtual display, must be non-empty.
+         * @param width The width of the virtual display in pixels. Must be greater than 0.
+         * @param height The height of the virtual display in pixels. Must be greater than 0.
+         * @param densityDpi The density of the virtual display in dpi. Must be greater than 0.
          */
         public Builder(
                 @NonNull String name,
                 @IntRange(from = 1) int width,
                 @IntRange(from = 1) int height,
                 @IntRange(from = 1) int densityDpi) {
+            if (name == null) {
+                throw new IllegalArgumentException("Virtual display name is required");
+            }
+            if (width <= 0) {
+                throw new IllegalArgumentException("Virtual display width must be positive");
+            }
+            if (height <= 0) {
+                throw new IllegalArgumentException("Virtual display height must be positive");
+            }
+            if (densityDpi <= 0) {
+                throw new IllegalArgumentException("Virtual display density must be positive");
+            }
             mName = name;
-            com.android.internal.util.AnnotationValidations.validate(
-                    NonNull.class, null, mName);
             mWidth = width;
-            com.android.internal.util.AnnotationValidations.validate(
-                    IntRange.class, null, mWidth,
-                    "from", 1);
             mHeight = height;
-            com.android.internal.util.AnnotationValidations.validate(
-                    IntRange.class, null, mHeight,
-                    "from", 1);
             mDensityDpi = densityDpi;
-            com.android.internal.util.AnnotationValidations.validate(
-                    IntRange.class, null, mDensityDpi,
-                    "from", 1);
         }
 
         /**
-         * The name of the virtual display, must be non-empty.
-         */
-        @DataClass.Generated.Member
-        public @NonNull Builder setName(@NonNull String value) {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x1;
-            mName = value;
-            return this;
-        }
-
-        /**
-         * The width of the virtual display in pixels. Must be greater than 0.
-         */
-        @DataClass.Generated.Member
-        public @NonNull Builder setWidth(@IntRange(from = 1) int value) {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x2;
-            mWidth = value;
-            return this;
-        }
-
-        /**
-         * The height of the virtual display in pixels. Must be greater than 0.
-         */
-        @DataClass.Generated.Member
-        public @NonNull Builder setHeight(@IntRange(from = 1) int value) {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x4;
-            mHeight = value;
-            return this;
-        }
-
-        /**
-         * The density of the virtual display in dpi. Must be greater than 0.
-         */
-        @DataClass.Generated.Member
-        public @NonNull Builder setDensityDpi(@IntRange(from = 1) int value) {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x8;
-            mDensityDpi = value;
-            return this;
-        }
-
-        /**
-         * A combination of virtual display flags.
+         * Sets the virtual display flags, a combination of
          * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PUBLIC},
          * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PRESENTATION},
          * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_SECURE},
          * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY},
          * or {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}.
          */
-        @DataClass.Generated.Member
-        public @NonNull Builder setFlags(@VirtualDisplayFlag int value) {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x10;
-            mFlags = value;
+        @NonNull
+        public Builder setFlags(@VirtualDisplayFlag int flags) {
+            mFlags = flags;
             return this;
         }
 
         /**
-         * The surface to which the content of the virtual display should be rendered, or null if
-         * there is none initially.
+         * Sets the surface to which the content of the virtual display should be rendered.
+         *
+         * <p>The surface can also be set after the display creation using
+         * {@link VirtualDisplay#setSurface(Surface)}.
          */
-        @DataClass.Generated.Member
-        public @NonNull Builder setSurface(@NonNull Surface value) {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x20;
-            mSurface = value;
+        @NonNull
+        public Builder setSurface(@Nullable Surface surface) {
+            mSurface = surface;
             return this;
         }
 
         /**
-         * The unique identifier for the display. Shouldn't be displayed to the user.
+         * Sets the unique identifier for the display.
+         * @hide
+         */
+        @NonNull
+        public Builder setUniqueId(@Nullable String uniqueId) {
+            mUniqueId = uniqueId;
+            return this;
+        }
+
+        /**
+         * Sets the id of the display that the virtual display should mirror.
+         * @hide
+         */
+        @NonNull
+        public Builder setDisplayIdToMirror(int displayIdToMirror) {
+            mDisplayIdToMirror = displayIdToMirror;
+            return this;
+        }
+
+        /**
+         * Sets whether WindowManager is responsible for mirroring content to this VirtualDisplay.
+         * If unset or false, DisplayManager should record contents instead.
+         * @hide
+         */
+        @NonNull
+        public Builder setWindowManagerMirroringEnabled(boolean windowManagerMirroringEnabled) {
+            mWindowManagerMirroringEnabled = windowManagerMirroringEnabled;
+            return this;
+        }
+
+        /**
+         * Sets the recording session associated with this {@link VirtualDisplay}. Only used for
+         * recording via {@link MediaProjection}.
          *
          * @hide
          */
-        @DataClass.Generated.Member
-        public @NonNull Builder setUniqueId(@NonNull String value) {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x40;
-            mUniqueId = value;
+        @NonNull
+        public Builder setContentRecordingSession(@Nullable ContentRecordingSession session) {
+            mContentRecordingSession = session;
             return this;
         }
 
         /**
-         * The id of the display that the virtual display should mirror, or
-         * {@link android.view.Display#DEFAULT_DISPLAY} if there is none initially.
+         * Sets the display categories.
+         *
+         * <p>The categories of the display indicate the type of activities allowed to run on that
+         * display. Activities can declare a display category using
+         * {@link android.content.pm.ActivityInfo#requiredDisplayCategory}.
          */
-        @DataClass.Generated.Member
-        public @NonNull Builder setDisplayIdToMirror(int value) {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x80;
-            mDisplayIdToMirror = value;
+        @NonNull
+        public Builder setDisplayCategories(@NonNull Set<String> displayCategories) {
+            mDisplayCategories.clear();
+            mDisplayCategories.addAll(Objects.requireNonNull(displayCategories));
             return this;
         }
 
         /**
-         * Indicates if WindowManager is responsible for mirroring content to this VirtualDisplay, or
-         * if DisplayManager should record contents instead.
+         * Adds a display category.
+         *
+         * @see #setDisplayCategories
          */
-        @DataClass.Generated.Member
-        public @NonNull Builder setWindowManagerMirroring(boolean value) {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x100;
-            mWindowManagerMirroring = value;
+        @NonNull
+        public Builder addDisplayCategory(@NonNull String displayCategory) {
+            mDisplayCategories.add(Objects.requireNonNull(displayCategory));
             return this;
         }
 
         /**
-         * The display categories. If set, only corresponding activities from the same category can be
-         * shown on the display.
+         * Sets the refresh rate of a virtual display in frames per second.
+         *
+         * <p>For best results, specify a divisor of the physical refresh rate, e.g., 30 or 60 on
+         * a 120hz display. If an arbitrary refresh rate is specified, the rate will be rounded up
+         * down to a divisor of the physical display. If unset or zero, the virtual display will be
+         * refreshed at the physical display refresh rate.
+         *
+         * @see Display#getRefreshRate()
          */
-        @DataClass.Generated.Member
-        public @NonNull Builder setDisplayCategories(@NonNull List<String> value) {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x200;
-            mDisplayCategories = value;
-            return this;
-        }
-
-        /** @see #setDisplayCategories */
-        @DataClass.Generated.Member
-        public @NonNull Builder addDisplayCategory(@NonNull String value) {
-            if (mDisplayCategories == null) setDisplayCategories(new ArrayList<>());
-            mDisplayCategories.add(value);
+        @NonNull
+        public Builder setRequestedRefreshRate(
+                @FloatRange(from = 0.0f) float requestedRefreshRate) {
+            if (requestedRefreshRate < 0.0f) {
+                throw new IllegalArgumentException(
+                        "Virtual display requested refresh rate must be non-negative");
+            }
+            mRequestedRefreshRate = requestedRefreshRate;
             return this;
         }
 
         /**
-         * The refresh rate of a virtual display in frames per second.
-         * If this value is none zero, this is the requested refresh rate to set.
-         * If this value is zero, the system chooses a default refresh rate.
+         * Builds the {@link VirtualDisplayConfig} instance.
          */
-        @DataClass.Generated.Member
-        public @NonNull Builder setRequestedRefreshRate(float value) {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x400;
-            mRequestedRefreshRate = value;
-            return this;
-        }
-
-        /** Builds the instance. This builder should not be touched after calling this! */
-        public @NonNull VirtualDisplayConfig build() {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x800; // Mark builder used
-
-            if ((mBuilderFieldsSet & 0x10) == 0) {
-                mFlags = 0;
-            }
-            if ((mBuilderFieldsSet & 0x20) == 0) {
-                mSurface = null;
-            }
-            if ((mBuilderFieldsSet & 0x40) == 0) {
-                mUniqueId = null;
-            }
-            if ((mBuilderFieldsSet & 0x80) == 0) {
-                mDisplayIdToMirror = DEFAULT_DISPLAY;
-            }
-            if ((mBuilderFieldsSet & 0x100) == 0) {
-                mWindowManagerMirroring = false;
-            }
-            if ((mBuilderFieldsSet & 0x200) == 0) {
-                mDisplayCategories = new ArrayList<>();
-            }
-            if ((mBuilderFieldsSet & 0x400) == 0) {
-                mRequestedRefreshRate = 0.0f;
-            }
-            VirtualDisplayConfig o = new VirtualDisplayConfig(
+        @NonNull
+        public VirtualDisplayConfig build() {
+            return new VirtualDisplayConfig(
                     mName,
                     mWidth,
                     mHeight,
@@ -599,30 +468,10 @@
                     mSurface,
                     mUniqueId,
                     mDisplayIdToMirror,
-                    mWindowManagerMirroring,
+                    mWindowManagerMirroringEnabled,
+                    mContentRecordingSession,
                     mDisplayCategories,
                     mRequestedRefreshRate);
-            return o;
-        }
-
-        private void checkNotUsed() {
-            if ((mBuilderFieldsSet & 0x800) != 0) {
-                throw new IllegalStateException(
-                        "This Builder should not be reused. Use a new Builder instance instead");
-            }
         }
     }
-
-    @DataClass.Generated(
-            time = 1671047069703L,
-            codegenVersion = "1.0.23",
-            sourceFile = "frameworks/base/core/java/android/hardware/display/VirtualDisplayConfig.java",
-            inputSignatures = "private @android.annotation.NonNull java.lang.String mName\nprivate @android.annotation.IntRange int mWidth\nprivate @android.annotation.IntRange int mHeight\nprivate @android.annotation.IntRange int mDensityDpi\nprivate @android.hardware.display.DisplayManager.VirtualDisplayFlag int mFlags\nprivate @android.annotation.Nullable android.view.Surface mSurface\nprivate @android.annotation.Nullable java.lang.String mUniqueId\nprivate  int mDisplayIdToMirror\nprivate  boolean mWindowManagerMirroring\nprivate @com.android.internal.util.DataClass.PluralOf(\"displayCategory\") @android.annotation.NonNull java.util.List<java.lang.String> mDisplayCategories\nprivate  float mRequestedRefreshRate\nclass VirtualDisplayConfig extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genAidl=true, genBuilder=true)")
-    @Deprecated
-    private void __metadata() {}
-
-
-    //@formatter:on
-    // End of generated code
-
 }
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index a33cd97..9662be3 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -44,12 +44,8 @@
 import android.os.IBinder;
 import android.os.IVibratorStateListener;
 import android.os.InputEventInjectionSync;
-import android.os.Looper;
-import android.os.Message;
 import android.os.Process;
 import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.ServiceManager.ServiceNotFoundException;
 import android.os.SystemClock;
 import android.os.VibrationEffect;
 import android.os.Vibrator;
@@ -70,7 +66,6 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.os.SomeArgs;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -90,10 +85,6 @@
     // To enable these logs, run: 'adb shell setprop log.tag.InputManager DEBUG' (requires restart)
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
-    private static final int MSG_DEVICE_ADDED = 1;
-    private static final int MSG_DEVICE_REMOVED = 2;
-    private static final int MSG_DEVICE_CHANGED = 3;
-
     private static InputManager sInstance;
 
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
@@ -114,18 +105,6 @@
     @Nullable
     private Boolean mIsStylusPointerIconEnabled = null;
 
-    // Guarded by mInputDevicesLock
-    private final Object mInputDevicesLock = new Object();
-    private SparseArray<InputDevice> mInputDevices;
-    private InputDevicesChangedListener mInputDevicesChangedListener;
-    private final ArrayList<InputDeviceListenerDelegate> mInputDeviceListeners = new ArrayList<>();
-
-    // Guarded by mTabletModeLock
-    private final Object mTabletModeLock = new Object();
-    @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
-    private TabletModeChangedListener mTabletModeChangedListener;
-    private ArrayList<OnTabletModeChangedListenerDelegate> mOnTabletModeChangedListeners;
-
     private final Object mBatteryListenersLock = new Object();
     // Maps a deviceId whose battery is currently being monitored to an entry containing the
     // registered listeners for that device.
@@ -305,8 +284,11 @@
 
     private static String sVelocityTrackerStrategy;
 
-    private InputManager(IInputManager im) {
-        mIm = im;
+    private InputManagerGlobal mGlobal;
+
+    private InputManager() {
+        mGlobal = InputManagerGlobal.getInstance();
+        mIm = mGlobal.getInputManagerService();
         try {
             sVelocityTrackerStrategy = mIm.getVelocityTrackerStrategy();
         } catch (RemoteException ex) {
@@ -324,7 +306,8 @@
     @VisibleForTesting
     public static InputManager resetInstance(IInputManager inputManagerService) {
         synchronized (InputManager.class) {
-            sInstance = new InputManager(inputManagerService);
+            InputManagerGlobal.resetInstance(inputManagerService);
+            sInstance = new InputManager();
             return sInstance;
         }
     }
@@ -337,6 +320,7 @@
     @VisibleForTesting
     public static void clearInstance() {
         synchronized (InputManager.class) {
+            InputManagerGlobal.clearInstance();
             sInstance = null;
         }
     }
@@ -364,13 +348,7 @@
     public static InputManager getInstance(Context context) {
         synchronized (InputManager.class) {
             if (sInstance == null) {
-                try {
-                    sInstance = new InputManager(IInputManager.Stub
-                            .asInterface(ServiceManager.getServiceOrThrow(Context.INPUT_SERVICE)));
-
-                } catch (ServiceNotFoundException e) {
-                    throw new IllegalStateException(e);
-                }
+                sInstance = new InputManager();
             }
             if (sInstance.mWeakContext == null || sInstance.mWeakContext.get() == null) {
                 sInstance.mWeakContext = new WeakReference(context);
@@ -406,27 +384,7 @@
      */
     @Nullable
     public InputDevice getInputDevice(int id) {
-        synchronized (mInputDevicesLock) {
-            populateInputDevicesLocked();
-
-            int index = mInputDevices.indexOfKey(id);
-            if (index < 0) {
-                return null;
-            }
-
-            InputDevice inputDevice = mInputDevices.valueAt(index);
-            if (inputDevice == null) {
-                try {
-                    inputDevice = mIm.getInputDevice(id);
-                } catch (RemoteException ex) {
-                    throw ex.rethrowFromSystemServer();
-                }
-                if (inputDevice != null) {
-                    mInputDevices.setValueAt(index, inputDevice);
-                }
-            }
-            return inputDevice;
-        }
+        return mGlobal.getInputDevice(id);
     }
 
     /**
@@ -436,34 +394,7 @@
      * @hide
      */
     public InputDevice getInputDeviceByDescriptor(String descriptor) {
-        if (descriptor == null) {
-            throw new IllegalArgumentException("descriptor must not be null.");
-        }
-
-        synchronized (mInputDevicesLock) {
-            populateInputDevicesLocked();
-
-            int numDevices = mInputDevices.size();
-            for (int i = 0; i < numDevices; i++) {
-                InputDevice inputDevice = mInputDevices.valueAt(i);
-                if (inputDevice == null) {
-                    int id = mInputDevices.keyAt(i);
-                    try {
-                        inputDevice = mIm.getInputDevice(id);
-                    } catch (RemoteException ex) {
-                        throw ex.rethrowFromSystemServer();
-                    }
-                    if (inputDevice == null) {
-                        continue;
-                    }
-                    mInputDevices.setValueAt(i, inputDevice);
-                }
-                if (descriptor.equals(inputDevice.getDescriptor())) {
-                    return inputDevice;
-                }
-            }
-            return null;
-        }
+        return mGlobal.getInputDeviceByDescriptor(descriptor);
     }
 
     /**
@@ -471,16 +402,7 @@
      * @return The input device ids.
      */
     public int[] getInputDeviceIds() {
-        synchronized (mInputDevicesLock) {
-            populateInputDevicesLocked();
-
-            final int count = mInputDevices.size();
-            final int[] ids = new int[count];
-            for (int i = 0; i < count; i++) {
-                ids[i] = mInputDevices.keyAt(i);
-            }
-            return ids;
-        }
+        return mGlobal.getInputDeviceIds();
     }
 
     /**
@@ -550,17 +472,7 @@
      * @see #unregisterInputDeviceListener
      */
     public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) {
-        if (listener == null) {
-            throw new IllegalArgumentException("listener must not be null");
-        }
-
-        synchronized (mInputDevicesLock) {
-            populateInputDevicesLocked();
-            int index = findInputDeviceListenerLocked(listener);
-            if (index < 0) {
-                mInputDeviceListeners.add(new InputDeviceListenerDelegate(listener, handler));
-            }
-        }
+        mGlobal.registerInputDeviceListener(listener, handler);
     }
 
     /**
@@ -571,28 +483,7 @@
      * @see #registerInputDeviceListener
      */
     public void unregisterInputDeviceListener(InputDeviceListener listener) {
-        if (listener == null) {
-            throw new IllegalArgumentException("listener must not be null");
-        }
-
-        synchronized (mInputDevicesLock) {
-            int index = findInputDeviceListenerLocked(listener);
-            if (index >= 0) {
-                InputDeviceListenerDelegate d = mInputDeviceListeners.get(index);
-                d.removeCallbacksAndMessages(null);
-                mInputDeviceListeners.remove(index);
-            }
-        }
-    }
-
-    private int findInputDeviceListenerLocked(InputDeviceListener listener) {
-        final int numListeners = mInputDeviceListeners.size();
-        for (int i = 0; i < numListeners; i++) {
-            if (mInputDeviceListeners.get(i).mListener == listener) {
-                return i;
-            }
-        }
-        return -1;
+        mGlobal.unregisterInputDeviceListener(listener);
     }
 
     /**
@@ -621,20 +512,7 @@
      */
     public void registerOnTabletModeChangedListener(
             OnTabletModeChangedListener listener, Handler handler) {
-        if (listener == null) {
-            throw new IllegalArgumentException("listener must not be null");
-        }
-        synchronized (mTabletModeLock) {
-            if (mOnTabletModeChangedListeners == null) {
-                initializeTabletModeListenerLocked();
-            }
-            int idx = findOnTabletModeChangedListenerLocked(listener);
-            if (idx < 0) {
-                OnTabletModeChangedListenerDelegate d =
-                    new OnTabletModeChangedListenerDelegate(listener, handler);
-                mOnTabletModeChangedListeners.add(d);
-            }
-        }
+        mGlobal.registerOnTabletModeChangedListener(listener, handler);
     }
 
     /**
@@ -644,37 +522,7 @@
      * @hide
      */
     public void unregisterOnTabletModeChangedListener(OnTabletModeChangedListener listener) {
-        if (listener == null) {
-            throw new IllegalArgumentException("listener must not be null");
-        }
-        synchronized (mTabletModeLock) {
-            int idx = findOnTabletModeChangedListenerLocked(listener);
-            if (idx >= 0) {
-                OnTabletModeChangedListenerDelegate d = mOnTabletModeChangedListeners.remove(idx);
-                d.removeCallbacksAndMessages(null);
-            }
-        }
-    }
-
-    private void initializeTabletModeListenerLocked() {
-        final TabletModeChangedListener listener = new TabletModeChangedListener();
-        try {
-            mIm.registerTabletModeChangedListener(listener);
-        } catch (RemoteException ex) {
-            throw ex.rethrowFromSystemServer();
-        }
-        mTabletModeChangedListener = listener;
-        mOnTabletModeChangedListeners = new ArrayList<>();
-    }
-
-    private int findOnTabletModeChangedListenerLocked(OnTabletModeChangedListener listener) {
-        final int N = mOnTabletModeChangedListeners.size();
-        for (int i = 0; i < N; i++) {
-            if (mOnTabletModeChangedListeners.get(i).mListener == listener) {
-                return i;
-            }
-        }
-        return -1;
+        mGlobal.unregisterOnTabletModeChangedListener(listener);
     }
 
     /**
@@ -1546,133 +1394,7 @@
      */
     @Nullable
     public HostUsiVersion getHostUsiVersion(@NonNull Display display) {
-        Objects.requireNonNull(display, "display should not be null");
-
-        // Return the first valid USI version reported by any input device associated with
-        // the display.
-        synchronized (mInputDevicesLock) {
-            populateInputDevicesLocked();
-
-            for (int i = 0; i < mInputDevices.size(); i++) {
-                final InputDevice device = getInputDevice(mInputDevices.keyAt(i));
-                if (device != null && device.getAssociatedDisplayId() == display.getDisplayId()) {
-                    if (device.getHostUsiVersion() != null) {
-                        return device.getHostUsiVersion();
-                    }
-                }
-            }
-        }
-
-        // If there are no input devices that report a valid USI version, see if there is a config
-        // that specifies the USI version for the display. This is to handle cases where the USI
-        // input device is not registered by the kernel/driver all the time.
-        try {
-            return mIm.getHostUsiVersionFromDisplayConfig(display.getDisplayId());
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    private void populateInputDevicesLocked() {
-        if (mInputDevicesChangedListener == null) {
-            final InputDevicesChangedListener listener = new InputDevicesChangedListener();
-            try {
-                mIm.registerInputDevicesChangedListener(listener);
-            } catch (RemoteException ex) {
-                throw ex.rethrowFromSystemServer();
-            }
-            mInputDevicesChangedListener = listener;
-        }
-
-        if (mInputDevices == null) {
-            final int[] ids;
-            try {
-                ids = mIm.getInputDeviceIds();
-            } catch (RemoteException ex) {
-                throw ex.rethrowFromSystemServer();
-            }
-
-            mInputDevices = new SparseArray<>();
-            for (int id : ids) {
-                mInputDevices.put(id, null);
-            }
-        }
-    }
-
-    private void onInputDevicesChanged(int[] deviceIdAndGeneration) {
-        if (DEBUG) {
-            Log.d(TAG, "Received input devices changed.");
-        }
-
-        synchronized (mInputDevicesLock) {
-            for (int i = mInputDevices.size(); --i > 0; ) {
-                final int deviceId = mInputDevices.keyAt(i);
-                if (!containsDeviceId(deviceIdAndGeneration, deviceId)) {
-                    if (DEBUG) {
-                        Log.d(TAG, "Device removed: " + deviceId);
-                    }
-                    mInputDevices.removeAt(i);
-                    sendMessageToInputDeviceListenersLocked(MSG_DEVICE_REMOVED, deviceId);
-                }
-            }
-
-            for (int i = 0; i < deviceIdAndGeneration.length; i += 2) {
-                final int deviceId = deviceIdAndGeneration[i];
-                int index = mInputDevices.indexOfKey(deviceId);
-                if (index >= 0) {
-                    final InputDevice device = mInputDevices.valueAt(index);
-                    if (device != null) {
-                        final int generation = deviceIdAndGeneration[i + 1];
-                        if (device.getGeneration() != generation) {
-                            if (DEBUG) {
-                                Log.d(TAG, "Device changed: " + deviceId);
-                            }
-                            mInputDevices.setValueAt(index, null);
-                            sendMessageToInputDeviceListenersLocked(MSG_DEVICE_CHANGED, deviceId);
-                        }
-                    }
-                } else {
-                    if (DEBUG) {
-                        Log.d(TAG, "Device added: " + deviceId);
-                    }
-                    mInputDevices.put(deviceId, null);
-                    sendMessageToInputDeviceListenersLocked(MSG_DEVICE_ADDED, deviceId);
-                }
-            }
-        }
-    }
-
-    private void sendMessageToInputDeviceListenersLocked(int what, int deviceId) {
-        final int numListeners = mInputDeviceListeners.size();
-        for (int i = 0; i < numListeners; i++) {
-            InputDeviceListenerDelegate listener = mInputDeviceListeners.get(i);
-            listener.sendMessage(listener.obtainMessage(what, deviceId, 0));
-        }
-    }
-
-    private static boolean containsDeviceId(int[] deviceIdAndGeneration, int deviceId) {
-        for (int i = 0; i < deviceIdAndGeneration.length; i += 2) {
-            if (deviceIdAndGeneration[i] == deviceId) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-
-    private void onTabletModeChanged(long whenNanos, boolean inTabletMode) {
-        if (DEBUG) {
-            Log.d(TAG, "Received tablet mode changed: "
-                    + "whenNanos=" + whenNanos + ", inTabletMode=" + inTabletMode);
-        }
-        synchronized (mTabletModeLock) {
-            final int numListeners = mOnTabletModeChangedListeners.size();
-            for (int i = 0; i < numListeners; i++) {
-                OnTabletModeChangedListenerDelegate listener =
-                        mOnTabletModeChangedListeners.get(i);
-                listener.sendTabletModeChanged(whenNanos, inTabletMode);
-            }
-        }
+        return mGlobal.getHostUsiVersion(display);
     }
 
     /**
@@ -2152,7 +1874,7 @@
     public interface InputDeviceListener {
         /**
          * Called whenever an input device has been added to the system.
-         * Use {@link InputManager#getInputDevice} to get more information about the device.
+         * Use {@link InputManagerGlobal#getInputDevice} to get more information about the device.
          *
          * @param deviceId The id of the input device that was added.
          */
@@ -2175,37 +1897,6 @@
         void onInputDeviceChanged(int deviceId);
     }
 
-    private final class InputDevicesChangedListener extends IInputDevicesChangedListener.Stub {
-        @Override
-        public void onInputDevicesChanged(int[] deviceIdAndGeneration) throws RemoteException {
-            InputManager.this.onInputDevicesChanged(deviceIdAndGeneration);
-        }
-    }
-
-    private static final class InputDeviceListenerDelegate extends Handler {
-        public final InputDeviceListener mListener;
-
-        public InputDeviceListenerDelegate(InputDeviceListener listener, Handler handler) {
-            super(handler != null ? handler.getLooper() : Looper.myLooper());
-            mListener = listener;
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_DEVICE_ADDED:
-                    mListener.onInputDeviceAdded(msg.arg1);
-                    break;
-                case MSG_DEVICE_REMOVED:
-                    mListener.onInputDeviceRemoved(msg.arg1);
-                    break;
-                case MSG_DEVICE_CHANGED:
-                    mListener.onInputDeviceChanged(msg.arg1);
-                    break;
-            }
-        }
-    }
-
     /** @hide */
     public interface OnTabletModeChangedListener {
         /**
@@ -2239,43 +1930,6 @@
                 int deviceId, @NonNull KeyboardBacklightState state, boolean isTriggeredByKeyPress);
     }
 
-    private final class TabletModeChangedListener extends ITabletModeChangedListener.Stub {
-        @Override
-        public void onTabletModeChanged(long whenNanos, boolean inTabletMode) {
-            InputManager.this.onTabletModeChanged(whenNanos, inTabletMode);
-        }
-    }
-
-    private static final class OnTabletModeChangedListenerDelegate extends Handler {
-        private static final int MSG_TABLET_MODE_CHANGED = 0;
-
-        public final OnTabletModeChangedListener mListener;
-
-        public OnTabletModeChangedListenerDelegate(
-                OnTabletModeChangedListener listener, Handler handler) {
-            super(handler != null ? handler.getLooper() : Looper.myLooper());
-            mListener = listener;
-        }
-
-        public void sendTabletModeChanged(long whenNanos, boolean inTabletMode) {
-            SomeArgs args = SomeArgs.obtain();
-            args.argi1 = (int) whenNanos;
-            args.argi2 = (int) (whenNanos >> 32);
-            args.arg1 = inTabletMode;
-            obtainMessage(MSG_TABLET_MODE_CHANGED, args).sendToTarget();
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            if (msg.what == MSG_TABLET_MODE_CHANGED) {
-                SomeArgs args = (SomeArgs) msg.obj;
-                long whenNanos = (args.argi1 & 0xFFFFFFFFL) | ((long) args.argi2 << 32);
-                boolean inTabletMode = (boolean) args.arg1;
-                mListener.onTabletModeChanged(whenNanos, inTabletMode);
-            }
-        }
-    }
-
     // Implementation of the android.hardware.BatteryState interface used to report the battery
     // state via the InputDevice#getBatteryState() and InputDeviceBatteryListener interfaces.
     private static final class LocalBatteryState extends BatteryState {
diff --git a/core/java/android/hardware/input/InputManagerGlobal.java b/core/java/android/hardware/input/InputManagerGlobal.java
new file mode 100644
index 0000000..28699e0
--- /dev/null
+++ b/core/java/android/hardware/input/InputManagerGlobal.java
@@ -0,0 +1,506 @@
+/*
+ * 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.input;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.hardware.input.InputManager.InputDeviceListener;
+import android.hardware.input.InputManager.OnTabletModeChangedListener;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.Display;
+import android.view.InputDevice;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.SomeArgs;
+
+import java.util.ArrayList;
+import java.util.Objects;
+
+/**
+ * Manages communication with the input manager service on behalf of
+ * an application process.  You're probably looking for {@link InputManager}.
+ *
+ * @hide
+ */
+public final class InputManagerGlobal {
+    private static final String TAG = "InputManagerGlobal";
+    // To enable these logs, run: 'adb shell setprop log.tag.InputManagerGlobal DEBUG'
+    // (requires restart)
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+    @GuardedBy("mInputDeviceListeners")
+    @Nullable private SparseArray<InputDevice> mInputDevices;
+    @GuardedBy("mInputDeviceListeners")
+    @Nullable private InputDevicesChangedListener mInputDevicesChangedListener;
+    @GuardedBy("mInputDeviceListeners")
+    private final ArrayList<InputDeviceListenerDelegate> mInputDeviceListeners = new ArrayList<>();
+
+    @GuardedBy("mOnTabletModeChangedListeners")
+    private final ArrayList<OnTabletModeChangedListenerDelegate> mOnTabletModeChangedListeners =
+            new ArrayList<>();
+
+    private static InputManagerGlobal sInstance;
+
+    private final IInputManager mIm;
+
+    public InputManagerGlobal(IInputManager im) {
+        mIm = im;
+    }
+
+    /**
+     * Gets an instance of the input manager global singleton.
+     *
+     * @return The display manager instance, may be null early in system startup
+     * before the display manager has been fully initialized.
+     */
+    public static InputManagerGlobal getInstance() {
+        synchronized (InputManagerGlobal.class) {
+            if (sInstance == null) {
+                IBinder b = ServiceManager.getService(Context.INPUT_SERVICE);
+                if (b != null) {
+                    sInstance = new InputManagerGlobal(IInputManager.Stub.asInterface(b));
+                }
+            }
+            return sInstance;
+        }
+    }
+
+    public IInputManager getInputManagerService() {
+        return mIm;
+    }
+
+    /**
+     * Gets an instance of the input manager.
+     *
+     * @return The input manager instance.
+     */
+    public static InputManagerGlobal resetInstance(IInputManager inputManagerService) {
+        synchronized (InputManager.class) {
+            sInstance = new InputManagerGlobal(inputManagerService);
+            return sInstance;
+        }
+    }
+
+    /**
+     * Clear the instance of the input manager.
+     */
+    public static void clearInstance() {
+        synchronized (InputManagerGlobal.class) {
+            sInstance = null;
+        }
+    }
+
+    /**
+     * @see InputManager#getInputDevice(int)
+     */
+    @Nullable
+    public InputDevice getInputDevice(int id) {
+        synchronized (mInputDeviceListeners) {
+            populateInputDevicesLocked();
+
+            int index = mInputDevices.indexOfKey(id);
+            if (index < 0) {
+                return null;
+            }
+
+            InputDevice inputDevice = mInputDevices.valueAt(index);
+            if (inputDevice == null) {
+                try {
+                    inputDevice = mIm.getInputDevice(id);
+                } catch (RemoteException ex) {
+                    throw ex.rethrowFromSystemServer();
+                }
+                if (inputDevice != null) {
+                    mInputDevices.setValueAt(index, inputDevice);
+                }
+            }
+            return inputDevice;
+        }
+    }
+
+    @GuardedBy("mInputDeviceListeners")
+    private void populateInputDevicesLocked() {
+        if (mInputDevicesChangedListener == null) {
+            final InputDevicesChangedListener
+                    listener = new InputDevicesChangedListener();
+            try {
+                mIm.registerInputDevicesChangedListener(listener);
+            } catch (RemoteException ex) {
+                throw ex.rethrowFromSystemServer();
+            }
+            mInputDevicesChangedListener = listener;
+        }
+
+        if (mInputDevices == null) {
+            final int[] ids;
+            try {
+                ids = mIm.getInputDeviceIds();
+            } catch (RemoteException ex) {
+                throw ex.rethrowFromSystemServer();
+            }
+
+            mInputDevices = new SparseArray<>();
+            for (int id : ids) {
+                mInputDevices.put(id, null);
+            }
+        }
+    }
+
+    private final class InputDevicesChangedListener extends IInputDevicesChangedListener.Stub {
+        @Override
+        public void onInputDevicesChanged(int[] deviceIdAndGeneration) throws RemoteException {
+            InputManagerGlobal.this.onInputDevicesChanged(deviceIdAndGeneration);
+        }
+    }
+
+    private void onInputDevicesChanged(int[] deviceIdAndGeneration) {
+        if (DEBUG) {
+            Log.d(TAG, "Received input devices changed.");
+        }
+
+        synchronized (mInputDeviceListeners) {
+            for (int i = mInputDevices.size(); --i > 0; ) {
+                final int deviceId = mInputDevices.keyAt(i);
+                if (!containsDeviceId(deviceIdAndGeneration, deviceId)) {
+                    if (DEBUG) {
+                        Log.d(TAG, "Device removed: " + deviceId);
+                    }
+                    mInputDevices.removeAt(i);
+                    sendMessageToInputDeviceListenersLocked(
+                            InputDeviceListenerDelegate.MSG_DEVICE_REMOVED, deviceId);
+                }
+            }
+
+            for (int i = 0; i < deviceIdAndGeneration.length; i += 2) {
+                final int deviceId = deviceIdAndGeneration[i];
+                int index = mInputDevices.indexOfKey(deviceId);
+                if (index >= 0) {
+                    final InputDevice device = mInputDevices.valueAt(index);
+                    if (device != null) {
+                        final int generation = deviceIdAndGeneration[i + 1];
+                        if (device.getGeneration() != generation) {
+                            if (DEBUG) {
+                                Log.d(TAG, "Device changed: " + deviceId);
+                            }
+                            mInputDevices.setValueAt(index, null);
+                            sendMessageToInputDeviceListenersLocked(
+                                    InputDeviceListenerDelegate.MSG_DEVICE_CHANGED, deviceId);
+                        }
+                    }
+                } else {
+                    if (DEBUG) {
+                        Log.d(TAG, "Device added: " + deviceId);
+                    }
+                    mInputDevices.put(deviceId, null);
+                    sendMessageToInputDeviceListenersLocked(
+                            InputDeviceListenerDelegate.MSG_DEVICE_ADDED, deviceId);
+                }
+            }
+        }
+    }
+
+    private static final class InputDeviceListenerDelegate extends Handler {
+        public final InputDeviceListener mListener;
+        static final int MSG_DEVICE_ADDED = 1;
+        static final int MSG_DEVICE_REMOVED = 2;
+        static final int MSG_DEVICE_CHANGED = 3;
+
+        InputDeviceListenerDelegate(InputDeviceListener listener, Handler handler) {
+            super(handler != null ? handler.getLooper() : Looper.myLooper());
+            mListener = listener;
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_DEVICE_ADDED:
+                    mListener.onInputDeviceAdded(msg.arg1);
+                    break;
+                case MSG_DEVICE_REMOVED:
+                    mListener.onInputDeviceRemoved(msg.arg1);
+                    break;
+                case MSG_DEVICE_CHANGED:
+                    mListener.onInputDeviceChanged(msg.arg1);
+                    break;
+            }
+        }
+    }
+
+    private static boolean containsDeviceId(int[] deviceIdAndGeneration, int deviceId) {
+        for (int i = 0; i < deviceIdAndGeneration.length; i += 2) {
+            if (deviceIdAndGeneration[i] == deviceId) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @GuardedBy("mInputDeviceListeners")
+    private void sendMessageToInputDeviceListenersLocked(int what, int deviceId) {
+        final int numListeners = mInputDeviceListeners.size();
+        for (int i = 0; i < numListeners; i++) {
+            InputDeviceListenerDelegate listener = mInputDeviceListeners.get(i);
+            listener.sendMessage(listener.obtainMessage(what, deviceId, 0));
+        }
+    }
+
+    /**
+     * @see InputManager#registerInputDeviceListener
+     */
+    void registerInputDeviceListener(InputDeviceListener listener, Handler handler) {
+        if (listener == null) {
+            throw new IllegalArgumentException("listener must not be null");
+        }
+
+        synchronized (mInputDeviceListeners) {
+            populateInputDevicesLocked();
+            int index = findInputDeviceListenerLocked(listener);
+            if (index < 0) {
+                mInputDeviceListeners.add(new InputDeviceListenerDelegate(listener, handler));
+            }
+        }
+    }
+
+    /**
+     * @see InputManager#unregisterInputDeviceListener
+     */
+    void unregisterInputDeviceListener(InputDeviceListener listener) {
+        if (listener == null) {
+            throw new IllegalArgumentException("listener must not be null");
+        }
+
+        synchronized (mInputDeviceListeners) {
+            int index = findInputDeviceListenerLocked(listener);
+            if (index >= 0) {
+                InputDeviceListenerDelegate d = mInputDeviceListeners.get(index);
+                d.removeCallbacksAndMessages(null);
+                mInputDeviceListeners.remove(index);
+            }
+        }
+    }
+
+    @GuardedBy("mInputDeviceListeners")
+    private int findInputDeviceListenerLocked(InputDeviceListener listener) {
+        final int numListeners = mInputDeviceListeners.size();
+        for (int i = 0; i < numListeners; i++) {
+            if (mInputDeviceListeners.get(i).mListener == listener) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * @see InputManager#getInputDeviceIds
+     */
+    public int[] getInputDeviceIds() {
+        synchronized (mInputDeviceListeners) {
+            populateInputDevicesLocked();
+
+            final int count = mInputDevices.size();
+            final int[] ids = new int[count];
+            for (int i = 0; i < count; i++) {
+                ids[i] = mInputDevices.keyAt(i);
+            }
+            return ids;
+        }
+    }
+
+    /**
+     * @see InputManager#getInputDeviceByDescriptor
+     */
+    InputDevice getInputDeviceByDescriptor(String descriptor) {
+        if (descriptor == null) {
+            throw new IllegalArgumentException("descriptor must not be null.");
+        }
+
+        synchronized (mInputDeviceListeners) {
+            populateInputDevicesLocked();
+
+            int numDevices = mInputDevices.size();
+            for (int i = 0; i < numDevices; i++) {
+                InputDevice inputDevice = mInputDevices.valueAt(i);
+                if (inputDevice == null) {
+                    int id = mInputDevices.keyAt(i);
+                    try {
+                        inputDevice = mIm.getInputDevice(id);
+                    } catch (RemoteException ex) {
+                        throw ex.rethrowFromSystemServer();
+                    }
+                    if (inputDevice == null) {
+                        continue;
+                    }
+                    mInputDevices.setValueAt(i, inputDevice);
+                }
+                if (descriptor.equals(inputDevice.getDescriptor())) {
+                    return inputDevice;
+                }
+            }
+            return null;
+        }
+    }
+
+    /**
+     * @see InputManager#getHostUsiVersion
+     */
+    @Nullable
+    HostUsiVersion getHostUsiVersion(@NonNull Display display) {
+        Objects.requireNonNull(display, "display should not be null");
+
+        // Return the first valid USI version reported by any input device associated with
+        // the display.
+        synchronized (mInputDeviceListeners) {
+            populateInputDevicesLocked();
+
+            for (int i = 0; i < mInputDevices.size(); i++) {
+                final InputDevice device = getInputDevice(mInputDevices.keyAt(i));
+                if (device != null && device.getAssociatedDisplayId() == display.getDisplayId()) {
+                    if (device.getHostUsiVersion() != null) {
+                        return device.getHostUsiVersion();
+                    }
+                }
+            }
+        }
+
+        // If there are no input devices that report a valid USI version, see if there is a config
+        // that specifies the USI version for the display. This is to handle cases where the USI
+        // input device is not registered by the kernel/driver all the time.
+        try {
+            return mIm.getHostUsiVersionFromDisplayConfig(display.getDisplayId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    private void onTabletModeChanged(long whenNanos, boolean inTabletMode) {
+        if (DEBUG) {
+            Log.d(TAG, "Received tablet mode changed: "
+                    + "whenNanos=" + whenNanos + ", inTabletMode=" + inTabletMode);
+        }
+        synchronized (mOnTabletModeChangedListeners) {
+            final int numListeners = mOnTabletModeChangedListeners.size();
+            for (int i = 0; i < numListeners; i++) {
+                OnTabletModeChangedListenerDelegate listener =
+                        mOnTabletModeChangedListeners.get(i);
+                listener.sendTabletModeChanged(whenNanos, inTabletMode);
+            }
+        }
+    }
+
+    private final class TabletModeChangedListener extends ITabletModeChangedListener.Stub {
+        @Override
+        public void onTabletModeChanged(long whenNanos, boolean inTabletMode) {
+            InputManagerGlobal.this.onTabletModeChanged(whenNanos, inTabletMode);
+        }
+    }
+
+    private static final class OnTabletModeChangedListenerDelegate extends Handler {
+        private static final int MSG_TABLET_MODE_CHANGED = 0;
+
+        public final OnTabletModeChangedListener mListener;
+
+        OnTabletModeChangedListenerDelegate(
+                OnTabletModeChangedListener listener, Handler handler) {
+            super(handler != null ? handler.getLooper() : Looper.myLooper());
+            mListener = listener;
+        }
+
+        public void sendTabletModeChanged(long whenNanos, boolean inTabletMode) {
+            SomeArgs args = SomeArgs.obtain();
+            args.argi1 = (int) whenNanos;
+            args.argi2 = (int) (whenNanos >> 32);
+            args.arg1 = inTabletMode;
+            obtainMessage(MSG_TABLET_MODE_CHANGED, args).sendToTarget();
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            if (msg.what == MSG_TABLET_MODE_CHANGED) {
+                SomeArgs args = (SomeArgs) msg.obj;
+                long whenNanos = (args.argi1 & 0xFFFFFFFFL) | ((long) args.argi2 << 32);
+                boolean inTabletMode = (boolean) args.arg1;
+                mListener.onTabletModeChanged(whenNanos, inTabletMode);
+            }
+        }
+    }
+
+    /**
+     * @see InputManager#registerInputDeviceListener(InputDeviceListener, Handler)
+     */
+    void registerOnTabletModeChangedListener(
+            OnTabletModeChangedListener listener, Handler handler) {
+        if (listener == null) {
+            throw new IllegalArgumentException("listener must not be null");
+        }
+        synchronized (mOnTabletModeChangedListeners) {
+            if (mOnTabletModeChangedListeners == null) {
+                initializeTabletModeListenerLocked();
+            }
+            int idx = findOnTabletModeChangedListenerLocked(listener);
+            if (idx < 0) {
+                OnTabletModeChangedListenerDelegate d =
+                        new OnTabletModeChangedListenerDelegate(listener, handler);
+                mOnTabletModeChangedListeners.add(d);
+            }
+        }
+    }
+
+    /**
+     * @see InputManager#unregisterOnTabletModeChangedListener(OnTabletModeChangedListener)
+     */
+    void unregisterOnTabletModeChangedListener(OnTabletModeChangedListener listener) {
+        if (listener == null) {
+            throw new IllegalArgumentException("listener must not be null");
+        }
+        synchronized (mOnTabletModeChangedListeners) {
+            int idx = findOnTabletModeChangedListenerLocked(listener);
+            if (idx >= 0) {
+                OnTabletModeChangedListenerDelegate d = mOnTabletModeChangedListeners.remove(idx);
+                d.removeCallbacksAndMessages(null);
+            }
+        }
+    }
+
+    @GuardedBy("mOnTabletModeChangedListeners")
+    private void initializeTabletModeListenerLocked() {
+        final TabletModeChangedListener listener = new TabletModeChangedListener();
+        try {
+            mIm.registerTabletModeChangedListener(listener);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    @GuardedBy("mOnTabletModeChangedListeners")
+    private int findOnTabletModeChangedListenerLocked(OnTabletModeChangedListener listener) {
+        final int n = mOnTabletModeChangedListeners.size();
+        for (int i = 0; i < n; i++) {
+            if (mOnTabletModeChangedListeners.get(i).mListener == listener) {
+                return i;
+            }
+        }
+        return -1;
+    }
+}
diff --git a/core/java/android/hardware/soundtrigger/ConversionUtil.java b/core/java/android/hardware/soundtrigger/ConversionUtil.java
index 9a2cd06..58e7f01 100644
--- a/core/java/android/hardware/soundtrigger/ConversionUtil.java
+++ b/core/java/android/hardware/soundtrigger/ConversionUtil.java
@@ -34,14 +34,16 @@
 import android.media.soundtrigger.SoundModel;
 import android.media.soundtrigger_middleware.SoundTriggerModuleDescriptor;
 import android.os.ParcelFileDescriptor;
+import android.system.ErrnoException;
 import android.os.SharedMemory;
 
 import java.nio.ByteBuffer;
 import java.util.Arrays;
+import java.util.Locale;
 import java.util.UUID;
 
 /** @hide */
-class ConversionUtil {
+public class ConversionUtil {
     public static SoundTrigger.ModuleProperties aidl2apiModuleDescriptor(
             SoundTriggerModuleDescriptor aidlDesc) {
         Properties properties = aidlDesc.properties;
@@ -140,6 +142,14 @@
         return aidlPhrase;
     }
 
+    public static SoundTrigger.Keyphrase aidl2apiPhrase(Phrase aidlPhrase) {
+        return new SoundTrigger.Keyphrase(aidlPhrase.id,
+                aidl2apiRecognitionModes(aidlPhrase.recognitionModes),
+                new Locale.Builder().setLanguageTag(aidlPhrase.locale).build(),
+                aidlPhrase.text,
+                Arrays.copyOf(aidlPhrase.users, aidlPhrase.users.length));
+    }
+
     public static RecognitionConfig api2aidlRecognitionConfig(
             SoundTrigger.RecognitionConfig apiConfig) {
         RecognitionConfig aidlConfig = new RecognitionConfig();
@@ -156,6 +166,21 @@
         return aidlConfig;
     }
 
+    public static SoundTrigger.RecognitionConfig aidl2apiRecognitionConfig(
+            RecognitionConfig aidlConfig) {
+        var keyphrases =
+            new SoundTrigger.KeyphraseRecognitionExtra[aidlConfig.phraseRecognitionExtras.length];
+        int i = 0;
+        for (var extras : aidlConfig.phraseRecognitionExtras) {
+            keyphrases[i++] = aidl2apiPhraseRecognitionExtra(extras);
+        }
+        return new SoundTrigger.RecognitionConfig(aidlConfig.captureRequested,
+                false /** allowMultipleTriggers **/,
+                keyphrases,
+                Arrays.copyOf(aidlConfig.data, aidlConfig.data.length),
+                aidl2apiAudioCapabilities(aidlConfig.audioCapabilities));
+    }
+
     public static PhraseRecognitionExtra api2aidlPhraseRecognitionExtra(
             SoundTrigger.KeyphraseRecognitionExtra apiExtra) {
         PhraseRecognitionExtra aidlExtra = new PhraseRecognitionExtra();
@@ -233,7 +258,11 @@
         if (audioConfig != null) {
             return AidlConversion.aidl2api_AudioConfig_AudioFormat(audioConfig, isInput);
         }
-        return new AudioFormat.Builder().build();
+        return new AudioFormat.Builder()
+            .setSampleRate(48000)
+            .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
+            .setChannelMask(AudioFormat.CHANNEL_IN_MONO)
+            .build();
     }
 
     public static int api2aidlModelParameter(int apiParam) {
@@ -277,7 +306,7 @@
         return result;
     }
 
-    private static @Nullable ParcelFileDescriptor byteArrayToSharedMemory(byte[] data, String name) {
+    public static @Nullable ParcelFileDescriptor byteArrayToSharedMemory(byte[] data, String name) {
         if (data.length == 0) {
             return null;
         }
@@ -294,4 +323,19 @@
             throw new RuntimeException(e);
         }
     }
+
+    public static byte[] sharedMemoryToByteArray(@Nullable ParcelFileDescriptor pfd, int size) {
+        if (pfd == null || size == 0) {
+            return new byte[0];
+        }
+        try (SharedMemory mem = SharedMemory.fromFileDescriptor(pfd)) {
+            ByteBuffer buffer = mem.mapReadOnly();
+            byte[] data = new byte[(size > mem.getSize()) ? mem.getSize() : size];
+            buffer.get(data);
+            mem.unmap(buffer);
+            return data;
+        } catch (ErrnoException e) {
+            throw new RuntimeException(e);
+        }
+    }
 }
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index b7a694c..5593989 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -79,6 +79,11 @@
     }
 
     /**
+     * @hide
+     */
+    public static final String FAKE_HAL_ARCH = "injection";
+
+    /**
      * Status code used when the operation succeeded
      */
     public static final int STATUS_OK = 0;
@@ -1493,6 +1498,45 @@
                     + Arrays.toString(keyphrases) + ", data=" + Arrays.toString(data)
                     + ", audioCapabilities=" + Integer.toHexString(audioCapabilities) + "]";
         }
+
+        @Override
+        public final boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (!(obj instanceof RecognitionConfig))
+                return false;
+            RecognitionConfig other = (RecognitionConfig) obj;
+            if (captureRequested != other.captureRequested) {
+                return false;
+            }
+            if (allowMultipleTriggers != other.allowMultipleTriggers) {
+                return false;
+            }
+            if (!Arrays.equals(keyphrases, other.keyphrases)) {
+                return false;
+            }
+            if (!Arrays.equals(data, other.data)) {
+                return false;
+            }
+            if (audioCapabilities != other.audioCapabilities) {
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        public final int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + (captureRequested ? 1 : 0);
+            result = prime * result + (allowMultipleTriggers ? 1 : 0);
+            result = prime * result + Arrays.hashCode(keyphrases);
+            result = prime * result + Arrays.hashCode(data);
+            result = prime * result + audioCapabilities;
+            return result;
+        }
     }
 
     /**
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 9341105..104a8b2 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -475,8 +475,8 @@
      *
      * @param uid The UID whose status needs to be checked.
      * @return {@link ConnectivityManager#RESTRICT_BACKGROUND_STATUS_DISABLED},
-     *         {@link ConnectivityManager##RESTRICT_BACKGROUND_STATUS_ENABLED},
-     *         or {@link ConnectivityManager##RESTRICT_BACKGROUND_STATUS_WHITELISTED} to denote
+     *         {@link ConnectivityManager#RESTRICT_BACKGROUND_STATUS_ENABLED},
+     *         or {@link ConnectivityManager#RESTRICT_BACKGROUND_STATUS_WHITELISTED} to denote
      *         the current status of the UID.
      * @hide
      */
@@ -769,6 +769,28 @@
     }
 
     /**
+     * Returns the default network capabilities
+     * ({@link ActivityManager#PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK
+     * ActivityManager.PROCESS_CAPABILITY_*}) of the specified process state.
+     * This <b>DOES NOT</b> return all default process capabilities for a proc state.
+     * @hide
+     */
+    public static int getDefaultProcessNetworkCapabilities(int procState) {
+        switch (procState) {
+            case ActivityManager.PROCESS_STATE_PERSISTENT:
+            case ActivityManager.PROCESS_STATE_PERSISTENT_UI:
+            case ActivityManager.PROCESS_STATE_TOP:
+                return ActivityManager.PROCESS_CAPABILITY_ALL;
+            case ActivityManager.PROCESS_STATE_BOUND_TOP:
+            case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE:
+            case ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
+                return ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
+            default:
+                return ActivityManager.PROCESS_CAPABILITY_NONE;
+        }
+    }
+
+    /**
      * Returns true if {@param procState} is considered foreground and as such will be allowed
      * to access network when the device is idle or in battery saver mode. Otherwise, false.
      * @hide
@@ -784,7 +806,7 @@
     public static boolean isProcStateAllowedWhileIdleOrPowerSaveMode(
             int procState, @ProcessCapability int capability) {
         return procState <= FOREGROUND_THRESHOLD_STATE
-                || (capability & ActivityManager.PROCESS_CAPABILITY_NETWORK) != 0;
+                || (capability & ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0;
     }
 
     /** @hide */
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index e2af9b0..cacde7f 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -26,6 +26,8 @@
 import android.annotation.SystemApi;
 import android.annotation.UserIdInt;
 import android.app.Activity;
+import android.app.ActivityThread;
+import android.app.OnActivityPausedListener;
 import android.app.PendingIntent;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
@@ -420,6 +422,7 @@
     // Guarded by NfcAdapter.class
     static boolean sIsInitialized = false;
     static boolean sHasNfcFeature;
+    static boolean sHasCeFeature;
 
     // Final after first constructor, except for
     // attemptDeadServiceRecovery() when NFC crashes - we accept a best effort
@@ -616,11 +619,13 @@
             PackageManager pm;
             pm = context.getPackageManager();
             sHasNfcFeature = pm.hasSystemFeature(PackageManager.FEATURE_NFC);
-            boolean hasHceFeature =
+            sHasCeFeature =
                     pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)
-                    || pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF);
+                    || pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF)
+                    || pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC)
+                    || pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE);
             /* is this device meant to have NFC */
-            if (!sHasNfcFeature && !hasHceFeature) {
+            if (!sHasNfcFeature && !sHasCeFeature) {
                 Log.v(TAG, "this device does not have NFC support");
                 throw new UnsupportedOperationException();
             }
@@ -643,7 +648,7 @@
                     throw new UnsupportedOperationException();
                 }
             }
-            if (hasHceFeature) {
+            if (sHasCeFeature) {
                 try {
                     sNfcFCardEmulationService = sService.getNfcFCardEmulationInterface();
                 } catch (RemoteException e) {
@@ -1467,11 +1472,17 @@
         if (activity == null || intent == null) {
             throw new NullPointerException();
         }
+        if (!activity.isResumed()) {
+            throw new IllegalStateException("Foreground dispatch can only be enabled " +
+                    "when your activity is resumed");
+        }
         try {
             TechListParcel parcel = null;
             if (techLists != null && techLists.length > 0) {
                 parcel = new TechListParcel(techLists);
             }
+            ActivityThread.currentActivityThread().registerOnActivityPausedListener(activity,
+                    mForegroundDispatchListener);
             sService.setForegroundDispatch(intent, filters, parcel);
         } catch (RemoteException e) {
             attemptDeadServiceRecovery(e);
@@ -1499,8 +1510,25 @@
                 throw new UnsupportedOperationException();
             }
         }
+        ActivityThread.currentActivityThread().unregisterOnActivityPausedListener(activity,
+                mForegroundDispatchListener);
+        disableForegroundDispatchInternal(activity, false);
+    }
+
+    OnActivityPausedListener mForegroundDispatchListener = new OnActivityPausedListener() {
+        @Override
+        public void onPaused(Activity activity) {
+            disableForegroundDispatchInternal(activity, true);
+        }
+    };
+
+    void disableForegroundDispatchInternal(Activity activity, boolean force) {
         try {
             sService.setForegroundDispatch(null, null, null);
+            if (!force && !activity.isResumed()) {
+                throw new IllegalStateException("You must disable foreground dispatching " +
+                        "while your activity is still resumed");
+            }
         } catch (RemoteException e) {
             attemptDeadServiceRecovery(e);
         }
@@ -1669,7 +1697,7 @@
     @SystemApi
     @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     public boolean enableSecureNfc(boolean enable) {
-        if (!sHasNfcFeature) {
+        if (!sHasNfcFeature && !sHasCeFeature) {
             throw new UnsupportedOperationException();
         }
         try {
@@ -1694,10 +1722,13 @@
      * Checks if the device supports Secure NFC functionality.
      *
      * @return True if device supports Secure NFC, false otherwise
-     * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
+     * @throws UnsupportedOperationException if FEATURE_NFC,
+     * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF,
+     * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE
+     * are unavailable
      */
     public boolean isSecureNfcSupported() {
-        if (!sHasNfcFeature) {
+        if (!sHasNfcFeature && !sHasCeFeature) {
             throw new UnsupportedOperationException();
         }
         try {
@@ -1723,11 +1754,14 @@
      * such as their relative positioning on the device.
      *
      * @return Information on the nfc antenna(s) on the device.
-     * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
+     * @throws UnsupportedOperationException if FEATURE_NFC,
+     * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF,
+     * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE
+     * are unavailable
      */
     @Nullable
     public NfcAntennaInfo getNfcAntennaInfo() {
-        if (!sHasNfcFeature) {
+        if (!sHasNfcFeature && !sHasCeFeature) {
             throw new UnsupportedOperationException();
         }
         try {
@@ -1752,12 +1786,15 @@
      * Checks Secure NFC feature is enabled.
      *
      * @return True if Secure NFC is enabled, false otherwise
-     * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
+     * @throws UnsupportedOperationException if FEATURE_NFC,
+     * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF,
+     * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE
+     * are unavailable
      * @throws UnsupportedOperationException if device doesn't support
      *         Secure NFC functionality. {@link #isSecureNfcSupported}
      */
     public boolean isSecureNfcEnabled() {
-        if (!sHasNfcFeature) {
+        if (!sHasNfcFeature && !sHasCeFeature) {
             throw new UnsupportedOperationException();
         }
         try {
@@ -2071,14 +2108,17 @@
      * always on.
      * @param value if true the NFCC will be kept on (with no RF enabled if NFC adapter is
      * disabled), if false the NFCC will follow completely the Nfc adapter state.
-     * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
+     * @throws UnsupportedOperationException if FEATURE_NFC,
+     * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF,
+     * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE
+     * are unavailable
      * @return void
      * @hide
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
     public boolean setControllerAlwaysOn(boolean value) {
-        if (!sHasNfcFeature) {
+        if (!sHasNfcFeature && !sHasCeFeature) {
             throw new UnsupportedOperationException();
         }
         try {
@@ -2103,7 +2143,10 @@
      * Checks NFC controller always on feature is enabled.
      *
      * @return True if NFC controller always on is enabled, false otherwise
-     * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
+     * @throws UnsupportedOperationException if FEATURE_NFC,
+     * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF,
+     * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE
+     * are unavailable
      * @hide
      */
     @SystemApi
@@ -2131,13 +2174,16 @@
      * Checks if the device supports NFC controller always on functionality.
      *
      * @return True if device supports NFC controller always on, false otherwise
-     * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
+     * @throws UnsupportedOperationException if FEATURE_NFC,
+     * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF,
+     * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE
+     * are unavailable
      * @hide
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
     public boolean isControllerAlwaysOnSupported() {
-        if (!sHasNfcFeature) {
+        if (!sHasNfcFeature && !sHasCeFeature) {
             throw new UnsupportedOperationException();
         }
         try {
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index 0954013..793a70e 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -660,7 +660,7 @@
      * @param proto the ProtoOutputStream to write to
      */
     public void dumpDebug(ProtoOutputStream proto) {
-        getComponent().dumpDebug(proto, ApduServiceInfoProto.COMPONENT_NAME);
+        Utils.dumpDebugComponentName(getComponent(), proto, ApduServiceInfoProto.COMPONENT_NAME);
         proto.write(ApduServiceInfoProto.DESCRIPTION, getDescription());
         proto.write(ApduServiceInfoProto.ON_HOST, mOnHost);
         if (!mOnHost) {
diff --git a/core/java/android/nfc/cardemulation/NfcFServiceInfo.java b/core/java/android/nfc/cardemulation/NfcFServiceInfo.java
index f8f7dfe..7a36b26 100644
--- a/core/java/android/nfc/cardemulation/NfcFServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/NfcFServiceInfo.java
@@ -340,7 +340,7 @@
      * @param proto the ProtoOutputStream to write to
      */
     public void dumpDebug(ProtoOutputStream proto) {
-        getComponent().dumpDebug(proto, NfcFServiceInfoProto.COMPONENT_NAME);
+        Utils.dumpDebugComponentName(getComponent(), proto, NfcFServiceInfoProto.COMPONENT_NAME);
         proto.write(NfcFServiceInfoProto.DESCRIPTION, getDescription());
         proto.write(NfcFServiceInfoProto.SYSTEM_CODE, getSystemCode());
         proto.write(NfcFServiceInfoProto.NFCID2, getNfcid2());
diff --git a/core/java/android/nfc/cardemulation/Utils.java b/core/java/android/nfc/cardemulation/Utils.java
new file mode 100644
index 0000000..202e1cf
--- /dev/null
+++ b/core/java/android/nfc/cardemulation/Utils.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc.cardemulation;
+
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.ComponentNameProto;
+import android.util.proto.ProtoOutputStream;
+
+/** @hide */
+public final class Utils {
+    private Utils() {
+    }
+
+    /** Copied from {@link ComponentName#dumpDebug(ProtoOutputStream, long)} */
+    public static void dumpDebugComponentName(
+            @NonNull ComponentName componentName, @NonNull ProtoOutputStream proto, long fieldId) {
+        final long token = proto.start(fieldId);
+        proto.write(ComponentNameProto.PACKAGE_NAME, componentName.getPackageName());
+        proto.write(ComponentNameProto.CLASS_NAME, componentName.getClassName());
+        proto.end(token);
+    }
+}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 9689be2..244632a 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -64,17 +64,27 @@
     /**
      * The product name for attestation. In non-default builds (like the AOSP build) the value of
      * the 'PRODUCT' system property may be different to the one provisioned to KeyMint,
-     * and Keymint attestation would still attest to the product name, it's running on.
+     * and Keymint attestation would still attest to the product name which was provisioned.
      * @hide
      */
     @Nullable
     @TestApi
-    public static final String PRODUCT_FOR_ATTESTATION =
-            getString("ro.product.name_for_attestation");
+    public static final String PRODUCT_FOR_ATTESTATION = getVendorDeviceIdProperty("name");
 
     /** The name of the industrial design. */
     public static final String DEVICE = getString("ro.product.device");
 
+    /**
+     * The device name for attestation. In non-default builds (like the AOSP build) the value of
+     * the 'DEVICE' system property may be different to the one provisioned to KeyMint,
+     * and Keymint attestation would still attest to the device name which was provisioned.
+     * @hide
+     */
+    @Nullable
+    @TestApi
+    public static final String DEVICE_FOR_ATTESTATION =
+            getVendorDeviceIdProperty("device");
+
     /** The name of the underlying board, like "goldfish". */
     public static final String BOARD = getString("ro.product.board");
 
@@ -97,19 +107,29 @@
     /** The manufacturer of the product/hardware. */
     public static final String MANUFACTURER = getString("ro.product.manufacturer");
 
+    /**
+     * The manufacturer name for attestation. In non-default builds (like the AOSP build) the value
+     * of the 'MANUFACTURER' system property may be different to the one provisioned to KeyMint,
+     * and Keymint attestation would still attest to the manufacturer which was provisioned.
+     * @hide
+     */
+    @Nullable
+    @TestApi
+    public static final String MANUFACTURER_FOR_ATTESTATION =
+            getVendorDeviceIdProperty("manufacturer");
+
     /** The consumer-visible brand with which the product/hardware will be associated, if any. */
     public static final String BRAND = getString("ro.product.brand");
 
     /**
      * The product brand for attestation. In non-default builds (like the AOSP build) the value of
      * the 'BRAND' system property may be different to the one provisioned to KeyMint,
-     * and Keymint attestation would still attest to the product brand, it's running on.
+     * and Keymint attestation would still attest to the product brand which was provisioned.
      * @hide
      */
     @Nullable
     @TestApi
-    public static final String BRAND_FOR_ATTESTATION =
-                getString("ro.product.brand_for_attestation");
+    public static final String BRAND_FOR_ATTESTATION = getVendorDeviceIdProperty("brand");
 
     /** The end-user-visible name for the end product. */
     public static final String MODEL = getString("ro.product.model");
@@ -117,13 +137,12 @@
     /**
      * The product model for attestation. In non-default builds (like the AOSP build) the value of
      * the 'MODEL' system property may be different to the one provisioned to KeyMint,
-     * and Keymint attestation would still attest to the product model, it's running on.
+     * and Keymint attestation would still attest to the product model which was provisioned.
      * @hide
      */
     @Nullable
     @TestApi
-    public static final String MODEL_FOR_ATTESTATION =
-                getString("ro.product.model_for_attestation");
+    public static final String MODEL_FOR_ATTESTATION = getVendorDeviceIdProperty("model");
 
     /** The manufacturer of the device's primary system-on-chip. */
     @NonNull
@@ -1527,6 +1546,17 @@
     private static String getString(String property) {
         return SystemProperties.get(property, UNKNOWN);
     }
+    /**
+     * Return attestation specific proerties.
+     * @param property model, name, brand, device or manufacturer.
+     * @return property value or UNKNOWN
+     */
+    private static String getVendorDeviceIdProperty(String property) {
+        String attestProp = getString(
+                TextUtils.formatSimple("ro.product.%s_for_attestation", property));
+        return attestProp.equals(UNKNOWN)
+                ? getString(TextUtils.formatSimple("ro.product.vendor.%s", property)) : UNKNOWN;
+    }
 
     private static String[] getStringList(String property, String separator) {
         String value = SystemProperties.get(property);
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index fb8f84a..a52e3d49 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -474,9 +474,8 @@
      *        target functionality.  The ANGLE broadcast receiver code will apply a "deferlist" at
      *        the first boot of a newly-flashed device.  However, there is a gap in time between
      *        when applications can start and when the deferlist is applied.  For now, assume that
-     *        if ANGLE is the system driver and Settings.Global.ANGLE_GL_DRIVER_SELECTION_PKGS is
-     *        empty, that the deferlist has not yet been applied.  In this case, select the Legacy
-     *        driver.
+     *        if ANGLE is the system driver and Settings.Global.ANGLE_DEFERLIST is empty, that the
+     *        deferlist has not yet been applied.  In this case, select the Legacy driver.
      *    otherwise ...
      * 3) Use ANGLE if isAngleEnabledByGameMode() returns true; otherwise ...
      * 4) The global switch (i.e. use the system driver, whether ANGLE or legacy;
@@ -516,14 +515,17 @@
                 contentResolver, bundle, Settings.Global.ANGLE_GL_DRIVER_SELECTION_PKGS);
         final List<String> optInValues = getGlobalSettingsString(
                 contentResolver, bundle, Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES);
+        final List<String> angleDeferlist = getGlobalSettingsString(
+                contentResolver, bundle, Settings.Global.ANGLE_DEFERLIST);
         Log.v(TAG, "Currently set values for:");
         Log.v(TAG, "    angle_gl_driver_selection_pkgs =" + optInPackages);
         Log.v(TAG, "  angle_gl_driver_selection_values =" + optInValues);
 
         // If ANGLE is the system driver AND the deferlist has not yet been applied, select the
         // Legacy driver
-        if (mAngleIsSystemDriver && optInPackages.size() <= 1) {
-            Log.v(TAG, "Ignoring angle_gl_driver_selection_* until deferlist has been applied");
+        if (mAngleIsSystemDriver && angleDeferlist.size() == 0) {
+            Log.v(TAG, "ANGLE deferlist (" + Settings.Global.ANGLE_DEFERLIST + ") has not been "
+                           + "applied, defaulting to legacy driver");
             return ANGLE_GL_DRIVER_TO_USE_LEGACY;
         }
 
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 3cf3ea2..fcebb45 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -117,6 +117,7 @@
     boolean someUserHasAccount(in String accountName, in String accountType);
     String getProfileType(int userId);
     boolean isDemoUser(int userId);
+    boolean isAdminUser(int userId);
     boolean isPreCreated(int userId);
     UserInfo createProfileForUserEvenWhenDisallowedWithThrow(in String name, in String userType, int flags,
             int userId, in String[] disallowedPackages);
diff --git a/core/java/android/os/Parcelable.java b/core/java/android/os/Parcelable.java
index a2b0486..f2b60a4 100644
--- a/core/java/android/os/Parcelable.java
+++ b/core/java/android/os/Parcelable.java
@@ -16,8 +16,8 @@
 
 package android.os;
 
-import android.annotation.NonNull;
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 
 import java.lang.annotation.Retention;
@@ -26,8 +26,9 @@
 /**
  * Interface for classes whose instances can be written to
  * and restored from a {@link Parcel}.  Classes implementing the Parcelable
- * interface must also have a non-null static field called <code>CREATOR</code>
- * of a type that implements the {@link Parcelable.Creator} interface.
+ * interface must also have a non-null public static field called
+ * <code>CREATOR</code> of a type that implements the {@link Parcelable.Creator}
+ * interface.
  *
  * <p>A typical implementation of Parcelable is:</p>
  *
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index ac1583a..b2208d1 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -365,6 +365,11 @@
     public static final int LAST_APPLICATION_CACHE_GID = 29999;
 
     /**
+     * An invalid PID value.
+     */
+    public static final int INVALID_PID = -1;
+
+    /**
      * Standard priority of application threads.
      * Use with {@link #setThreadPriority(int)} and
      * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 8d8deaa..290f929 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -2433,21 +2433,24 @@
     }
 
     /**
-     * Used to check if the context user is an admin user. An admin user is allowed to
+     * Used to check if the context user is an admin user. An admin user may be allowed to
      * modify or configure certain settings that aren't available to non-admin users,
      * create and delete additional users, etc. There can be more than one admin users.
      *
      * @return whether the context user is an admin user.
-     * @hide
      */
-    @SystemApi
-    @RequiresPermission(anyOf = {
-            Manifest.permission.MANAGE_USERS,
-            Manifest.permission.CREATE_USERS,
-            Manifest.permission.QUERY_USERS})
-    @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+    @UserHandleAware(
+            enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU,
+            requiresAnyOfPermissionsIfNotCallerProfileGroup = {
+                    Manifest.permission.MANAGE_USERS,
+                    Manifest.permission.CREATE_USERS,
+                    Manifest.permission.QUERY_USERS})
     public boolean isAdminUser() {
-        return isUserAdmin(getContextUserIfAppropriate());
+        try {
+            return mService.isAdminUser(getContextUserIfAppropriate());
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -3972,6 +3975,9 @@
      * time, the preferred user name and account information are used by the setup process for that
      * user.
      *
+     * This API should only be called if the current user is an {@link #isAdminUser() admin} user,
+     * as otherwise the returned intent will not be able to create a user.
+     *
      * @param userName Optional name to assign to the user.
      * @param accountName Optional account name that will be used by the setup wizard to initialize
      *                    the user.
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 07d5001..5b527c7 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -979,6 +979,19 @@
     }
 
     /**
+     * An unrestricted version of getType, which does not reveal sensitive information
+     */
+    @Override
+    public final @Nullable String getTypeAnonymous(@NonNull Uri uri) {
+        switch (mMatcher.match(uri)) {
+            case MATCH_ROOT:
+                return DocumentsContract.Root.MIME_TYPE_ITEM;
+            default:
+                return null;
+        }
+    }
+
+    /**
      * Implementation is provided by the parent class. Can be overridden to
      * provide additional functionality, but subclasses <em>must</em> always
      * call the superclass. If the superclass returns {@code null}, the subclass
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 54e4909..07d265b 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -99,7 +99,6 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
-import com.android.internal.widget.ILockSettings;
 
 import java.io.IOException;
 import java.lang.annotation.ElementType;
@@ -116,6 +115,7 @@
 import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.Executor;
+import java.util.function.Consumer;
 
 /**
  * The Settings provider contains global system-level device preferences.
@@ -2978,19 +2978,22 @@
     }
 
     private static final class GenerationTracker {
-        private final MemoryIntArray mArray;
-        private final Runnable mErrorHandler;
+        @NonNull private final String mName;
+        @NonNull private final MemoryIntArray mArray;
+        @NonNull private final Consumer<String> mErrorHandler;
         private final int mIndex;
         private int mCurrentGeneration;
 
-        public GenerationTracker(@NonNull MemoryIntArray array, int index,
-                int generation, Runnable errorHandler) {
+        GenerationTracker(@NonNull String name, @NonNull MemoryIntArray array, int index,
+                int generation, Consumer<String> errorHandler) {
+            mName = name;
             mArray = array;
             mIndex = index;
             mErrorHandler = errorHandler;
             mCurrentGeneration = generation;
         }
 
+        // This method also updates the obsolete generation code stored locally
         public boolean isGenerationChanged() {
             final int currentGeneration = readCurrentGeneration();
             if (currentGeneration >= 0) {
@@ -3011,21 +3014,20 @@
                 return mArray.get(mIndex);
             } catch (IOException e) {
                 Log.e(TAG, "Error getting current generation", e);
-                if (mErrorHandler != null) {
-                    mErrorHandler.run();
-                }
+                mErrorHandler.accept(mName);
             }
             return -1;
         }
 
         public void destroy() {
             try {
-                mArray.close();
+                // If this process is the system server process, mArray is the same object as
+                // the memory int array kept inside SetingsProvider, so skipping the close()
+                if (!Settings.isInSystemServer()) {
+                    mArray.close();
+                }
             } catch (IOException e) {
                 Log.e(TAG, "Error closing backing array", e);
-                if (mErrorHandler != null) {
-                    mErrorHandler.run();
-                }
             }
         }
     }
@@ -3088,8 +3090,21 @@
         private final ArraySet<String> mAllFields;
         private final ArrayMap<String, Integer> mReadableFieldsWithMaxTargetSdk;
 
+        // Mapping from the name of a setting (or the prefix of a namespace) to a generation tracker
         @GuardedBy("this")
-        private GenerationTracker mGenerationTracker;
+        private ArrayMap<String, GenerationTracker> mGenerationTrackers = new ArrayMap<>();
+
+        private Consumer<String> mGenerationTrackerErrorHandler = (String name) -> {
+            synchronized (NameValueCache.this) {
+                Log.e(TAG, "Error accessing generation tracker - removing");
+                final GenerationTracker tracker = mGenerationTrackers.get(name);
+                if (tracker != null) {
+                    tracker.destroy();
+                    mGenerationTrackers.remove(name);
+                }
+                mValues.remove(name);
+            }
+        };
 
         <T extends NameValueTable> NameValueCache(Uri uri, String getCommand,
                 String setCommand, String deleteCommand, ContentProviderHolder providerHolder,
@@ -3178,6 +3193,45 @@
 
         @UnsupportedAppUsage
         public String getStringForUser(ContentResolver cr, String name, final int userHandle) {
+            final boolean isSelf = (userHandle == UserHandle.myUserId());
+            boolean needsGenerationTracker = false;
+            if (isSelf) {
+                synchronized (NameValueCache.this) {
+                    final GenerationTracker generationTracker = mGenerationTrackers.get(name);
+                    if (generationTracker != null) {
+                        if (generationTracker.isGenerationChanged()) {
+                            if (DEBUG) {
+                                Log.i(TAG, "Generation changed for setting:" + name
+                                        + " type:" + mUri.getPath()
+                                        + " in package:" + cr.getPackageName()
+                                        + " and user:" + userHandle);
+                            }
+                            // When a generation number changes, remove cached value, remove the old
+                            // generation tracker and request a new one
+                            mValues.remove(name);
+                            generationTracker.destroy();
+                            mGenerationTrackers.remove(name);
+                        } else if (mValues.containsKey(name)) {
+                            if (DEBUG) {
+                                Log.i(TAG, "Cache hit for setting:" + name);
+                            }
+                            return mValues.get(name);
+                        }
+                    }
+                }
+                if (DEBUG) {
+                    Log.i(TAG, "Cache miss for setting:" + name + " for user:"
+                            + userHandle);
+                }
+                // Generation tracker doesn't exist or the value isn't cached
+                needsGenerationTracker = true;
+            } else {
+                if (DEBUG || LOCAL_LOGV) {
+                    Log.v(TAG, "get setting for user " + userHandle
+                            + " by user " + UserHandle.myUserId() + " so skipping cache");
+                }
+            }
+
             // Check if the target settings key is readable. Reject if the caller is not system and
             // is trying to access a settings key defined in the Settings.Secure, Settings.System or
             // Settings.Global and is not annotated as @Readable.
@@ -3211,31 +3265,6 @@
                 }
             }
 
-            final boolean isSelf = (userHandle == UserHandle.myUserId());
-            int currentGeneration = -1;
-            if (isSelf) {
-                synchronized (NameValueCache.this) {
-                    if (mGenerationTracker != null) {
-                        if (mGenerationTracker.isGenerationChanged()) {
-                            if (DEBUG) {
-                                Log.i(TAG, "Generation changed for type:"
-                                        + mUri.getPath() + " in package:"
-                                        + cr.getPackageName() +" and user:" + userHandle);
-                            }
-                            mValues.clear();
-                        } else if (mValues.containsKey(name)) {
-                            return mValues.get(name);
-                        }
-                        if (mGenerationTracker != null) {
-                            currentGeneration = mGenerationTracker.getCurrentGeneration();
-                        }
-                    }
-                }
-            } else {
-                if (LOCAL_LOGV) Log.v(TAG, "get setting for user " + userHandle
-                        + " by user " + UserHandle.myUserId() + " so skipping cache");
-            }
-
             IContentProvider cp = mProviderHolder.getProvider(cr);
 
             // Try the fast path first, not using query().  If this
@@ -3244,24 +3273,17 @@
             // interface.
             if (mCallGetCommand != null) {
                 try {
-                    Bundle args = null;
+                    Bundle args = new Bundle();
                     if (!isSelf) {
-                        args = new Bundle();
                         args.putInt(CALL_METHOD_USER_KEY, userHandle);
                     }
-                    boolean needsGenerationTracker = false;
-                    synchronized (NameValueCache.this) {
-                        if (isSelf && mGenerationTracker == null) {
-                            needsGenerationTracker = true;
-                            if (args == null) {
-                                args = new Bundle();
-                            }
-                            args.putString(CALL_METHOD_TRACK_GENERATION_KEY, null);
-                            if (DEBUG) {
-                                Log.i(TAG, "Requested generation tracker for type: "+ mUri.getPath()
-                                        + " in package:" + cr.getPackageName() +" and user:"
-                                        + userHandle);
-                            }
+                    if (needsGenerationTracker) {
+                        args.putString(CALL_METHOD_TRACK_GENERATION_KEY, null);
+                        if (DEBUG) {
+                            Log.i(TAG, "Requested generation tracker for setting:" + name
+                                    + " type:" + mUri.getPath()
+                                    + " in package:" + cr.getPackageName()
+                                    + " and user:" + userHandle);
                         }
                     }
                     Bundle b;
@@ -3298,33 +3320,23 @@
                                         final int generation = b.getInt(
                                                 CALL_METHOD_GENERATION_KEY, 0);
                                         if (DEBUG) {
-                                            Log.i(TAG, "Received generation tracker for type:"
-                                                    + mUri.getPath() + " in package:"
-                                                    + cr.getPackageName() + " and user:"
-                                                    + userHandle + " with index:" + index);
+                                            Log.i(TAG, "Received generation tracker for setting:"
+                                                    + name
+                                                    + " type:" + mUri.getPath()
+                                                    + " in package:" + cr.getPackageName()
+                                                    + " and user:" + userHandle
+                                                    + " with index:" + index);
                                         }
-                                        if (mGenerationTracker != null) {
-                                            mGenerationTracker.destroy();
-                                        }
-                                        mGenerationTracker = new GenerationTracker(array, index,
-                                                generation, () -> {
-                                            synchronized (NameValueCache.this) {
-                                                Log.e(TAG, "Error accessing generation"
-                                                        + " tracker - removing");
-                                                if (mGenerationTracker != null) {
-                                                    GenerationTracker generationTracker =
-                                                            mGenerationTracker;
-                                                    mGenerationTracker = null;
-                                                    generationTracker.destroy();
-                                                    mValues.clear();
-                                                }
-                                            }
-                                        });
-                                        currentGeneration = generation;
+                                        mGenerationTrackers.put(name, new GenerationTracker(name,
+                                                array, index, generation,
+                                                mGenerationTrackerErrorHandler));
                                     }
                                 }
-                                if (mGenerationTracker != null && currentGeneration ==
-                                        mGenerationTracker.getCurrentGeneration()) {
+                                if (mGenerationTrackers.get(name) != null
+                                        && !mGenerationTrackers.get(name).isGenerationChanged()) {
+                                    if (DEBUG) {
+                                        Log.i(TAG, "Updating cache for setting:" + name);
+                                    }
                                     mValues.put(name, value);
                                 }
                             }
@@ -3367,15 +3379,14 @@
 
                 String value = c.moveToNext() ? c.getString(0) : null;
                 synchronized (NameValueCache.this) {
-                    if (mGenerationTracker != null
-                            && currentGeneration == mGenerationTracker.getCurrentGeneration()) {
+                    if (mGenerationTrackers.get(name) != null
+                            && !mGenerationTrackers.get(name).isGenerationChanged()) {
+                        if (DEBUG) {
+                            Log.i(TAG, "Updating cache for setting:" + name + " using query");
+                        }
                         mValues.put(name, value);
                     }
                 }
-                if (LOCAL_LOGV) {
-                    Log.v(TAG, "cache miss [" + mUri.getLastPathSegment() + "]: " +
-                            name + " = " + (value == null ? "(null)" : value));
-                }
                 return value;
             } catch (RemoteException e) {
                 Log.w(TAG, "Can't get key " + name + " from " + mUri, e);
@@ -3409,18 +3420,29 @@
             Config.enforceReadPermission(namespace);
             ArrayMap<String, String> keyValues = new ArrayMap<>();
             int currentGeneration = -1;
+            boolean needsGenerationTracker = false;
 
             synchronized (NameValueCache.this) {
-                if (mGenerationTracker != null) {
-                    if (mGenerationTracker.isGenerationChanged()) {
+                final GenerationTracker generationTracker = mGenerationTrackers.get(prefix);
+                if (generationTracker != null) {
+                    if (generationTracker.isGenerationChanged()) {
                         if (DEBUG) {
-                            Log.i(TAG, "Generation changed for type:" + mUri.getPath()
+                            Log.i(TAG, "Generation changed for prefix:" + prefix
+                                    + " type:" + mUri.getPath()
                                     + " in package:" + cr.getPackageName());
                         }
-                        mValues.clear();
+                        for (int i = 0; i < mValues.size(); ++i) {
+                            String key = mValues.keyAt(i);
+                            if (key.startsWith(prefix)) {
+                                mValues.remove(key);
+                            }
+                        }
                     } else {
                         boolean prefixCached = mValues.containsKey(prefix);
                         if (prefixCached) {
+                            if (DEBUG) {
+                                Log.i(TAG, "Cache hit for prefix:" + prefix);
+                            }
                             if (!names.isEmpty()) {
                                 for (String name : names) {
                                     if (mValues.containsKey(name)) {
@@ -3440,9 +3462,9 @@
                             return keyValues;
                         }
                     }
-                    if (mGenerationTracker != null) {
-                        currentGeneration = mGenerationTracker.getCurrentGeneration();
-                    }
+                    currentGeneration = generationTracker.getCurrentGeneration();
+                } else {
+                    needsGenerationTracker = true;
                 }
             }
 
@@ -3450,20 +3472,20 @@
                 // No list command specified, return empty map
                 return keyValues;
             }
+            if (DEBUG) {
+                Log.i(TAG, "Cache miss for prefix:" + prefix);
+            }
             IContentProvider cp = mProviderHolder.getProvider(cr);
 
             try {
                 Bundle args = new Bundle();
                 args.putString(Settings.CALL_METHOD_PREFIX_KEY, prefix);
-                boolean needsGenerationTracker = false;
-                synchronized (NameValueCache.this) {
-                    if (mGenerationTracker == null) {
-                        needsGenerationTracker = true;
-                        args.putString(CALL_METHOD_TRACK_GENERATION_KEY, null);
-                        if (DEBUG) {
-                            Log.i(TAG, "Requested generation tracker for type: "
-                                    + mUri.getPath() + " in package:" + cr.getPackageName());
-                        }
+                if (needsGenerationTracker) {
+                    args.putString(CALL_METHOD_TRACK_GENERATION_KEY, null);
+                    if (DEBUG) {
+                        Log.i(TAG, "Requested generation tracker for prefix:" + prefix
+                                + " type: " + mUri.getPath()
+                                + " in package:" + cr.getPackageName());
                     }
                 }
 
@@ -3516,32 +3538,22 @@
                             final int generation = b.getInt(
                                     CALL_METHOD_GENERATION_KEY, 0);
                             if (DEBUG) {
-                                Log.i(TAG, "Received generation tracker for type:"
-                                        + mUri.getPath() + " in package:"
-                                        + cr.getPackageName() + " with index:" + index);
+                                Log.i(TAG, "Received generation tracker for prefix:" + prefix
+                                        + " type:" + mUri.getPath()
+                                        + " in package:" + cr.getPackageName()
+                                        + " with index:" + index);
                             }
-                            if (mGenerationTracker != null) {
-                                mGenerationTracker.destroy();
-                            }
-                            mGenerationTracker = new GenerationTracker(array, index,
-                                    generation, () -> {
-                                synchronized (NameValueCache.this) {
-                                    Log.e(TAG, "Error accessing generation tracker"
-                                            + " - removing");
-                                    if (mGenerationTracker != null) {
-                                        GenerationTracker generationTracker =
-                                                mGenerationTracker;
-                                        mGenerationTracker = null;
-                                        generationTracker.destroy();
-                                        mValues.clear();
-                                    }
-                                }
-                            });
+                            mGenerationTrackers.put(prefix,
+                                    new GenerationTracker(prefix, array, index, generation,
+                                            mGenerationTrackerErrorHandler));
                             currentGeneration = generation;
                         }
                     }
-                    if (mGenerationTracker != null && currentGeneration
-                            == mGenerationTracker.getCurrentGeneration()) {
+                    if (mGenerationTrackers.get(prefix) != null && currentGeneration
+                            == mGenerationTrackers.get(prefix).getCurrentGeneration()) {
+                        if (DEBUG) {
+                            Log.i(TAG, "Updating cache for prefix:" + prefix);
+                        }
                         // cache the complete list of flags for the namespace
                         mValues.putAll(flagsToValues);
                         // Adding the prefix as a signal that the prefix is cached.
@@ -3557,11 +3569,11 @@
 
         public void clearGenerationTrackerForTest() {
             synchronized (NameValueCache.this) {
-                if (mGenerationTracker != null) {
-                    mGenerationTracker.destroy();
+                for (int i = 0; i < mGenerationTrackers.size(); i++) {
+                    mGenerationTrackers.valueAt(i).destroy();
                 }
+                mGenerationTrackers.clear();
                 mValues.clear();
-                mGenerationTracker = null;
             }
         }
     }
@@ -5671,6 +5683,36 @@
         public static final String LOCALE_PREFERENCES = "locale_preferences";
 
         /**
+         * Setting to enable camera flash notification feature.
+         * <ul>
+         *     <li> 0 = Off
+         *     <li> 1 = On
+         * </ul>
+         * @hide
+         */
+        public static final String CAMERA_FLASH_NOTIFICATION = "camera_flash_notification";
+
+        /**
+         * Setting to enable screen flash notification feature.
+         * <ul>
+         *     <li> 0 = Off
+         *     <li> 1 = On
+         * </ul>
+         *  @hide
+         */
+        public static final String SCREEN_FLASH_NOTIFICATION = "screen_flash_notification";
+
+        /**
+         * Integer property that specifes the color for screen flash notification as a
+         * packed 32-bit color.
+         *
+         * @see android.graphics.Color#argb
+         * @hide
+         */
+        public static final String SCREEN_FLASH_NOTIFICATION_COLOR =
+                "screen_flash_notification_color_global";
+
+        /**
          * IMPORTANT: If you add a new public settings you also have to add it to
          * PUBLIC_SETTINGS below. If the new setting is hidden you have to add
          * it to PRIVATE_SETTINGS below. Also add a validator that can validate
@@ -5803,6 +5845,9 @@
             PRIVATE_SETTINGS.add(TOUCHPAD_NATURAL_SCROLLING);
             PRIVATE_SETTINGS.add(TOUCHPAD_TAP_TO_CLICK);
             PRIVATE_SETTINGS.add(TOUCHPAD_RIGHT_CLICK_ZONE);
+            PRIVATE_SETTINGS.add(CAMERA_FLASH_NOTIFICATION);
+            PRIVATE_SETTINGS.add(SCREEN_FLASH_NOTIFICATION);
+            PRIVATE_SETTINGS.add(SCREEN_FLASH_NOTIFICATION_COLOR);
         }
 
         /**
@@ -6184,9 +6229,6 @@
                 sProviderHolder,
                 Secure.class);
 
-        private static ILockSettings sLockSettings = null;
-
-        private static boolean sIsSystemProcess;
         @UnsupportedAppUsage
         private static final HashSet<String> MOVED_TO_LOCK_SETTINGS;
         @UnsupportedAppUsage
@@ -6350,35 +6392,25 @@
                 return Global.getStringForUser(resolver, name, userHandle);
             }
 
-            if (MOVED_TO_LOCK_SETTINGS.contains(name)) {
-                synchronized (Secure.class) {
-                    if (sLockSettings == null) {
-                        sLockSettings = ILockSettings.Stub.asInterface(
-                                (IBinder) ServiceManager.getService("lock_settings"));
-                        sIsSystemProcess = Process.myUid() == Process.SYSTEM_UID;
-                    }
-                }
-                if (sLockSettings != null && !sIsSystemProcess) {
-                    // No context; use the ActivityThread's context as an approximation for
-                    // determining the target API level.
-                    Application application = ActivityThread.currentApplication();
+            if (MOVED_TO_LOCK_SETTINGS.contains(name) && Process.myUid() != Process.SYSTEM_UID) {
+                // No context; use the ActivityThread's context as an approximation for
+                // determining the target API level.
+                Application application = ActivityThread.currentApplication();
 
-                    boolean isPreMnc = application != null
-                            && application.getApplicationInfo() != null
-                            && application.getApplicationInfo().targetSdkVersion
-                            <= VERSION_CODES.LOLLIPOP_MR1;
-                    if (isPreMnc) {
-                        try {
-                            return sLockSettings.getString(name, "0", userHandle);
-                        } catch (RemoteException re) {
-                            // Fall through
-                        }
-                    } else {
-                        throw new SecurityException("Settings.Secure." + name
-                                + " is deprecated and no longer accessible."
-                                + " See API documentation for potential replacements.");
-                    }
+                boolean isPreMnc = application != null
+                    && application.getApplicationInfo() != null
+                    && application.getApplicationInfo().targetSdkVersion
+                    <= VERSION_CODES.LOLLIPOP_MR1;
+                if (isPreMnc) {
+                    // Old apps used to get the three deprecated LOCK_PATTERN_* settings from
+                    // ILockSettings.getString().  For security reasons, we now just return a
+                    // stubbed-out value.  Note: the only one of these three settings actually known
+                    // to have been used was LOCK_PATTERN_ENABLED, and ILockSettings.getString()
+                    // already always returned "0" for that starting in Android 11.
+                    return "0";
                 }
+                throw new SecurityException("Settings.Secure." + name + " is deprecated and no" +
+                        " longer accessible. See API documentation for potential replacements.");
             }
 
             return sNameValueCache.getStringForUser(resolver, name, userHandle);
@@ -8295,6 +8327,15 @@
                 "accessibility_display_inversion_enabled";
 
         /**
+         * Flag that specifies whether font size has been changed. The flag will
+         * be set when users change the scaled value of font size for the first time.
+         * @hide
+         */
+        @Readable
+        public static final String ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED =
+                "accessibility_font_scaling_has_been_changed";
+
+        /**
          * Setting that specifies whether display color space adjustment is
          * enabled.
          *
@@ -10784,6 +10825,15 @@
                 "low_power_warning_acknowledged";
 
         /**
+         * Whether the "first time extra battery saver warning" dialog needs to be shown
+         * (0: default) or not (1).
+         *
+         * @hide
+         */
+        public static final String EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED =
+                "extra_low_power_warning_acknowledged";
+
+        /**
          * 0 (default) Auto battery saver suggestion has not been suppressed. 1) it has been
          * suppressed.
          * @hide
@@ -15199,6 +15249,12 @@
         public static final String LOW_POWER_MODE = "low_power";
 
         /**
+         * If 1 extra low power mode is enabled.
+         * @hide
+         */
+        public static final String EXTRA_LOW_POWER_MODE = "extra_low_power";
+
+        /**
          * If 1, battery saver ({@link #LOW_POWER_MODE}) will be re-activated after the device
          * is unplugged from a charger or rebooted.
          * @hide
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 6896e02..d2f9ff0 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -3396,8 +3396,10 @@
         public static final int MATCH_ALL_APN_SET_ID = -1;
 
         /**
-         * A unique carrier id associated with this APN
-         * {@see TelephonyManager#getSimCarrierId()}
+         * A unique carrier id associated with this APN {@link TelephonyManager#getSimCarrierId()}
+         * In case of matching carrier information, this should be used by default instead of
+         * those fields of {@link #MCC}, {@link #MNC}, {@link #NUMERIC}, {@link #MVNO_TYPE},
+         * {@link #MVNO_MATCH_DATA}, etc.
          * <p>Type: STRING</p>
          */
         public static final String CARRIER_ID = "carrier_id";
@@ -4937,4 +4939,66 @@
             return ALL_COLUMNS;
         }
     }
+
+    /**
+     * Stores incoming satellite datagrams.
+     * @hide
+     */
+    public static final class SatelliteDatagrams {
+        /**
+         * Not instantiable.
+         * @hide
+         */
+        private SatelliteDatagrams() {}
+
+        /**
+         * Provider name for Satellite Datagrams table.
+         */
+        public static final String PROVIDER_NAME = "satellite";
+
+        /**
+         * Table name for Satellite Datagrams table.
+         */
+        public static final String TABLE_NAME = "incoming_datagrams";
+
+        /**
+         * URL for satellite incoming datagrams table.
+         */
+        private static final String URL = "content://" + PROVIDER_NAME + "/" + TABLE_NAME;
+
+        /**
+         * The {@code content://} style URI for this provider.
+         * @hide
+         */
+        public static final Uri CONTENT_URI = Uri.parse(URL);
+
+        /**
+         * SatelliteProvider unique key column name is the datagram id.
+         * <P>Type: INTEGER (int)</P>
+         * @hide
+         */
+        public static final String COLUMN_UNIQUE_KEY_DATAGRAM_ID = "datagram_id";
+
+        /**
+         * SatelliteProvider column name for storing datagram.
+         * <p>TYPE: BLOB
+         * @hide
+         */
+        public static final String COLUMN_DATAGRAM = "datagram";
+
+        /** All columns in {@link SatelliteDatagrams} table. */
+        private static final List<String> ALL_COLUMNS = List.of(
+                COLUMN_UNIQUE_KEY_DATAGRAM_ID,
+                COLUMN_DATAGRAM
+        );
+
+        /**
+         * @return All columns in {@link SatelliteDatagrams} table.
+         * @hide
+         */
+        @NonNull
+        public static List<String> getAllColumns() {
+            return ALL_COLUMNS;
+        }
+    }
 }
diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java
index d943bf9..e81ca1a 100644
--- a/core/java/android/service/autofill/Dataset.java
+++ b/core/java/android/service/autofill/Dataset.java
@@ -28,7 +28,9 @@
 import android.content.IntentSender;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.ArrayMap;
 import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillManager;
 import android.view.autofill.AutofillValue;
 import android.widget.RemoteViews;
 
@@ -283,24 +285,28 @@
     }
 
     /** @hide */
-    public RemoteViews getFieldPresentation(int index) {
+    @TestApi
+    public @Nullable RemoteViews getFieldPresentation(int index) {
         final RemoteViews customPresentation = mFieldPresentations.get(index);
         return customPresentation != null ? customPresentation : mPresentation;
     }
 
     /** @hide */
-    public RemoteViews getFieldDialogPresentation(int index) {
+    @TestApi
+    public @Nullable RemoteViews getFieldDialogPresentation(int index) {
         final RemoteViews customPresentation = mFieldDialogPresentations.get(index);
         return customPresentation != null ? customPresentation : mDialogPresentation;
     }
 
     /** @hide */
+    @TestApi
     public @Nullable InlinePresentation getFieldInlinePresentation(int index) {
         final InlinePresentation inlinePresentation = mFieldInlinePresentations.get(index);
         return inlinePresentation != null ? inlinePresentation : mInlinePresentation;
     }
 
     /** @hide */
+    @TestApi
     public @Nullable InlinePresentation getFieldInlineTooltipPresentation(int index) {
         final InlinePresentation inlineTooltipPresentation =
                 mFieldInlineTooltipPresentations.get(index);
@@ -309,6 +315,7 @@
     }
 
     /** @hide */
+    @TestApi
     public @Nullable DatasetFieldFilter getFilter(int index) {
         return mFieldFilters.get(index);
     }
@@ -389,6 +396,9 @@
         if (mAuthentication != null) {
             builder.append(", hasAuthentication");
         }
+        if (mAutofillDatatypes != null) {
+            builder.append(", autofillDatatypes=").append(mAutofillDatatypes);
+        }
         return builder.append(']').toString();
     }
 
@@ -425,14 +435,14 @@
      * one value for a field or set an authentication intent.
      */
     public static final class Builder {
-        private ArrayList<AutofillId> mFieldIds;
-        private ArrayList<AutofillValue> mFieldValues;
-        private ArrayList<RemoteViews> mFieldPresentations;
-        private ArrayList<RemoteViews> mFieldDialogPresentations;
-        private ArrayList<InlinePresentation> mFieldInlinePresentations;
-        private ArrayList<InlinePresentation> mFieldInlineTooltipPresentations;
-        private ArrayList<DatasetFieldFilter> mFieldFilters;
-        private ArrayList<String> mAutofillDatatypes;
+        private ArrayList<AutofillId> mFieldIds = new ArrayList<>();
+        private ArrayList<AutofillValue> mFieldValues = new ArrayList();
+        private ArrayList<RemoteViews> mFieldPresentations = new ArrayList();
+        private ArrayList<RemoteViews> mFieldDialogPresentations = new ArrayList();
+        private ArrayList<InlinePresentation> mFieldInlinePresentations = new ArrayList();
+        private ArrayList<InlinePresentation> mFieldInlineTooltipPresentations = new ArrayList();
+        private ArrayList<DatasetFieldFilter> mFieldFilters = new ArrayList();
+        private ArrayList<String> mAutofillDatatypes = new ArrayList();
         @Nullable private ClipData mFieldContent;
         private RemoteViews mPresentation;
         private RemoteViews mDialogPresentation;
@@ -443,6 +453,15 @@
         @Nullable private String mId;
 
         /**
+         * Usually, a field will be associated with a single autofill id and/or datatype.
+         * There could be null field value corresponding to different autofill ids or datatye
+         * values, but the implementation is ok with duplicating that information.
+         * This map is just for the purpose of optimization, to reduce the size of the pelled data
+         * over the binder transaction.
+         */
+        private ArrayMap<Field, Integer> mFieldToIndexdMap = new ArrayMap<>();
+
+        /**
          * Creates a new builder.
          *
          * @param presentation The presentation used to visualize this dataset.
@@ -1042,29 +1061,40 @@
          */
         public @NonNull Builder setField(@NonNull AutofillId id, @Nullable Field field) {
             throwIfDestroyed();
+
+            if (mFieldToIndexdMap.containsKey(field)) {
+                int index = mFieldToIndexdMap.get(field);
+                if (mFieldIds.get(index) == null) {
+                    mFieldIds.set(index, id);
+                    return this;
+                }
+                // if the Autofill Id is already set, ignore and proceed as if setting in a new
+                // value.
+            }
+            int index;
             if (field == null) {
-                setLifeTheUniverseAndEverything(id, null, null, null, null, null, null);
+                index = setLifeTheUniverseAndEverything(id, null, null, null, null, null, null);
             } else {
                 final DatasetFieldFilter filter = field.getDatasetFieldFilter();
                 final Presentations presentations = field.getPresentations();
                 if (presentations == null) {
-                    setLifeTheUniverseAndEverything(id, field.getValue(), null, null, null,
+                    index = setLifeTheUniverseAndEverything(id, field.getValue(), null, null, null,
                             filter, null);
                 } else {
-                    setLifeTheUniverseAndEverything(id, field.getValue(),
+                    index = setLifeTheUniverseAndEverything(id, field.getValue(),
                             presentations.getMenuPresentation(),
                             presentations.getInlinePresentation(),
                             presentations.getInlineTooltipPresentation(), filter,
                             presentations.getDialogPresentation());
                 }
             }
+            mFieldToIndexdMap.put(field, index);
             return this;
         }
 
         /**
-         * Adds a field to this Dataset with a specific type and no
-         * AutofillId. This is used to send back Field information
-         * when Autofilling with platform detections is on.
+         * Adds a field to this Dataset with a specific type. This is used to send back Field
+         * information when Autofilling with platform detections is on.
          * Platform detections are on when receiving a populated list from
          * FillRequest#getHints().
          *
@@ -1077,9 +1107,6 @@
          * has two credential pairs, then two Datasets should be created,
          * and so on.
          *
-         * Using this will remove any data populated with
-         * setField(@NonNull AutofillId id, @Nullable Field field).
-         *
          * @param hint An autofill hint returned from {@link
          *         FillRequest#getHints()}.
          *
@@ -1090,27 +1117,53 @@
          *
          * @return this builder.
          */
-        public @NonNull Dataset.Builder setField(
-                @NonNull String hint, @NonNull Field field) {
+        public @NonNull Dataset.Builder setField(@NonNull String hint, @NonNull Field field) {
             throwIfDestroyed();
 
+            if (mFieldToIndexdMap.containsKey(field)) {
+                int index = mFieldToIndexdMap.get(field);
+                if (mAutofillDatatypes.get(index) == null) {
+                    mAutofillDatatypes.set(index, hint);
+                    return this;
+                }
+                // if the hint is already set, ignore and proceed as if setting in a new hint.
+            }
+
+            int index;
             final DatasetFieldFilter filter = field.getDatasetFieldFilter();
             final Presentations presentations = field.getPresentations();
             if (presentations == null) {
-                setLifeTheUniverseAndEverything(hint, field.getValue(), null, null, null,
+                index = setLifeTheUniverseAndEverything(hint, field.getValue(), null, null, null,
                         filter, null);
             } else {
-                setLifeTheUniverseAndEverything(hint, field.getValue(),
+                index = setLifeTheUniverseAndEverything(hint, field.getValue(),
                         presentations.getMenuPresentation(),
                         presentations.getInlinePresentation(),
                         presentations.getInlineTooltipPresentation(), filter,
                         presentations.getDialogPresentation());
             }
-
+            mFieldToIndexdMap.put(field, index);
             return this;
         }
 
         /**
+         * Adds a field to this Dataset that is relevant to all applicable hints. This is used to
+         * provide field information when autofill with platform detections is enabled.
+         * Platform detections are on when receiving a populated list from
+         * FillRequest#getHints().
+         *
+         * @param field the fill information about the field.
+         *
+         * @throws IllegalStateException if {@link #build()} was already called
+         * or this builder also contains AutofillId information
+         *
+         * @return this builder.
+         */
+        public @NonNull Dataset.Builder setFieldForAllHints(@NonNull Field field) {
+            return setField(AutofillManager.ANY_HINT, field);
+        }
+
+        /**
          * Sets the value of a field with an <a href="#Filtering">explicit filter</a>, and using an
          * {@link InlinePresentation} to visualize it as an inline suggestion.
          *
@@ -1147,67 +1200,64 @@
             return this;
         }
 
-        private void setLifeTheUniverseAndEverything(String datatype,
+        /** Returns the index at which this id was modified or inserted */
+        private int setLifeTheUniverseAndEverything(@NonNull String datatype,
                 @Nullable AutofillValue value,
                 @Nullable RemoteViews presentation,
                 @Nullable InlinePresentation inlinePresentation,
                 @Nullable InlinePresentation tooltip,
                 @Nullable DatasetFieldFilter filter,
                 @Nullable RemoteViews dialogPresentation) {
-            if (mAutofillDatatypes == null) {
-                mFieldValues = new ArrayList<>();
-                mFieldPresentations = new ArrayList<>();
-                mFieldDialogPresentations = new ArrayList<>();
-                mFieldInlinePresentations = new ArrayList<>();
-                mFieldInlineTooltipPresentations = new ArrayList<>();
-                mFieldFilters = new ArrayList<>();
-                mAutofillDatatypes = new ArrayList<>();
-                mFieldIds = null;
+            Objects.requireNonNull(datatype, "datatype cannot be null");
+            final int existingIdx = mAutofillDatatypes.indexOf(datatype);
+            if (existingIdx >= 0) {
+                mAutofillDatatypes.add(datatype);
+                mFieldValues.set(existingIdx, value);
+                mFieldPresentations.set(existingIdx, presentation);
+                mFieldDialogPresentations.set(existingIdx, dialogPresentation);
+                mFieldInlinePresentations.set(existingIdx, inlinePresentation);
+                mFieldInlineTooltipPresentations.set(existingIdx, tooltip);
+                mFieldFilters.set(existingIdx, filter);
+                return existingIdx;
             }
+            mFieldIds.add(null);
+            mAutofillDatatypes.add(datatype);
             mFieldValues.add(value);
             mFieldPresentations.add(presentation);
             mFieldDialogPresentations.add(dialogPresentation);
             mFieldInlinePresentations.add(inlinePresentation);
             mFieldInlineTooltipPresentations.add(tooltip);
             mFieldFilters.add(filter);
-            mAutofillDatatypes.add(datatype);
+            return mFieldIds.size() - 1;
         }
 
-        private void setLifeTheUniverseAndEverything(@NonNull AutofillId id,
+        /** Returns the index at which this id was modified or inserted */
+        private int setLifeTheUniverseAndEverything(@NonNull AutofillId id,
                 @Nullable AutofillValue value, @Nullable RemoteViews presentation,
                 @Nullable InlinePresentation inlinePresentation,
                 @Nullable InlinePresentation tooltip,
                 @Nullable DatasetFieldFilter filter,
                 @Nullable RemoteViews dialogPresentation) {
             Objects.requireNonNull(id, "id cannot be null");
-            if (mFieldIds != null) {
-                final int existingIdx = mFieldIds.indexOf(id);
-                if (existingIdx >= 0) {
-                    mFieldValues.set(existingIdx, value);
-                    mFieldPresentations.set(existingIdx, presentation);
-                    mFieldDialogPresentations.set(existingIdx, dialogPresentation);
-                    mFieldInlinePresentations.set(existingIdx, inlinePresentation);
-                    mFieldInlineTooltipPresentations.set(existingIdx, tooltip);
-                    mFieldFilters.set(existingIdx, filter);
-                    return;
-                }
-            } else {
-                mFieldIds = new ArrayList<>();
-                mFieldValues = new ArrayList<>();
-                mFieldPresentations = new ArrayList<>();
-                mFieldDialogPresentations = new ArrayList<>();
-                mFieldInlinePresentations = new ArrayList<>();
-                mFieldInlineTooltipPresentations = new ArrayList<>();
-                mFieldFilters = new ArrayList<>();
-                mAutofillDatatypes = null;
+            final int existingIdx = mFieldIds.indexOf(id);
+            if (existingIdx >= 0) {
+                mFieldValues.set(existingIdx, value);
+                mFieldPresentations.set(existingIdx, presentation);
+                mFieldDialogPresentations.set(existingIdx, dialogPresentation);
+                mFieldInlinePresentations.set(existingIdx, inlinePresentation);
+                mFieldInlineTooltipPresentations.set(existingIdx, tooltip);
+                mFieldFilters.set(existingIdx, filter);
+                return existingIdx;
             }
             mFieldIds.add(id);
+            mAutofillDatatypes.add(null);
             mFieldValues.add(value);
             mFieldPresentations.add(presentation);
             mFieldDialogPresentations.add(dialogPresentation);
             mFieldInlinePresentations.add(inlinePresentation);
             mFieldInlineTooltipPresentations.add(tooltip);
             mFieldFilters.add(filter);
+            return mFieldIds.size() - 1;
         }
 
         /**
@@ -1224,11 +1274,12 @@
             throwIfDestroyed();
             mDestroyed = true;
             if (mFieldIds == null && mAutofillDatatypes == null) {
-                throw new IllegalStateException("at least one value must be set");
+                throw new IllegalStateException("at least one of field or datatype must be set");
             }
             if (mFieldIds != null && mAutofillDatatypes != null) {
-                if (mFieldIds.size() > 0 && mAutofillDatatypes.size() > 0) {
-                    throw new IllegalStateException("both field and datatype were populated");
+                if (mFieldIds.size() == 0 && mAutofillDatatypes.size() == 0) {
+                    throw new IllegalStateException(
+                            "at least one of field or datatype must be set");
                 }
             }
             if (mFieldContent != null) {
@@ -1304,7 +1355,7 @@
                     parcel.createTypedArrayList(InlinePresentation.CREATOR);
             final ArrayList<DatasetFieldFilter> filters =
                     parcel.createTypedArrayList(DatasetFieldFilter.CREATOR);
-            final ArrayList<String> datatypes =
+            final ArrayList<String> autofillDatatypes =
                     parcel.createStringArrayList();
             final ClipData fieldContent = parcel.readParcelable(null,
                     android.content.ClipData.class);
@@ -1341,9 +1392,9 @@
             }
             final int inlinePresentationsSize = inlinePresentations.size();
 
-            if (ids.size() == 0 && datatypes.size() > 0) {
-                for (int i = 0; i < ids.size(); i++) {
-                    final String datatype = datatypes.get(i);
+            if (ids.size() == 0 && autofillDatatypes.size() > 0) {
+                for (int i = 0; i < autofillDatatypes.size(); i++) {
+                    final String datatype = autofillDatatypes.get(i);
                     final AutofillValue value = values.get(i);
                     final RemoteViews fieldPresentation = presentations.get(i);
                     final RemoteViews fieldDialogPresentation = dialogPresentations.get(i);
@@ -1393,8 +1444,10 @@
      *
      * @hide
      */
+    @TestApi
     public static final class DatasetFieldFilter implements Parcelable {
 
+        /** @hide */
         @Nullable
         public final Pattern pattern;
 
@@ -1402,6 +1455,10 @@
             this.pattern = pattern;
         }
 
+        public @Nullable Pattern getPattern() {
+            return pattern;
+        }
+
         @Override
         public String toString() {
             if (!sDebug) return super.toString();
@@ -1416,7 +1473,7 @@
         }
 
         @Override
-        public void writeToParcel(Parcel parcel, int flags) {
+        public void writeToParcel(@NonNull Parcel parcel, int flags) {
             parcel.writeSerializable(pattern);
         }
 
diff --git a/core/java/android/service/autofill/FillEventHistory.java b/core/java/android/service/autofill/FillEventHistory.java
index b0e847c..5d58120 100644
--- a/core/java/android/service/autofill/FillEventHistory.java
+++ b/core/java/android/service/autofill/FillEventHistory.java
@@ -233,6 +233,22 @@
          */
         public static final int TYPE_DATASETS_SHOWN = 5;
 
+        /**
+         * The app/user requested for a field to be Autofilled.
+         *
+         * This event is fired when the view has been entered (by user or app) in order
+         * to differentiate from FillRequests that have been pretriggered for FillDialogs.
+         *
+         * For example, the user might navigate away from a screen without tapping any
+         * fields. In this case, a FillRequest/FillResponse has been generated, but was
+         * not used for Autofilling. The user did not intend to see an Autofill result,
+         * but a FillRequest was still generated. This is different from when the user
+         * did tap on a field after the pretriggered FillRequest, this event will appear
+         * in the FillEventHistory, signaling that the user did intend to Autofill
+         * something.
+         */
+        public static final int TYPE_VIEW_REQUESTED_AUTOFILL = 6;
+
         /** @hide */
         @IntDef(prefix = { "TYPE_" }, value = {
                 TYPE_DATASET_SELECTED,
@@ -240,7 +256,8 @@
                 TYPE_AUTHENTICATION_SELECTED,
                 TYPE_SAVE_SHOWN,
                 TYPE_CONTEXT_COMMITTED,
-                TYPE_DATASETS_SHOWN
+                TYPE_DATASETS_SHOWN,
+                TYPE_VIEW_REQUESTED_AUTOFILL
         })
         @Retention(RetentionPolicy.SOURCE)
         @interface EventIds{}
@@ -659,8 +676,8 @@
                 @Nullable AutofillId[] detectedFieldIds,
                 @Nullable FieldClassification[] detectedFieldClassifications,
                 int saveDialogNotShowReason, int uiType) {
-            mEventType = Preconditions.checkArgumentInRange(eventType, 0, TYPE_DATASETS_SHOWN,
-                    "eventType");
+            mEventType = Preconditions.checkArgumentInRange(eventType, 0,
+                    TYPE_VIEW_REQUESTED_AUTOFILL, "eventType");
             mDatasetId = datasetId;
             mClientState = clientState;
             mSelectedDatasetIds = selectedDatasetIds;
@@ -723,6 +740,8 @@
                     return "TYPE_CONTEXT_COMMITTED";
                 case TYPE_DATASETS_SHOWN:
                     return "TYPE_DATASETS_SHOWN";
+                case TYPE_VIEW_REQUESTED_AUTOFILL:
+                    return "TYPE_VIEW_REQUESTED_AUTOFILL";
                 default:
                     return "TYPE_UNKNOWN";
             }
diff --git a/core/java/android/service/credentials/BeginCreateCredentialResponse.java b/core/java/android/service/credentials/BeginCreateCredentialResponse.java
index f0f954d..cd53cb6 100644
--- a/core/java/android/service/credentials/BeginCreateCredentialResponse.java
+++ b/core/java/android/service/credentials/BeginCreateCredentialResponse.java
@@ -16,8 +16,10 @@
 
 package android.service.credentials;
 
+import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -32,7 +34,7 @@
  */
 public final class BeginCreateCredentialResponse implements Parcelable {
     private final @NonNull List<CreateEntry> mCreateEntries;
-    private final @Nullable CreateEntry mRemoteCreateEntry;
+    private final @Nullable RemoteEntry mRemoteCreateEntry;
 
     /**
      * Creates an empty response instance, to be used when there are no {@link CreateEntry}
@@ -46,7 +48,7 @@
         List<CreateEntry> createEntries = new ArrayList<>();
         in.readTypedList(createEntries, CreateEntry.CREATOR);
         mCreateEntries = createEntries;
-        mRemoteCreateEntry = in.readTypedObject(CreateEntry.CREATOR);
+        mRemoteCreateEntry = in.readTypedObject(RemoteEntry.CREATOR);
     }
 
     @Override
@@ -75,7 +77,7 @@
 
     /* package-private */ BeginCreateCredentialResponse(
             @NonNull List<CreateEntry> createEntries,
-            @Nullable CreateEntry remoteCreateEntry) {
+            @Nullable RemoteEntry remoteCreateEntry) {
         this.mCreateEntries = createEntries;
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mCreateEntries);
@@ -88,7 +90,7 @@
     }
 
     /** Returns the remote create entry to be displayed on the UI. */
-    public @Nullable CreateEntry getRemoteCreateEntry() {
+    public @Nullable RemoteEntry getRemoteCreateEntry() {
         return mRemoteCreateEntry;
     }
 
@@ -98,7 +100,7 @@
     @SuppressWarnings("WeakerAccess") /* synthetic access */
     public static final class Builder {
         private @NonNull List<CreateEntry> mCreateEntries = new ArrayList<>();
-        private @Nullable CreateEntry mRemoteCreateEntry;
+        private @Nullable RemoteEntry mRemoteCreateEntry;
 
         /**
          * Sets the list of create entries to be shown on the UI.
@@ -137,8 +139,18 @@
          * result should be set to {@link android.app.Activity#RESULT_OK} and an extra with the
          * {@link CredentialProviderService#EXTRA_CREATE_CREDENTIAL_RESPONSE} key should be populated
          * with a {@link android.credentials.CreateCredentialResponse} object.
+         *
+         * <p> Note that as a provider service you will only be able to set a remote entry if :
+         * - Provider service possesses the
+         * {@link Manifest.permission.PROVIDE_REMOTE_CREDENTIALS} permission.
+         * - Provider service is configured as the provider that can provide remote entries.
+         *
+         * If the above conditions are not met, setting back {@link BeginCreateCredentialResponse}
+         * on the callback from {@link CredentialProviderService#onBeginCreateCredential}
+         * will throw a {@link SecurityException}.
          */
-        public @NonNull Builder setRemoteCreateEntry(@Nullable CreateEntry remoteCreateEntry) {
+        @RequiresPermission(Manifest.permission.PROVIDE_REMOTE_CREDENTIALS)
+        public @NonNull Builder setRemoteCreateEntry(@Nullable RemoteEntry remoteCreateEntry) {
             mRemoteCreateEntry = remoteCreateEntry;
             return this;
         }
diff --git a/core/java/android/service/credentials/BeginGetCredentialResponse.java b/core/java/android/service/credentials/BeginGetCredentialResponse.java
index 3652742..e25b686 100644
--- a/core/java/android/service/credentials/BeginGetCredentialResponse.java
+++ b/core/java/android/service/credentials/BeginGetCredentialResponse.java
@@ -16,8 +16,10 @@
 
 package android.service.credentials;
 
+import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -42,7 +44,7 @@
     private final @NonNull List<Action> mActions;
 
     /** Remote credential entry to get the response from a different device. */
-    private final @Nullable CredentialEntry mRemoteCredentialEntry;
+    private final @Nullable RemoteEntry mRemoteCredentialEntry;
 
     /**
      * Creates an empty response instance, to be used when there are no {@link CredentialEntry},
@@ -57,7 +59,7 @@
 
     private BeginGetCredentialResponse(@NonNull List<CredentialEntry> credentialEntries,
             @NonNull List<Action> authenticationEntries, @NonNull List<Action> actions,
-            @Nullable CredentialEntry remoteCredentialEntry) {
+            @Nullable RemoteEntry remoteCredentialEntry) {
         mCredentialEntries = new ArrayList<>(credentialEntries);
         mAuthenticationEntries = new ArrayList<>(authenticationEntries);
         mActions = new ArrayList<>(actions);
@@ -74,7 +76,7 @@
         List<Action> actions = new ArrayList<>();
         in.readTypedList(actions, Action.CREATOR);
         mActions = actions;
-        mRemoteCredentialEntry = in.readTypedObject(CredentialEntry.CREATOR);
+        mRemoteCredentialEntry = in.readTypedObject(RemoteEntry.CREATOR);
     }
 
     public static final @NonNull Creator<BeginGetCredentialResponse> CREATOR =
@@ -127,7 +129,7 @@
     /**
      * Returns the remote credential entry to be displayed on the UI.
      */
-    public @Nullable CredentialEntry getRemoteCredentialEntry() {
+    public @Nullable RemoteEntry getRemoteCredentialEntry() {
         return mRemoteCredentialEntry;
     }
 
@@ -139,7 +141,7 @@
 
         private List<Action> mAuthenticationEntries = new ArrayList<>();
         private List<Action> mActions = new ArrayList<>();
-        private CredentialEntry mRemoteCredentialEntry;
+        private RemoteEntry mRemoteCredentialEntry;
 
         /**
          * Sets a remote credential entry to be shown on the UI. Provider must set this if they
@@ -154,8 +156,18 @@
          * result should be set to {@link android.app.Activity#RESULT_OK} and an extra with the
          * {@link CredentialProviderService#EXTRA_GET_CREDENTIAL_RESPONSE} key should be populated
          * with a {@link android.credentials.Credential} object.
+         *
+         * <p> Note that as a provider service you will only be able to set a remote entry if :
+         * - Provider service possesses the
+         * {@link Manifest.permission.PROVIDE_REMOTE_CREDENTIALS} permission.
+         * - Provider service is configured as the provider that can provide remote entries.
+         *
+         * If the above conditions are not met, setting back {@link BeginGetCredentialResponse}
+         * on the callback from {@link CredentialProviderService#onBeginGetCredential} will
+         * throw a {@link SecurityException}.
          */
-        public @NonNull Builder setRemoteCredentialEntry(@Nullable CredentialEntry
+        @RequiresPermission(Manifest.permission.PROVIDE_REMOTE_CREDENTIALS)
+        public @NonNull Builder setRemoteCredentialEntry(@Nullable RemoteEntry
                 remoteCredentialEntry) {
             mRemoteCredentialEntry = remoteCredentialEntry;
             return this;
diff --git a/core/java/android/service/credentials/CredentialEntry.java b/core/java/android/service/credentials/CredentialEntry.java
index 7e98bc7..e9cebd2 100644
--- a/core/java/android/service/credentials/CredentialEntry.java
+++ b/core/java/android/service/credentials/CredentialEntry.java
@@ -27,6 +27,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import com.android.internal.util.Preconditions;
+
 /**
  * A credential entry that is to be displayed on the account selector that is presented to the
  * user.
@@ -56,7 +58,7 @@
 @SuppressLint("ParcelNotFinal")
 public class CredentialEntry implements Parcelable {
     /** The request option that corresponds to this entry. **/
-    private final @Nullable BeginGetCredentialOption mBeginGetCredentialOption;
+    private final @Nullable String mBeginGetCredentialOptionId;
 
     /** The type of the credential entry to be shown on the UI. */
     private final @NonNull String mType;
@@ -72,19 +74,51 @@
      * to respond to query phase {@link CredentialProviderService#onBeginGetCredential}
      * credential retrieval requests.
      *
+     * @param beginGetCredentialOptionId the beginGetCredentialOptionId to be retrieved from
+     * {@link BeginGetCredentialOption#getId()} - the request option for which this CredentialEntry
+     *                                   is being constructed This helps maintain an association
+     *                                   such that when the user selects this entry, providers can
+     *                                   receive the complete corresponding
+     *                                   {@link GetCredentialRequest}.
+     * @param type the type of the credential for which this credential entry is being created
+     * @param slice the slice containing the metadata to be shown on the UI. Must be
+     *              constructed through the androidx.credentials jetpack library.
+     *
+     * @throws IllegalArgumentException If {@code beginGetCredentialOptionId} or {@code type}
+     * is null, or empty
+     */
+    public CredentialEntry(@NonNull String beginGetCredentialOptionId, @NonNull String type,
+            @NonNull Slice slice) {
+        mBeginGetCredentialOptionId = Preconditions.checkStringNotEmpty(
+                beginGetCredentialOptionId, "beginGetCredentialOptionId must not be "
+                        + "null, or empty");
+        mType = Preconditions.checkStringNotEmpty(type, "type must not be null, or "
+                + "empty");
+        mSlice = requireNonNull(slice, "slice must not be null");
+    }
+
+    /**
+     * Creates an entry that is associated with a {@link BeginGetCredentialOption} request.
+     * Providers must use this constructor when they extend from {@link CredentialProviderService}
+     * to respond to query phase {@link CredentialProviderService#onBeginGetCredential}
+     * credential retrieval requests.
+     *
      * @param beginGetCredentialOption the request option for which this credential entry is
      *                                 being constructed This helps maintain an association,
      *                                 such that when the user selects this entry, providers
-     *                                 can receive the conmplete corresponding request.
+     *                                 can receive the complete corresponding request.
      * @param slice the slice containing the metadata to be shown on the UI. Must be
      *              constructed through the androidx.credentials jetpack library.
      */
     public CredentialEntry(@NonNull BeginGetCredentialOption beginGetCredentialOption,
             @NonNull Slice slice) {
-        mBeginGetCredentialOption = requireNonNull(beginGetCredentialOption,
-                "beginGetCredentialOption must not be null");
-        mType = requireNonNull(mBeginGetCredentialOption.getType(),
-                "type must not be null");
+        requireNonNull(beginGetCredentialOption, "beginGetCredentialOption must not"
+                + " be null");
+        mBeginGetCredentialOptionId = Preconditions.checkStringNotEmpty(
+                beginGetCredentialOption.getId(), "Id in beginGetCredentialOption "
+                        + "must not be null");
+        mType = Preconditions.checkStringNotEmpty(beginGetCredentialOption.getType(),
+                "type in beginGetCredentialOption must not be null");
         mSlice = requireNonNull(slice, "slice must not be null");
     }
 
@@ -97,11 +131,9 @@
      * @param slice the slice containing the metadata to be shown on the UI. Must be
      *              constructed through the androidx.credentials jetpack library.
      *
-     * @hide
      */
-    // TODO: Unhide this constructor when the registry APIs are stable
     public CredentialEntry(@NonNull String type, @NonNull Slice slice) {
-        mBeginGetCredentialOption = null;
+        mBeginGetCredentialOptionId = null;
         mType = requireNonNull(type, "type must not be null");
         mSlice = requireNonNull(slice, "slice must not be null");
     }
@@ -110,7 +142,7 @@
         requireNonNull(in, "parcel must not be null");
         mType = in.readString8();
         mSlice = in.readTypedObject(Slice.CREATOR);
-        mBeginGetCredentialOption = in.readTypedObject(BeginGetCredentialOption.CREATOR);
+        mBeginGetCredentialOptionId = in.readString8();
     }
 
     @NonNull
@@ -136,15 +168,16 @@
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeString8(mType);
         dest.writeTypedObject(mSlice, flags);
-        dest.writeTypedObject(mBeginGetCredentialOption, flags);
+        dest.writeString8(mBeginGetCredentialOptionId);
     }
 
     /**
-     * Returns the request option for which this credential entry has been constructed.
+     * Returns the id of the {@link BeginGetCredentialOption} for which this credential
+     * entry has been constructed.
      */
     @NonNull
-    public BeginGetCredentialOption getBeginGetCredentialOption() {
-        return mBeginGetCredentialOption;
+    public String getBeginGetCredentialOptionId() {
+        return mBeginGetCredentialOptionId;
     }
 
     /**
diff --git a/core/java/android/service/credentials/CredentialProviderInfo.java b/core/java/android/service/credentials/CredentialProviderInfoFactory.java
similarity index 65%
rename from core/java/android/service/credentials/CredentialProviderInfo.java
rename to core/java/android/service/credentials/CredentialProviderInfoFactory.java
index b5464db..3190c69 100644
--- a/core/java/android/service/credentials/CredentialProviderInfo.java
+++ b/core/java/android/service/credentials/CredentialProviderInfoFactory.java
@@ -34,40 +34,29 @@
 import android.content.pm.ServiceInfo;
 import android.content.res.Resources;
 import android.credentials.CredentialManager;
-import android.graphics.drawable.Drawable;
+import android.credentials.CredentialProviderInfo;
 import android.os.Bundle;
 import android.os.RemoteException;
-import android.text.TextUtils;
+import android.os.UserHandle;
 import android.util.Log;
 import android.util.Slog;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
- * {@link ServiceInfo} and meta-data about a credential provider.
+ * {@link CredentialProviderInfo} generator.
  *
  * @hide
  */
-public final class CredentialProviderInfo {
-    private static final String TAG = "CredentialProviderInfo";
-
-    @NonNull
-    private final ServiceInfo mServiceInfo;
-    @NonNull
-    private final List<String> mCapabilities;
-
-    @NonNull
-    private final Context mContext;
-    @Nullable
-    private final Drawable mIcon;
-    @Nullable
-    private final CharSequence mLabel;
-    private final boolean mIsSystemProvider;
+public final class CredentialProviderInfoFactory {
+    private static final String TAG = "CredentialProviderInfoFactory";
 
     /**
      * Constructs an information instance of the credential provider.
@@ -79,14 +68,18 @@
      * @throws PackageManager.NameNotFoundException If provider service is not found
      * @throws SecurityException If provider does not require the relevant permission
      */
-    public CredentialProviderInfo(@NonNull Context context,
-            @NonNull ComponentName serviceComponent, int userId, boolean isSystemProvider)
+    public static CredentialProviderInfo create(
+            @NonNull Context context,
+            @NonNull ComponentName serviceComponent,
+            int userId,
+            boolean isSystemProvider)
             throws PackageManager.NameNotFoundException {
-        this(
+        return create(
                 context,
                 getServiceInfoOrThrow(serviceComponent, userId),
                 isSystemProvider,
-                /* disableSystemAppVerificationForTests= */ false);
+                /* disableSystemAppVerificationForTests= */ false,
+                /* isEnabled= */ false);
     }
 
     /**
@@ -98,13 +91,16 @@
      * @param isSystemProvider whether the provider app is a system provider
      * @param disableSystemAppVerificationForTests whether to disable system app permission
      *     verification so that tests can install system providers
+     * @param isEnabled whether the user enabled this provider
      * @throws SecurityException If provider does not require the relevant permission
      */
-    public CredentialProviderInfo(
+    public static CredentialProviderInfo create(
             @NonNull Context context,
             @NonNull ServiceInfo serviceInfo,
             boolean isSystemProvider,
-            boolean disableSystemAppVerificationForTests) {
+            boolean disableSystemAppVerificationForTests,
+            boolean isEnabled)
+            throws SecurityException {
         verifyProviderPermission(serviceInfo);
         if (isSystemProvider) {
             if (!isValidSystemProvider(
@@ -114,23 +110,31 @@
                         "Provider is not a valid system provider: " + serviceInfo);
             }
         }
-        mIsSystemProvider = isSystemProvider;
-        mContext =  requireNonNull(context, "context must not be null");
-        mServiceInfo = requireNonNull(serviceInfo, "serviceInfo must not be null");
-        mCapabilities = new ArrayList<>();
-        mIcon = mServiceInfo.loadIcon(mContext.getPackageManager());
-        mLabel =
-                mServiceInfo.loadSafeLabel(
-                        mContext.getPackageManager(),
-                        0 /* do not ellipsize */,
-                        TextUtils.SAFE_STRING_FLAG_FIRST_LINE | TextUtils.SAFE_STRING_FLAG_TRIM);
-        Log.i(
-                TAG,
-                "mLabel is : "
-                        + mLabel
-                        + ", for: "
-                        + mServiceInfo.getComponentName().flattenToString());
-        populateProviderCapabilities(context, serviceInfo);
+
+        return populateMetadata(context, serviceInfo)
+                .setSystemProvider(isSystemProvider)
+                .setEnabled(isEnabled)
+                .build();
+    }
+
+    /**
+     * Constructs an information instance of the credential provider for testing purposes. Does
+     * not run any verifications and passes parameters as is.
+     */
+    @VisibleForTesting
+    public static CredentialProviderInfo createForTests(
+            @NonNull ServiceInfo serviceInfo,
+            @NonNull CharSequence overrideLabel,
+            boolean isSystemProvider,
+            boolean isEnabled,
+            @NonNull List<String> capabilities) {
+        return new CredentialProviderInfo.Builder(serviceInfo)
+                .setEnabled(isEnabled)
+                .setOverrideLabel(overrideLabel)
+                .setSystemProvider(isSystemProvider)
+                .addCapabilities(capabilities)
+                .build();
+
     }
 
     private static void verifyProviderPermission(ServiceInfo serviceInfo) throws SecurityException {
@@ -138,19 +142,14 @@
         if (permission.equals(serviceInfo.permission)) {
             return;
         }
-
-        Slog.e(
-                TAG,
-                "Credential Provider Service from : "
-                        + serviceInfo.packageName
-                        + "does not require permission"
-                        + permission);
         throw new SecurityException(
                 "Service does not require the expected permission : " + permission);
     }
 
     private static boolean isSystemProviderWithValidPermission(
             ServiceInfo serviceInfo, Context context) {
+        requireNonNull(context, "context must not be null");
+
         final String permission = Manifest.permission.PROVIDE_DEFAULT_ENABLED_CREDENTIAL_SERVICE;
         try {
             ApplicationInfo appInfo =
@@ -177,67 +176,88 @@
             Context context,
             ServiceInfo serviceInfo,
             boolean disableSystemAppVerificationForTests) {
-        boolean isValidSystemTestProvider =
-                isTestSystemProvider(serviceInfo, disableSystemAppVerificationForTests);
-        if (isValidSystemTestProvider) {
-            return true;
+        requireNonNull(context, "context must not be null");
+
+        if (disableSystemAppVerificationForTests) {
+            Bundle metadata = serviceInfo.metaData;
+            if (metadata == null) {
+                Slog.e(TAG, "isValidSystemProvider - metadata is null: " + serviceInfo);
+                return false;
+            }
+            return metadata.getBoolean(
+                    CredentialProviderService.TEST_SYSTEM_PROVIDER_META_DATA_KEY);
         }
+
         return isSystemProviderWithValidPermission(serviceInfo, context);
     }
 
-    private static boolean isTestSystemProvider(
-            ServiceInfo serviceInfo, boolean disableSystemAppVerificationForTests) {
-        if (!disableSystemAppVerificationForTests) {
-            return false;
-        }
+    private static CredentialProviderInfo.Builder populateMetadata(
+            @NonNull Context context, ServiceInfo serviceInfo) {
+        requireNonNull(context, "context must not be null");
 
-        Bundle metadata = serviceInfo.metaData;
-        if (metadata == null) {
-            Slog.e(TAG, "metadata is null: " + serviceInfo);
-            return false;
-        }
-        return metadata.getBoolean(CredentialProviderService.TEST_SYSTEM_PROVIDER_META_DATA_KEY);
-    }
-
-    private void populateProviderCapabilities(@NonNull Context context, ServiceInfo serviceInfo) {
+        final CredentialProviderInfo.Builder builder =
+                new CredentialProviderInfo.Builder(serviceInfo);
         final PackageManager pm = context.getPackageManager();
+
+        // 1. Get the metadata for the service.
+        final Bundle metadata = serviceInfo.metaData;
+        if (metadata == null) {
+            Log.i(TAG, "populateMetadata - metadata is null");
+            return builder;
+        }
+
+        // 2. Extract the capabilities from the bundle.
         try {
-            Bundle metadata = serviceInfo.metaData;
             Resources resources = pm.getResourcesForApplication(serviceInfo.applicationInfo);
             if (metadata == null || resources == null) {
-                Log.i(TAG, "populateProviderCapabilities - metadata or resources is null");
-                return;
+                Log.i(TAG, "populateMetadata - resources is null");
+                return builder;
             }
 
-            String[] capabilities = resources.getStringArray(metadata.getInt(
-                    CredentialProviderService.CAPABILITY_META_DATA_KEY));
-            if (capabilities == null || capabilities.length == 0) {
-                Slog.i(TAG, "No capabilities found for provider:" + serviceInfo.packageName);
-                return;
-            }
-
-            for (String capability : capabilities) {
-                if (capability.isEmpty()) {
-                    Slog.i(TAG, "Skipping empty capability");
-                    continue;
-                }
-                Slog.i(TAG, "Capabilities found for provider: " + capability);
-                mCapabilities.add(capability);
-            }
+            builder.addCapabilities(populateProviderCapabilities(resources, metadata, serviceInfo));
         } catch (PackageManager.NameNotFoundException e) {
             Slog.e(TAG, e.getMessage());
-        } catch (Resources.NotFoundException e) {
-            Slog.e(TAG, e.getMessage());
         }
+
+        return builder;
     }
 
-    private static ServiceInfo getServiceInfoOrThrow(@NonNull ComponentName serviceComponent,
-            int userId) throws PackageManager.NameNotFoundException {
+    private static List<String> populateProviderCapabilities(
+            Resources resources, Bundle metadata, ServiceInfo serviceInfo) {
+        List<String> output = new ArrayList<>();
+        String[] capabilities = new String[0];
+
         try {
-            ServiceInfo si = AppGlobals.getPackageManager().getServiceInfo(
-                    serviceComponent,
-                    PackageManager.GET_META_DATA,
-                    userId);
+            capabilities =
+                    resources.getStringArray(
+                            metadata.getInt(CredentialProviderService.CAPABILITY_META_DATA_KEY));
+        } catch (Resources.NotFoundException e) {
+            Slog.e(TAG, "Failed to get capabilities: " + e.getMessage());
+        }
+
+        if (capabilities == null || capabilities.length == 0) {
+            Slog.e(TAG, "No capabilities found for provider:" + serviceInfo.packageName);
+            return output;
+        }
+
+        for (String capability : capabilities) {
+            if (capability.isEmpty()) {
+                Slog.e(TAG, "Skipping empty capability");
+                continue;
+            }
+            Slog.e(TAG, "Capabilities found for provider: " + capability);
+            output.add(capability);
+        }
+        return output;
+    }
+
+    private static ServiceInfo getServiceInfoOrThrow(
+            @NonNull ComponentName serviceComponent, int userId)
+            throws PackageManager.NameNotFoundException {
+        try {
+            ServiceInfo si =
+                    AppGlobals.getPackageManager()
+                            .getServiceInfo(serviceComponent, PackageManager.GET_META_DATA, userId);
             if (si != null) {
                 return si;
             }
@@ -256,6 +276,8 @@
             @NonNull Context context,
             @UserIdInt int userId,
             boolean disableSystemAppVerificationForTests) {
+        requireNonNull(context, "context must not be null");
+
         final List<ServiceInfo> services = new ArrayList<>();
         final List<ResolveInfo> resolveInfos = new ArrayList<>();
 
@@ -268,15 +290,20 @@
 
         for (ResolveInfo resolveInfo : resolveInfos) {
             final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
+            if (disableSystemAppVerificationForTests) {
+                if (serviceInfo != null) {
+                    services.add(serviceInfo);
+                }
+                continue;
+            }
+
             try {
-                PackageManager.ApplicationInfoFlags appInfoFlags =
-                        disableSystemAppVerificationForTests
-                                ? PackageManager.ApplicationInfoFlags.of(0)
-                                : PackageManager.ApplicationInfoFlags.of(
-                                        PackageManager.MATCH_SYSTEM_ONLY);
                 ApplicationInfo appInfo =
                         context.getPackageManager()
-                                .getApplicationInfo(serviceInfo.packageName, appInfoFlags);
+                                .getApplicationInfo(
+                                        serviceInfo.packageName,
+                                        PackageManager.ApplicationInfoFlags.of(
+                                                PackageManager.MATCH_SYSTEM_ONLY));
 
                 if (appInfo == null || serviceInfo == null) {
                     continue;
@@ -300,19 +327,22 @@
     public static List<CredentialProviderInfo> getAvailableSystemServices(
             @NonNull Context context,
             @UserIdInt int userId,
-            boolean disableSystemAppVerificationForTests) {
+            boolean disableSystemAppVerificationForTests,
+            Set<ComponentName> enabledServices) {
         requireNonNull(context, "context must not be null");
+
         final List<CredentialProviderInfo> providerInfos = new ArrayList<>();
         for (ServiceInfo si :
                 getAvailableSystemServiceInfos(
                         context, userId, disableSystemAppVerificationForTests)) {
             try {
                 CredentialProviderInfo cpi =
-                        new CredentialProviderInfo(
+                        CredentialProviderInfoFactory.create(
                                 context,
                                 si,
                                 /* isSystemProvider= */ true,
-                                disableSystemAppVerificationForTests);
+                                disableSystemAppVerificationForTests,
+                                enabledServices.contains(si.getComponentName()));
                 if (cpi.isSystemProvider()) {
                     providerInfos.add(cpi);
                 } else {
@@ -325,45 +355,12 @@
         return providerInfos;
     }
 
-    /**
-     * Returns true if the service supports the given {@code credentialType}, false otherwise.
-     */
-    @NonNull
-    public boolean hasCapability(@NonNull String credentialType) {
-        return mCapabilities.contains(credentialType);
-    }
+    private static @Nullable PackagePolicy getDeviceManagerPolicy(
+            @NonNull Context context, int userId) {
+        Context newContext = context.createContextAsUser(UserHandle.of(userId), 0);
 
-    /** Returns the service info. */
-    @NonNull
-    public ServiceInfo getServiceInfo() {
-        return mServiceInfo;
-    }
-
-    public boolean isSystemProvider() {
-        return mIsSystemProvider;
-    }
-
-    /** Returns the service icon. */
-    @Nullable
-    public Drawable getServiceIcon() {
-        return mIcon;
-    }
-
-    /** Returns the service label. */
-    @Nullable
-    public CharSequence getServiceLabel() {
-        return mLabel;
-    }
-
-    /** Returns an immutable list of capabilities this provider service can support. */
-    @NonNull
-    public List<String> getCapabilities() {
-        return Collections.unmodifiableList(mCapabilities);
-    }
-
-    private static @Nullable PackagePolicy getDeviceManagerPolicy(@NonNull Context context) {
         try {
-            DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
+            DevicePolicyManager dpm = newContext.getSystemService(DevicePolicyManager.class);
             return dpm.getCredentialManagerPolicy();
         } catch (SecurityException e) {
             // If the current user is not enrolled in DPM then this can throw a security error.
@@ -381,21 +378,53 @@
     public static List<CredentialProviderInfo> getCredentialProviderServices(
             @NonNull Context context,
             int userId,
-            boolean disableSystemAppVerificationForTests,
-            int providerFilter) {
+            int providerFilter,
+            Set<ComponentName> enabledServices) {
         requireNonNull(context, "context must not be null");
 
         // Get the device policy.
-        PackagePolicy pp = getDeviceManagerPolicy(context);
+        PackagePolicy pp = getDeviceManagerPolicy(context, userId);
 
         // Generate the provider list.
+        final boolean disableSystemAppVerificationForTests = false;
         ProviderGenerator generator =
                 new ProviderGenerator(
                         context, pp, disableSystemAppVerificationForTests, providerFilter);
         generator.addUserProviders(
-                getUserProviders(context, userId, disableSystemAppVerificationForTests));
+                getUserProviders(
+                        context, userId, disableSystemAppVerificationForTests, enabledServices));
         generator.addSystemProviders(
-                getAvailableSystemServices(context, userId, disableSystemAppVerificationForTests));
+                getAvailableSystemServices(
+                        context, userId, disableSystemAppVerificationForTests, enabledServices));
+        return generator.getProviders();
+    }
+
+    /**
+     * Returns the valid credential provider services available for the user with the given {@code
+     * userId}. Includes test providers.
+     */
+    @NonNull
+    public static List<CredentialProviderInfo> getCredentialProviderServicesForTesting(
+            @NonNull Context context,
+            int userId,
+            int providerFilter,
+            Set<ComponentName> enabledServices) {
+        requireNonNull(context, "context must not be null");
+
+        // Get the device policy.
+        PackagePolicy pp = getDeviceManagerPolicy(context, userId);
+
+        // Generate the provider list.
+        final boolean disableSystemAppVerificationForTests = true;
+        ProviderGenerator generator =
+                new ProviderGenerator(
+                        context, pp, disableSystemAppVerificationForTests, providerFilter);
+        generator.addUserProviders(
+                getUserProviders(
+                        context, userId, disableSystemAppVerificationForTests, enabledServices));
+        generator.addSystemProviders(
+                getAvailableSystemServices(
+                        context, userId, disableSystemAppVerificationForTests, enabledServices));
         return generator.getProviders();
     }
 
@@ -484,7 +513,8 @@
     private static List<CredentialProviderInfo> getUserProviders(
             @NonNull Context context,
             @UserIdInt int userId,
-            boolean disableSystemAppVerificationForTests) {
+            boolean disableSystemAppVerificationForTests,
+            Set<ComponentName> enabledServices) {
         final List<CredentialProviderInfo> services = new ArrayList<>();
         final List<ResolveInfo> resolveInfos =
                 context.getPackageManager()
@@ -494,13 +524,19 @@
                                 userId);
         for (ResolveInfo resolveInfo : resolveInfos) {
             final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
+            if (serviceInfo == null) {
+                Log.i(TAG, "No serviceInfo found for resolveInfo so skipping this provider");
+                continue;
+            }
+
             try {
                 CredentialProviderInfo cpi =
-                        new CredentialProviderInfo(
+                        CredentialProviderInfoFactory.create(
                                 context,
                                 serviceInfo,
                                 /* isSystemProvider= */ false,
-                                disableSystemAppVerificationForTests);
+                                disableSystemAppVerificationForTests,
+                                enabledServices.contains(serviceInfo.getComponentName()));
                 if (!cpi.isSystemProvider()) {
                     services.add(cpi);
                 }
diff --git a/core/java/android/service/credentials/CredentialProviderService.java b/core/java/android/service/credentials/CredentialProviderService.java
index d737f6b..e88474d 100644
--- a/core/java/android/service/credentials/CredentialProviderService.java
+++ b/core/java/android/service/credentials/CredentialProviderService.java
@@ -18,6 +18,7 @@
 
 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
 
+import android.Manifest;
 import android.annotation.CallSuper;
 import android.annotation.NonNull;
 import android.annotation.SdkConstant;
@@ -218,6 +219,11 @@
                             GetCredentialException>() {
                         @Override
                         public void onResult(BeginGetCredentialResponse result) {
+                            // If provider service does not possess the HYBRID permission, this
+                            // check will throw an exception in the provider process.
+                            if (result.getRemoteCredentialEntry() != null) {
+                                enforceRemoteEntryPermission();
+                            }
                             try {
                                 callback.onSuccess(result);
                             } catch (RemoteException e) {
@@ -236,6 +242,15 @@
             ));
             return transport;
         }
+        private void enforceRemoteEntryPermission() {
+            String permission =
+                    Manifest.permission.PROVIDE_REMOTE_CREDENTIALS;
+            getApplicationContext().enforceCallingOrSelfPermission(
+                    permission,
+                    String.format("Provider must have %s, in order to set a "
+                            + "remote entry", permission)
+            );
+        }
 
         @Override
         public ICancellationSignal onBeginCreateCredential(BeginCreateCredentialRequest request,
@@ -253,6 +268,11 @@
                             BeginCreateCredentialResponse, CreateCredentialException>() {
                         @Override
                         public void onResult(BeginCreateCredentialResponse result) {
+                            // If provider service does not possess the HYBRID permission, this
+                            // check will throw an exception in the provider process.
+                            if (result.getRemoteCreateEntry() != null) {
+                                enforceRemoteEntryPermission();
+                            }
                             try {
                                 callback.onSuccess(result);
                             } catch (RemoteException e) {
diff --git a/core/java/android/service/credentials/GetCredentialRequest.java b/core/java/android/service/credentials/GetCredentialRequest.java
index 4f13922..5bad9ab 100644
--- a/core/java/android/service/credentials/GetCredentialRequest.java
+++ b/core/java/android/service/credentials/GetCredentialRequest.java
@@ -23,14 +23,16 @@
 
 import com.android.internal.util.AnnotationValidations;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Objects;
 
 /**
  * Request for getting user's credential from a given credential provider.
  *
- * <p>Provider will receive this request once the user selects a given {@link CredentialEntry}
- * on the selector, that was sourced from provider's result to
- * {@link CredentialProviderService#onBeginGetCredential}.
+ * <p>A credential provider will receive this request once the user selects a
+ * given {@link CredentialEntry}, or {@link RemoteEntry} on the selector, that was sourced
+ * from provider's initial response to {@link CredentialProviderService#onBeginGetCredential}.
  */
 public final class GetCredentialRequest implements Parcelable {
     /** Calling package of the app requesting for credentials. */
@@ -38,24 +40,27 @@
     private final CallingAppInfo mCallingAppInfo;
 
     /**
-     * Holds parameters to be used for retrieving a specific type of credential.
+     * Holds a list of options (parameters) to be used for retrieving a specific type of credential.
      */
     @NonNull
-    private final CredentialOption mCredentialOption;
+    private final List<CredentialOption> mCredentialOptions;
 
     public GetCredentialRequest(@NonNull CallingAppInfo callingAppInfo,
-            @NonNull CredentialOption credentialOption) {
+            @NonNull List<CredentialOption> credentialOptions) {
         this.mCallingAppInfo = Objects.requireNonNull(callingAppInfo,
                 "callingAppInfo must not be null");
-        this.mCredentialOption = Objects.requireNonNull(credentialOption,
-                "credentialOption must not be null");
+        this.mCredentialOptions = Objects.requireNonNull(credentialOptions,
+                "credentialOptions must not be null");
     }
 
     private GetCredentialRequest(@NonNull Parcel in) {
         mCallingAppInfo = in.readTypedObject(CallingAppInfo.CREATOR);
         AnnotationValidations.validate(NonNull.class, null, mCallingAppInfo);
-        mCredentialOption = in.readTypedObject(CredentialOption.CREATOR);
-        AnnotationValidations.validate(NonNull.class, null, mCredentialOption);
+
+        List<CredentialOption> credentialOptions = new ArrayList<>();
+        in.readTypedList(credentialOptions, CredentialOption.CREATOR);
+        mCredentialOptions = credentialOptions;
+        AnnotationValidations.validate(NonNull.class, null, mCredentialOptions);
     }
 
     @NonNull public static final  Creator<GetCredentialRequest> CREATOR =
@@ -79,7 +84,7 @@
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeTypedObject(mCallingAppInfo, flags);
-        dest.writeTypedObject(mCredentialOption, flags);
+        dest.writeTypedList(mCredentialOptions, flags);
     }
 
     /**
@@ -91,10 +96,26 @@
     }
 
     /**
-     * Returns the parameters needed to return a given type of credential.
+     * Returns a list of options containing parameters needed to return a given type of credential.
+     * This is part of the request that the credential provider receives after the user has
+     * selected an entry on a selector UI.
+     *
+     * When the user selects a {@link CredentialEntry} and the credential provider receives a
+     * {@link GetCredentialRequest}, this list is expected to contain a single
+     * {@link CredentialOption} only. A {@link CredentialEntry} is always created for a given
+     * {@link BeginGetCredentialOption}, and hence when the user selects it, the provider
+     * receives a corresponding {@link CredentialOption} that contains all the required parameters
+     * to actually retrieve the credential.
+     *
+     * When the user selects a {@link RemoteEntry} and the credential provider receives a
+     * {@link GetCredentialRequest}, this list may contain greater than a single
+     * {@link CredentialOption}, representing the number of options specified by the developer
+     * in the original {@link android.credentials.GetCredentialRequest}. This is because a
+     * {@link RemoteEntry} indicates that the entire request will be processed on a different
+     * device and is not tied to a particular option.
      */
     @NonNull
-    public CredentialOption getCredentialOption() {
-        return mCredentialOption;
+    public List<CredentialOption> getCredentialOptions() {
+        return mCredentialOptions;
     }
 }
diff --git a/core/java/android/service/credentials/RemoteEntry.java b/core/java/android/service/credentials/RemoteEntry.java
new file mode 100644
index 0000000..716c00d
--- /dev/null
+++ b/core/java/android/service/credentials/RemoteEntry.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.credentials;
+
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.app.PendingIntent;
+import android.app.slice.Slice;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * An entry to be shown on the UI. This entry represents remote execution of a get/create flow
+ * whereby credentials are retrieved from, or stored to a remote device.
+ *
+ * <p>If user selects this entry, the corresponding {@link PendingIntent} set on the
+ * {@code slice} as a {@link androidx.slice.core.SliceAction} will get invoked.
+ * Once the resulting activity fulfills the required user engagement,
+ * the {@link android.app.Activity} result should be set to {@link android.app.Activity#RESULT_OK},
+ * and the result of the operation must be set as the activity result.
+ *
+ * For a get flow, invoked through {@link CredentialProviderService#onBeginGetCredential},
+ * providers must set a {@link android.credentials.GetCredentialResponse} on the activity result,
+ * against the key {@link CredentialProviderService#EXTRA_GET_CREDENTIAL_RESPONSE}.
+ *
+ * For a creates flow, invoked through {@link CredentialProviderService#onBeginCreateCredential},
+ * providers must set a {@link android.credentials.CreateCredentialResponse} on the activity
+ * result against the ket {@link CredentialProviderService#EXTRA_CREATE_CREDENTIAL_RESPONSE}.
+ *
+ * <p>Any class that extends this class must only add extra field values to the {@code slice}
+ * object passed into the constructor. Any other field will not be parceled through. If the
+ * derived class has custom parceling implementation, this class will not be able to unpack
+ * the parcel without having access to that implementation.
+ */
+@SuppressLint("ParcelNotFinal")
+public class RemoteEntry implements Parcelable {
+    private final @NonNull Slice mSlice;
+
+    private RemoteEntry(@NonNull Parcel in) {
+        mSlice = in.readTypedObject(Slice.CREATOR);
+    }
+
+    @NonNull
+    public static final Creator<RemoteEntry> CREATOR = new Creator<RemoteEntry>() {
+        @Override
+        public RemoteEntry createFromParcel(@NonNull Parcel in) {
+            return new RemoteEntry(in);
+        }
+
+        @Override
+        public RemoteEntry[] newArray(int size) {
+            return new RemoteEntry[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeTypedObject(mSlice, flags);
+    }
+
+    /**
+     * Constructs a RemoteEntry to be displayed on the UI.
+     *
+     * @param slice the display content to be displayed on the UI, along with this entry
+     */
+    public RemoteEntry(
+            @NonNull Slice slice) {
+        this.mSlice = slice;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mSlice);
+    }
+
+    /** Returns the content to be displayed with this remote entry on the UI. */
+    @NonNull
+    public Slice getSlice() {
+        return mSlice;
+    }
+}
diff --git a/core/java/android/service/dreams/DreamActivity.java b/core/java/android/service/dreams/DreamActivity.java
index ff14404..a389223 100644
--- a/core/java/android/service/dreams/DreamActivity.java
+++ b/core/java/android/service/dreams/DreamActivity.java
@@ -70,7 +70,7 @@
 
     @Override
     public void onDestroy() {
-        if (mCallback != null && !isFinishing()) {
+        if (mCallback != null) {
             mCallback.onActivityDestroyed();
         }
 
diff --git a/core/java/android/service/dreams/DreamOverlayService.java b/core/java/android/service/dreams/DreamOverlayService.java
index 6e4535b..5469916 100644
--- a/core/java/android/service/dreams/DreamOverlayService.java
+++ b/core/java/android/service/dreams/DreamOverlayService.java
@@ -27,6 +27,8 @@
 import android.util.Log;
 import android.view.WindowManager;
 
+import java.util.concurrent.Executor;
+
 
 /**
  * Basic implementation of for {@link IDreamOverlay} for testing.
@@ -40,6 +42,12 @@
     // The last client that started dreaming and hasn't ended
     private OverlayClient mCurrentClient;
 
+    /**
+     * Executor used to run callbacks that subclasses will implement. Any calls coming over Binder
+     * from {@link OverlayClient} should perform the work they need to do on this executor.
+     */
+    private Executor mExecutor;
+
     // An {@link IDreamOverlayClient} implementation that identifies itself when forwarding
     // requests to the {@link DreamOverlayService}
     private static class OverlayClient extends IDreamOverlayClient.Stub {
@@ -61,8 +69,6 @@
             mService.startDream(this, params);
         }
 
-
-
         @Override
         public void wakeUp() {
             mService.wakeUp(this, () -> {
@@ -97,12 +103,20 @@
     }
 
     private void startDream(OverlayClient client, WindowManager.LayoutParams params) {
-        endDream(mCurrentClient);
-        mCurrentClient = client;
-        onStartDream(params);
+        // Run on executor as this is a binder call from OverlayClient.
+        mExecutor.execute(() -> {
+            endDreamInternal(mCurrentClient);
+            mCurrentClient = client;
+            onStartDream(params);
+        });
     }
 
     private void endDream(OverlayClient client) {
+        // Run on executor as this is a binder call from OverlayClient.
+        mExecutor.execute(() -> endDreamInternal(client));
+    }
+
+    private void endDreamInternal(OverlayClient client) {
         if (client == null || client != mCurrentClient) {
             return;
         }
@@ -112,11 +126,14 @@
     }
 
     private void wakeUp(OverlayClient client, Runnable callback) {
-        if (mCurrentClient != client) {
-            return;
-        }
+        // Run on executor as this is a binder call from OverlayClient.
+        mExecutor.execute(() -> {
+            if (mCurrentClient != client) {
+                return;
+            }
 
-        onWakeUp(callback);
+            onWakeUp(callback);
+        });
     }
 
     private IDreamOverlay mDreamOverlay = new IDreamOverlay.Stub() {
@@ -134,6 +151,25 @@
     public DreamOverlayService() {
     }
 
+    /**
+     * This constructor allows providing an executor to run callbacks on.
+     *
+     * @hide
+     */
+    public DreamOverlayService(@NonNull Executor executor) {
+        mExecutor = executor;
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        if (mExecutor == null) {
+            // If no executor was provided, use the main executor. onCreate is the earliest time
+            // getMainExecutor is available.
+            mExecutor = getMainExecutor();
+        }
+    }
+
     @Nullable
     @Override
     public final IBinder onBind(@NonNull Intent intent) {
@@ -143,6 +179,10 @@
     /**
      * This method is overridden by implementations to handle when the dream has started and the
      * window is ready to be interacted with.
+     *
+     * This callback will be run on the {@link Executor} provided in the constructor if provided, or
+     * on the main executor if none was provided.
+     *
      * @param layoutParams The {@link android.view.WindowManager.LayoutParams} associated with the
      *                     dream window.
      */
@@ -153,6 +193,9 @@
      * to wakeup. This allows any overlay animations to run. By default, the method will invoke
      * the callback immediately.
      *
+     * This callback will be run on the {@link Executor} provided in the constructor if provided, or
+     * on the main executor if none was provided.
+     *
      * @param onCompleteCallback The callback to trigger to notify the dream service that the
      *                           overlay has completed waking up.
      * @hide
@@ -164,6 +207,9 @@
     /**
      * This method is overridden by implementations to handle when the dream has ended. There may
      * be earlier signals leading up to this step, such as @{@link #onWakeUp(Runnable)}.
+     *
+     * This callback will be run on the {@link Executor} provided in the constructor if provided, or
+     * on the main executor if none was provided.
      */
     public void onEndDream() {
     }
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index d79ea89..ce8af83 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -1409,6 +1409,10 @@
                             // Request the DreamOverlay be told to dream with dream's window
                             // parameters once the window has been attached.
                             mDreamStartOverlayConsumer = overlay -> {
+                                if (mWindow == null) {
+                                    Slog.d(TAG, "mWindow is null");
+                                    return;
+                                }
                                 try {
                                     overlay.startDream(mWindow.getAttributes(), mOverlayCallback,
                                             mDreamComponent.flattenToString(),
@@ -1588,7 +1592,8 @@
         // If DreamActivity is destroyed, wake up from Dream.
         void onActivityDestroyed() {
             mActivity = null;
-            onDestroy();
+            mWindow = null;
+            detach();
         }
     }
 
diff --git a/core/java/android/service/quickaccesswallet/GetWalletCardsCallbackImpl.java b/core/java/android/service/quickaccesswallet/GetWalletCardsCallbackImpl.java
index ae67068..8409503 100644
--- a/core/java/android/service/quickaccesswallet/GetWalletCardsCallbackImpl.java
+++ b/core/java/android/service/quickaccesswallet/GetWalletCardsCallbackImpl.java
@@ -17,6 +17,8 @@
 package android.service.quickaccesswallet;
 
 import android.annotation.NonNull;
+import android.content.Context;
+import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
 import android.graphics.drawable.Icon;
 import android.os.Handler;
@@ -36,13 +38,18 @@
     private final IQuickAccessWalletServiceCallbacks mCallback;
     private final GetWalletCardsRequest mRequest;
     private final Handler mHandler;
+    private final Context mContext;
     private boolean mCalled;
 
-    GetWalletCardsCallbackImpl(GetWalletCardsRequest request,
-            IQuickAccessWalletServiceCallbacks callback, Handler handler) {
+    GetWalletCardsCallbackImpl(
+            GetWalletCardsRequest request,
+            IQuickAccessWalletServiceCallbacks callback,
+            Handler handler,
+            Context context) {
         mRequest = request;
         mCallback = callback;
         mHandler = handler;
+        mContext = context;
     }
 
     /**
@@ -50,11 +57,17 @@
      * was successfully handled by the service.
      *
      * @param response The response contains the list of {@link WalletCard walletCards} to be shown
-     *                 to the user as well as the index of the card that should initially be
-     *                 presented as the selected card.
+     *     to the user as well as the index of the card that should initially be presented as the
+     *     selected card.
      */
     public void onSuccess(@NonNull GetWalletCardsResponse response) {
         if (isValidResponse(response)) {
+            // Strip location info from response if the feature is not enabled.
+            if (!mContext.getPackageManager()
+                    .hasSystemFeature(PackageManager.FEATURE_WALLET_LOCATION_BASED_SUGGESTIONS)) {
+                removeLocationsFromResponse(response);
+            }
+
             mHandler.post(() -> onSuccessInternal(response));
         } else {
             Log.w(TAG, "Invalid GetWalletCards response");
@@ -152,4 +165,10 @@
         }
         return true;
     }
+
+    private void removeLocationsFromResponse(@NonNull GetWalletCardsResponse response) {
+        for (WalletCard card : response.getWalletCards()) {
+            card.removeCardLocations();
+        }
+    }
 }
diff --git a/core/java/android/service/quickaccesswallet/QuickAccessWalletService.java b/core/java/android/service/quickaccesswallet/QuickAccessWalletService.java
index d004f34..36fa21c 100644
--- a/core/java/android/service/quickaccesswallet/QuickAccessWalletService.java
+++ b/core/java/android/service/quickaccesswallet/QuickAccessWalletService.java
@@ -262,8 +262,8 @@
     private void onWalletCardsRequestedInternal(
             GetWalletCardsRequest request,
             IQuickAccessWalletServiceCallbacks callback) {
-        onWalletCardsRequested(request,
-                new GetWalletCardsCallbackImpl(request, callback, mHandler));
+        onWalletCardsRequested(
+                request, new GetWalletCardsCallbackImpl(request, callback, mHandler, this));
     }
 
     private void onTargetActivityIntentRequestedInternal(
diff --git a/core/java/android/service/quickaccesswallet/WalletCard.java b/core/java/android/service/quickaccesswallet/WalletCard.java
index e52adcc..4a4fd04 100644
--- a/core/java/android/service/quickaccesswallet/WalletCard.java
+++ b/core/java/android/service/quickaccesswallet/WalletCard.java
@@ -21,6 +21,7 @@
 import android.annotation.Nullable;
 import android.app.PendingIntent;
 import android.graphics.drawable.Icon;
+import android.location.Location;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -29,7 +30,8 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * A {@link WalletCard} can represent anything that a user might carry in their wallet -- a credit
@@ -67,6 +69,7 @@
     private final Icon mCardIcon;
     private final CharSequence mCardLabel;
     private final Icon mNonPaymentCardSecondaryImage;
+    private List<Location> mCardLocations;
 
     private WalletCard(Builder builder) {
         this.mCardId = builder.mCardId;
@@ -77,6 +80,7 @@
         this.mCardIcon = builder.mCardIcon;
         this.mCardLabel = builder.mCardLabel;
         this.mNonPaymentCardSecondaryImage = builder.mNonPaymentCardSecondaryImage;
+        this.mCardLocations = builder.mCardLocations;
     }
 
     /**
@@ -106,7 +110,7 @@
         writeIconIfNonNull(mCardIcon, dest, flags);
         TextUtils.writeToParcel(mCardLabel, dest, flags);
         writeIconIfNonNull(mNonPaymentCardSecondaryImage, dest, flags);
-
+        dest.writeTypedList(mCardLocations, flags);
     }
 
     /** Utility function called by writeToParcel
@@ -128,15 +132,20 @@
         PendingIntent pendingIntent = PendingIntent.readPendingIntentOrNullFromParcel(source);
         Icon cardIcon = source.readByte() == 0 ? null : Icon.CREATOR.createFromParcel(source);
         CharSequence cardLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
-        Icon nonPaymentCardSecondaryImage = source.readByte() == 0 ? null :
-                Icon.CREATOR.createFromParcel(source);
-        Builder builder = new Builder(cardId, cardType, cardImage, contentDesc, pendingIntent)
-                .setCardIcon(cardIcon)
-                .setCardLabel(cardLabel);
+        Icon nonPaymentCardSecondaryImage =
+                source.readByte() == 0 ? null : Icon.CREATOR.createFromParcel(source);
+        Builder builder =
+                new Builder(cardId, cardType, cardImage, contentDesc, pendingIntent)
+                        .setCardIcon(cardIcon)
+                        .setCardLabel(cardLabel);
+        if (cardType == CARD_TYPE_NON_PAYMENT) {
+            builder.setNonPaymentCardSecondaryImage(nonPaymentCardSecondaryImage);
+        }
+        List<Location> cardLocations = new ArrayList<>();
+        source.readTypedList(cardLocations, Location.CREATOR);
+        builder.setCardLocations(cardLocations);
 
-        return cardType == CARD_TYPE_NON_PAYMENT
-                ? builder.setNonPaymentCardSecondaryImage(nonPaymentCardSecondaryImage).build() :
-                 builder.build();
+        return builder.build();
     }
 
     @NonNull
@@ -226,13 +235,29 @@
 
     /**
      * Visual representation of the card when it is tapped. May include additional information
-     *  unique to the card, such as a barcode or number. Only valid for CARD_TYPE_NON_PAYMENT.
+     * unique to the card, such as a barcode or number. Only valid for CARD_TYPE_NON_PAYMENT.
      */
     @Nullable
     public Icon getNonPaymentCardSecondaryImage() {
         return mNonPaymentCardSecondaryImage;
     }
 
+    /** List of locations that this card might be useful at. */
+    @NonNull
+    public List<Location> getCardLocations() {
+        return mCardLocations;
+    }
+
+    /**
+     * Removes locations from card. Should be called if {@link
+     * PackageManager.FEATURE_WALLET_LOCATION_BASED_SUGGESTIONS} is disabled.
+     *
+     * @hide
+     */
+    public void removeCardLocations() {
+        mCardLocations = new ArrayList<>();
+    }
+
     /**
      * Builder for {@link WalletCard} objects. You must provide cardId, cardImage,
      * contentDescription, and pendingIntent. If the card is opaque and should be shown with
@@ -247,6 +272,7 @@
         private Icon mCardIcon;
         private CharSequence mCardLabel;
         private Icon mNonPaymentCardSecondaryImage;
+        private List<Location> mCardLocations = new ArrayList<>();
 
         /**
          * @param cardId             The card id must be non-null and unique within the list of
@@ -333,18 +359,31 @@
 
         /**
          * Visual representation of the card when it is tapped. May include additional information
-         *  unique to the card, such as a barcode or number. Only valid for CARD_TYPE_NON_PAYMENT.
+         * unique to the card, such as a barcode or number. Only valid for CARD_TYPE_NON_PAYMENT.
          */
         @NonNull
-        public Builder
-                setNonPaymentCardSecondaryImage(@Nullable Icon nonPaymentCardSecondaryImage) {
-            Preconditions.checkState(mCardType == CARD_TYPE_NON_PAYMENT,
+        public Builder setNonPaymentCardSecondaryImage(
+                @Nullable Icon nonPaymentCardSecondaryImage) {
+            Preconditions.checkState(
+                    mCardType == CARD_TYPE_NON_PAYMENT,
                     "This field can only be set on non-payment cards");
             mNonPaymentCardSecondaryImage = nonPaymentCardSecondaryImage;
             return this;
         }
 
         /**
+         * Set of locations this card might be useful at. If {@link
+         * PackageManager.FEATURE_WALLET_LOCATION_BASED_SUGGESTIONS} is enabled, the card might be
+         * shown to the user when a user is near one of these locations.
+         */
+        @NonNull
+        public Builder setCardLocations(@NonNull List<Location> cardLocations) {
+            Preconditions.checkCollectionElementsNotNull(cardLocations, "cardLocations");
+            mCardLocations = cardLocations;
+            return this;
+        }
+
+        /**
          * Builds a new {@link WalletCard} instance.
          *
          * @return A built response.
diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java
index 94384b0..f74f533 100644
--- a/core/java/android/service/quicksettings/TileService.java
+++ b/core/java/android/service/quicksettings/TileService.java
@@ -533,7 +533,7 @@
      *     the calling package or if the calling user cannot act on behalf of the user from the
      *     {@code context}.</li>
      *     <li> {@link IllegalArgumentException} if the user of the {@code context} is not the
-     *     current user.</li>
+     *     current user. Only thrown for apps targeting {@link Build.VERSION_CODES#TIRAMISU}</li>
      * </ul>
      */
     public static final void requestListeningState(Context context, ComponentName component) {
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index b1dc686..2830fb7 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -805,11 +805,13 @@
             Identity identity = new Identity();
             identity.packageName = ActivityThread.currentOpPackageName();
             if (moduleProperties == null) {
-                List<SoundTrigger.ModuleProperties> modulePropList =
-                        mModelManagementService.listModuleProperties(identity);
-                if (modulePropList.size() > 0) {
-                    moduleProperties = modulePropList.get(0);
-                }
+                moduleProperties = mModelManagementService
+                        .listModuleProperties(identity)
+                        .stream()
+                        .filter(prop -> !prop.getSupportedModelArch()
+                                .equals(SoundTrigger.FAKE_HAL_ARCH))
+                        .findFirst()
+                        .orElse(null);
                 // (@atneya) intentionally let a null moduleProperties through until
                 // all CTS tests are fixed
             }
diff --git a/core/java/android/service/voice/HotwordDetectionService.java b/core/java/android/service/voice/HotwordDetectionService.java
index 0384454..d9ee859 100644
--- a/core/java/android/service/voice/HotwordDetectionService.java
+++ b/core/java/android/service/voice/HotwordDetectionService.java
@@ -72,7 +72,7 @@
  */
 @SystemApi
 public abstract class HotwordDetectionService extends Service
-        implements SandboxedDetectionServiceBase {
+        implements SandboxedDetectionInitializer {
     private static final String TAG = "HotwordDetectionService";
     private static final boolean DBG = false;
 
@@ -89,21 +89,23 @@
     /**
      * Indicates that the updated status is successful.
      *
-     * @deprecated Replaced with {@link SandboxedDetectionServiceBase#INITIALIZATION_STATUS_SUCCESS}
+     * @deprecated Replaced with
+     * {@link SandboxedDetectionInitializer#INITIALIZATION_STATUS_SUCCESS}
      */
     @Deprecated
     public static final int INITIALIZATION_STATUS_SUCCESS =
-            SandboxedDetectionServiceBase.INITIALIZATION_STATUS_SUCCESS;
+            SandboxedDetectionInitializer.INITIALIZATION_STATUS_SUCCESS;
 
     /**
      * Indicates that the callback wasn’t invoked within the timeout.
      * This is used by system.
      *
-     * @deprecated Replaced with {@link SandboxedDetectionServiceBase#INITIALIZATION_STATUS_UNKNOWN}
+     * @deprecated Replaced with
+     * {@link SandboxedDetectionInitializer#INITIALIZATION_STATUS_UNKNOWN}
      */
     @Deprecated
     public static final int INITIALIZATION_STATUS_UNKNOWN =
-            SandboxedDetectionServiceBase.INITIALIZATION_STATUS_UNKNOWN;
+            SandboxedDetectionInitializer.INITIALIZATION_STATUS_UNKNOWN;
 
     /**
      * Source for the given audio stream.
@@ -259,7 +261,7 @@
      *
      * @hide
      * @deprecated Replaced with
-     * {@link SandboxedDetectionServiceBase#getMaxCustomInitializationStatus()}
+     * {@link SandboxedDetectionInitializer#getMaxCustomInitializationStatus()}
      */
     @SystemApi
     @Deprecated
@@ -368,7 +370,7 @@
     private void onUpdateStateInternal(@Nullable PersistableBundle options,
             @Nullable SharedMemory sharedMemory, IRemoteCallback callback) {
         IntConsumer intConsumer =
-                SandboxedDetectionServiceBase.createInitializationStatusConsumer(callback);
+                SandboxedDetectionInitializer.createInitializationStatusConsumer(callback);
         onUpdateState(options, sharedMemory, UPDATE_TIMEOUT_MILLIS, intConsumer);
     }
 
diff --git a/core/java/android/service/voice/HotwordDetector.java b/core/java/android/service/voice/HotwordDetector.java
index 22d97b7..93fcec1 100644
--- a/core/java/android/service/voice/HotwordDetector.java
+++ b/core/java/android/service/voice/HotwordDetector.java
@@ -283,9 +283,9 @@
          *
          * @param status Info about initialization state of {@link HotwordDetectionService} or
          * {@link VisualQueryDetectionService}; allowed values are
-         * {@link SandboxedDetectionServiceBase#INITIALIZATION_STATUS_SUCCESS},
-         * 1<->{@link SandboxedDetectionServiceBase#getMaxCustomInitializationStatus()},
-         * {@link SandboxedDetectionServiceBase#INITIALIZATION_STATUS_UNKNOWN}.
+         * {@link SandboxedDetectionInitializer#INITIALIZATION_STATUS_SUCCESS},
+         * 1<->{@link SandboxedDetectionInitializer#getMaxCustomInitializationStatus()},
+         * {@link SandboxedDetectionInitializer#INITIALIZATION_STATUS_UNKNOWN}.
          */
         void onHotwordDetectionServiceInitialized(int status);
 
diff --git a/core/java/android/service/voice/SandboxedDetectionServiceBase.java b/core/java/android/service/voice/SandboxedDetectionInitializer.java
similarity index 94%
rename from core/java/android/service/voice/SandboxedDetectionServiceBase.java
rename to core/java/android/service/voice/SandboxedDetectionInitializer.java
index 4333164..4a41968 100644
--- a/core/java/android/service/voice/SandboxedDetectionServiceBase.java
+++ b/core/java/android/service/voice/SandboxedDetectionInitializer.java
@@ -28,12 +28,12 @@
 import java.util.function.IntConsumer;
 
 /**
- * Base for all sandboxed detection services, providing a common interface for initialization.
+ * Provides common initialzation methods for sandboxed detection services.
  *
  * @hide
  */
 @SystemApi
-public interface SandboxedDetectionServiceBase {
+public interface SandboxedDetectionInitializer {
 
     /**
      * Indicates that the updated status is successful.
@@ -77,7 +77,7 @@
         if (callback != null) {
             intConsumer =
                     value -> {
-                        if (value > SandboxedDetectionServiceBase
+                        if (value > SandboxedDetectionInitializer
                                 .getMaxCustomInitializationStatus()) {
                             throw new IllegalArgumentException(
                                     "The initialization status is invalid for " + value);
diff --git a/core/java/android/service/voice/VisualQueryDetectionService.java b/core/java/android/service/voice/VisualQueryDetectionService.java
index 2e455c2..cbe7666 100644
--- a/core/java/android/service/voice/VisualQueryDetectionService.java
+++ b/core/java/android/service/voice/VisualQueryDetectionService.java
@@ -20,9 +20,11 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.app.Service;
 import android.content.ContentCaptureOptions;
+import android.content.Context;
 import android.content.Intent;
 import android.hardware.soundtrigger.SoundTrigger;
 import android.media.AudioFormat;
@@ -35,6 +37,7 @@
 import android.os.SharedMemory;
 import android.speech.IRecognitionServiceManager;
 import android.util.Log;
+import android.view.contentcapture.ContentCaptureManager;
 import android.view.contentcapture.IContentCaptureManager;
 
 import java.util.Objects;
@@ -49,7 +52,7 @@
  * {@link VoiceInteractionService#createVisualQueryDetector(PersistableBundle, SharedMemory,
  * Executor, VisualQueryDetector.Callback)} is called, the system will bind the application's
  * {@link VisualQueryDetectionService}. When requested from {@link VoiceInteractionService}, the
- * system calls into the {@link VisualQueryDetectionService#onStartDetection(Callback)} to enable
+ * system calls into the {@link VisualQueryDetectionService#onStartDetection()} to enable
  * detection. This method MUST be implemented to support visual query detection service.
  *
  * Note: Methods in this class may be called concurrently.
@@ -58,7 +61,7 @@
  */
 @SystemApi
 public abstract class VisualQueryDetectionService extends Service
-        implements SandboxedDetectionServiceBase {
+        implements SandboxedDetectionInitializer {
 
     private static final String TAG = VisualQueryDetectionService.class.getSimpleName();
 
@@ -78,6 +81,12 @@
     /** @hide */
     public static final String KEY_INITIALIZATION_STATUS = "initialization_status";
 
+    private IDetectorSessionVisualQueryDetectionCallback mRemoteCallback = null;
+    @Nullable
+    private ContentCaptureManager mContentCaptureManager;
+    @Nullable
+    private IRecognitionServiceManager mIRecognitionServiceManager;
+
 
     private final ISandboxedDetectionService mInterface = new ISandboxedDetectionService.Stub() {
 
@@ -85,7 +94,8 @@
         public void detectWithVisualSignals(
                 IDetectorSessionVisualQueryDetectionCallback callback) {
             Log.v(TAG, "#detectWithVisualSignals");
-            VisualQueryDetectionService.this.onStartDetection(new Callback(callback));
+            mRemoteCallback = callback;
+            VisualQueryDetectionService.this.onStartDetection();
         }
 
         @Override
@@ -136,15 +146,29 @@
         @Override
         public void updateContentCaptureManager(IContentCaptureManager manager,
                 ContentCaptureOptions options) {
-            Log.v(TAG, "Ignore #updateContentCaptureManager");
+            mContentCaptureManager = new ContentCaptureManager(
+                    VisualQueryDetectionService.this, manager, options);
         }
 
         @Override
         public void updateRecognitionServiceManager(IRecognitionServiceManager manager) {
-            Log.v(TAG, "Ignore #updateRecognitionServiceManager");
+            mIRecognitionServiceManager = manager;
         }
     };
 
+    @Override
+    @SuppressLint("OnNameExpected")
+    public @Nullable Object getSystemService(@ServiceName @NonNull String name) {
+        if (Context.CONTENT_CAPTURE_MANAGER_SERVICE.equals(name)) {
+            return mContentCaptureManager;
+        } else if (Context.SPEECH_RECOGNITION_SERVICE.equals(name)
+                && mIRecognitionServiceManager != null) {
+            return mIRecognitionServiceManager.asBinder();
+        } else {
+            return super.getSystemService(name);
+        }
+    }
+
     /**
      * {@inheritDoc}
      * @hide
@@ -172,22 +196,47 @@
     private void onUpdateStateInternal(@Nullable PersistableBundle options,
             @Nullable SharedMemory sharedMemory, IRemoteCallback callback) {
         IntConsumer intConsumer =
-                SandboxedDetectionServiceBase.createInitializationStatusConsumer(callback);
+                SandboxedDetectionInitializer.createInitializationStatusConsumer(callback);
         onUpdateState(options, sharedMemory, UPDATE_TIMEOUT_MILLIS, intConsumer);
     }
 
     /**
      * This is called after the service is set up and the client should open the camera and the
-     * microphone to start recognition.
-     *
-     * Called when the {@link VoiceInteractionService} requests that this service
-     * {@link HotwordDetector#startRecognition()} start recognition on audio coming directly
+     * microphone to start recognition. When the {@link VoiceInteractionService} requests that this
+     * service {@link HotwordDetector#startRecognition()} start recognition on audio coming directly
      * from the device microphone.
-     *
-     * @param callback The callback to use for responding to the detection request.
-     *
+     * <p>
+     * Signal senders that return attention and query results are also expected to be called in this
+     * method according to the detection outcomes.
+     * <p>
+     * On successful user attention, developers should call
+     * {@link VisualQueryDetectionService#gainedAttention()} to enable the streaming of the query.
+     * <p>
+     * On user attention is lost, developers should call
+     * {@link VisualQueryDetectionService#lostAttention()} to disable the streaming of the query.
+     * <p>
+     * On query is detected and ready to stream, developers should call
+     * {@link VisualQueryDetectionService#streamQuery(String)} to return detected query to the
+     * {@link VisualQueryDetector}.
+     * <p>
+     * On streamed query should be rejected, clients should call
+     * {@link VisualQueryDetectionService#rejectQuery()} to abandon query streamed to the
+     * {@link VisualQueryDetector}.
+     * <p>
+     * On streamed query is finished, clients should call
+     * {@link VisualQueryDetectionService#finishQuery()} to complete query streamed to
+     * {@link VisualQueryDetector}.
+     * <p>
+     * Before a call for {@link VisualQueryDetectionService#streamQuery(String)} is triggered,
+     * {@link VisualQueryDetectionService#gainedAttention()} MUST be called to enable the streaming
+     * of query. A query streaming is also expected to be finished by calling either
+     * {@link VisualQueryDetectionService#finishQuery()} or
+     * {@link VisualQueryDetectionService#rejectQuery()} before a new query should start streaming.
+     * When the service enters the state where query streaming should be disabled,
+     * {@link VisualQueryDetectionService#lostAttention()} MUST be called to block unnecessary
+     * streaming.
      */
-    public void onStartDetection(@NonNull Callback callback) {
+    public void onStartDetection() {
         throw new UnsupportedOperationException();
     }
 
@@ -199,118 +248,78 @@
     }
 
     /**
-     * Callback for sending out signals and returning query results.
-     *
-     * On successful user attention, developers should call {@link Callback#onAttentionGained()}
-     * to enable the streaming of the query.
-     * <p>
-     * On user attention is lost, developers should call {@link Callback#onAttentionLost()} to
-     * disable the streaming of the query.
-     * <p>
-     * On query is detected and ready to stream, developers should call
-     * {@link Callback#onQueryDetected(String)} to return detected query to the
-     * {@link VisualQueryDetector}.
-     * <p>
-     * On streamed query should be rejected, clients should call {@link Callback#onQueryRejected()}
-     * to abandon query streamed to the {@link VisualQueryDetector}.
-     * <p>
-     * On streamed query is finished, clients should call {@link Callback#onQueryFinished()} to
-     * complete query streamed to {@link VisualQueryDetector}.
-     * <p>
-     * Before a call for {@link Callback#onQueryDetected(String)} is triggered,
-     * {@link Callback#onAttentionGained()} MUST be called to enable the streaming of query. A query
-     * streaming is also expected to be finished by calling either
-     * {@link Callback#onQueryFinished()} or {@link Callback#onQueryRejected()} before a new query
-     * should start streaming. When the service enters the state where query streaming should be
-     * disabled, {@link Callback#onAttentionLost()} MUST be called to block unnecessary streaming.
+     * Informs the system that the user attention is gained so queries can be streamed.
      */
-    public static final class Callback {
-
-        // TODO: consider making the constructor a test api for testing purpose
-        public Callback() {
-            mRemoteCallback = null;
+    public final void gainedAttention() {
+        try {
+            mRemoteCallback.onAttentionGained();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
+    }
 
-        private final IDetectorSessionVisualQueryDetectionCallback mRemoteCallback;
-
-        private Callback(IDetectorSessionVisualQueryDetectionCallback remoteCallback) {
-            mRemoteCallback = remoteCallback;
+    /**
+     * Informs the system that the user attention is lost to stop streaming.
+     */
+    public final void lostAttention() {
+        try {
+            mRemoteCallback.onAttentionLost();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
+    }
 
-        /**
-         * Informs attention listener that the user attention is gained.
-         */
-        public void onAttentionGained() {
-            try {
-                mRemoteCallback.onAttentionGained();
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
+    /**
+     * Informs the {@link VisualQueryDetector} with the text content being captured about the
+     * query from the audio source. {@code partialQuery} is provided to the
+     * {@link VisualQueryDetector}. This method is expected to be only triggered if
+     * {@link VisualQueryDetectionService#gainedAttention()} is called to put the service into the
+     * attention gained state.
+     *
+     * @param partialQuery Partially detected query in string.
+     * @throws IllegalStateException if method called without attention gained.
+     */
+    public final void streamQuery(@NonNull String partialQuery) throws IllegalStateException {
+        Objects.requireNonNull(partialQuery);
+        try {
+            mRemoteCallback.onQueryDetected(partialQuery);
+        } catch (RemoteException e) {
+            throw new IllegalStateException("#streamQuery must be only be triggered after "
+                    + "calling #gainedAttention to be in the attention gained state.");
         }
+    }
 
-        /**
-         * Informs attention listener that the user attention is lost.
-         */
-        public void onAttentionLost() {
-            try {
-                mRemoteCallback.onAttentionLost();
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
+    /**
+     * Informs the {@link VisualQueryDetector} to abandon the streamed partial query that has
+     * been sent to {@link VisualQueryDetector}.This method is expected to be only triggered if
+     * {@link VisualQueryDetectionService#streamQuery(String)} is called to put the service into
+     * the query streaming state.
+     *
+     * @throws IllegalStateException if method called without query streamed.
+     */
+    public final void rejectQuery() throws IllegalStateException {
+        try {
+            mRemoteCallback.onQueryRejected();
+        } catch (RemoteException e) {
+            throw new IllegalStateException("#rejectQuery must be only be triggered after "
+                    + "calling #streamQuery to be in the query streaming state.");
         }
+    }
 
-        /**
-         * Informs the {@link VisualQueryDetector} with the text content being captured about the
-         * query from the audio source. {@code partialQuery} is provided to the
-         * {@link VisualQueryDetector}. This method is expected to be only triggered if
-         * {@link Callback#onAttentionGained()} is called to put the service into the attention
-         * gained state.
-         *
-         * @param partialQuery Partially detected query in string.
-         * @throws IllegalStateException if method called without attention gained.
-         */
-        public void onQueryDetected(@NonNull String partialQuery) throws IllegalStateException {
-            Objects.requireNonNull(partialQuery);
-            try {
-                mRemoteCallback.onQueryDetected(partialQuery);
-            } catch (RemoteException e) {
-                throw new IllegalStateException("#onQueryDetected must be only be triggered after "
-                        + "calling #onAttentionGained to be in the attention gained state.");
-            }
-        }
-
-        /**
-         * Informs the {@link VisualQueryDetector} to abandon the streamed partial query that has
-         * been sent to {@link VisualQueryDetector}.This method is expected to be only triggered if
-         * {@link Callback#onQueryDetected()} is called to put the service into the query streaming
-         * state.
-         *
-         * @throws IllegalStateException if method called without query streamed.
-         */
-        public void onQueryRejected() throws IllegalStateException {
-            try {
-                mRemoteCallback.onQueryRejected();
-            } catch (RemoteException e) {
-                throw new IllegalStateException("#onQueryRejected must be only be triggered after "
-                        + "calling #onQueryDetected to be in the query streaming state.");
-            }
-        }
-
-        /**
-         * Informs {@link VisualQueryDetector} with the metadata to complete the streamed partial
-         * query that has been sent to {@link VisualQueryDetector}. This method is expected to be
-         * only triggered if {@link Callback#onQueryDetected()} is called to put the service into
-         * the query streaming state.
-         *
-         * @throws IllegalStateException if method called without query streamed.
-         */
-        public void onQueryFinished() throws IllegalStateException {
-            try {
-                mRemoteCallback.onQueryFinished();
-            } catch (RemoteException e) {
-                throw new IllegalStateException("#onQueryFinished must be only be triggered after "
-                        + "calling #onQueryDetected to be in the query streaming state.");
-            }
+    /**
+     * Informs {@link VisualQueryDetector} with the metadata to complete the streamed partial
+     * query that has been sent to {@link VisualQueryDetector}. This method is expected to be
+     * only triggered if {@link VisualQueryDetectionService#streamQuery(String)} is called to put
+     * the service into the query streaming state.
+     *
+     * @throws IllegalStateException if method called without query streamed.
+     */
+    public final void finishQuery() throws IllegalStateException {
+        try {
+            mRemoteCallback.onQueryFinished();
+        } catch (RemoteException e) {
+            throw new IllegalStateException("#finishQuery must be only be triggered after "
+                    + "calling #streamQuery to be in the query streaming state.");
         }
     }
 
diff --git a/core/java/android/service/voice/VisualQueryDetector.java b/core/java/android/service/voice/VisualQueryDetector.java
index 0be3253..7dc0687 100644
--- a/core/java/android/service/voice/VisualQueryDetector.java
+++ b/core/java/android/service/voice/VisualQueryDetector.java
@@ -177,7 +177,8 @@
     public interface Callback {
 
         /**
-         * Called when the {@link VisualQueryDetectionService} starts to stream partial queries.
+         * Called when the {@link VisualQueryDetectionService} starts to stream partial queries
+         * with {@link VisualQueryDetectionService#streamQuery(String)}.
          *
          * @param partialQuery The partial query in a text form being streamed.
          */
@@ -185,12 +186,13 @@
 
         /**
          * Called when the {@link VisualQueryDetectionService} decides to abandon the streamed
-         * partial queries.
+         * partial queries with {@link VisualQueryDetectionService#rejectQuery()}.
          */
         void onQueryRejected();
 
         /**
-         *  Called when the {@link VisualQueryDetectionService} finishes streaming partial queries.
+         *  Called when the {@link VisualQueryDetectionService} finishes streaming partial queries
+         *  with {@link VisualQueryDetectionService#finishQuery()}.
          */
         void onQueryFinished();
 
@@ -199,9 +201,10 @@
          * short amount of time to report its initialization state.
          *
          * @param status Info about initialization state of {@link VisualQueryDetectionService}; the
-         * allowed values are {@link SandboxedDetectionServiceBase#INITIALIZATION_STATUS_SUCCESS},
-         * 1<->{@link SandboxedDetectionServiceBase#getMaxCustomInitializationStatus()},
-         * {@link SandboxedDetectionServiceBase#INITIALIZATION_STATUS_UNKNOWN}.
+         * allowed values are
+         * {@link SandboxedDetectionInitializer#INITIALIZATION_STATUS_SUCCESS},
+         * 1<->{@link SandboxedDetectionInitializer#getMaxCustomInitializationStatus()},
+         * {@link SandboxedDetectionInitializer#INITIALIZATION_STATUS_UNKNOWN}.
          */
         void onVisualQueryDetectionServiceInitialized(int status);
 
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index f53abce..259012f 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -60,7 +60,6 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
@@ -181,9 +180,6 @@
 
     private final ArrayMap<IBinder, IWallpaperEngineWrapper> mActiveEngines = new ArrayMap<>();
 
-    private Handler mBackgroundHandler;
-    private HandlerThread mBackgroundThread;
-
     static final class WallpaperCommand {
         String action;
         int x;
@@ -202,6 +198,14 @@
      */
     public class Engine {
         IWallpaperEngineWrapper mIWallpaperEngine;
+        final ArraySet<RectF> mLocalColorAreas = new ArraySet<>(4);
+        final ArraySet<RectF> mLocalColorsToAdd = new ArraySet<>(4);
+
+        // 2D matrix [x][y] to represent a page of a portion of a window
+        EngineWindowPage[] mWindowPages = new EngineWindowPage[0];
+        Bitmap mLastScreenshot;
+        int mLastWindowPage = -1;
+        private boolean mResetWindowPages;
 
         // Copies from mIWallpaperEngine.
         HandlerCaller mCaller;
@@ -262,27 +266,11 @@
 
         final Object mLock = new Object();
         boolean mOffsetMessageEnqueued;
-
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         float mPendingXOffset;
         float mPendingYOffset;
         float mPendingXOffsetStep;
         float mPendingYOffsetStep;
-
-        /**
-         * local color extraction related fields
-         * to be used by the background thread only (except the atomic boolean)
-         */
-        final ArraySet<RectF> mLocalColorAreas = new ArraySet<>(4);
-        final ArraySet<RectF> mLocalColorsToAdd = new ArraySet<>(4);
-        private long mLastProcessLocalColorsTimestamp;
-        private AtomicBoolean mProcessLocalColorsPending = new AtomicBoolean(false);
-        private int mPixelCopyCount = 0;
-        // 2D matrix [x][y] to represent a page of a portion of a window
-        EngineWindowPage[] mWindowPages = new EngineWindowPage[0];
-        Bitmap mLastScreenshot;
-        private boolean mResetWindowPages;
-
         boolean mPendingSync;
         MotionEvent mPendingMove;
         boolean mIsInAmbientMode;
@@ -291,8 +279,12 @@
         private long mLastColorInvalidation;
         private final Runnable mNotifyColorsChanged = this::notifyColorsChanged;
 
+        // used to throttle processLocalColors
+        private long mLastProcessLocalColorsTimestamp;
+        private AtomicBoolean mProcessLocalColorsPending = new AtomicBoolean(false);
         private final Supplier<Long> mClockFunction;
         private final Handler mHandler;
+
         private Display mDisplay;
         private Context mDisplayContext;
         private int mDisplayState;
@@ -862,7 +854,7 @@
                             + "was not established.");
                 }
                 mResetWindowPages = true;
-                processLocalColors();
+                processLocalColors(mPendingXOffset, mPendingXOffsetStep);
             } catch (RemoteException e) {
                 Log.w(TAG, "Can't notify system because wallpaper connection was lost.", e);
             }
@@ -1400,7 +1392,7 @@
                             resetWindowPages();
                             mSession.finishDrawing(mWindow, null /* postDrawTransaction */,
                                                    Integer.MAX_VALUE);
-                            processLocalColors();
+                            processLocalColors(mPendingXOffset, mPendingXOffsetStep);
                         }
                         reposition();
                         reportEngineShown(shouldWaitForEngineShown());
@@ -1543,14 +1535,14 @@
         void doVisibilityChanged(boolean visible) {
             if (!mDestroyed) {
                 mVisible = visible;
-                reportVisibility();
-                if (mReportedVisible) processLocalColors();
+                reportVisibility(false);
+                if (mReportedVisible) processLocalColors(mPendingXOffset, mPendingXOffsetStep);
             } else {
                 AnimationHandler.requestAnimatorsEnabled(visible, this);
             }
         }
 
-        void reportVisibility() {
+        void reportVisibility(boolean forceReport) {
             if (mScreenshotSurfaceControl != null && mVisible) {
                 if (DEBUG) Log.v(TAG, "Frozen so don't report visibility change");
                 return;
@@ -1558,10 +1550,29 @@
             if (!mDestroyed) {
                 mDisplayState = mDisplay == null ? Display.STATE_UNKNOWN : mDisplay.getState();
                 boolean visible = mVisible && mDisplayState != Display.STATE_OFF;
-                if (mReportedVisible != visible) {
+                if (DEBUG) {
+                    Log.v(
+                            TAG,
+                            "reportVisibility"
+                                    + " mReportedVisible="
+                                    + mReportedVisible
+                                    + " mVisible="
+                                    + mVisible
+                                    + " mDisplayState="
+                                    + mDisplayState);
+                }
+                if (mReportedVisible != visible || forceReport) {
                     mReportedVisible = visible;
-                    if (DEBUG) Log.v(TAG, "onVisibilityChanged(" + visible
-                            + "): " + this);
+                    if (DEBUG) {
+                        Log.v(
+                                TAG,
+                                "onVisibilityChanged("
+                                        + visible
+                                        + "): "
+                                        + this
+                                        + " forceReport="
+                                        + forceReport);
+                    }
                     if (visible) {
                         // If becoming visible, in preview mode the surface
                         // may have been destroyed so now we need to make
@@ -1628,41 +1639,31 @@
             }
 
             // setup local color extraction data
-            processLocalColors();
+            processLocalColors(xOffset, xOffsetStep);
         }
 
         /**
          * Thread-safe util to call {@link #processLocalColorsInternal} with a minimum interval of
          * {@link #PROCESS_LOCAL_COLORS_INTERVAL_MS} between two calls.
          */
-        private void processLocalColors() {
+        private void processLocalColors(float xOffset, float xOffsetStep) {
             if (mProcessLocalColorsPending.compareAndSet(false, true)) {
                 final long now = mClockFunction.get();
                 final long timeSinceLastColorProcess = now - mLastProcessLocalColorsTimestamp;
                 final long timeToWait = Math.max(0,
                         PROCESS_LOCAL_COLORS_INTERVAL_MS - timeSinceLastColorProcess);
 
-                mBackgroundHandler.postDelayed(() -> {
+                mHandler.postDelayed(() -> {
                     mLastProcessLocalColorsTimestamp = now + timeToWait;
                     mProcessLocalColorsPending.set(false);
-                    processLocalColorsInternal();
+                    processLocalColorsInternal(xOffset, xOffsetStep);
                 }, timeToWait);
             }
         }
 
-        private void processLocalColorsInternal() {
+        private void processLocalColorsInternal(float xOffset, float xOffsetStep) {
             // implemented by the wallpaper
             if (supportsLocalColorExtraction()) return;
-            assertBackgroundThread();
-            float xOffset;
-            float xOffsetStep;
-            float wallpaperDimAmount;
-            synchronized (mLock) {
-                xOffset = mPendingXOffset;
-                xOffsetStep = mPendingXOffsetStep;
-                wallpaperDimAmount = mWallpaperDimAmount;
-            }
-
             if (DEBUG) {
                 Log.d(TAG, "processLocalColors " + xOffset + " of step "
                         + xOffsetStep);
@@ -1725,7 +1726,7 @@
                 xPage = mWindowPages.length - 1;
             }
             current = mWindowPages[xPage];
-            updatePage(current, xPage, xPages, wallpaperDimAmount);
+            updatePage(current, xPage, xPages, finalXOffsetStep);
             Trace.endSection();
         }
 
@@ -1745,23 +1746,16 @@
             }
         }
 
-        /**
-         * Must be called with the surface lock held.
-         * Must not be called if the surface is not valid.
-         * Will unlock the surface when done using it.
-         */
         void updatePage(EngineWindowPage currentPage, int pageIndx, int numPages,
-                float wallpaperDimAmount) {
-
-            assertBackgroundThread();
-
+                float xOffsetStep) {
             // in case the clock is zero, we start with negative time
             long current = SystemClock.elapsedRealtime() - DEFAULT_UPDATE_SCREENSHOT_DURATION;
             long lapsed = current - currentPage.getLastUpdateTime();
             // Always update the page when the last update time is <= 0
             // This is important especially when the device first boots
-            if (lapsed < DEFAULT_UPDATE_SCREENSHOT_DURATION) return;
-
+            if (lapsed < DEFAULT_UPDATE_SCREENSHOT_DURATION) {
+                return;
+            }
             Surface surface = mSurfaceHolder.getSurface();
             if (!surface.isValid()) return;
             boolean widthIsLarger = mSurfaceSize.x > mSurfaceSize.y;
@@ -1777,42 +1771,33 @@
             Bitmap screenShot = Bitmap.createBitmap(width, height,
                     Bitmap.Config.ARGB_8888);
             final Bitmap finalScreenShot = screenShot;
-            final String pixelCopySectionName = "WallpaperService#pixelCopy";
-            final int pixelCopyCount = mPixelCopyCount++;
-            Trace.beginAsyncSection(pixelCopySectionName, pixelCopyCount);
-            try {
-                PixelCopy.request(surface, screenShot, (res) -> {
-                    Trace.endAsyncSection(pixelCopySectionName, pixelCopyCount);
-                    if (DEBUG) Log.d(TAG, "result of pixel copy is " + res);
-                    if (res != PixelCopy.SUCCESS) {
-                        Bitmap lastBitmap = currentPage.getBitmap();
-                        // assign the last bitmap taken for now
-                        currentPage.setBitmap(mLastScreenshot);
-                        Bitmap lastScreenshot = mLastScreenshot;
-                        if (lastScreenshot != null && !lastScreenshot.isRecycled()
-                                && !Objects.equals(lastBitmap, lastScreenshot)) {
-                            updatePageColors(currentPage, pageIndx, numPages, wallpaperDimAmount);
-                        }
-                    } else {
-                        mLastScreenshot = finalScreenShot;
-                        // going to hold this lock for a while
-                        currentPage.setBitmap(finalScreenShot);
-                        currentPage.setLastUpdateTime(current);
-                        updatePageColors(currentPage, pageIndx, numPages, wallpaperDimAmount);
+            Trace.beginSection("WallpaperService#pixelCopy");
+            PixelCopy.request(surface, screenShot, (res) -> {
+                Trace.endSection();
+                if (DEBUG) Log.d(TAG, "result of pixel copy is " + res);
+                if (res != PixelCopy.SUCCESS) {
+                    Bitmap lastBitmap = currentPage.getBitmap();
+                    // assign the last bitmap taken for now
+                    currentPage.setBitmap(mLastScreenshot);
+                    Bitmap lastScreenshot = mLastScreenshot;
+                    if (lastScreenshot != null && !lastScreenshot.isRecycled()
+                            && !Objects.equals(lastBitmap, lastScreenshot)) {
+                        updatePageColors(currentPage, pageIndx, numPages, xOffsetStep);
                     }
-                }, mBackgroundHandler);
-            } catch (IllegalArgumentException e) {
-                // this can potentially happen if the surface is invalidated right between the
-                // surface.isValid() check and the PixelCopy operation.
-                // in this case, stop: we'll compute colors on the next processLocalColors call.
-                Log.i(TAG, "Cancelling processLocalColors: exception caught during PixelCopy");
-            }
+                } else {
+                    mLastScreenshot = finalScreenShot;
+                    // going to hold this lock for a while
+                    currentPage.setBitmap(finalScreenShot);
+                    currentPage.setLastUpdateTime(current);
+                    updatePageColors(currentPage, pageIndx, numPages, xOffsetStep);
+                }
+            }, mHandler);
+
         }
         // locked by the passed page
-        private void updatePageColors(
-                EngineWindowPage page, int pageIndx, int numPages, float wallpaperDimAmount) {
+        private void updatePageColors(EngineWindowPage page, int pageIndx, int numPages,
+                float xOffsetStep) {
             if (page.getBitmap() == null) return;
-            assertBackgroundThread();
             Trace.beginSection("WallpaperService#updatePageColors");
             if (DEBUG) {
                 Log.d(TAG, "updatePageColorsLocked for page " + pageIndx + " with areas "
@@ -1834,7 +1819,7 @@
                     Log.e(TAG, "Error creating page local color bitmap", e);
                     continue;
                 }
-                WallpaperColors color = WallpaperColors.fromBitmap(target, wallpaperDimAmount);
+                WallpaperColors color = WallpaperColors.fromBitmap(target, mWallpaperDimAmount);
                 target.recycle();
                 WallpaperColors currentColor = page.getColors(area);
 
@@ -1851,26 +1836,17 @@
                                 + " local color callback for area" + area + " for page " + pageIndx
                                 + " of " + numPages);
                     }
-                    mHandler.post(() -> {
-                        try {
-                            mConnection.onLocalWallpaperColorsChanged(area, color,
-                                    mDisplayContext.getDisplayId());
-                        } catch (RemoteException e) {
-                            Log.e(TAG, "Error calling Connection.onLocalWallpaperColorsChanged", e);
-                        }
-                    });
+                    try {
+                        mConnection.onLocalWallpaperColorsChanged(area, color,
+                                mDisplayContext.getDisplayId());
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Error calling Connection.onLocalWallpaperColorsChanged", e);
+                    }
                 }
             }
             Trace.endSection();
         }
 
-        private void assertBackgroundThread() {
-            if (!mBackgroundHandler.getLooper().isCurrentThread()) {
-                throw new IllegalStateException(
-                        "ProcessLocalColors should be called from the background thread");
-            }
-        }
-
         private RectF generateSubRect(RectF in, int pageInx, int numPages) {
             float minLeft = (float) (pageInx) / (float) (numPages);
             float maxRight = (float) (pageInx + 1) / (float) (numPages);
@@ -1895,6 +1871,7 @@
             if (supportsLocalColorExtraction()) return;
             if (!mResetWindowPages) return;
             mResetWindowPages = false;
+            mLastWindowPage = -1;
             for (int i = 0; i < mWindowPages.length; i++) {
                 mWindowPages[i].setLastUpdateTime(0L);
             }
@@ -1920,10 +1897,12 @@
             if (DEBUG) {
                 Log.d(TAG, "addLocalColorsAreas adding local color areas " + regions);
             }
-            mBackgroundHandler.post(() -> {
+            mHandler.post(() -> {
                 mLocalColorsToAdd.addAll(regions);
-                processLocalColors();
+                processLocalColors(mPendingXOffset, mPendingYOffset);
             });
+
+
         }
 
         /**
@@ -1933,7 +1912,7 @@
          */
         public void removeLocalColorsAreas(@NonNull List<RectF> regions) {
             if (supportsLocalColorExtraction()) return;
-            mBackgroundHandler.post(() -> {
+            mHandler.post(() -> {
                 float step = mPendingXOffsetStep;
                 mLocalColorsToAdd.removeAll(regions);
                 mLocalColorAreas.removeAll(regions);
@@ -2205,22 +2184,22 @@
             }
         }
 
-        private final DisplayListener mDisplayListener = new DisplayListener() {
-            @Override
-            public void onDisplayChanged(int displayId) {
-                if (mDisplay.getDisplayId() == displayId) {
-                    reportVisibility();
-                }
-            }
+        private final DisplayListener mDisplayListener =
+                new DisplayListener() {
+                    @Override
+                    public void onDisplayChanged(int displayId) {
+                        if (mDisplay.getDisplayId() == displayId) {
+                            boolean forceReport = mDisplay.getState() != Display.STATE_DOZE_SUSPEND;
+                            reportVisibility(forceReport);
+                        }
+                    }
 
-            @Override
-            public void onDisplayRemoved(int displayId) {
-            }
+                    @Override
+                    public void onDisplayRemoved(int displayId) {}
 
-            @Override
-            public void onDisplayAdded(int displayId) {
-            }
-        };
+                    @Override
+                    public void onDisplayAdded(int displayId) {}
+                };
 
         private Surface getOrCreateBLASTSurface(int width, int height, int format) {
             Surface ret = null;
@@ -2599,9 +2578,6 @@
     @Override
     public void onCreate() {
         Trace.beginSection("WPMS.onCreate");
-        mBackgroundThread = new HandlerThread("DefaultWallpaperLocalColorExtractor");
-        mBackgroundThread.start();
-        mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
         super.onCreate();
         Trace.endSection();
     }
@@ -2614,7 +2590,6 @@
             engineWrapper.destroy();
         }
         mActiveEngines.clear();
-        mBackgroundThread.quitSafely();
         Trace.endSection();
     }
 
diff --git a/core/java/android/speech/IRecognitionService.aidl b/core/java/android/speech/IRecognitionService.aidl
index 3134dcd..1148fe3 100644
--- a/core/java/android/speech/IRecognitionService.aidl
+++ b/core/java/android/speech/IRecognitionService.aidl
@@ -78,23 +78,10 @@
      * information see {@link #checkRecognitionSupport},  {@link #startListening} and
      * {@link RecognizerIntent}.
      *
-     * Progress can be monitord by calling {@link #setModelDownloadListener} before a trigger.
+     * Progress updates can be received via {@link #IModelDownloadListener}.
      */
-    void triggerModelDownload(in Intent recognizerIntent, in AttributionSource attributionSource);
-
-    /**
-     * Sets listener to received download progress updates. Clients still have to call
-     * {@link #triggerModelDownload} to trigger a model download.
-     */
-    void setModelDownloadListener(
+    void triggerModelDownload(
         in Intent recognizerIntent,
         in AttributionSource attributionSource,
         in IModelDownloadListener listener);
-
-    /**
-     * Clears the listener for model download events attached to a recognitionIntent if any.
-     */
-    void clearModelDownloadListener(
-        in Intent recognizerIntent,
-        in AttributionSource attributionSource);
 }
diff --git a/core/java/android/speech/ModelDownloadListener.java b/core/java/android/speech/ModelDownloadListener.java
index 6c24399..a58ec90c 100644
--- a/core/java/android/speech/ModelDownloadListener.java
+++ b/core/java/android/speech/ModelDownloadListener.java
@@ -22,20 +22,27 @@
  */
 public interface ModelDownloadListener {
     /**
-     * Called by {@link RecognitionService} when there's an update on the download progress.
+     * Called by {@link RecognitionService} only if the download has started after the request.
      *
-     * <p>RecognitionService will call this zero or more times during the download.</p>
+     * <p> The number of calls to this method varies depending of the {@link RecognitionService}
+     * implementation. If the download finished quickly enough, {@link #onSuccess()} may be called
+     * directly. In other cases, this method may be called any number of times during the download.
+     *
+     * @param completedPercent the percentage of download that is completed
      */
     void onProgress(int completedPercent);
 
     /**
-     * Called when {@link RecognitionService} completed the download and it can now be used to
-     * satisfy recognition requests.
+     * This method is called:
+     * <li> if the model is already available;
+     * <li> if the {@link RecognitionService} has started and completed the download.
+     *
+     * <p> Once this method is called, the model can be safely used to satisfy recognition requests.
      */
     void onSuccess();
 
     /**
-     * Called when {@link RecognitionService} scheduled the download but won't satisfy it
+     * Called when {@link RecognitionService} scheduled the download, but won't satisfy it
      * immediately. There will be no further updates on this listener.
      */
     void onScheduled();
diff --git a/core/java/android/speech/RecognitionService.java b/core/java/android/speech/RecognitionService.java
index 4ecec8f..9656f36 100644
--- a/core/java/android/speech/RecognitionService.java
+++ b/core/java/android/speech/RecognitionService.java
@@ -36,9 +36,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
-import android.text.TextUtils;
 import android.util.Log;
-import android.util.Pair;
 
 import com.android.internal.util.function.pooled.PooledLambda;
 
@@ -93,10 +91,6 @@
 
     private static final int MSG_TRIGGER_MODEL_DOWNLOAD = 6;
 
-    private static final int MSG_SET_MODEL_DOWNLOAD_LISTENER = 7;
-
-    private static final int MSG_CLEAR_MODEL_DOWNLOAD_LISTENER = 8;
-
     private final Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
@@ -120,21 +114,11 @@
                             checkArgs.mIntent, checkArgs.callback, checkArgs.mAttributionSource);
                     break;
                 case MSG_TRIGGER_MODEL_DOWNLOAD:
-                    Pair<Intent, AttributionSource> params =
-                            (Pair<Intent, AttributionSource>) msg.obj;
-                    dispatchTriggerModelDownload(params.first, params.second);
-                    break;
-                case MSG_SET_MODEL_DOWNLOAD_LISTENER:
-                    ModelDownloadListenerArgs dListenerArgs = (ModelDownloadListenerArgs) msg.obj;
-                    dispatchSetModelDownloadListener(
-                            dListenerArgs.mIntent,
-                            dListenerArgs.mListener,
-                            dListenerArgs.mAttributionSource);
-                    break;
-                case MSG_CLEAR_MODEL_DOWNLOAD_LISTENER:
-                    Pair<Intent, AttributionSource> clearDlPair =
-                            (Pair<Intent, AttributionSource>) msg.obj;
-                    dispatchClearModelDownloadListener(clearDlPair.first, clearDlPair.second);
+                    ModelDownloadArgs modelDownloadArgs = (ModelDownloadArgs) msg.obj;
+                    dispatchTriggerModelDownload(
+                            modelDownloadArgs.mIntent,
+                            modelDownloadArgs.mAttributionSource,
+                            modelDownloadArgs.mListener);
                     break;
             }
         }
@@ -239,59 +223,52 @@
 
     private void dispatchTriggerModelDownload(
             Intent intent,
-            AttributionSource attributionSource) {
-        RecognitionService.this.onTriggerModelDownload(intent, attributionSource);
-    }
-
-    private void dispatchSetModelDownloadListener(
-            Intent intent,
-            IModelDownloadListener listener,
-            AttributionSource attributionSource) {
-        RecognitionService.this.setModelDownloadListener(
-                intent,
-                attributionSource,
-                new ModelDownloadListener() {
-                    @Override
-                    public void onProgress(int completedPercent) {
-                        try {
-                            listener.onProgress(completedPercent);
-                        } catch (RemoteException e) {
-                            throw e.rethrowFromSystemServer();
+            AttributionSource attributionSource,
+            IModelDownloadListener listener) {
+        if (listener == null) {
+            RecognitionService.this.onTriggerModelDownload(intent, attributionSource);
+        } else {
+            RecognitionService.this.onTriggerModelDownload(
+                    intent,
+                    attributionSource,
+                    new ModelDownloadListener() {
+                        @Override
+                        public void onProgress(int completedPercent) {
+                            try {
+                                listener.onProgress(completedPercent);
+                            } catch (RemoteException e) {
+                                throw e.rethrowFromSystemServer();
+                            }
                         }
-                    }
 
-                    @Override
-                    public void onSuccess() {
-                        try {
-                            listener.onSuccess();
-                        } catch (RemoteException e) {
-                            throw e.rethrowFromSystemServer();
+                        @Override
+                        public void onSuccess() {
+                            try {
+                                listener.onSuccess();
+                            } catch (RemoteException e) {
+                                throw e.rethrowFromSystemServer();
+                            }
                         }
-                    }
 
-                    @Override
-                    public void onScheduled() {
-                        try {
-                            listener.onScheduled();
-                        } catch (RemoteException e) {
-                            throw e.rethrowFromSystemServer();
+                        @Override
+                        public void onScheduled() {
+                            try {
+                                listener.onScheduled();
+                            } catch (RemoteException e) {
+                                throw e.rethrowFromSystemServer();
+                            }
                         }
-                    }
 
-                    @Override
-                    public void onError(int error) {
-                        try {
-                            listener.onError(error);
-                        } catch (RemoteException e) {
-                            throw e.rethrowFromSystemServer();
+                        @Override
+                        public void onError(int error) {
+                            try {
+                                listener.onError(error);
+                            } catch (RemoteException e) {
+                                throw e.rethrowFromSystemServer();
+                            }
                         }
-                    }
-                });
-    }
-
-    private void dispatchClearModelDownloadListener(
-            Intent intent, AttributionSource attributionSource) {
-        RecognitionService.this.clearModelDownloadListener(intent, attributionSource);
+                    });
+        }
     }
 
     private static class StartListeningArgs {
@@ -323,17 +300,18 @@
         }
     }
 
-    private static class ModelDownloadListenerArgs {
+    private static class ModelDownloadArgs {
         final Intent mIntent;
-        final IModelDownloadListener mListener;
         final AttributionSource mAttributionSource;
+        @Nullable final IModelDownloadListener mListener;
 
-        private ModelDownloadListenerArgs(Intent intent,
-                IModelDownloadListener listener,
-                AttributionSource attributionSource) {
-            mIntent = intent;
+        private ModelDownloadArgs(
+                Intent intent,
+                AttributionSource attributionSource,
+                @Nullable IModelDownloadListener listener) {
+            this.mIntent = intent;
+            this.mAttributionSource = attributionSource;
             this.mListener = listener;
-            mAttributionSource = attributionSource;
         }
     }
 
@@ -443,38 +421,39 @@
     }
 
     /**
-     * Sets a {@link ModelDownloadListener} to receive progress updates after
-     * {@link #onTriggerModelDownload} calls.
+     * Requests the download of the recognizer support for {@code recognizerIntent}.
      *
-     * @param recognizerIntent the request to monitor model download progress for.
-     * @param modelDownloadListener the listener to keep updated.
+     * <p> Provides the calling {@link AttributionSource} to the service implementation so that
+     * permissions and bandwidth could be correctly blamed.
+     *
+     * <p> Client will receive the progress updates via the given {@link ModelDownloadListener}:
+     *
+     * <li> If the model is already available, {@link ModelDownloadListener#onSuccess()} will be
+     * called directly. The model can be safely used afterwards.
+     *
+     * <li> If the {@link RecognitionService} has started the download,
+     * {@link ModelDownloadListener#onProgress(int)} will be called an unspecified (zero or more)
+     * number of times until the download is complete.
+     * When the download finishes, {@link ModelDownloadListener#onSuccess()} will be called.
+     * The model can be safely used afterwards.
+     *
+     * <li> If the {@link RecognitionService} has only scheduled the download, but won't satisfy it
+     * immediately, {@link ModelDownloadListener#onScheduled()} will be called.
+     * There will be no further updates on this listener.
+     *
+     * <li> If the request fails at any time due to a network or scheduling error,
+     * {@link ModelDownloadListener#onError(int)} will be called.
+     *
+     * @param recognizerIntent contains parameters for the recognition to be performed. The intent
+     *        may also contain optional extras, see {@link RecognizerIntent}.
+     * @param attributionSource the attribution source of the caller.
+     * @param listener on which to receive updates about the model download request.
      */
-    public void setModelDownloadListener(
+    public void onTriggerModelDownload(
             @NonNull Intent recognizerIntent,
             @NonNull AttributionSource attributionSource,
-            @NonNull ModelDownloadListener modelDownloadListener) {
-        if (DBG) {
-            Log.i(TAG, TextUtils.formatSimple(
-                    "#setModelDownloadListener [%s] [%s]",
-                    recognizerIntent,
-                    modelDownloadListener));
-        }
-        modelDownloadListener.onError(SpeechRecognizer.ERROR_CANNOT_LISTEN_TO_DOWNLOAD_EVENTS);
-    }
-
-    /**
-     * Clears the {@link ModelDownloadListener} set to receive progress updates for the given
-     * {@code recognizerIntent}, if any.
-     *
-     * @param recognizerIntent the request to monitor model download progress for.
-     */
-    public void clearModelDownloadListener(
-            @NonNull Intent recognizerIntent,
-            @NonNull AttributionSource attributionSource) {
-        if (DBG) {
-            Log.i(TAG, TextUtils.formatSimple(
-                    "#clearModelDownloadListener [%s]", recognizerIntent));
-        }
+            @NonNull ModelDownloadListener listener) {
+        listener.onError(SpeechRecognizer.ERROR_CANNOT_LISTEN_TO_DOWNLOAD_EVENTS);
     }
 
     @Override
@@ -815,41 +794,18 @@
 
         @Override
         public void triggerModelDownload(
-                Intent recognizerIntent, @NonNull AttributionSource attributionSource) {
+                Intent recognizerIntent,
+                @NonNull AttributionSource attributionSource,
+                IModelDownloadListener listener) {
             final RecognitionService service = mServiceRef.get();
             if (service != null) {
                 service.mHandler.sendMessage(
                         Message.obtain(
                                 service.mHandler, MSG_TRIGGER_MODEL_DOWNLOAD,
-                                Pair.create(recognizerIntent, attributionSource)));
-            }
-        }
-
-        @Override
-        public void setModelDownloadListener(
-                Intent recognizerIntent,
-                AttributionSource attributionSource,
-                IModelDownloadListener listener) throws RemoteException {
-            final RecognitionService service = mServiceRef.get();
-            if (service != null) {
-                service.mHandler.sendMessage(
-                        Message.obtain(service.mHandler, MSG_SET_MODEL_DOWNLOAD_LISTENER,
-                                new ModelDownloadListenerArgs(
+                                new ModelDownloadArgs(
                                         recognizerIntent,
-                                        listener,
-                                        attributionSource)));
-            }
-        }
-
-        @Override
-        public void clearModelDownloadListener(
-                Intent recognizerIntent,
-                AttributionSource attributionSource) throws RemoteException {
-            final RecognitionService service = mServiceRef.get();
-            if (service != null) {
-                service.mHandler.sendMessage(
-                        Message.obtain(service.mHandler, MSG_CLEAR_MODEL_DOWNLOAD_LISTENER,
-                                Pair.create(recognizerIntent, attributionSource)));
+                                        attributionSource,
+                                        listener)));
             }
         }
 
diff --git a/core/java/android/speech/SpeechRecognizer.java b/core/java/android/speech/SpeechRecognizer.java
index 76eb09e..dacb25c 100644
--- a/core/java/android/speech/SpeechRecognizer.java
+++ b/core/java/android/speech/SpeechRecognizer.java
@@ -297,8 +297,6 @@
     private static final int MSG_SET_TEMPORARY_ON_DEVICE_COMPONENT = 5;
     private static final int MSG_CHECK_RECOGNITION_SUPPORT = 6;
     private static final int MSG_TRIGGER_MODEL_DOWNLOAD = 7;
-    private static final int MSG_SET_MODEL_DOWNLOAD_LISTENER = 8;
-    private static final int MSG_CLEAR_MODEL_DOWNLOAD_LISTENER = 9;
 
     /** The actual RecognitionService endpoint */
     private IRecognitionService mService;
@@ -341,19 +339,13 @@
                             args.mIntent, args.mCallbackExecutor, args.mCallback);
                     break;
                 case MSG_TRIGGER_MODEL_DOWNLOAD:
-                    handleTriggerModelDownload((Intent) msg.obj);
-                    break;
-                case MSG_SET_MODEL_DOWNLOAD_LISTENER:
                     ModelDownloadListenerArgs modelDownloadListenerArgs =
                             (ModelDownloadListenerArgs) msg.obj;
-                    handleSetModelDownloadListener(
+                    handleTriggerModelDownload(
                             modelDownloadListenerArgs.mIntent,
                             modelDownloadListenerArgs.mExecutor,
                             modelDownloadListenerArgs.mModelDownloadListener);
                     break;
-                case MSG_CLEAR_MODEL_DOWNLOAD_LISTENER:
-                    handleClearModelDownloadListener((Intent) msg.obj);
-                    break;
             }
         }
     };
@@ -657,17 +649,13 @@
      * user interaction to approve the download. Callers can verify the status of the request via
      * {@link #checkRecognitionSupport(Intent, Executor, RecognitionSupportCallback)}.
      *
-     * <p>Listeners set via
-     * {@link #setModelDownloadListener(Intent, Executor, ModelDownloadListener)} will receive
-     * updates about this download request.</p>
-     *
      * @param recognizerIntent contains parameters for the recognition to be performed. The intent
      *        may also contain optional extras, see {@link RecognizerIntent}.
      */
     public void triggerModelDownload(@NonNull Intent recognizerIntent) {
         Objects.requireNonNull(recognizerIntent, "intent must not be null");
         if (DBG) {
-            Slog.i(TAG, "#triggerModelDownload called");
+            Slog.i(TAG, "#triggerModelDownload without a listener called");
             if (mService == null) {
                 Slog.i(TAG, "Connection is not established yet");
             }
@@ -676,23 +664,47 @@
             // First time connection: first establish a connection, then dispatch.
             connectToSystemService();
         }
-        putMessage(Message.obtain(mHandler, MSG_TRIGGER_MODEL_DOWNLOAD, recognizerIntent));
+        putMessage(Message.obtain(
+                mHandler, MSG_TRIGGER_MODEL_DOWNLOAD,
+                new ModelDownloadListenerArgs(recognizerIntent, null, null)));
     }
 
     /**
-     * Sets a listener to model download updates. Clients will have to call this method before
-     * {@link #triggerModelDownload(Intent)}.
+     * Attempts to download the support for the given {@code recognizerIntent}. This might trigger
+     * user interaction to approve the download. Callers can verify the status of the request via
+     * {@link #checkRecognitionSupport(Intent, Executor, RecognitionSupportCallback)}.
      *
-     * @param recognizerIntent the request to monitor support for.
+     * <p> The updates about the model download request are received via the given
+     * {@link ModelDownloadListener}:
+     *
+     * <li> If the model is already available, {@link ModelDownloadListener#onSuccess()} will be
+     * called directly. The model can be safely used afterwards.
+     *
+     * <li> If the {@link RecognitionService} has started the download,
+     * {@link ModelDownloadListener#onProgress(int)} will be called an unspecified (zero or more)
+     * number of times until the download is complete.
+     * When the download finishes, {@link ModelDownloadListener#onSuccess()} will be called.
+     * The model can be safely used afterwards.
+     *
+     * <li> If the {@link RecognitionService} has only scheduled the download, but won't satisfy it
+     * immediately, {@link ModelDownloadListener#onScheduled()} will be called.
+     * There will be no further updates on this listener.
+     *
+     * <li> If the request fails at any time due to a network or scheduling error,
+     * {@link ModelDownloadListener#onError(int)} will be called.
+     *
+     * @param recognizerIntent contains parameters for the recognition to be performed. The intent
+     *        may also contain optional extras, see {@link RecognizerIntent}.
+     * @param executor for dispatching listener callbacks
      * @param listener on which to receive updates about the model download request.
      */
-    public void setModelDownloadListener(
+    public void triggerModelDownload(
             @NonNull Intent recognizerIntent,
             @NonNull @CallbackExecutor Executor executor,
             @NonNull ModelDownloadListener listener) {
         Objects.requireNonNull(recognizerIntent, "intent must not be null");
         if (DBG) {
-            Slog.i(TAG, "#setModelDownloadListener called");
+            Slog.i(TAG, "#triggerModelDownload with a listener called");
             if (mService == null) {
                 Slog.i(TAG, "Connection is not established yet");
             }
@@ -702,32 +714,11 @@
             connectToSystemService();
         }
         putMessage(Message.obtain(
-                mHandler, MSG_SET_MODEL_DOWNLOAD_LISTENER,
+                mHandler, MSG_TRIGGER_MODEL_DOWNLOAD,
                 new ModelDownloadListenerArgs(recognizerIntent, executor, listener)));
     }
 
     /**
-     * Clears the listener for model download updates if any.
-     *
-     * @param recognizerIntent the request to monitor support for.
-     */
-    public void clearModelDownloadListener(@NonNull Intent recognizerIntent) {
-        Objects.requireNonNull(recognizerIntent, "intent must not be null");
-        if (DBG) {
-            Slog.i(TAG, "#clearModelDownloadListener called");
-            if (mService == null) {
-                Slog.i(TAG, "Connection is not established yet");
-            }
-        }
-        if (mService == null) {
-            // First time connection: first establish a connection, then dispatch.
-            connectToSystemService();
-        }
-        putMessage(Message.obtain(
-                mHandler, MSG_CLEAR_MODEL_DOWNLOAD_LISTENER, recognizerIntent));
-    }
-
-    /**
      * Sets a temporary component to power on-device speech recognizer.
      *
      * <p>This is only expected to be called in tests, system would reject calls from client apps.
@@ -836,51 +827,36 @@
         }
     }
 
-    private void handleTriggerModelDownload(Intent recognizerIntent) {
-        if (!maybeInitializeManagerService()) {
-            return;
-        }
-        try {
-            mService.triggerModelDownload(recognizerIntent, mContext.getAttributionSource());
-        } catch (final RemoteException e) {
-            Log.e(TAG, "downloadModel() failed", e);
-            mListener.onError(ERROR_CLIENT);
-        }
-    }
-
-    private void handleSetModelDownloadListener(
+    private void handleTriggerModelDownload(
             Intent recognizerIntent,
-            Executor callbackExecutor,
+            @Nullable Executor callbackExecutor,
             @Nullable ModelDownloadListener modelDownloadListener) {
         if (!maybeInitializeManagerService()) {
             return;
         }
-        try {
-            InternalModelDownloadListener listener =
-                    modelDownloadListener == null
-                            ? null
-                            : new InternalModelDownloadListener(
-                                    callbackExecutor,
-                                    modelDownloadListener);
-            mService.setModelDownloadListener(
-                    recognizerIntent, mContext.getAttributionSource(), listener);
-            if (DBG) Log.d(TAG, "setModelDownloadListener()");
-        } catch (final RemoteException e) {
-            Log.e(TAG, "setModelDownloadListener() failed", e);
-            callbackExecutor.execute(() -> modelDownloadListener.onError(ERROR_CLIENT));
-        }
-    }
 
-    private void handleClearModelDownloadListener(Intent recognizerIntent) {
-        if (!maybeInitializeManagerService()) {
-            return;
+        // Trigger model download without a listener.
+        if (modelDownloadListener == null) {
+            try {
+                mService.triggerModelDownload(
+                        recognizerIntent, mContext.getAttributionSource(), null);
+                if (DBG) Log.d(TAG, "triggerModelDownload() without a listener");
+            } catch (final RemoteException e) {
+                Log.e(TAG, "triggerModelDownload() without a listener failed", e);
+                mListener.onError(ERROR_CLIENT);
+            }
         }
-        try {
-            mService.clearModelDownloadListener(
-                    recognizerIntent, mContext.getAttributionSource());
-            if (DBG) Log.d(TAG, "clearModelDownloadListener()");
-        } catch (final RemoteException e) {
-            Log.e(TAG, "clearModelDownloadListener() failed", e);
+        // Trigger model download with a listener.
+        else {
+            try {
+                mService.triggerModelDownload(
+                        recognizerIntent, mContext.getAttributionSource(),
+                        new InternalModelDownloadListener(callbackExecutor, modelDownloadListener));
+                if (DBG) Log.d(TAG, "triggerModelDownload() with a listener");
+            } catch (final RemoteException e) {
+                Log.e(TAG, "triggerModelDownload() with a listener failed", e);
+                callbackExecutor.execute(() -> modelDownloadListener.onError(ERROR_CLIENT));
+            }
         }
     }
 
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index f648ad4..434b1c7 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -53,9 +53,7 @@
 
 import java.lang.ref.WeakReference;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 import java.util.WeakHashMap;
@@ -83,15 +81,16 @@
      * A mapping between {@link SubscriptionManager.OnSubscriptionsChangedListener} and
      * its callback IOnSubscriptionsChangedListener.
      */
-    private final Map<SubscriptionManager.OnSubscriptionsChangedListener,
-                IOnSubscriptionsChangedListener> mSubscriptionChangedListenerMap = new HashMap<>();
+    private final ConcurrentHashMap<SubscriptionManager.OnSubscriptionsChangedListener,
+            IOnSubscriptionsChangedListener>
+                    mSubscriptionChangedListenerMap = new ConcurrentHashMap<>();
     /**
      * A mapping between {@link SubscriptionManager.OnOpportunisticSubscriptionsChangedListener} and
      * its callback IOnSubscriptionsChangedListener.
      */
-    private final Map<SubscriptionManager.OnOpportunisticSubscriptionsChangedListener,
-            IOnSubscriptionsChangedListener> mOpportunisticSubscriptionChangedListenerMap
-            = new HashMap<>();
+    private final ConcurrentHashMap<SubscriptionManager.OnOpportunisticSubscriptionsChangedListener,
+            IOnSubscriptionsChangedListener>
+                    mOpportunisticSubscriptionChangedListenerMap = new ConcurrentHashMap<>();
 
     /**
      * A mapping between {@link CarrierConfigManager.CarrierConfigChangeListener} and its callback
diff --git a/core/java/android/text/GraphemeClusterSegmentFinder.java b/core/java/android/text/GraphemeClusterSegmentFinder.java
index 656774f..0f6fdaf 100644
--- a/core/java/android/text/GraphemeClusterSegmentFinder.java
+++ b/core/java/android/text/GraphemeClusterSegmentFinder.java
@@ -18,7 +18,8 @@
 
 import android.annotation.IntRange;
 import android.annotation.NonNull;
-import android.graphics.Paint;
+import android.graphics.TemporaryBuffer;
+import android.graphics.text.GraphemeBreak;
 
 /**
  * Implementation of {@code SegmentFinder} using grapheme clusters as the text segment. Whitespace
@@ -31,8 +32,8 @@
  *     Segmentation - Grapheme Cluster Boundaries</a>
  */
 public class GraphemeClusterSegmentFinder extends SegmentFinder {
-    private final CharSequence mText;
-    private final TextPaint mTextPaint;
+    private static AutoGrowArray.FloatArray sTempAdvances = null;
+    private final boolean[] mIsGraphemeBreak;
 
     /**
      * Constructs a GraphemeClusterSegmentFinder instance for the specified text which uses the
@@ -43,51 +44,73 @@
      */
     public GraphemeClusterSegmentFinder(
             @NonNull CharSequence text, @NonNull TextPaint textPaint) {
-        mText = text;
-        mTextPaint = textPaint;
+
+        if (sTempAdvances == null) {
+            sTempAdvances = new AutoGrowArray.FloatArray(text.length());
+        } else if (sTempAdvances.size() < text.length()) {
+            sTempAdvances.resize(text.length());
+        }
+
+        mIsGraphemeBreak = new boolean[text.length()];
+        float[] advances = sTempAdvances.getRawArray();
+        char[] chars = TemporaryBuffer.obtain(text.length());
+
+        TextUtils.getChars(text, 0, text.length(), chars, 0);
+
+        textPaint.getTextWidths(chars, 0, text.length(), advances);
+
+        GraphemeBreak.isGraphemeBreak(advances, chars, /* start= */ 0, /* end= */ text.length(),
+                mIsGraphemeBreak);
+        TemporaryBuffer.recycle(chars);
+    }
+
+    private int previousBoundary(@IntRange(from = 0) int offset) {
+        if (offset <= 0) return DONE;
+        do {
+            --offset;
+        } while (offset > 0 && !mIsGraphemeBreak[offset]);
+        return offset;
+    }
+
+    private int nextBoundary(@IntRange(from = 0) int offset) {
+        if (offset >= mIsGraphemeBreak.length) return DONE;
+        do {
+            ++offset;
+        } while (offset < mIsGraphemeBreak.length && !mIsGraphemeBreak[offset]);
+        return offset;
     }
 
     @Override
     public int previousStartBoundary(@IntRange(from = 0) int offset) {
-        if (offset == 0) return DONE;
-        int boundary = mTextPaint.getTextRunCursor(
-                mText, 0, mText.length(), false, offset, Paint.CURSOR_BEFORE);
-        return boundary == -1 ? DONE : boundary;
+        return previousBoundary(offset);
     }
 
     @Override
     public int previousEndBoundary(@IntRange(from = 0) int offset) {
         if (offset == 0) return DONE;
-        int boundary = mTextPaint.getTextRunCursor(
-                mText, 0, mText.length(), false, offset, Paint.CURSOR_BEFORE);
+        int boundary = previousBoundary(offset);
         // Check that there is another cursor position before, otherwise this is not a valid
         // end boundary.
-        if (mTextPaint.getTextRunCursor(
-                mText, 0, mText.length(), false, boundary, Paint.CURSOR_BEFORE) == -1) {
+        if (boundary == DONE || previousBoundary(boundary) == DONE) {
             return DONE;
         }
-        return boundary == -1 ? DONE : boundary;
+        return boundary;
     }
 
     @Override
     public int nextStartBoundary(@IntRange(from = 0) int offset) {
-        if (offset == mText.length()) return DONE;
-        int boundary = mTextPaint.getTextRunCursor(
-                mText, 0, mText.length(), false, offset, Paint.CURSOR_AFTER);
+        if (offset == mIsGraphemeBreak.length) return DONE;
+        int boundary = nextBoundary(offset);
         // Check that there is another cursor position after, otherwise this is not a valid
         // start boundary.
-        if (mTextPaint.getTextRunCursor(
-                mText, 0, mText.length(), false, boundary, Paint.CURSOR_AFTER) == -1) {
+        if (boundary == DONE || nextBoundary(boundary) == DONE) {
             return DONE;
         }
-        return boundary == -1 ? DONE : boundary;
+        return boundary;
     }
 
     @Override
     public int nextEndBoundary(@IntRange(from = 0) int offset) {
-        if (offset == mText.length()) return DONE;
-        int boundary = mTextPaint.getTextRunCursor(
-                mText, 0, mText.length(), false, offset, Paint.CURSOR_AFTER);
-        return boundary == -1 ? DONE : boundary;
+        return nextBoundary(offset);
     }
 }
diff --git a/core/java/android/text/method/QwertyKeyListener.java b/core/java/android/text/method/QwertyKeyListener.java
index b4a1e8c..c43864d 100644
--- a/core/java/android/text/method/QwertyKeyListener.java
+++ b/core/java/android/text/method/QwertyKeyListener.java
@@ -362,6 +362,15 @@
 
                 return true;
             }
+        } else if (keyCode == KeyEvent.KEYCODE_ESCAPE && event.hasNoModifiers()) {
+            // If user is in the process of composing with a dead key, and
+            // presses Escape, cancel it. We need special handling because
+            // the Escape key will not produce a Unicode character
+            if (activeStart == selStart && activeEnd == selEnd) {
+                Selection.setSelection(content, selEnd);
+                content.removeSpan(TextKeyListener.ACTIVE);
+                return true;
+            }
         }
 
         return super.onKeyDown(view, content, keyCode, event);
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index a746dc6..2ae882c 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -164,10 +164,10 @@
      */
     public static final String SETTINGS_AUDIO_ROUTING = "settings_audio_routing";
 
-    /** Flag to enable/disable flash alerts
+    /** Flag to enable/disable flash notifications
      *  @hide
      */
-    public static final String SETTINGS_FLASH_ALERTS = "settings_flash_alerts";
+    public static final String SETTINGS_FLASH_NOTIFICATIONS = "settings_flash_notifications";
 
     /**
      * Flag to disable/enable showing udfps enroll view in settings. If it's disabled, udfps enroll
@@ -232,7 +232,7 @@
         DEFAULT_FLAGS.put(SETTINGS_ACCESSIBILITY_HEARING_AID_PAGE, "false");
         DEFAULT_FLAGS.put(SETTINGS_PREFER_ACCESSIBILITY_MENU_IN_SYSTEM, "false");
         DEFAULT_FLAGS.put(SETTINGS_AUDIO_ROUTING, "false");
-        DEFAULT_FLAGS.put(SETTINGS_FLASH_ALERTS, "false");
+        DEFAULT_FLAGS.put(SETTINGS_FLASH_NOTIFICATIONS, "true");
         DEFAULT_FLAGS.put(SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, "true");
         DEFAULT_FLAGS.put(SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API, "false");
         DEFAULT_FLAGS.put(SETTINGS_REMOTE_DEVICE_CREDENTIAL_VALIDATION, "false");
diff --git a/core/java/android/util/SparseArrayMap.java b/core/java/android/util/SparseArrayMap.java
index 1a2c4df..b4e1f59 100644
--- a/core/java/android/util/SparseArrayMap.java
+++ b/core/java/android/util/SparseArrayMap.java
@@ -90,6 +90,14 @@
     }
 
     /**
+     * Removes the data for the keyIndex and mapIndex, if there was any.
+     * @hide
+     */
+    public void deleteAt(int keyIndex, int mapIndex) {
+        mData.valueAt(keyIndex).removeAt(mapIndex);
+    }
+
+    /**
      * Get the value associated with the int-K pair.
      */
     @Nullable
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 3cf56c0..6901b72 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -172,7 +172,7 @@
 
     private boolean isVisibleToAccessibilityService(View view) {
         return view != null && (mA11yManager.isRequestFromAccessibilityTool()
-                || !view.isAccessibilityDataPrivate());
+                || !view.isAccessibilityDataSensitive());
     }
 
     public void findAccessibilityNodeInfoByAccessibilityIdClientThread(
@@ -874,8 +874,11 @@
             return;
         }
         try {
+            // Clearing focus does not expose sensitive data, so set fetch flags to ensure that the
+            // root view is always returned if present.
             setAccessibilityFetchFlags(
-                    AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS);
+                    AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS
+                            | AccessibilityNodeInfo.FLAG_SERVICE_IS_ACCESSIBILITY_TOOL);
             final View root = getRootView();
             if (root != null && isShown(root)) {
                 final View host = mViewRootImpl.mAccessibilityFocusedHost;
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index 4a83bbe..8c4e90c 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -197,6 +197,7 @@
     private int mFPSDivisor = 1;
     private DisplayEventReceiver.VsyncEventData mLastVsyncEventData =
             new DisplayEventReceiver.VsyncEventData();
+    private final FrameData mFrameData = new FrameData();
 
     /**
      * Contains information about the current frame for jank-tracking,
@@ -789,7 +790,7 @@
                 Trace.traceBegin(Trace.TRACE_TAG_VIEW,
                         "Choreographer#doFrame " + vsyncEventData.preferredFrameTimeline().vsyncId);
             }
-            FrameData frameData = new FrameData(frameTimeNanos, vsyncEventData);
+            mFrameData.update(frameTimeNanos, vsyncEventData);
             synchronized (mLock) {
                 if (!mFrameScheduled) {
                     traceMessage("Frame not scheduled");
@@ -827,7 +828,7 @@
                                     + " ms in the past.");
                         }
                     }
-                    frameData = getUpdatedFrameData(frameTimeNanos, frameData, jitterNanos);
+                    mFrameData.update(frameTimeNanos, mDisplayEventReceiver, jitterNanos);
                 }
 
                 if (frameTimeNanos < mLastFrameTimeNanos) {
@@ -862,17 +863,16 @@
             AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS);
 
             mFrameInfo.markInputHandlingStart();
-            doCallbacks(Choreographer.CALLBACK_INPUT, frameData, frameIntervalNanos);
+            doCallbacks(Choreographer.CALLBACK_INPUT, frameIntervalNanos);
 
             mFrameInfo.markAnimationsStart();
-            doCallbacks(Choreographer.CALLBACK_ANIMATION, frameData, frameIntervalNanos);
-            doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameData,
-                    frameIntervalNanos);
+            doCallbacks(Choreographer.CALLBACK_ANIMATION, frameIntervalNanos);
+            doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameIntervalNanos);
 
             mFrameInfo.markPerformTraversalsStart();
-            doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameData, frameIntervalNanos);
+            doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameIntervalNanos);
 
-            doCallbacks(Choreographer.CALLBACK_COMMIT, frameData, frameIntervalNanos);
+            doCallbacks(Choreographer.CALLBACK_COMMIT, frameIntervalNanos);
         } finally {
             AnimationUtils.unlockAnimationClock();
             Trace.traceEnd(Trace.TRACE_TAG_VIEW);
@@ -886,9 +886,9 @@
         }
     }
 
-    void doCallbacks(int callbackType, FrameData frameData, long frameIntervalNanos) {
+    void doCallbacks(int callbackType, long frameIntervalNanos) {
         CallbackRecord callbacks;
-        long frameTimeNanos = frameData.mFrameTimeNanos;
+        long frameTimeNanos = mFrameData.mFrameTimeNanos;
         synchronized (mLock) {
             // We use "now" to determine when callbacks become due because it's possible
             // for earlier processing phases in a frame to post callbacks that should run
@@ -925,7 +925,7 @@
                     }
                     frameTimeNanos = now - lastFrameOffset;
                     mLastFrameTimeNanos = frameTimeNanos;
-                    frameData = getUpdatedFrameData(frameTimeNanos, frameData, jitterNanos);
+                    mFrameData.update(frameTimeNanos, mDisplayEventReceiver, jitterNanos);
                 }
             }
         }
@@ -937,7 +937,7 @@
                             + ", action=" + c.action + ", token=" + c.token
                             + ", latencyMillis=" + (SystemClock.uptimeMillis() - c.dueTime));
                 }
-                c.run(frameData);
+                c.run(mFrameData);
             }
         } finally {
             synchronized (mLock) {
@@ -1039,21 +1039,38 @@
 
     /** Holds data that describes one possible VSync frame event to render at. */
     public static class FrameTimeline {
-        FrameTimeline(long vsyncId, long expectedPresentTimeNanos, long deadlineNanos) {
-            this.mVsyncId = vsyncId;
-            this.mExpectedPresentTimeNanos = expectedPresentTimeNanos;
-            this.mDeadlineNanos = deadlineNanos;
+        private long mVsyncId = FrameInfo.INVALID_VSYNC_ID;
+        private long mExpectedPresentationTimeNanos = -1;
+        private long mDeadlineNanos = -1;
+        private boolean mInCallback = false;
+
+        FrameTimeline() {
+            // Intentionally empty; defined so that it is not API/public by default.
         }
 
-        private long mVsyncId;
-        private long mExpectedPresentTimeNanos;
-        private long mDeadlineNanos;
+        void setInCallback(boolean inCallback) {
+            mInCallback = inCallback;
+        }
+
+        private void checkInCallback() {
+            if (!mInCallback) {
+                throw new IllegalStateException(
+                        "FrameTimeline is not valid outside of the vsync callback");
+            }
+        }
+
+        void update(long vsyncId, long expectedPresentationTimeNanos, long deadlineNanos) {
+            mVsyncId = vsyncId;
+            mExpectedPresentationTimeNanos = expectedPresentationTimeNanos;
+            mDeadlineNanos = deadlineNanos;
+        }
 
         /**
          * The id that corresponds to this frame timeline, used to correlate a frame
          * produced by HWUI with the timeline data stored in Surface Flinger.
          */
         public long getVsyncId() {
+            checkInCallback();
             return mVsyncId;
         }
 
@@ -1062,13 +1079,15 @@
          * presented.
          */
         public long getExpectedPresentationTimeNanos() {
-            return mExpectedPresentTimeNanos;
+            checkInCallback();
+            return mExpectedPresentationTimeNanos;
         }
 
         /**
          * The time in  {@link System#nanoTime()} timebase which this frame needs to be ready by.
          */
         public long getDeadlineNanos() {
+            checkInCallback();
             return mDeadlineNanos;
         }
     }
@@ -1079,24 +1098,21 @@
      * information including deadline and expected present time.
      */
     public static class FrameData {
-        FrameData(long frameTimeNanos, DisplayEventReceiver.VsyncEventData vsyncEventData) {
-            this.mFrameTimeNanos = frameTimeNanos;
-            this.mFrameTimelines = convertFrameTimelines(vsyncEventData);
-            this.mPreferredFrameTimelineIndex =
-                    vsyncEventData.preferredFrameTimelineIndex;
-        }
-
         private long mFrameTimeNanos;
-        private final FrameTimeline[] mFrameTimelines;
+        private final FrameTimeline[] mFrameTimelines =
+                new FrameTimeline[DisplayEventReceiver.VsyncEventData.FRAME_TIMELINES_LENGTH];
         private int mPreferredFrameTimelineIndex;
+        private boolean mInCallback = false;
 
-        void updateFrameData(long frameTimeNanos, int newPreferredFrameTimelineIndex) {
-            mFrameTimeNanos = frameTimeNanos;
-            mPreferredFrameTimelineIndex = newPreferredFrameTimelineIndex;
+        FrameData() {
+            for (int i = 0; i < mFrameTimelines.length; i++) {
+                mFrameTimelines[i] = new FrameTimeline();
+            }
         }
 
         /** The time in nanoseconds when the frame started being rendered. */
         public long getFrameTimeNanos() {
+            checkInCallback();
             return mFrameTimeNanos;
         }
 
@@ -1104,58 +1120,83 @@
         @NonNull
         @SuppressLint("ArrayReturn") // For API consistency and speed.
         public FrameTimeline[] getFrameTimelines() {
+            checkInCallback();
             return mFrameTimelines;
         }
 
         /** The platform-preferred frame timeline. */
         @NonNull
         public FrameTimeline getPreferredFrameTimeline() {
+            checkInCallback();
             return mFrameTimelines[mPreferredFrameTimelineIndex];
         }
 
-        private FrameTimeline[] convertFrameTimelines(
-                DisplayEventReceiver.VsyncEventData vsyncEventData) {
-            FrameTimeline[] frameTimelines =
-                    new FrameTimeline[vsyncEventData.frameTimelines.length];
+        void setInCallback(boolean inCallback) {
+            mInCallback = inCallback;
+            for (int i = 0; i < mFrameTimelines.length; i++) {
+                mFrameTimelines[i].setInCallback(inCallback);
+            }
+        }
+
+        private void checkInCallback() {
+            if (!mInCallback) {
+                throw new IllegalStateException(
+                        "FrameData is not valid outside of the vsync callback");
+            }
+        }
+
+        /**
+         * Update the frame data with a {@code DisplayEventReceiver.VsyncEventData} received from
+         * native.
+         */
+        void update(long frameTimeNanos, DisplayEventReceiver.VsyncEventData vsyncEventData) {
+            if (vsyncEventData.frameTimelines.length != mFrameTimelines.length) {
+                throw new IllegalStateException(
+                        "Length of native frame timelines received does not match Java. Did "
+                                + "FRAME_TIMELINES_LENGTH or kFrameTimelinesLength (native) "
+                                + "change?");
+            }
+            mFrameTimeNanos = frameTimeNanos;
+            mPreferredFrameTimelineIndex = vsyncEventData.preferredFrameTimelineIndex;
             for (int i = 0; i < vsyncEventData.frameTimelines.length; i++) {
                 DisplayEventReceiver.VsyncEventData.FrameTimeline frameTimeline =
                         vsyncEventData.frameTimelines[i];
-                frameTimelines[i] = new FrameTimeline(frameTimeline.vsyncId,
-                        frameTimeline.expectedPresentTime, frameTimeline.deadline);
+                mFrameTimelines[i].update(frameTimeline.vsyncId,
+                        frameTimeline.expectedPresentationTime, frameTimeline.deadline);
             }
-            return frameTimelines;
-        }
-    }
-
-    /**
-     * Update the frame data when the frame is late.
-     *
-     * @param jitterNanos currentTime - frameTime
-     */
-    private FrameData getUpdatedFrameData(long frameTimeNanos, FrameData frameData,
-            long jitterNanos) {
-        int newPreferredIndex = 0;
-        FrameTimeline[] frameTimelines = frameData.getFrameTimelines();
-        final long minimumDeadline =
-                frameData.getPreferredFrameTimeline().getDeadlineNanos() + jitterNanos;
-        // Look for a non-past deadline timestamp in the existing frame data. Otherwise, binder
-        // query for new frame data. Note that binder is relatively slow, O(ms), so it is
-        // only called when the existing frame data does not hold a valid frame.
-        while (newPreferredIndex < frameTimelines.length - 1
-                && frameTimelines[newPreferredIndex].getDeadlineNanos()
-                < minimumDeadline) {
-            newPreferredIndex++;
         }
 
-        long newPreferredDeadline =
-                frameData.getFrameTimelines()[newPreferredIndex].getDeadlineNanos();
-        if (newPreferredDeadline < minimumDeadline) {
-            DisplayEventReceiver.VsyncEventData latestVsyncEventData =
-                    mDisplayEventReceiver.getLatestVsyncEventData();
-            return new FrameData(frameTimeNanos, latestVsyncEventData);
-        } else {
-            frameData.updateFrameData(frameTimeNanos, newPreferredIndex);
-            return frameData;
+        /**
+         * Update the frame data when the frame is late.
+         *
+         * @param jitterNanos currentTime - frameTime
+         */
+        void update(
+                long frameTimeNanos, DisplayEventReceiver displayEventReceiver, long jitterNanos) {
+            int newPreferredIndex = 0;
+            final long minimumDeadline =
+                    mFrameTimelines[mPreferredFrameTimelineIndex].mDeadlineNanos + jitterNanos;
+            // Look for a non-past deadline timestamp in the existing frame data. Otherwise, binder
+            // query for new frame data. Note that binder is relatively slow, O(ms), so it is
+            // only called when the existing frame data does not hold a valid frame.
+            while (newPreferredIndex < mFrameTimelines.length - 1
+                    && mFrameTimelines[newPreferredIndex].mDeadlineNanos < minimumDeadline) {
+                newPreferredIndex++;
+            }
+
+            long newPreferredDeadline = mFrameTimelines[newPreferredIndex].mDeadlineNanos;
+            if (newPreferredDeadline < minimumDeadline) {
+                DisplayEventReceiver.VsyncEventData latestVsyncEventData =
+                        displayEventReceiver.getLatestVsyncEventData();
+                update(frameTimeNanos, latestVsyncEventData);
+            } else {
+                update(frameTimeNanos, newPreferredIndex);
+            }
+        }
+
+        void update(long frameTimeNanos, int newPreferredFrameTimelineIndex) {
+            mFrameTimeNanos = frameTimeNanos;
+            mPreferredFrameTimelineIndex = newPreferredFrameTimelineIndex;
         }
     }
 
@@ -1280,11 +1321,13 @@
         }
 
         void run(FrameData frameData) {
+            frameData.setInCallback(true);
             if (token == VSYNC_CALLBACK_TOKEN) {
                 ((VsyncCallback) action).onVsync(frameData);
             } else {
                 run(frameData.getFrameTimeNanos());
             }
+            frameData.setInCallback(false);
         }
     }
 
diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java
index edce001..b4675e0 100644
--- a/core/java/android/view/DisplayEventReceiver.java
+++ b/core/java/android/view/DisplayEventReceiver.java
@@ -81,7 +81,10 @@
     // GC'd while the native peer of the receiver is using them.
     private MessageQueue mMessageQueue;
 
+    private final VsyncEventData mVsyncEventData = new VsyncEventData();
+
     private static native long nativeInit(WeakReference<DisplayEventReceiver> receiver,
+            WeakReference<VsyncEventData> vsyncEventData,
             MessageQueue messageQueue, int vsyncSource, int eventRegistration, long layerHandle);
     private static native long nativeGetDisplayEventReceiverFinalizer();
     @FastNative
@@ -124,7 +127,9 @@
         }
 
         mMessageQueue = looper.getQueue();
-        mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue,
+        mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this),
+                new WeakReference<VsyncEventData>(mVsyncEventData),
+                mMessageQueue,
                 vsyncSource, eventRegistration, layerHandle);
         mFreeNativeResources = sNativeAllocationRegistry.registerNativeAllocation(this,
                 mReceiverPtr);
@@ -142,27 +147,33 @@
     }
 
     static final class VsyncEventData {
-
-        static final FrameTimeline[] INVALID_FRAME_TIMELINES =
-                {new FrameTimeline(FrameInfo.INVALID_VSYNC_ID, Long.MAX_VALUE, Long.MAX_VALUE)};
+        // The amount of frame timeline choices.
+        // Must be in sync with VsyncEventData::kFrameTimelinesLength in
+        // frameworks/native/libs/gui/include/gui/VsyncEventData.h. If they do not match, a runtime
+        // assertion is thrown when Choreographer is processing VsyncEventData.
+        static final int FRAME_TIMELINES_LENGTH = 7;
 
         public static class FrameTimeline {
-            FrameTimeline(long vsyncId, long expectedPresentTime, long deadline) {
+            FrameTimeline() {}
+
+            // Called from native code.
+            @SuppressWarnings("unused")
+            FrameTimeline(long vsyncId, long expectedPresentationTime, long deadline) {
                 this.vsyncId = vsyncId;
-                this.expectedPresentTime = expectedPresentTime;
+                this.expectedPresentationTime = expectedPresentationTime;
                 this.deadline = deadline;
             }
 
             // The frame timeline vsync id, used to correlate a frame
             // produced by HWUI with the timeline data stored in Surface Flinger.
-            public final long vsyncId;
+            public long vsyncId = FrameInfo.INVALID_VSYNC_ID;
 
             // The frame timestamp for when the frame is expected to be presented.
-            public final long expectedPresentTime;
+            public long expectedPresentationTime = Long.MAX_VALUE;
 
             // The frame deadline timestamp in {@link System#nanoTime()} timebase that it is
             // allotted for the frame to be completed.
-            public final long deadline;
+            public long deadline = Long.MAX_VALUE;
         }
 
         /**
@@ -170,11 +181,18 @@
          * {@link FrameInfo#VSYNC} to the current vsync in case Choreographer callback was heavily
          * delayed by the app.
          */
-        public final long frameInterval;
+        public long frameInterval = -1;
 
         public final FrameTimeline[] frameTimelines;
 
-        public final int preferredFrameTimelineIndex;
+        public int preferredFrameTimelineIndex = 0;
+
+        VsyncEventData() {
+            frameTimelines = new FrameTimeline[FRAME_TIMELINES_LENGTH];
+            for (int i = 0; i < frameTimelines.length; i++) {
+                frameTimelines[i] = new FrameTimeline();
+            }
+        }
 
         // Called from native code.
         @SuppressWarnings("unused")
@@ -185,12 +203,6 @@
             this.frameInterval = frameInterval;
         }
 
-        VsyncEventData() {
-            this.frameInterval = -1;
-            this.frameTimelines = INVALID_FRAME_TIMELINES;
-            this.preferredFrameTimelineIndex = 0;
-        }
-
         public FrameTimeline preferredFrameTimeline() {
             return frameTimelines[preferredFrameTimelineIndex];
         }
@@ -294,9 +306,8 @@
 
     // Called from native code.
     @SuppressWarnings("unused")
-    private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame,
-            VsyncEventData vsyncEventData) {
-        onVsync(timestampNanos, physicalDisplayId, frame, vsyncEventData);
+    private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame) {
+        onVsync(timestampNanos, physicalDisplayId, frame, mVsyncEventData);
     }
 
     // Called from native code.
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 0368918..e31adcf 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -24,6 +24,7 @@
 import static android.view.DisplayInfoProto.LOGICAL_WIDTH;
 import static android.view.DisplayInfoProto.NAME;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.WindowConfiguration;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -37,6 +38,7 @@
 import android.os.Process;
 import android.util.ArraySet;
 import android.util.DisplayMetrics;
+import android.util.SparseArray;
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.display.BrightnessSynchronizer;
@@ -348,6 +350,12 @@
      */
     public float hdrSdrRatio = Float.NaN;
 
+    /**
+     * RefreshRateRange limitation for @Temperature.ThrottlingStatus
+     */
+    @NonNull
+    public SparseArray<SurfaceControl.RefreshRateRange> refreshRateThermalThrottling =
+            new SparseArray<>();
 
     public static final @android.annotation.NonNull Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() {
         @Override
@@ -425,7 +433,8 @@
                 && installOrientation == other.installOrientation
                 && Objects.equals(displayShape, other.displayShape)
                 && Objects.equals(layoutLimitedRefreshRate, other.layoutLimitedRefreshRate)
-                && BrightnessSynchronizer.floatEquals(hdrSdrRatio, other.hdrSdrRatio);
+                && BrightnessSynchronizer.floatEquals(hdrSdrRatio, other.hdrSdrRatio)
+                && refreshRateThermalThrottling.contentEquals(other.refreshRateThermalThrottling);
     }
 
     @Override
@@ -482,6 +491,7 @@
         displayShape = other.displayShape;
         layoutLimitedRefreshRate = other.layoutLimitedRefreshRate;
         hdrSdrRatio = other.hdrSdrRatio;
+        refreshRateThermalThrottling = other.refreshRateThermalThrottling;
     }
 
     public void readFromParcel(Parcel source) {
@@ -544,6 +554,8 @@
         displayShape = source.readTypedObject(DisplayShape.CREATOR);
         layoutLimitedRefreshRate = source.readTypedObject(SurfaceControl.RefreshRateRange.CREATOR);
         hdrSdrRatio = source.readFloat();
+        refreshRateThermalThrottling = source.readSparseArray(null,
+                SurfaceControl.RefreshRateRange.class);
     }
 
     @Override
@@ -604,6 +616,7 @@
         dest.writeTypedObject(displayShape, flags);
         dest.writeTypedObject(layoutLimitedRefreshRate, flags);
         dest.writeFloat(hdrSdrRatio);
+        dest.writeSparseArray(refreshRateThermalThrottling);
     }
 
     @Override
@@ -871,6 +884,8 @@
         } else {
             sb.append(hdrSdrRatio);
         }
+        sb.append(", refreshRateThermalThrottling ");
+        sb.append(refreshRateThermalThrottling);
         sb.append("}");
         return sb.toString();
     }
diff --git a/core/java/android/view/HandwritingInitiator.java b/core/java/android/view/HandwritingInitiator.java
index 98f61a3..a47783c 100644
--- a/core/java/android/view/HandwritingInitiator.java
+++ b/core/java/android/view/HandwritingInitiator.java
@@ -170,20 +170,21 @@
                             findBestCandidateView(mState.mStylusDownX, mState.mStylusDownY);
                     if (candidateView != null) {
                         if (candidateView == getConnectedView()) {
+                            if (!candidateView.hasFocus()) {
+                                requestFocusWithoutReveal(candidateView);
+                            }
                             startHandwriting(candidateView);
                         } else if (candidateView.getHandwritingDelegatorCallback() != null) {
+                            String delegatePackageName =
+                                    candidateView.getAllowedHandwritingDelegatePackageName();
+                            if (delegatePackageName == null) {
+                                delegatePackageName = candidateView.getContext().getOpPackageName();
+                            }
                             mImm.prepareStylusHandwritingDelegation(
-                                    candidateView,
-                                    candidateView.getAllowedHandwritingDelegatePackageName());
+                                    candidateView, delegatePackageName);
                             candidateView.getHandwritingDelegatorCallback().run();
                         } else {
-                            if (candidateView.getRevealOnFocusHint()) {
-                                candidateView.setRevealOnFocusHint(false);
-                                candidateView.requestFocus();
-                                candidateView.setRevealOnFocusHint(true);
-                            } else {
-                                candidateView.requestFocus();
-                            }
+                            requestFocusWithoutReveal(candidateView);
                         }
                     }
                 }
@@ -299,8 +300,12 @@
      */
     @VisibleForTesting
     public boolean tryAcceptStylusHandwritingDelegation(@NonNull View view) {
-        if (mImm.acceptStylusHandwritingDelegation(
-                view, view.getAllowedHandwritingDelegatorPackageName())) {
+        String delegatorPackageName =
+                view.getAllowedHandwritingDelegatorPackageName();
+        if (delegatorPackageName == null) {
+            delegatorPackageName = view.getContext().getOpPackageName();
+        }
+        if (mImm.acceptStylusHandwritingDelegation(view, delegatorPackageName)) {
             if (mState != null) {
                 mState.mHasInitiatedHandwriting = true;
                 mState.mShouldInitHandwriting = false;
@@ -372,6 +377,16 @@
         return false;
     }
 
+    private static void requestFocusWithoutReveal(View view) {
+        if (view.getRevealOnFocusHint()) {
+            view.setRevealOnFocusHint(false);
+            view.requestFocus();
+            view.setRevealOnFocusHint(true);
+        } else {
+            view.requestFocus();
+        }
+    }
+
     /**
      * Given the location of the stylus event, return the best candidate view to initialize
      * handwriting mode.
@@ -381,9 +396,6 @@
      */
     @Nullable
     private View findBestCandidateView(float x, float y) {
-        float minDistance = Float.MAX_VALUE;
-        View bestCandidate = null;
-
         // If the connectedView is not null and do not set any handwriting area, it will check
         // whether the connectedView's boundary contains the initial stylus position. If true,
         // directly return the connectedView.
@@ -392,14 +404,12 @@
             Rect handwritingArea = getViewHandwritingArea(connectedView);
             if (isInHandwritingArea(handwritingArea, x, y, connectedView)
                     && shouldTriggerStylusHandwritingForView(connectedView)) {
-                final float distance = distance(handwritingArea, x, y);
-                if (distance == 0f) return connectedView;
-
-                bestCandidate = connectedView;
-                minDistance = distance;
+                return connectedView;
             }
         }
 
+        float minDistance = Float.MAX_VALUE;
+        View bestCandidate = null;
         // Check the registered handwriting areas.
         final List<HandwritableViewInfo> handwritableViewInfos =
                 mHandwritingAreasTracker.computeViewInfos();
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 720f569..9225cd9 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -29,6 +29,7 @@
 import android.hardware.input.HostUsiVersion;
 import android.hardware.input.InputDeviceIdentifier;
 import android.hardware.input.InputManager;
+import android.hardware.input.InputManagerGlobal;
 import android.hardware.lights.LightsManager;
 import android.icu.util.ULocale;
 import android.os.Build;
@@ -742,7 +743,7 @@
      */
     @Nullable
     public static InputDevice getDevice(int id) {
-        return InputManager.getInstance().getInputDevice(id);
+        return InputManagerGlobal.getInstance().getInputDevice(id);
     }
 
     /**
@@ -750,7 +751,7 @@
      * @return The input device ids.
      */
     public static int[] getDeviceIds() {
-        return InputManager.getInstance().getInputDeviceIds();
+        return InputManagerGlobal.getInstance().getInputDeviceIds();
     }
 
     /**
diff --git a/core/java/android/view/InputWindowHandle.java b/core/java/android/view/InputWindowHandle.java
index 406f446..24a0355 100644
--- a/core/java/android/view/InputWindowHandle.java
+++ b/core/java/android/view/InputWindowHandle.java
@@ -244,6 +244,10 @@
         window = iwindow;
     }
 
+    public @Nullable IBinder getWindowToken() {
+        return windowToken;
+    }
+
     public IWindow getWindow() {
         if (window != null) {
             return window;
diff --git a/core/java/android/view/InsetsFrameProvider.java b/core/java/android/view/InsetsFrameProvider.java
index 0a2b06c..867d2b4 100644
--- a/core/java/android/view/InsetsFrameProvider.java
+++ b/core/java/android/view/InsetsFrameProvider.java
@@ -18,10 +18,14 @@
 
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT;
 
+import android.annotation.IntRange;
+import android.annotation.NonNull;
 import android.graphics.Insets;
 import android.graphics.Rect;
+import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.view.WindowInsets.Type.InsetsType;
 
 import java.util.Arrays;
 import java.util.Objects;
@@ -62,19 +66,18 @@
     private static final int HAS_INSETS_SIZE = 1;
     private static final int HAS_INSETS_SIZE_OVERRIDE = 2;
 
-    private static Rect sTmpRect = new Rect();
-    private static Rect sTmpRect2 = new Rect();
+    private static final Rect sTmpRect = new Rect();
+    private static final Rect sTmpRect2 = new Rect();
 
-    /**
-     * The type of insets to provide.
-     */
-    public @InsetsState.InternalInsetsType int type;
+    private final IBinder mOwner;
+    private final int mIndex;
+    private final @InsetsType int mType;
 
     /**
      * The source of frame. By default, all adjustment will be based on the window frame, it
      * can be set to window bounds or display bounds instead.
      */
-    public int source = SOURCE_FRAME;
+    private int mSource = SOURCE_FRAME;
 
     /**
      * The provided insets size based on the source frame. The result will be used as the insets
@@ -85,13 +88,13 @@
      * (0, 0, 0, 50) instead, the insets frame will be a frame starting from the bottom side of the
      * source frame with height of 50, i.e., (0, 150) - (100, 200).
      */
-    public Insets insetsSize = null;
+    private Insets mInsetsSize = null;
 
     /**
      * If null, the size set in insetsSize will be applied to all window types. If it contains
      * element of some types, the insets reported to the window with that types will be overridden.
      */
-    public InsetsSizeOverride[] insetsSizeOverrides = null;
+    private InsetsSizeOverride[] mInsetsSizeOverrides = null;
 
     /**
      * This field, if set, is indicating the insets needs to be at least the given size inside the
@@ -103,22 +106,80 @@
      *
      * Be cautious, this will not be in effect for the window types whose insets size is overridden.
      */
-    public Insets minimalInsetsSizeInDisplayCutoutSafe = null;
+    private Insets mMinimalInsetsSizeInDisplayCutoutSafe = null;
 
-    public InsetsFrameProvider(int type) {
-        this(type, SOURCE_FRAME, null, null);
+    /**
+     * Creates an InsetsFrameProvider which describes what frame an insets source should have.
+     *
+     * @param owner the owner of this provider. We might have multiple sources with the same type on
+     *              a display, this is used to identify them.
+     * @param index the index of this provider. An owner might provide multiple sources with the
+     *              same type, this is used to identify them.
+     *              The value must be in a range of [0, 2047].
+     * @param type the {@link InsetsType}.
+     * @see InsetsSource#createId(Object, int, int)
+     */
+    public InsetsFrameProvider(IBinder owner, @IntRange(from = 0, to = 2047) int index,
+            @InsetsType int type) {
+        if (index < 0 || index >= 2048) {
+            throw new IllegalArgumentException();
+        }
+
+        // This throws IllegalArgumentException if the type is not valid.
+        WindowInsets.Type.indexOf(type);
+
+        mOwner = owner;
+        mIndex = index;
+        mType = type;
     }
 
-    public InsetsFrameProvider(int type, Insets insetsSize) {
-        this(type, SOURCE_FRAME, insetsSize, null);
+    public IBinder getOwner() {
+        return mOwner;
     }
 
-    public InsetsFrameProvider(int type, int source, Insets insetsSize,
-            InsetsSizeOverride[] insetsSizeOverride) {
-        this.type = type;
-        this.source = source;
-        this.insetsSize = insetsSize;
-        this.insetsSizeOverrides = insetsSizeOverride;
+    public int getIndex() {
+        return mIndex;
+    }
+
+    public int getType() {
+        return mType;
+    }
+
+    public InsetsFrameProvider setSource(int source) {
+        mSource = source;
+        return this;
+    }
+
+    public int getSource() {
+        return mSource;
+    }
+
+    public InsetsFrameProvider setInsetsSize(Insets insetsSize) {
+        mInsetsSize = insetsSize;
+        return this;
+    }
+
+    public Insets getInsetsSize() {
+        return mInsetsSize;
+    }
+
+    public InsetsFrameProvider setInsetsSizeOverrides(InsetsSizeOverride[] insetsSizeOverrides) {
+        mInsetsSizeOverrides = insetsSizeOverrides;
+        return this;
+    }
+
+    public InsetsSizeOverride[] getInsetsSizeOverrides() {
+        return mInsetsSizeOverrides;
+    }
+
+    public InsetsFrameProvider setMinimalInsetsSizeInDisplayCutoutSafe(
+            Insets minimalInsetsSizeInDisplayCutoutSafe) {
+        mMinimalInsetsSizeInDisplayCutoutSafe = minimalInsetsSizeInDisplayCutoutSafe;
+        return this;
+    }
+
+    public Insets getMinimalInsetsSizeInDisplayCutoutSafe() {
+        return mMinimalInsetsSizeInDisplayCutoutSafe;
     }
 
     @Override
@@ -128,63 +189,73 @@
 
     @Override
     public String toString() {
-        StringBuilder sb = new StringBuilder(32);
-        sb.append("InsetsFrameProvider: {");
-        sb.append("type=").append(InsetsState.typeToString(type));
-        sb.append(", source=");
-        switch (source) {
-            case SOURCE_DISPLAY:
-                sb.append("SOURCE_DISPLAY");
-                break;
-            case SOURCE_CONTAINER_BOUNDS:
-                sb.append("SOURCE_CONTAINER_BOUNDS Bounds");
-                break;
-            case SOURCE_FRAME:
-                sb.append("SOURCE_FRAME");
-                break;
+        final StringBuilder sb = new StringBuilder("InsetsFrameProvider: {");
+        sb.append("owner=").append(mOwner);
+        sb.append(", index=").append(mIndex);
+        sb.append(", type=").append(WindowInsets.Type.toString(mType));
+        sb.append(", source=").append(sourceToString(mSource));
+        if (mInsetsSize != null) {
+            sb.append(", insetsSize=").append(mInsetsSize);
         }
-        if (insetsSize != null) {
-            sb.append(", insetsSize=").append(insetsSize);
-        }
-        if (insetsSizeOverrides != null) {
-            sb.append(", insetsSizeOverrides=").append(Arrays.toString(insetsSizeOverrides));
+        if (mInsetsSizeOverrides != null) {
+            sb.append(", insetsSizeOverrides=").append(Arrays.toString(mInsetsSizeOverrides));
         }
         sb.append("}");
         return sb.toString();
     }
 
+    private static String sourceToString(int source) {
+        switch (source) {
+            case SOURCE_DISPLAY:
+                return "DISPLAY";
+            case SOURCE_CONTAINER_BOUNDS:
+                return "CONTAINER_BOUNDS";
+            case SOURCE_FRAME:
+                return "FRAME";
+        }
+        return "UNDEFINED";
+    }
+
     public InsetsFrameProvider(Parcel in) {
+        mOwner = in.readStrongBinder();
+        mIndex = in.readInt();
+        mType = in.readInt();
         int insetsSizeModified = in.readInt();
-        type = in.readInt();
-        source = in.readInt();
+        mSource = in.readInt();
         if ((insetsSizeModified & HAS_INSETS_SIZE) != 0) {
-            insetsSize = Insets.CREATOR.createFromParcel(in);
+            mInsetsSize = Insets.CREATOR.createFromParcel(in);
         }
         if ((insetsSizeModified & HAS_INSETS_SIZE_OVERRIDE) != 0) {
-            insetsSizeOverrides = in.createTypedArray(InsetsSizeOverride.CREATOR);
+            mInsetsSizeOverrides = in.createTypedArray(InsetsSizeOverride.CREATOR);
         }
     }
 
     @Override
     public void writeToParcel(Parcel out, int flags) {
+        out.writeStrongBinder(mOwner);
+        out.writeInt(mIndex);
+        out.writeInt(mType);
         int insetsSizeModified = 0;
-        if (insetsSize != null) {
+        if (mInsetsSize != null) {
             insetsSizeModified |= HAS_INSETS_SIZE;
         }
-        if (insetsSizeOverrides != null) {
+        if (mInsetsSizeOverrides != null) {
             insetsSizeModified |= HAS_INSETS_SIZE_OVERRIDE;
         }
         out.writeInt(insetsSizeModified);
-        out.writeInt(type);
-        out.writeInt(source);
-        if (insetsSize != null) {
-            insetsSize.writeToParcel(out, flags);
+        out.writeInt(mSource);
+        if (mInsetsSize != null) {
+            mInsetsSize.writeToParcel(out, flags);
         }
-        if (insetsSizeOverrides != null) {
-            out.writeTypedArray(insetsSizeOverrides, flags);
+        if (mInsetsSizeOverrides != null) {
+            out.writeTypedArray(mInsetsSizeOverrides, flags);
         }
     }
 
+    public boolean idEquals(InsetsFrameProvider o) {
+        return Objects.equals(mOwner, o.mOwner) && mIndex == o.mIndex && mType == o.mType;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) {
@@ -193,19 +264,21 @@
         if (o == null || getClass() != o.getClass()) {
             return false;
         }
-        InsetsFrameProvider other = (InsetsFrameProvider) o;
-        return type == other.type && source == other.source
-                && Objects.equals(insetsSize, other.insetsSize)
-                && Arrays.equals(insetsSizeOverrides, other.insetsSizeOverrides);
+        final InsetsFrameProvider other = (InsetsFrameProvider) o;
+        return Objects.equals(mOwner, other.mOwner) && mIndex == other.mIndex
+                && mType == other.mType && mSource == other.mSource
+                && Objects.equals(mInsetsSize, other.mInsetsSize)
+                && Arrays.equals(mInsetsSizeOverrides, other.mInsetsSizeOverrides);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(type, source, insetsSize, Arrays.hashCode(insetsSizeOverrides));
+        return Objects.hash(mOwner, mIndex, mType, mSource, mInsetsSize,
+                Arrays.hashCode(mInsetsSizeOverrides));
     }
 
-    public static final @android.annotation.NonNull Parcelable.Creator<InsetsFrameProvider>
-            CREATOR = new Parcelable.Creator<InsetsFrameProvider>() {
+    public static final @NonNull Parcelable.Creator<InsetsFrameProvider> CREATOR =
+            new Parcelable.Creator<>() {
                 @Override
                 public InsetsFrameProvider createFromParcel(Parcel in) {
                     return new InsetsFrameProvider(in);
@@ -282,21 +355,28 @@
      * directly for that window type.
      */
     public static class InsetsSizeOverride implements Parcelable {
-        public final int windowType;
-        public Insets insetsSize;
+
+        private final int mWindowType;
+        private final Insets mInsetsSize;
 
         protected InsetsSizeOverride(Parcel in) {
-            windowType = in.readInt();
-            insetsSize = in.readParcelable(null, Insets.class);
+            mWindowType = in.readInt();
+            mInsetsSize = in.readParcelable(null, Insets.class);
         }
 
-        public InsetsSizeOverride(int type, Insets size) {
-            windowType = type;
-            insetsSize = size;
+        public InsetsSizeOverride(int windowType, Insets insetsSize) {
+            mWindowType = windowType;
+            mInsetsSize = insetsSize;
+        }
+        public int getWindowType() {
+            return mWindowType;
         }
 
-        public static final Creator<InsetsSizeOverride> CREATOR =
-                new Creator<InsetsSizeOverride>() {
+        public Insets getInsetsSize() {
+            return mInsetsSize;
+        }
+
+        public static final Creator<InsetsSizeOverride> CREATOR = new Creator<>() {
             @Override
             public InsetsSizeOverride createFromParcel(Parcel in) {
                 return new InsetsSizeOverride(in);
@@ -315,8 +395,8 @@
 
         @Override
         public void writeToParcel(Parcel out, int flags) {
-            out.writeInt(windowType);
-            out.writeParcelable(insetsSize, flags);
+            out.writeInt(mWindowType);
+            out.writeParcelable(mInsetsSize, flags);
         }
 
         @Override
@@ -324,15 +404,15 @@
             StringBuilder sb = new StringBuilder(32);
             sb.append("TypedInsetsSize: {");
             sb.append("windowType=").append(ViewDebug.intToString(
-                    WindowManager.LayoutParams.class, "type", windowType));
-            sb.append(", insetsSize=").append(insetsSize);
+                    WindowManager.LayoutParams.class, "type", mWindowType));
+            sb.append(", insetsSize=").append(mInsetsSize);
             sb.append("}");
             return sb.toString();
         }
 
         @Override
         public int hashCode() {
-            return Objects.hash(windowType, insetsSize);
+            return Objects.hash(mWindowType, mInsetsSize);
         }
     }
 }
diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java
index e02e600..3947738 100644
--- a/core/java/android/view/InsetsSource.java
+++ b/core/java/android/view/InsetsSource.java
@@ -20,7 +20,6 @@
 import static android.view.InsetsSourceProto.TYPE;
 import static android.view.InsetsSourceProto.VISIBLE;
 import static android.view.InsetsSourceProto.VISIBLE_FRAME;
-import static android.view.ViewRootImpl.CAPTION_ON_SHELL;
 import static android.view.WindowInsets.Type.ime;
 
 import android.annotation.IntRange;
@@ -169,7 +168,7 @@
         // During drag-move and drag-resizing, the caption insets position may not get updated
         // before the app frame get updated. To layout the app content correctly during drag events,
         // we always return the insets with the corresponding height covering the top.
-        if (!CAPTION_ON_SHELL && getType() == WindowInsets.Type.captionBar()) {
+        if (getType() == WindowInsets.Type.captionBar()) {
             return Insets.of(0, frame.height(), 0, 0);
         }
         // Checks for whether there is shared edge with insets for 0-width/height window.
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 997e4a5..16bc155 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -42,7 +42,6 @@
 import android.graphics.Rect;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.util.ArraySet;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 import android.util.proto.ProtoOutputStream;
@@ -71,23 +70,11 @@
      */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = "ITYPE", value = {
-            ITYPE_STATUS_BAR,
-            ITYPE_NAVIGATION_BAR,
             ITYPE_CAPTION_BAR,
-            ITYPE_TOP_GESTURES,
-            ITYPE_BOTTOM_GESTURES,
-            ITYPE_LEFT_GESTURES,
-            ITYPE_RIGHT_GESTURES,
-            ITYPE_TOP_MANDATORY_GESTURES,
-            ITYPE_BOTTOM_MANDATORY_GESTURES,
-            ITYPE_LEFT_MANDATORY_GESTURES,
-            ITYPE_RIGHT_MANDATORY_GESTURES,
             ITYPE_LEFT_TAPPABLE_ELEMENT,
             ITYPE_TOP_TAPPABLE_ELEMENT,
             ITYPE_RIGHT_TAPPABLE_ELEMENT,
             ITYPE_BOTTOM_TAPPABLE_ELEMENT,
-            ITYPE_CLIMATE_BAR,
-            ITYPE_EXTRA_NAVIGATION_BAR,
             ITYPE_LEFT_GENERIC_OVERLAY,
             ITYPE_TOP_GENERIC_OVERLAY,
             ITYPE_RIGHT_GENERIC_OVERLAY,
@@ -95,34 +82,17 @@
     })
     public @interface InternalInsetsType {}
 
-    public static final int ITYPE_STATUS_BAR = 0;
-    public static final int ITYPE_NAVIGATION_BAR = 1;
-    public static final int ITYPE_CAPTION_BAR = 2;
+    public static final int ITYPE_CAPTION_BAR = 0;
 
-    public static final int ITYPE_TOP_GESTURES = 3;
-    public static final int ITYPE_BOTTOM_GESTURES = 4;
-    public static final int ITYPE_LEFT_GESTURES = 5;
-    public static final int ITYPE_RIGHT_GESTURES = 6;
+    public static final int ITYPE_LEFT_TAPPABLE_ELEMENT = 1;
+    public static final int ITYPE_TOP_TAPPABLE_ELEMENT = 2;
+    public static final int ITYPE_RIGHT_TAPPABLE_ELEMENT = 3;
+    public static final int ITYPE_BOTTOM_TAPPABLE_ELEMENT = 4;
 
-    public static final int ITYPE_TOP_MANDATORY_GESTURES = 7;
-    public static final int ITYPE_BOTTOM_MANDATORY_GESTURES = 8;
-    public static final int ITYPE_LEFT_MANDATORY_GESTURES = 9;
-    public static final int ITYPE_RIGHT_MANDATORY_GESTURES = 10;
-
-    public static final int ITYPE_LEFT_TAPPABLE_ELEMENT = 15;
-    public static final int ITYPE_TOP_TAPPABLE_ELEMENT = 16;
-    public static final int ITYPE_RIGHT_TAPPABLE_ELEMENT = 17;
-    public static final int ITYPE_BOTTOM_TAPPABLE_ELEMENT = 18;
-
-    /** Additional system decorations inset type. */
-    public static final int ITYPE_CLIMATE_BAR = 20;
-    public static final int ITYPE_EXTRA_NAVIGATION_BAR = 21;
-
-    /** Additional types for local insets. **/
-    public static final int ITYPE_LEFT_GENERIC_OVERLAY = 22;
-    public static final int ITYPE_TOP_GENERIC_OVERLAY = 23;
-    public static final int ITYPE_RIGHT_GENERIC_OVERLAY = 24;
-    public static final int ITYPE_BOTTOM_GENERIC_OVERLAY = 25;
+    public static final int ITYPE_LEFT_GENERIC_OVERLAY = 5;
+    public static final int ITYPE_TOP_GENERIC_OVERLAY = 6;
+    public static final int ITYPE_RIGHT_GENERIC_OVERLAY = 7;
+    public static final int ITYPE_BOTTOM_GENERIC_OVERLAY = 8;
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = "ISIDE", value = {
@@ -707,40 +677,6 @@
                 && !WindowConfiguration.inMultiWindowMode(windowingMode);
     }
 
-    public static @InternalInsetsType ArraySet<Integer> toInternalType(@InsetsType int types) {
-        final ArraySet<Integer> result = new ArraySet<>();
-        if ((types & Type.STATUS_BARS) != 0) {
-            result.add(ITYPE_STATUS_BAR);
-            result.add(ITYPE_CLIMATE_BAR);
-        }
-        if ((types & Type.NAVIGATION_BARS) != 0) {
-            result.add(ITYPE_NAVIGATION_BAR);
-            result.add(ITYPE_EXTRA_NAVIGATION_BAR);
-        }
-        if ((types & Type.SYSTEM_OVERLAYS) != 0) {
-            result.add(ITYPE_LEFT_GENERIC_OVERLAY);
-            result.add(ITYPE_TOP_GENERIC_OVERLAY);
-            result.add(ITYPE_RIGHT_GENERIC_OVERLAY);
-            result.add(ITYPE_BOTTOM_GENERIC_OVERLAY);
-        }
-        if ((types & Type.CAPTION_BAR) != 0) {
-            result.add(ITYPE_CAPTION_BAR);
-        }
-        if ((types & Type.SYSTEM_GESTURES) != 0) {
-            result.add(ITYPE_LEFT_GESTURES);
-            result.add(ITYPE_TOP_GESTURES);
-            result.add(ITYPE_RIGHT_GESTURES);
-            result.add(ITYPE_BOTTOM_GESTURES);
-        }
-        if ((types & Type.MANDATORY_SYSTEM_GESTURES) != 0) {
-            result.add(ITYPE_LEFT_MANDATORY_GESTURES);
-            result.add(ITYPE_TOP_MANDATORY_GESTURES);
-            result.add(ITYPE_RIGHT_MANDATORY_GESTURES);
-            result.add(ITYPE_BOTTOM_MANDATORY_GESTURES);
-        }
-        return result;
-    }
-
     /**
      * Converting a internal type to the public type.
      * @param type internal insets type, {@code InternalInsetsType}.
@@ -748,12 +684,6 @@
      */
     public static @Type.InsetsType int toPublicType(@InternalInsetsType int type) {
         switch (type) {
-            case ITYPE_STATUS_BAR:
-            case ITYPE_CLIMATE_BAR:
-                return Type.STATUS_BARS;
-            case ITYPE_NAVIGATION_BAR:
-            case ITYPE_EXTRA_NAVIGATION_BAR:
-                return Type.NAVIGATION_BARS;
             case ITYPE_LEFT_GENERIC_OVERLAY:
             case ITYPE_TOP_GENERIC_OVERLAY:
             case ITYPE_RIGHT_GENERIC_OVERLAY:
@@ -761,16 +691,6 @@
                 return Type.SYSTEM_OVERLAYS;
             case ITYPE_CAPTION_BAR:
                 return Type.CAPTION_BAR;
-            case ITYPE_TOP_MANDATORY_GESTURES:
-            case ITYPE_BOTTOM_MANDATORY_GESTURES:
-            case ITYPE_LEFT_MANDATORY_GESTURES:
-            case ITYPE_RIGHT_MANDATORY_GESTURES:
-                return Type.MANDATORY_SYSTEM_GESTURES;
-            case ITYPE_TOP_GESTURES:
-            case ITYPE_BOTTOM_GESTURES:
-            case ITYPE_LEFT_GESTURES:
-            case ITYPE_RIGHT_GESTURES:
-                return Type.SYSTEM_GESTURES;
             case ITYPE_LEFT_TAPPABLE_ELEMENT:
             case ITYPE_TOP_TAPPABLE_ELEMENT:
             case ITYPE_RIGHT_TAPPABLE_ELEMENT:
@@ -806,55 +726,6 @@
         proto.end(token);
     }
 
-    public static String typeToString(@InternalInsetsType int type) {
-        switch (type) {
-            case ITYPE_STATUS_BAR:
-                return "ITYPE_STATUS_BAR";
-            case ITYPE_NAVIGATION_BAR:
-                return "ITYPE_NAVIGATION_BAR";
-            case ITYPE_CAPTION_BAR:
-                return "ITYPE_CAPTION_BAR";
-            case ITYPE_TOP_GESTURES:
-                return "ITYPE_TOP_GESTURES";
-            case ITYPE_BOTTOM_GESTURES:
-                return "ITYPE_BOTTOM_GESTURES";
-            case ITYPE_LEFT_GESTURES:
-                return "ITYPE_LEFT_GESTURES";
-            case ITYPE_RIGHT_GESTURES:
-                return "ITYPE_RIGHT_GESTURES";
-            case ITYPE_TOP_MANDATORY_GESTURES:
-                return "ITYPE_TOP_MANDATORY_GESTURES";
-            case ITYPE_BOTTOM_MANDATORY_GESTURES:
-                return "ITYPE_BOTTOM_MANDATORY_GESTURES";
-            case ITYPE_LEFT_MANDATORY_GESTURES:
-                return "ITYPE_LEFT_MANDATORY_GESTURES";
-            case ITYPE_RIGHT_MANDATORY_GESTURES:
-                return "ITYPE_RIGHT_MANDATORY_GESTURES";
-            case ITYPE_LEFT_TAPPABLE_ELEMENT:
-                return "ITYPE_LEFT_TAPPABLE_ELEMENT";
-            case ITYPE_TOP_TAPPABLE_ELEMENT:
-                return "ITYPE_TOP_TAPPABLE_ELEMENT";
-            case ITYPE_RIGHT_TAPPABLE_ELEMENT:
-                return "ITYPE_RIGHT_TAPPABLE_ELEMENT";
-            case ITYPE_BOTTOM_TAPPABLE_ELEMENT:
-                return "ITYPE_BOTTOM_TAPPABLE_ELEMENT";
-            case ITYPE_CLIMATE_BAR:
-                return "ITYPE_CLIMATE_BAR";
-            case ITYPE_EXTRA_NAVIGATION_BAR:
-                return "ITYPE_EXTRA_NAVIGATION_BAR";
-            case ITYPE_LEFT_GENERIC_OVERLAY:
-                return "ITYPE_LEFT_GENERIC_OVERLAY";
-            case ITYPE_TOP_GENERIC_OVERLAY:
-                return "ITYPE_TOP_GENERIC_OVERLAY";
-            case ITYPE_RIGHT_GENERIC_OVERLAY:
-                return "ITYPE_RIGHT_GENERIC_OVERLAY";
-            case ITYPE_BOTTOM_GENERIC_OVERLAY:
-                return "ITYPE_BOTTOM_GENERIC_OVERLAY";
-            default:
-                return "ITYPE_UNKNOWN_" + type;
-        }
-    }
-
     @Override
     public boolean equals(@Nullable Object o) {
         return equals(o, false, false);
diff --git a/core/java/android/view/MotionPredictor.java b/core/java/android/view/MotionPredictor.java
index 4d32efe..27af300 100644
--- a/core/java/android/view/MotionPredictor.java
+++ b/core/java/android/view/MotionPredictor.java
@@ -17,14 +17,11 @@
 package android.view;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 
 import libcore.util.NativeAllocationRegistry;
 
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
 /**
  * Calculate motion predictions.
  *
@@ -52,15 +49,17 @@
 
     // Pointer to the native object.
     private final long mPtr;
-    private final Context mContext;
+    // Device-specific override to enable/disable motion prediction.
+    private final boolean mIsPredictionEnabled;
 
     /**
      * Create a new MotionPredictor for the provided {@link Context}.
      * @param context The context for the predictions
      */
     public MotionPredictor(@NonNull Context context) {
-        mContext = context;
-        final int offsetNanos = mContext.getResources().getInteger(
+        mIsPredictionEnabled = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_enableMotionPrediction);
+        final int offsetNanos = context.getResources().getInteger(
                 com.android.internal.R.integer.config_motionPredictionOffsetNanos);
         mPtr = nativeInitialize(offsetNanos);
         RegistryHolder.REGISTRY.registerNativeAllocation(this, mPtr);
@@ -68,49 +67,39 @@
 
     /**
      * Record a movement so that in the future, a prediction for the current gesture can be
-     * generated. Ensure to add all motions from the gesture of interest to generate correct
-     * predictions.
+     * generated. Only gestures from one input device at a time should be provided to an instance of
+     * MotionPredictor.
+     *
      * @param event The received event
+     *
+     * @throws IllegalArgumentException if an inconsistent MotionEvent stream is sent.
      */
     public void record(@NonNull MotionEvent event) {
-        if (!isPredictionEnabled()) {
+        if (!mIsPredictionEnabled) {
             return;
         }
         nativeRecord(mPtr, event);
     }
 
     /**
-     * Get predicted events for all gestures that have been provided to {@link #record}.
-     * If events from multiple devices were sent to 'record', this will produce a separate
-     * {@link MotionEvent} for each device. The returned list may be empty if no predictions for
-     * any of the added events/devices are available.
+     * Get a predicted event for the gesture that has been provided to {@link #record}.
      * Predictions may not reach the requested timestamp if the confidence in the prediction results
      * is low.
      *
      * @param predictionTimeNanos The time that the prediction should target, in the
      * {@link android.os.SystemClock#uptimeMillis} time base, but in nanoseconds.
      *
-     * @return A list of predicted motion events, with at most one for each device observed by
-     * {@link #record}. Be sure to check the historical data in addition to the latest
-     * ({@link MotionEvent#getX getX()}, {@link MotionEvent#getY getY()}) coordinates for smooth
-     * prediction curves. An empty list is returned if predictions are not supported, or not
-     * possible for the current set of gestures.
+     * @return The predicted motion event, or `null` if predictions are not supported, or not
+     * possible for the current gesture. Be sure to check the historical data in addition to the
+     * latest ({@link MotionEvent#getX getX()}, {@link MotionEvent#getY getY()}) coordinates for
+     * smooth prediction curves.
      */
-    @NonNull
-    public List<MotionEvent> predict(long predictionTimeNanos) {
-        if (!isPredictionEnabled()) {
-            return Collections.emptyList();
+    @Nullable
+    public MotionEvent predict(long predictionTimeNanos) {
+        if (!mIsPredictionEnabled) {
+            return null;
         }
-        return Arrays.asList(nativePredict(mPtr, predictionTimeNanos));
-    }
-
-    private boolean isPredictionEnabled() {
-        // Device-specific override
-        if (!mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_enableMotionPrediction)) {
-            return false;
-        }
-        return true;
+        return nativePredict(mPtr, predictionTimeNanos);
     }
 
     /**
@@ -124,12 +113,12 @@
      * @see MotionEvent#getSource
      */
     public boolean isPredictionAvailable(int deviceId, int source) {
-        return isPredictionEnabled() && nativeIsPredictionAvailable(mPtr, deviceId, source);
+        return mIsPredictionEnabled && nativeIsPredictionAvailable(mPtr, deviceId, source);
     }
 
     private static native long nativeInitialize(int offsetNanos);
     private static native void nativeRecord(long nativePtr, MotionEvent event);
-    private static native MotionEvent[] nativePredict(long nativePtr, long predictionTimeNanos);
+    private static native MotionEvent nativePredict(long nativePtr, long predictionTimeNanos);
     private static native boolean nativeIsPredictionAvailable(long nativePtr, int deviceId,
             int source);
     private static native long nativeGetNativeMotionPredictorFinalizer();
diff --git a/core/java/android/view/OWNERS b/core/java/android/view/OWNERS
index 9e17620..b574ecf 100644
--- a/core/java/android/view/OWNERS
+++ b/core/java/android/view/OWNERS
@@ -31,6 +31,7 @@
 per-file Input*.aidl = file:/services/core/java/com/android/server/input/OWNERS
 per-file KeyEvent.java = file:/services/core/java/com/android/server/input/OWNERS
 per-file MotionEvent.java = file:/services/core/java/com/android/server/input/OWNERS
+per-file MotionPredictor.java = file:/services/core/java/com/android/server/input/OWNERS
 per-file PointerIcon.java = file:/services/core/java/com/android/server/input/OWNERS
 per-file SimulatedDpad.java = file:/services/core/java/com/android/server/input/OWNERS
 per-file BatchedInputEventReceiver.java = file:/services/core/java/com/android/server/input/OWNERS
diff --git a/core/java/android/view/SurfaceControlHdrLayerInfoListener.java b/core/java/android/view/SurfaceControlHdrLayerInfoListener.java
index 13d68d0..b79fd2d 100644
--- a/core/java/android/view/SurfaceControlHdrLayerInfoListener.java
+++ b/core/java/android/view/SurfaceControlHdrLayerInfoListener.java
@@ -42,10 +42,13 @@
      * @param maxH The height of the HDR layer with the largest area
      * @param flags Additional metadata flags, currently always 0
      *              TODO(b/182312559): Add some flags
+     * @param maxDesiredHdrSdrRatio The max desired HDR/SDR ratio. Unbounded if the ratio is
+     *                              positive infinity.
      *
-     * @hide */
+     * @hide
+     */
     public abstract void onHdrInfoChanged(IBinder displayToken, int numberOfHdrLayers,
-            int maxW, int maxH, int flags);
+            int maxW, int maxH, int flags, float maxDesiredHdrSdrRatio);
 
     /**
      * Registers this as an HDR info listener on the provided display
diff --git a/core/java/android/view/VelocityTracker.java b/core/java/android/view/VelocityTracker.java
index 85aea85..4a7ed64 100644
--- a/core/java/android/view/VelocityTracker.java
+++ b/core/java/android/view/VelocityTracker.java
@@ -32,9 +32,10 @@
  *
  * Use {@link #obtain} to retrieve a new instance of the class when you are going
  * to begin tracking.  Put the motion events you receive into it with
- * {@link #addMovement(MotionEvent)}.  When you want to determine the velocity call
- * {@link #computeCurrentVelocity(int)} and then call {@link #getXVelocity(int)}
- * and {@link #getYVelocity(int)} to retrieve the velocity for each pointer id.
+ * {@link #addMovement(MotionEvent)}.  When you want to determine the velocity, call
+ * {@link #computeCurrentVelocity(int)} and then call the velocity-getter methods like
+ * {@link #getXVelocity(int)}, {@link #getYVelocity(int)}, or {@link #getAxisVelocity(int, int)}
+ * to retrieve velocity for different axes and/or pointer IDs.
  */
 public final class VelocityTracker {
     private static final SynchronizedPool<VelocityTracker> sPool =
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index fee2051..800fc97 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -142,7 +142,6 @@
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Transformation;
-import android.view.autofill.AutofillFeatureFlags;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillManager;
 import android.view.autofill.AutofillValue;
@@ -164,6 +163,7 @@
 import android.view.translation.ViewTranslationRequest;
 import android.view.translation.ViewTranslationResponse;
 import android.widget.Checkable;
+import android.widget.EditText;
 import android.widget.FrameLayout;
 import android.widget.ScrollBarDrawable;
 import android.window.OnBackInvokedDispatcher;
@@ -3114,33 +3114,33 @@
      * Accessibility interactions from services without {@code isAccessibilityTool} set to true are
      * disallowed for any of the following conditions:
      * <li>this view sets {@link #getFilterTouchesWhenObscured()}.</li>
-     * <li>any parent of this view returns true from {@link #isAccessibilityDataPrivate()}.</li>
+     * <li>any parent of this view returns true from {@link #isAccessibilityDataSensitive()}.</li>
      * </p>
      */
-    public static final int ACCESSIBILITY_DATA_PRIVATE_AUTO = 0x00000000;
+    public static final int ACCESSIBILITY_DATA_SENSITIVE_AUTO = 0x00000000;
 
     /**
      * Only allow interactions from {@link android.accessibilityservice.AccessibilityService}s
      * with the {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool}
      * property set to true.
      */
-    public static final int ACCESSIBILITY_DATA_PRIVATE_YES = 0x00000001;
+    public static final int ACCESSIBILITY_DATA_SENSITIVE_YES = 0x00000001;
 
     /**
      * Allow interactions from all {@link android.accessibilityservice.AccessibilityService}s,
      * regardless of their
      * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property.
      */
-    public static final int ACCESSIBILITY_DATA_PRIVATE_NO = 0x00000002;
+    public static final int ACCESSIBILITY_DATA_SENSITIVE_NO = 0x00000002;
 
     /** @hide */
-    @IntDef(prefix = { "ACCESSIBILITY_DATA_PRIVATE_" }, value = {
-            ACCESSIBILITY_DATA_PRIVATE_AUTO,
-            ACCESSIBILITY_DATA_PRIVATE_YES,
-            ACCESSIBILITY_DATA_PRIVATE_NO,
+    @IntDef(prefix = { "ACCESSIBILITY_DATA_SENSITIVE_" }, value = {
+            ACCESSIBILITY_DATA_SENSITIVE_AUTO,
+            ACCESSIBILITY_DATA_SENSITIVE_YES,
+            ACCESSIBILITY_DATA_SENSITIVE_NO,
     })
     @Retention(RetentionPolicy.SOURCE)
-    public @interface AccessibilityDataPrivate {}
+    public @interface AccessibilityDataSensitive {}
 
     /**
      * Mask for obtaining the bits which specify how to determine
@@ -4611,9 +4611,9 @@
      * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property
      * set to true.
      */
-    private int mExplicitAccessibilityDataPrivate = ACCESSIBILITY_DATA_PRIVATE_AUTO;
-    /** Used to calculate and cache {@link #isAccessibilityDataPrivate()}. */
-    private int mInferredAccessibilityDataPrivate = ACCESSIBILITY_DATA_PRIVATE_AUTO;
+    private int mExplicitAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_AUTO;
+    /** Used to calculate and cache {@link #isAccessibilityDataSensitive()}. */
+    private int mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_AUTO;
 
     /**
      * Specifies the id of a view for which this view serves as a label for
@@ -6016,9 +6016,9 @@
                     setImportantForAccessibility(a.getInt(attr,
                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
                     break;
-                case R.styleable.View_accessibilityDataPrivate:
-                    setAccessibilityDataPrivate(a.getInt(attr,
-                            ACCESSIBILITY_DATA_PRIVATE_AUTO));
+                case R.styleable.View_accessibilityDataSensitive:
+                    setAccessibilityDataSensitive(a.getInt(attr,
+                            ACCESSIBILITY_DATA_SENSITIVE_AUTO));
                     break;
                 case R.styleable.View_accessibilityLiveRegion:
                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
@@ -8660,9 +8660,9 @@
      * is responsible for handling this call.
      * </p>
      * <p>
-     * If this view sets {@link #isAccessibilityDataPrivate()} then this view should only append
+     * If this view sets {@link #isAccessibilityDataSensitive()} then this view should only append
      * sensitive information to an event that also sets
-     * {@link AccessibilityEvent#isAccessibilityDataPrivate()}.
+     * {@link AccessibilityEvent#isAccessibilityDataSensitive()}.
      * </p>
      * <p>
      * <em>Note:</em> Accessibility events of certain types are not dispatched for
@@ -8920,7 +8920,8 @@
      * @hide
      */
     @UnsupportedAppUsage
-    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
+    @TestApi
+    public void getBoundsOnScreen(@NonNull Rect outRect, boolean clipToParent) {
         if (mAttachInfo == null) {
             return;
         }
@@ -8928,6 +8929,9 @@
         getBoundsToScreenInternal(position, clipToParent);
         outRect.set(Math.round(position.left), Math.round(position.top),
                 Math.round(position.right), Math.round(position.bottom));
+        // If "Sandboxing View Bounds APIs" override is enabled, applyViewBoundsSandboxingIfNeeded
+        // will sandbox outRect within window bounds.
+        mAttachInfo.mViewRootImpl.applyViewBoundsSandboxingIfNeeded(outRect);
     }
 
     /**
@@ -10353,37 +10357,63 @@
         final AutofillManager afm = getAutofillManager();
         // keep default behavior
         if (afm == null) return false;
-        return afm.isMatchingAutofillableHeuristics(this);
+        return afm.isMatchingAutofillableHeuristicsForNotImportantViews(this);
     }
 
     private boolean isAutofillable() {
         if (getAutofillType() == AUTOFILL_TYPE_NONE) return false;
 
+        final AutofillManager afm = getAutofillManager();
+        if (afm == null) {
+            return false;
+        }
+
         // Disable triggering autofill if the view is integrated with CredentialManager.
-        if (AutofillFeatureFlags.shouldIgnoreCredentialViews()
-                && isCredential()) return false;
+        if (afm.shouldIgnoreCredentialViews() && isCredential()) {
+            return false;
+        }
+
+        // Experiment imeAction heuristic on important views. If the important view doesn't pass
+        // heuristic check, also check augmented autofill in case augmented autofill is enabled
+        // for the activity
+        // TODO: refactor to have both important views and not important views use the same
+        // heuristic check
+        if (isImportantForAutofill()
+            && afm.isTriggerFillRequestOnFilteredImportantViewsEnabled()
+            && this instanceof EditText
+            && !afm.isPassingImeActionCheck((EditText) this)
+            && !notifyAugmentedAutofillIfNeeded(afm)) {
+            // TODO: add a log to indicate what has filtered out the view
+            return false;
+        }
 
         if (!isImportantForAutofill()) {
             // If view matches heuristics and is not denied, it will be treated same as view that's
             // important for autofill
-            if (isMatchingAutofillableHeuristics()
-                    && !isActivityDeniedForAutofillForUnimportantView()) {
+            if (afm.isMatchingAutofillableHeuristicsForNotImportantViews(this)
+                    && !afm.isActivityDeniedForAutofillForUnimportantView()) {
                 return getAutofillViewId() > LAST_APP_AUTOFILL_ID;
             }
             // View is not important for "regular" autofill, so we must check if Augmented Autofill
             // is enabled for the activity
-            final AutofillOptions options = mContext.getAutofillOptions();
-            if (options == null || !options.isAugmentedAutofillEnabled(mContext)) {
+            if (!notifyAugmentedAutofillIfNeeded(afm)){
                 return false;
             }
-            final AutofillManager afm = getAutofillManager();
-            if (afm == null) return false;
-            afm.notifyViewEnteredForAugmentedAutofill(this);
         }
 
         return getAutofillViewId() > LAST_APP_AUTOFILL_ID;
     }
 
+    /** @hide **/
+    public boolean notifyAugmentedAutofillIfNeeded(AutofillManager afm) {
+        final AutofillOptions options = mContext.getAutofillOptions();
+        if (options == null || !options.isAugmentedAutofillEnabled(mContext)) {
+            return false;
+        }
+        afm.notifyViewEnteredForAugmentedAutofill(this);
+        return true;
+    }
+
     /** @hide */
     public boolean canNotifyAutofillEnterExitEvent() {
         return isAutofillable() && isAttachedToWindow();
@@ -10697,6 +10727,7 @@
         info.setVisibleToUser(isVisibleToUser());
 
         info.setImportantForAccessibility(isImportantForAccessibility());
+        info.setAccessibilityDataSensitive(isAccessibilityDataSensitive());
         info.setPackageName(mContext.getPackageName());
         info.setClassName(getAccessibilityClassName());
         info.setStateDescription(getStateDescription());
@@ -12437,11 +12468,7 @@
     public void setHandwritingDelegatorCallback(@Nullable Runnable callback) {
         mHandwritingDelegatorCallback = callback;
         if (callback != null) {
-            // By default, the delegate must be from the same package as the delegator view.
-            mAllowedHandwritingDelegatePackageName = mContext.getOpPackageName();
             setHandwritingArea(new Rect(0, 0, getWidth(), getHeight()));
-        } else {
-            mAllowedHandwritingDelegatePackageName = null;
         }
     }
 
@@ -12460,8 +12487,10 @@
      * view from the specified package. If this method is not called, delegators may only be used to
      * initiate handwriting mode for a delegate editor view from the same package as the delegator
      * view. This method allows specifying a different trusted package which may contain a delegate
-     * editor view linked to this delegator view. This should be called after {@link
-     * #setHandwritingDelegatorCallback}.
+     * editor view linked to this delegator view.
+     *
+     * <p>This method has no effect unless {@link #setHandwritingDelegatorCallback} is also called
+     * to configure this view to act as a handwriting delegator.
      *
      * <p>If this method is called on the delegator view, then {@link
      * #setAllowedHandwritingDelegatorPackage} should also be called on the delegate editor view.
@@ -12479,33 +12508,23 @@
      * delegateEditorView.setAllowedHandwritingDelegatorPackage(package1);</pre>
      *
      * @param allowedPackageName the package name of a delegate editor view linked to this delegator
-     *     view
-     * @throws IllegalStateException If the view has not been configured as a handwriting delegator
-     *     using {@link #setHandwritingDelegatorCallback}.
+     *     view, or {@code null} to restore the default behavior of only allowing delegate editor
+     *     views from the same package as this delegator view
      */
-    public void setAllowedHandwritingDelegatePackage(@NonNull String allowedPackageName) {
-        if (mHandwritingDelegatorCallback == null) {
-            throw new IllegalStateException("This view is not a handwriting delegator.");
-        }
+    public void setAllowedHandwritingDelegatePackage(@Nullable String allowedPackageName) {
         mAllowedHandwritingDelegatePackageName = allowedPackageName;
     }
 
     /**
      * Returns the allowed package for delegate editor views for which this view may act as a
-     * handwriting delegator. If {@link #setAllowedHandwritingDelegatePackage} has not been called,
-     * this will return this view's package name, since by default delegators may only be used to
-     * initiate handwriting mode for a delegate editor view from the same package as the delegator
-     * view. This will return a different allowed package if set by {@link
-     * #setAllowedHandwritingDelegatePackage}.
-     *
-     * @throws IllegalStateException If the view has not been configured as a handwriting delegator
-     *     using {@link #setHandwritingDelegatorCallback}.
+     * handwriting delegator, as set by {@link #setAllowedHandwritingDelegatePackage}. If {@link
+     * #setAllowedHandwritingDelegatePackage} has not been called, or called with {@code null}
+     * argument, this will return {@code null}, meaning that this delegator view may only be used to
+     * initiate handwriting mode for a delegate editor view from the same package as this delegator
+     * view.
      */
-    @NonNull
+    @Nullable
     public String getAllowedHandwritingDelegatePackageName() {
-        if (mHandwritingDelegatorCallback == null) {
-            throw new IllegalStateException("This view is not a handwriting delegator.");
-        }
         return mAllowedHandwritingDelegatePackageName;
     }
 
@@ -12519,12 +12538,6 @@
      */
     public void setIsHandwritingDelegate(boolean isHandwritingDelegate) {
         mIsHandwritingDelegate = isHandwritingDelegate;
-        if (mIsHandwritingDelegate) {
-            // By default, the delegator must be from the same package as the delegate view.
-            mAllowedHandwritingDelegatorPackageName = mContext.getOpPackageName();
-        } else {
-            mAllowedHandwritingDelegatePackageName = null;
-        }
     }
 
     /**
@@ -12537,41 +12550,34 @@
 
     /**
      * Specifies that a view from the specified package may act as a handwriting delegator for this
-     * delegate editor view. If this method is not called, only views from the same package as the
+     * delegate editor view. If this method is not called, only views from the same package as this
      * delegate editor view may act as a handwriting delegator. This method allows specifying a
      * different trusted package which may contain a delegator view linked to this delegate editor
-     * view. This should be called after {@link #setIsHandwritingDelegate}.
+     * view.
+     *
+     * <p>This method has no effect unless {@link #setIsHandwritingDelegate} is also called to
+     * configure this view to act as a handwriting delegate.
      *
      * <p>If this method is called on the delegate editor view, then {@link
      * #setAllowedHandwritingDelegatePackage} should also be called on the delegator view.
      *
      * @param allowedPackageName the package name of a delegator view linked to this delegate editor
-     *     view
-     * @throws IllegalStateException If the view has not been configured as a handwriting delegate
-     *     using {@link #setIsHandwritingDelegate}.
+     *     view, or {@code null} to restore the default behavior of only allowing delegator views
+     *     from the same package as this delegate editor view
      */
-    public void setAllowedHandwritingDelegatorPackage(@NonNull String allowedPackageName) {
-        if (!mIsHandwritingDelegate) {
-            throw new IllegalStateException("This view is not a handwriting delegate.");
-        }
+    public void setAllowedHandwritingDelegatorPackage(@Nullable String allowedPackageName) {
         mAllowedHandwritingDelegatorPackageName = allowedPackageName;
     }
 
     /**
      * Returns the allowed package for views which may act as a handwriting delegator for this
-     * delegate editor view. If {@link #setAllowedHandwritingDelegatorPackage} has not been called,
-     * this will return this view's package name, since by default only views from the same package
-     * as the delegator editor view may act as a handwriting delegator. This will return a different
-     * allowed package if set by {@link #setAllowedHandwritingDelegatorPackage}.
-     *
-     * @throws IllegalStateException If the view has not been configured as a handwriting delegate
-     *     using {@link #setIsHandwritingDelegate}.
+     * delegate editor view, as set by {@link #setAllowedHandwritingDelegatorPackage}. If {@link
+     * #setAllowedHandwritingDelegatorPackage} has not been called, or called with {@code null}
+     * argument, this will return {@code null}, meaning that only views from the same package as
+     * this delegator editor view may act as a handwriting delegator.
      */
-    @NonNull
+    @Nullable
     public String getAllowedHandwritingDelegatorPackageName() {
-        if (!mIsHandwritingDelegate) {
-            throw new IllegalStateException("This view is not a handwriting delegate.");
-        }
         return mAllowedHandwritingDelegatorPackageName;
     }
 
@@ -13606,7 +13612,7 @@
     public void setFilterTouchesWhenObscured(boolean enabled) {
         setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
                 FILTER_TOUCHES_WHEN_OBSCURED);
-        calculateAccessibilityDataPrivate();
+        calculateAccessibilityDataSensitive();
     }
 
     /**
@@ -14842,7 +14848,7 @@
             // source View's AccessibilityDataPrivate value, and then filtering is done when
             // AccessibilityManagerService propagates events to each recipient AccessibilityService.
             if (!AccessibilityManager.getInstance(mContext).isRequestFromAccessibilityTool()
-                    && isAccessibilityDataPrivate()) {
+                    && isAccessibilityDataSensitive()) {
                 return false;
             }
         }
@@ -14858,43 +14864,43 @@
      * set to true.
      *
      * <p>
-     * See default behavior provided by {@link #ACCESSIBILITY_DATA_PRIVATE_AUTO}. Otherwise,
-     * returns true for {@link #ACCESSIBILITY_DATA_PRIVATE_YES} or false for {@link
-     * #ACCESSIBILITY_DATA_PRIVATE_NO}.
+     * See default behavior provided by {@link #ACCESSIBILITY_DATA_SENSITIVE_AUTO}. Otherwise,
+     * returns true for {@link #ACCESSIBILITY_DATA_SENSITIVE_YES} or false for {@link
+     * #ACCESSIBILITY_DATA_SENSITIVE_NO}.
      * </p>
      *
      * @return True if this view should restrict accessibility service access to services that have
      * the isAccessibilityTool property.
      */
     @ViewDebug.ExportedProperty(category = "accessibility")
-    public boolean isAccessibilityDataPrivate() {
-        if (mInferredAccessibilityDataPrivate == ACCESSIBILITY_DATA_PRIVATE_AUTO) {
-            calculateAccessibilityDataPrivate();
+    public boolean isAccessibilityDataSensitive() {
+        if (mInferredAccessibilityDataSensitive == ACCESSIBILITY_DATA_SENSITIVE_AUTO) {
+            calculateAccessibilityDataSensitive();
         }
-        return mInferredAccessibilityDataPrivate == ACCESSIBILITY_DATA_PRIVATE_YES;
+        return mInferredAccessibilityDataSensitive == ACCESSIBILITY_DATA_SENSITIVE_YES;
     }
 
     /**
-     * Calculate and cache the inferred value for {@link #isAccessibilityDataPrivate()}.
+     * Calculate and cache the inferred value for {@link #isAccessibilityDataSensitive()}.
      *
      * <p>
      * <strong>Note:</strong> This method needs to be called any time one of the below conditions
      * changes, to recalculate the new value.
      * </p>
      */
-    void calculateAccessibilityDataPrivate() {
+    void calculateAccessibilityDataSensitive() {
         // Use the explicit value if set.
-        if (mExplicitAccessibilityDataPrivate != ACCESSIBILITY_DATA_PRIVATE_AUTO) {
-            mInferredAccessibilityDataPrivate = mExplicitAccessibilityDataPrivate;
+        if (mExplicitAccessibilityDataSensitive != ACCESSIBILITY_DATA_SENSITIVE_AUTO) {
+            mInferredAccessibilityDataSensitive = mExplicitAccessibilityDataSensitive;
         } else if (getFilterTouchesWhenObscured()) {
-            // Views that set filterTouchesWhenObscured default to accessibilityDataPrivate.
-            mInferredAccessibilityDataPrivate = ACCESSIBILITY_DATA_PRIVATE_YES;
-        } else if (mParent instanceof View && ((View) mParent).isAccessibilityDataPrivate()) {
-            // Descendants of an accessibilityDataPrivate View are also accessibilityDataPrivate.
-            mInferredAccessibilityDataPrivate = ACCESSIBILITY_DATA_PRIVATE_YES;
+            // Views that set filterTouchesWhenObscured default to accessibilityDataSensitive.
+            mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_YES;
+        } else if (mParent instanceof View && ((View) mParent).isAccessibilityDataSensitive()) {
+            // Descendants of accessibilityDataSensitive Views are also accessibilityDataSensitive.
+            mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_YES;
         } else {
-            // Otherwise, default to not accessibilityDataPrivate.
-            mInferredAccessibilityDataPrivate = ACCESSIBILITY_DATA_PRIVATE_NO;
+            // Otherwise, default to not accessibilityDataSensitive.
+            mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_NO;
         }
     }
 
@@ -14904,10 +14910,10 @@
      * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property
      * set to true.
      */
-    public void setAccessibilityDataPrivate(
-            @AccessibilityDataPrivate int accessibilityDataPrivate) {
-        mExplicitAccessibilityDataPrivate = accessibilityDataPrivate;
-        calculateAccessibilityDataPrivate();
+    public void setAccessibilityDataSensitive(
+            @AccessibilityDataSensitive int accessibilityDataSensitive) {
+        mExplicitAccessibilityDataSensitive = accessibilityDataSensitive;
+        calculateAccessibilityDataSensitive();
     }
 
     /**
@@ -16183,7 +16189,8 @@
      * @hide
      */
     @UnsupportedAppUsage
-    public void getWindowDisplayFrame(Rect outRect) {
+    @TestApi
+    public void getWindowDisplayFrame(@NonNull Rect outRect) {
         if (mAttachInfo != null) {
             mAttachInfo.mViewRootImpl.getDisplayFrame(outRect);
             return;
@@ -26399,6 +26406,9 @@
         if (info != null) {
             outLocation[0] += info.mWindowLeft;
             outLocation[1] += info.mWindowTop;
+            // If OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS override is enabled,
+            // applyViewLocationSandboxingIfNeeded sandboxes outLocation within window bounds.
+            info.mViewRootImpl.applyViewLocationSandboxingIfNeeded(outLocation);
         }
     }
 
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index c96d298..d80819f 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -28,6 +28,7 @@
 import android.content.res.Resources;
 import android.graphics.Rect;
 import android.hardware.input.InputManager;
+import android.hardware.input.InputManagerGlobal;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -1188,7 +1189,7 @@
     }
 
     private static boolean isInputDeviceInfoValid(int id, int axis, int source) {
-        InputDevice device = InputManager.getInstance().getInputDevice(id);
+        InputDevice device = InputManagerGlobal.getInstance().getInputDevice(id);
         return device != null && device.getMotionRange(axis, source) != null;
     }
 
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 73d4471..46ae3ea 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3921,10 +3921,10 @@
     }
 
     @Override
-    void calculateAccessibilityDataPrivate() {
-        super.calculateAccessibilityDataPrivate();
+    void calculateAccessibilityDataSensitive() {
+        super.calculateAccessibilityDataSensitive();
         for (int i = 0; i < mChildrenCount; i++) {
-            mChildren[i].calculateAccessibilityDataPrivate();
+            mChildren[i].calculateAccessibilityDataSensitive();
         }
     }
 
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f430ec3..24dcb69 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import static android.content.pm.ActivityInfo.OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS;
 import static android.graphics.HardwareRenderer.SYNC_CONTEXT_IS_STOPPED;
 import static android.graphics.HardwareRenderer.SYNC_LOST_SURFACE_REWARD_IF_FOUND;
 import static android.os.IInputConstants.INVALID_INPUT_EVENT_ID;
@@ -79,6 +80,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
+import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS;
 import static android.view.WindowManagerGlobal.RELAYOUT_RES_CANCEL_AND_REDRAW;
 import static android.view.WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS;
 import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
@@ -92,12 +94,14 @@
 import android.annotation.AnyThread;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.Size;
 import android.annotation.UiContext;
 import android.app.ActivityManager;
 import android.app.ActivityThread;
 import android.app.ICompatCameraControlCallback;
 import android.app.ResourcesManager;
 import android.app.WindowConfiguration;
+import android.app.compat.CompatChanges;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ClipData;
 import android.content.ClipDescription;
@@ -895,6 +899,15 @@
 
     private boolean mRelayoutRequested;
 
+    /**
+     * Whether sandboxing of {@link android.view.View#getBoundsOnScreen},
+     * {@link android.view.View#getLocationOnScreen(int[])},
+     * {@link android.view.View#getWindowDisplayFrame} and
+     * {@link android.view.View#getWindowVisibleDisplayFrame}
+     * within Activity bounds is enabled for the current application.
+     */
+    private final boolean mViewBoundsSandboxingEnabled;
+
     private int mLastTransformHint = Integer.MIN_VALUE;
 
     private AccessibilityWindowAttributes mAccessibilityWindowAttributes;
@@ -986,6 +999,8 @@
                 mViewConfiguration,
                 mContext.getSystemService(InputMethodManager.class));
 
+        mViewBoundsSandboxingEnabled = getViewBoundsSandboxingEnabled();
+
         String processorOverrideName = context.getResources().getString(
                                     R.string.config_inputEventCompatProcessorOverrideClassName);
         if (processorOverrideName.isEmpty()) {
@@ -1650,6 +1665,7 @@
                 mAttachInfo.mThreadedRenderer = renderer;
                 renderer.setSurfaceControl(mSurfaceControl, mBlastBufferQueue);
                 updateColorModeIfNeeded(attrs.getColorMode());
+                updateRenderHdrSdrRatio();
                 updateForceDarkMode();
                 mAttachInfo.mHardwareAccelerated = true;
                 mAttachInfo.mHardwareAccelerationRequested = true;
@@ -5379,6 +5395,11 @@
         }
     }
 
+    private void updateRenderHdrSdrRatio() {
+        mRenderHdrSdrRatio = mDisplay.getHdrSdrRatio();
+        mUpdateHdrSdrRatioInfo = true;
+    }
+
     private void updateColorModeIfNeeded(@ActivityInfo.ColorMode int colorMode) {
         if (mAttachInfo.mThreadedRenderer == null) {
             return;
@@ -5396,8 +5417,7 @@
         float desiredRatio = mAttachInfo.mThreadedRenderer.setColorMode(colorMode);
         if (desiredRatio != mDesiredHdrSdrRatio) {
             mDesiredHdrSdrRatio = desiredRatio;
-            mRenderHdrSdrRatio = mDisplay.getHdrSdrRatio();
-            mUpdateHdrSdrRatioInfo = true;
+            updateRenderHdrSdrRatio();
 
             if (mDesiredHdrSdrRatio < 1.01f) {
                 mDisplay.unregisterHdrSdrRatioChangedListener(mHdrSdrRatioChangedListener);
@@ -5698,7 +5718,7 @@
     private static final int MSG_WINDOW_TOUCH_MODE_CHANGED = 34;
     private static final int MSG_KEEP_CLEAR_RECTS_CHANGED = 35;
     private static final int MSG_REPORT_KEEP_CLEAR_RECTS = 36;
-
+    private static final int MSG_PAUSED_FOR_SYNC_TIMEOUT = 37;
 
     final class ViewRootHandler extends Handler {
         @Override
@@ -5986,6 +6006,11 @@
                 case MSG_REQUEST_SCROLL_CAPTURE:
                     handleScrollCaptureRequest((IScrollCaptureResponseListener) msg.obj);
                     break;
+                case MSG_PAUSED_FOR_SYNC_TIMEOUT:
+                    Log.e(mTag, "Timedout waiting to unpause for sync");
+                    mNumPausedForSync = 0;
+                    scheduleTraversals();
+                    break;
             }
         }
     }
@@ -8496,6 +8521,7 @@
             if (mAttachInfo.mThreadedRenderer != null) {
                 mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl, mBlastBufferQueue);
             }
+            updateRenderHdrSdrRatio();
             if (mPreviousTransformHint != transformHint) {
                 mPreviousTransformHint = transformHint;
                 dispatchTransformHintChanged(transformHint);
@@ -8592,6 +8618,9 @@
      */
     void getDisplayFrame(Rect outFrame) {
         outFrame.set(mTmpFrames.displayFrame);
+        // Apply sandboxing here (in getter) due to possible layout updates on the client after
+        // mTmpFrames.displayFrame is received from the server.
+        applyViewBoundsSandboxingIfNeeded(outFrame);
     }
 
     /**
@@ -8608,6 +8637,69 @@
         outFrame.top += insets.top;
         outFrame.right -= insets.right;
         outFrame.bottom -= insets.bottom;
+        // Apply sandboxing here (in getter) due to possible layout updates on the client after
+        // mTmpFrames.displayFrame is received from the server.
+        applyViewBoundsSandboxingIfNeeded(outFrame);
+    }
+
+    /**
+     * Offset outRect to make it sandboxed within Window's bounds.
+     *
+     * <p>This is used by {@link android.view.View#getBoundsOnScreen},
+     * {@link android.view.ViewRootImpl#getDisplayFrame} and
+     * {@link android.view.ViewRootImpl#getWindowVisibleDisplayFrame}, which are invoked by
+     * {@link android.view.View#getWindowDisplayFrame} and
+     * {@link android.view.View#getWindowVisibleDisplayFrame}, as well as
+     * {@link android.view.ViewDebug#captureLayers} for debugging.
+     */
+    void applyViewBoundsSandboxingIfNeeded(final Rect inOutRect) {
+        if (mViewBoundsSandboxingEnabled) {
+            final Rect bounds = getConfiguration().windowConfiguration.getBounds();
+            inOutRect.offset(-bounds.left, -bounds.top);
+        }
+    }
+
+    /**
+     * Offset outLocation to make it sandboxed within Window's bounds.
+     *
+     * <p>This is used by {@link android.view.View#getLocationOnScreen(int[])}
+     */
+    public void applyViewLocationSandboxingIfNeeded(@Size(2) int[] outLocation) {
+        if (mViewBoundsSandboxingEnabled) {
+            final Rect bounds = getConfiguration().windowConfiguration.getBounds();
+            outLocation[0] -= bounds.left;
+            outLocation[1] -= bounds.top;
+        }
+    }
+
+    private boolean getViewBoundsSandboxingEnabled() {
+        // System dialogs (e.g. ANR) can be created within System process, so handleBindApplication
+        // may be never called. This results into all app compat changes being enabled
+        // (see b/268007823) because AppCompatCallbacks.install() is never called with non-empty
+        // array.
+        // With ActivityThread.isSystem we verify that it is not the system process,
+        // then this CompatChange can take effect.
+        if (ActivityThread.isSystem()
+                || !CompatChanges.isChangeEnabled(OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS)) {
+            // It is a system process or OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS change-id is disabled.
+            return false;
+        }
+
+        // OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS is enabled by the device manufacturer.
+        try {
+            final List<PackageManager.Property> properties = mContext.getPackageManager()
+                    .queryApplicationProperty(PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS);
+
+            final boolean isOptedOut = !properties.isEmpty() && !properties.get(0).getBoolean();
+            if (isOptedOut) {
+                // PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS is disabled by the app devs.
+                return false;
+            }
+        } catch (RuntimeException e) {
+            // remote exception.
+        }
+
+        return true;
     }
 
     /**
@@ -10078,9 +10170,12 @@
     }
 
     void checkThread() {
-        if (mThread != Thread.currentThread()) {
+        Thread current = Thread.currentThread();
+        if (mThread != current) {
             throw new CalledFromWrongThreadException(
-                    "Only the original thread that created a view hierarchy can touch its views.");
+                    "Only the original thread that created a view hierarchy can touch its views."
+                            + " Expected: " + mThread.getName()
+                            + " Calling: " + current.getName());
         }
     }
 
@@ -11382,6 +11477,10 @@
             sendBackKeyEvent(KeyEvent.ACTION_DOWN);
             sendBackKeyEvent(KeyEvent.ACTION_UP);
         };
+        if (mOnBackInvokedDispatcher.hasImeOnBackInvokedDispatcher()) {
+            Log.d(TAG, "Skip registering CompatOnBackInvokedCallback on IME dispatcher");
+            return;
+        }
         mOnBackInvokedDispatcher.registerOnBackInvokedCallback(
                 OnBackInvokedDispatcher.PRIORITY_DEFAULT, mCompatOnBackInvokedCallback);
     }
@@ -11490,9 +11589,16 @@
             mActiveSurfaceSyncGroup = new SurfaceSyncGroup(mTag);
             mActiveSurfaceSyncGroup.setAddedToSyncListener(() -> {
                 Runnable runnable = () -> {
-                    mNumPausedForSync--;
-                    if (!mIsInTraversal && mNumPausedForSync == 0) {
-                        scheduleTraversals();
+                    // Check if it's already 0 because the timeout could have reset the count to
+                    // 0 and we don't want to go negative.
+                    if (mNumPausedForSync > 0) {
+                        mNumPausedForSync--;
+                    }
+                    if (mNumPausedForSync == 0) {
+                        mHandler.removeMessages(MSG_PAUSED_FOR_SYNC_TIMEOUT);
+                        if (!mIsInTraversal) {
+                            scheduleTraversals();
+                        }
                     }
                 };
 
@@ -11519,6 +11625,8 @@
         }
 
         mNumPausedForSync++;
+        mHandler.removeMessages(MSG_PAUSED_FOR_SYNC_TIMEOUT);
+        mHandler.sendEmptyMessageDelayed(MSG_PAUSED_FOR_SYNC_TIMEOUT, 1000);
         return mActiveSurfaceSyncGroup;
     };
 
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index a208cb3..21fe87f 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -823,6 +823,11 @@
     /** @hide */
     public final void destroy() {
         mDestroyed = true;
+        onDestroy();
+    }
+
+    /** @hide */
+    protected void onDestroy() {
     }
 
     /** @hide */
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index e7cefd6..35ed88f 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -454,6 +454,11 @@
      */
     int TRANSIT_WAKE = 11;
     /**
+     * The screen is turning off. This is used as a message to stop all animations.
+     * @hide
+     */
+    int TRANSIT_SLEEP = 12;
+    /**
      * The first slot for custom transition types. Callers (like Shell) can make use of custom
      * transition types for dealing with special cases. These types are effectively ignored by
      * Core and will just be passed along as part of TransitionInfo objects. An example is
@@ -462,7 +467,7 @@
      * implementation.
      * @hide
      */
-    int TRANSIT_FIRST_CUSTOM = 12;
+    int TRANSIT_FIRST_CUSTOM = 13;
 
     /**
      * @hide
@@ -480,6 +485,7 @@
             TRANSIT_KEYGUARD_UNOCCLUDE,
             TRANSIT_PIP,
             TRANSIT_WAKE,
+            TRANSIT_SLEEP,
             TRANSIT_FIRST_CUSTOM
     })
     @Retention(RetentionPolicy.SOURCE)
@@ -817,6 +823,15 @@
     }
 
     /**
+     * If the display {@link Configuration#smallestScreenWidthDp} is greater or equal to this value,
+     * we will treat it as a large screen device, which will have some multi window features enabled
+     * by default.
+     * @hide
+     */
+    @TestApi
+    int LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP = 600;
+
+    /**
      * Application level {@link android.content.pm.PackageManager.Property PackageManager
      * .Property} for an app to inform the system that the app can be opted-in or opted-out
      * from the compatibility treatment that avoids {@link
@@ -857,6 +872,42 @@
 
     /**
      * Application level {@link android.content.pm.PackageManager.Property PackageManager
+     * .Property} for an app to inform the system that it needs to be opted-out from the
+     * compatibility treatment that sandboxes {@link android.view.View} API.
+     *
+     * <p>The treatment can be enabled by device manufacturers for applications which misuse
+     * {@link android.view.View} APIs by expecting that
+     * {@link android.view.View#getLocationOnScreen},
+     * {@link android.view.View#getBoundsOnScreen},
+     * {@link android.view.View#getWindowVisibleDisplayFrame},
+     * {@link android.view.View#getWindowDisplayFrame}
+     * return coordinates as if an activity is positioned in the top-left corner of the screen, with
+     * left coordinate equal to 0. This may not be the case for applications in multi-window and in
+     * letterbox modes.
+     *
+     * <p>Setting this property to {@code false} informs the system that the application must be
+     * opted-out from the "Sandbox {@link android.view.View} API to Activity bounds" treatment even
+     * if the device manufacturer has opted the app into the treatment.
+     *
+     * <p>Not setting this property at all, or setting this property to {@code true} has no effect.
+     *
+     * <p><b>Syntax:</b>
+     * <pre>
+     * &lt;application&gt;
+     *   &lt;property
+     *     android:name="android.window.PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS"
+     *     android:value="false"/&gt;
+     * &lt;/application&gt;
+     * </pre>
+     *
+     * @hide
+     */
+    // TODO(b/263984287): Make this public API.
+    String PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS =
+            "android.window.PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS";
+
+    /**
+     * Application level {@link android.content.pm.PackageManager.Property PackageManager
      * .Property} for an app to inform the system that the application can be opted-in or opted-out
      * from the compatibility treatment that enables sending a fake focus event for unfocused
      * resumed split screen activities. This is needed because some game engines wait to get
@@ -1428,6 +1479,7 @@
             case TRANSIT_KEYGUARD_UNOCCLUDE: return "KEYGUARD_UNOCCLUDE";
             case TRANSIT_PIP: return "PIP";
             case TRANSIT_WAKE: return "WAKE";
+            case TRANSIT_SLEEP: return "SLEEP";
             case TRANSIT_FIRST_CUSTOM: return "FIRST_CUSTOM";
             default:
                 if (type > TRANSIT_FIRST_CUSTOM) {
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 33b763b..0acc022 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -56,7 +56,7 @@
  * accessibility service has not requested to retrieve the window content the event will
  * not contain reference to its source. <strong>Note: </strong> for events of type
  * {@link #TYPE_NOTIFICATION_STATE_CHANGED} the source is never available, and Views that set
- * {@link android.view.View#isAccessibilityDataPrivate()} may not populate all event properties on
+ * {@link android.view.View#isAccessibilityDataSensitive()} may not populate all event properties on
  * events sent from higher up in the view hierarchy.
  * </p>
  * <p>
@@ -1168,17 +1168,17 @@
      * set to true.
      *
      * <p>
-     * Initial value matches the {@link android.view.View#isAccessibilityDataPrivate} property from
-     * the event's source node, if present, or false by default.
+     * Initial value matches the {@link android.view.View#isAccessibilityDataSensitive} property
+     * from the event's source node, if present, or false by default.
      * </p>
      *
      * @return True if the event should be delivered only to isAccessibilityTool services, false
      * otherwise.
-     * @see #setAccessibilityDataPrivate
+     * @see #setAccessibilityDataSensitive
      */
     @Override
-    public boolean isAccessibilityDataPrivate() {
-        return super.isAccessibilityDataPrivate();
+    public boolean isAccessibilityDataSensitive() {
+        return super.isAccessibilityDataSensitive();
     }
 
     /**
@@ -1193,13 +1193,13 @@
      * no source) then this method must be called explicitly if you want non-default behavior.
      * </p>
      *
-     * @param accessibilityDataPrivate True if the event should be delivered only to
+     * @param accessibilityDataSensitive True if the event should be delivered only to
      *                                 isAccessibilityTool services, false otherwise.
      * @throws IllegalStateException If called from an AccessibilityService.
      */
     @Override
-    public void setAccessibilityDataPrivate(boolean accessibilityDataPrivate) {
-        super.setAccessibilityDataPrivate(accessibilityDataPrivate);
+    public void setAccessibilityDataSensitive(boolean accessibilityDataSensitive) {
+        super.setAccessibilityDataSensitive(accessibilityDataSensitive);
     }
 
     /**
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index aa631cf..efa2a01 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -25,7 +25,6 @@
 import android.accessibilityservice.AccessibilityShortcutInfo;
 import android.annotation.CallbackExecutor;
 import android.annotation.ColorInt;
-import android.annotation.FloatRange;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -76,7 +75,6 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import java.util.Objects;
 import java.util.concurrent.Executor;
 
 /**
@@ -140,21 +138,6 @@
     public static final int AUTOCLICK_DELAY_DEFAULT = 600;
 
     /**
-     * The contrast is defined as a float in [-1, 1], with a default value of 0.
-     * @hide
-     */
-    public static final float CONTRAST_MIN_VALUE = -1f;
-
-    /** @hide */
-    public static final float CONTRAST_MAX_VALUE = 1f;
-
-    /** @hide */
-    public static final float CONTRAST_DEFAULT_VALUE = 0f;
-
-    /** @hide */
-    public static final float CONTRAST_NOT_SET = Float.MIN_VALUE;
-
-    /**
      * Activity action: Launch UI to manage which accessibility service or feature is assigned
      * to the navigation bar Accessibility button.
      * <p>
@@ -288,8 +271,6 @@
     @UnsupportedAppUsage(trackingBug = 123768939L)
     boolean mIsHighTextContrastEnabled;
 
-    private float mUiContrast;
-
     boolean mIsAudioDescriptionByDefaultRequested;
 
     // accessibility tracing state
@@ -314,9 +295,6 @@
     private final ArrayMap<HighTextContrastChangeListener, Handler>
             mHighTextContrastStateChangeListeners = new ArrayMap<>();
 
-    private final ArrayMap<UiContrastChangeListener, Executor>
-            mUiContrastChangeListeners = new ArrayMap<>();
-
     private final ArrayMap<AccessibilityServicesStateChangeListener, Executor>
             mServicesStateChangeListeners = new ArrayMap<>();
 
@@ -390,7 +368,7 @@
          *
          * @param manager The manager that is calling back
          */
-        void onAccessibilityServicesStateChanged(@NonNull AccessibilityManager manager);
+        void onAccessibilityServicesStateChanged(@NonNull  AccessibilityManager manager);
     }
 
     /**
@@ -412,21 +390,6 @@
     }
 
     /**
-     * Listener for the UI contrast. To listen for changes to
-     * the UI contrast on the device, implement this interface and
-     * register it with the system by calling {@link #addUiContrastChangeListener}.
-     */
-    public interface UiContrastChangeListener {
-
-        /**
-         * Called when the color contrast enabled state changes.
-         *
-         * @param uiContrast The color contrast as in {@link #getUiContrast}
-         */
-        void onUiContrastChanged(@FloatRange(from = -1.0f, to = 1.0f) float uiContrast);
-    }
-
-    /**
      * Listener for the audio description by default state. To listen for
      * changes to the audio description by default state on the device,
      * implement this interface and register it with the system by calling
@@ -540,16 +503,6 @@
                 updateFocusAppearanceLocked(strokeWidth, color);
             }
         }
-
-        @Override
-        public void setUiContrast(float contrast) {
-            synchronized (mLock) {
-                // if value changed in the settings, update the cached value and notify listeners
-                if (Math.abs(mUiContrast - contrast) < 1e-10) return;
-                mUiContrast = contrast;
-            }
-            mHandler.obtainMessage(MyCallback.MSG_NOTIFY_CONTRAST_CHANGED).sendToTarget();
-        }
     };
 
     /**
@@ -720,7 +673,7 @@
     /**
      * Returns if the high text contrast in the system is enabled.
      * <p>
-     * <strong>Note:</strong> You need to query this only if your application is
+     * <strong>Note:</strong> You need to query this only if you application is
      * doing its own rendering and does not rely on the platform rendering pipeline.
      * </p>
      *
@@ -740,24 +693,6 @@
     }
 
     /**
-     * Returns the color contrast for the user.
-     * <p>
-     * <strong>Note:</strong> You need to query this only if your application is
-     * doing its own rendering and does not rely on the platform rendering pipeline.
-     * </p>
-     * @return The color contrast, float in [-1, 1] where
-     *          0 corresponds to the default contrast
-     *         -1 corresponds to the minimum contrast that the user can set
-     *          1 corresponds to the maximum contrast that the user can set
-     */
-    @FloatRange(from = -1.0f, to = 1.0f)
-    public float getUiContrast() {
-        synchronized (mLock) {
-            return mUiContrast;
-        }
-    }
-
-    /**
      * Sends an {@link AccessibilityEvent}.
      *
      * @param event The event to send.
@@ -1346,35 +1281,6 @@
     }
 
     /**
-     * Registers a {@link UiContrastChangeListener} for the current user.
-     *
-     * @param executor The executor on which the listener should be called back.
-     * @param listener The listener.
-     */
-    public void addUiContrastChangeListener(
-            @NonNull @CallbackExecutor Executor executor,
-            @NonNull UiContrastChangeListener listener) {
-        Objects.requireNonNull(executor);
-        Objects.requireNonNull(listener);
-        synchronized (mLock) {
-            mUiContrastChangeListeners.put(listener, executor);
-        }
-    }
-
-    /**
-     * Unregisters a {@link UiContrastChangeListener} for the current user.
-     * If the listener was not registered, does nothing and returns.
-     *
-     * @param listener The listener to unregister.
-     */
-    public void removeUiContrastChangeListener(@NonNull UiContrastChangeListener listener) {
-        Objects.requireNonNull(listener);
-        synchronized (mLock) {
-            mUiContrastChangeListeners.remove(listener);
-        }
-    }
-
-    /**
      * Registers a {@link AudioDescriptionRequestedChangeListener}
      * for changes in the audio description by default state of the system.
      * The value could be read via {@link #isAudioDescriptionRequested}.
@@ -2068,12 +1974,14 @@
      * {@link android.view.Display#INVALID_DISPLAY}, or is already being proxy-ed.
      *
      * @throws SecurityException if the app does not hold the
-     * {@link Manifest.permission#MANAGE_ACCESSIBILITY} permission.
+     * {@link Manifest.permission#MANAGE_ACCESSIBILITY} permission or the
+     * {@link Manifest.permission#CREATE_VIRTUAL_DEVICE} permission.
      *
      * @hide
      */
     @SystemApi
-    @RequiresPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
+    @RequiresPermission(allOf = {Manifest.permission.MANAGE_ACCESSIBILITY,
+            Manifest.permission.CREATE_VIRTUAL_DEVICE})
     public boolean registerDisplayProxy(@NonNull AccessibilityDisplayProxy proxy) {
         final IAccessibilityManager service;
         synchronized (mLock) {
@@ -2096,12 +2004,14 @@
      * @return {@code true} if the proxy is successfully unregistered.
      *
      * @throws SecurityException if the app does not hold the
-     * {@link Manifest.permission#MANAGE_ACCESSIBILITY} permission.
+     * {@link Manifest.permission#MANAGE_ACCESSIBILITY} permission or the
+     * {@link Manifest.permission#CREATE_VIRTUAL_DEVICE} permission.
      *
      * @hide
      */
     @SystemApi
-    @RequiresPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
+    @RequiresPermission(allOf = {Manifest.permission.MANAGE_ACCESSIBILITY,
+            Manifest.permission.CREATE_VIRTUAL_DEVICE})
     public boolean unregisterDisplayProxy(@NonNull AccessibilityDisplayProxy proxy)  {
         final IAccessibilityManager service;
         synchronized (mLock) {
@@ -2206,6 +2116,58 @@
         }
     }
 
+    /**
+     * Determines if the accessibility target is allowed.
+     *
+     * @param packageName The name of the application attempting to perform the operation.
+     * @param uid The user id of the application attempting to perform the operation.
+     * @param userId The id of the user for whom to perform the operation.
+     * @return {@code true} the accessibility target is allowed.
+     * @hide
+     */
+    public boolean isAccessibilityTargetAllowed(String packageName, int uid, int userId) {
+        final IAccessibilityManager service;
+        synchronized (mLock) {
+            service = getServiceLocked();
+            if (service == null) {
+                return false;
+            }
+        }
+
+        try {
+            return service.isAccessibilityTargetAllowed(packageName, uid, userId);
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error while check accessibility target status", re);
+            return false;
+        }
+    }
+
+    /**
+     * Sends restricted dialog intent if the accessibility target is disallowed.
+     *
+     * @param packageName The name of the application attempting to perform the operation.
+     * @param uid The user id of the application attempting to perform the operation.
+     * @param userId The id of the user for whom to perform the operation.
+     * @return {@code true} if the restricted dialog is shown.
+     * @hide
+     */
+    public boolean sendRestrictedDialogIntent(String packageName, int uid, int userId) {
+        final IAccessibilityManager service;
+        synchronized (mLock) {
+            service = getServiceLocked();
+            if (service == null) {
+                return false;
+            }
+        }
+
+        try {
+            return service.sendRestrictedDialogIntent(packageName, uid, userId);
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error while show restricted dialog", re);
+            return false;
+        }
+    }
+
     private IAccessibilityManager getServiceLocked() {
         if (mService == null) {
             tryConnectToServiceLocked(null);
@@ -2228,7 +2190,6 @@
             mRelevantEventTypes = IntPair.second(userStateAndRelevantEvents);
             updateUiTimeout(service.getRecommendedTimeoutMillis());
             updateFocusAppearanceLocked(service.getFocusStrokeWidth(), service.getFocusColor());
-            mUiContrast = service.getUiContrast();
             mService = service;
         } catch (RemoteException re) {
             Log.e(LOG_TAG, "AccessibilityManagerService is dead", re);
@@ -2307,22 +2268,6 @@
     }
 
     /**
-     * Notifies the registered {@link UiContrastChangeListener}s if the value changed.
-     */
-    private void notifyUiContrastChanged() {
-        final ArrayMap<UiContrastChangeListener, Executor> listeners;
-        synchronized (mLock) {
-            listeners = new ArrayMap<>(mUiContrastChangeListeners);
-        }
-
-        listeners.entrySet().forEach(entry -> {
-            UiContrastChangeListener listener = entry.getKey();
-            Executor executor = entry.getValue();
-            executor.execute(() -> listener.onUiContrastChanged(mUiContrast));
-        });
-    }
-
-    /**
      * Notifies the registered {@link AudioDescriptionStateChangeListener}s.
      */
     private void notifyAudioDescriptionbyDefaultStateChanged() {
@@ -2412,7 +2357,6 @@
 
     private final class MyCallback implements Handler.Callback {
         public static final int MSG_SET_STATE = 1;
-        public static final int MSG_NOTIFY_CONTRAST_CHANGED = 2;
 
         @Override
         public boolean handleMessage(Message message) {
@@ -2424,9 +2368,6 @@
                         setStateLocked(state);
                     }
                 } break;
-                case MSG_NOTIFY_CONTRAST_CHANGED: {
-                    notifyUiContrastChanged();
-                }
             }
             return true;
         }
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 247e026..9d82b79 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -834,6 +834,8 @@
 
     private static final int BOOLEAN_PROPERTY_REQUEST_TOUCH_PASSTHROUGH = 1 << 25;
 
+    private static final int BOOLEAN_PROPERTY_ACCESSIBILITY_DATA_SENSITIVE = 1 << 26;
+
     /**
      * Bits that provide the id of a virtual descendant of a view.
      */
@@ -2644,6 +2646,34 @@
     }
 
     /**
+     * Gets if the node's accessibility data is considered sensitive.
+     *
+     * @return True if the node is editable, false otherwise.
+     * @see View#isAccessibilityDataSensitive()
+     */
+    public boolean isAccessibilityDataSensitive() {
+        return getBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_DATA_SENSITIVE);
+    }
+
+    /**
+     * Sets whether this node's accessibility data is considered sensitive.
+     *
+     * <p>
+     * <strong>Note:</strong> Cannot be called from an {@link AccessibilityService}.
+     * This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param accessibilityDataSensitive True if the node's accessibility data is considered
+     *                                   sensitive.
+     * @throws IllegalStateException If called from an AccessibilityService.
+     * @see View#setAccessibilityDataSensitive
+     */
+    public void setAccessibilityDataSensitive(boolean accessibilityDataSensitive) {
+        setBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_DATA_SENSITIVE,
+                accessibilityDataSensitive);
+    }
+
+    /**
      * If this node represents a visually distinct region of the screen that may update separately
      * from the rest of the window, it is considered a pane. Set the pane title to indicate that
      * the node is a pane, and to provide a title for it.
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index 789c740..38b564a 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -72,7 +72,7 @@
     private static final int PROPERTY_FULL_SCREEN = 0x00000080;
     private static final int PROPERTY_SCROLLABLE = 0x00000100;
     private static final int PROPERTY_IMPORTANT_FOR_ACCESSIBILITY = 0x00000200;
-    private static final int PROPERTY_ACCESSIBILITY_DATA_PRIVATE = 0x00000400;
+    private static final int PROPERTY_ACCESSIBILITY_DATA_SENSITIVE = 0x00000400;
 
     private static final int GET_SOURCE_PREFETCH_FLAGS =
             AccessibilityNodeInfo.FLAG_PREFETCH_ANCESTORS
@@ -160,8 +160,8 @@
             important = root.isImportantForAccessibility();
             rootViewId = root.getAccessibilityViewId();
             mSourceWindowId = root.getAccessibilityWindowId();
-            setBooleanProperty(PROPERTY_ACCESSIBILITY_DATA_PRIVATE,
-                    root.isAccessibilityDataPrivate());
+            setBooleanProperty(PROPERTY_ACCESSIBILITY_DATA_SENSITIVE,
+                    root.isAccessibilityDataSensitive());
         }
         setBooleanProperty(PROPERTY_IMPORTANT_FOR_ACCESSIBILITY, important);
         mSourceNodeId = AccessibilityNodeInfo.makeNodeId(rootViewId, virtualDescendantId);
@@ -391,20 +391,20 @@
     }
 
     /**
-     * @see AccessibilityEvent#isAccessibilityDataPrivate
+     * @see AccessibilityEvent#isAccessibilityDataSensitive
      * @hide
      */
-    boolean isAccessibilityDataPrivate() {
-        return getBooleanProperty(PROPERTY_ACCESSIBILITY_DATA_PRIVATE);
+    boolean isAccessibilityDataSensitive() {
+        return getBooleanProperty(PROPERTY_ACCESSIBILITY_DATA_SENSITIVE);
     }
 
     /**
-     * @see AccessibilityEvent#setAccessibilityDataPrivate
+     * @see AccessibilityEvent#setAccessibilityDataSensitive
      * @hide
      */
-    void setAccessibilityDataPrivate(boolean accessibilityDataPrivate) {
+    void setAccessibilityDataSensitive(boolean accessibilityDataSensitive) {
         enforceNotSealed();
-        setBooleanProperty(PROPERTY_ACCESSIBILITY_DATA_PRIVATE, accessibilityDataPrivate);
+        setBooleanProperty(PROPERTY_ACCESSIBILITY_DATA_SENSITIVE, accessibilityDataSensitive);
     }
 
     /**
@@ -962,7 +962,7 @@
         appendUnless(false, PROPERTY_FULL_SCREEN, builder);
         appendUnless(false, PROPERTY_SCROLLABLE, builder);
         appendUnless(false, PROPERTY_IMPORTANT_FOR_ACCESSIBILITY, builder);
-        appendUnless(false, PROPERTY_ACCESSIBILITY_DATA_PRIVATE, builder);
+        appendUnless(false, PROPERTY_ACCESSIBILITY_DATA_SENSITIVE, builder);
 
         append(builder, "BeforeText", mBeforeText);
         append(builder, "FromIndex", mFromIndex);
@@ -996,8 +996,8 @@
             case PROPERTY_SCROLLABLE: return "Scrollable";
             case PROPERTY_IMPORTANT_FOR_ACCESSIBILITY:
                 return "ImportantForAccessibility";
-            case PROPERTY_ACCESSIBILITY_DATA_PRIVATE:
-                return "AccessibilityDataPrivate";
+            case PROPERTY_ACCESSIBILITY_DATA_SENSITIVE:
+                return "AccessibilityDataSensitive";
             default: return Integer.toHexString(prop);
         }
     }
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
index d84e0fb..13ac329 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
@@ -839,6 +839,7 @@
         mConnectionId = UNDEFINED_WINDOW_ID;
         mAnchorId = AccessibilityNodeInfo.UNDEFINED_NODE_ID;
         mTitle = null;
+        mTransitionTime = 0;
     }
 
     /**
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index 1302421..1fac142 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -120,12 +120,13 @@
     // Used by UiAutomation for tests on the InputFilter
     void injectInputEventToInputFilter(in InputEvent event);
 
-    float getUiContrast();
-
     boolean startFlashNotificationSequence(String opPkg, int reason, IBinder token);
     boolean stopFlashNotificationSequence(String opPkg);
     boolean startFlashNotificationEvent(String opPkg, int reason, String reasonPkg);
 
+    boolean isAccessibilityTargetAllowed(String packageName, int uid, int userId);
+    boolean sendRestrictedDialogIntent(String packageName, int uid, int userId);
+
     parcelable WindowTransformationSpec {
         float[] transformationMatrix;
         MagnificationSpec magnificationSpec;
diff --git a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
index 931f862..041399c 100644
--- a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
@@ -31,6 +31,4 @@
     void setRelevantEventTypes(int eventTypes);
 
     void setFocusAppearance(int strokeWidth, int color);
-
-    void setUiContrast(float contrast);
 }
diff --git a/core/java/android/view/autofill/AutofillFeatureFlags.java b/core/java/android/view/autofill/AutofillFeatureFlags.java
index 6d78e60..7da69e7 100644
--- a/core/java/android/view/autofill/AutofillFeatureFlags.java
+++ b/core/java/android/view/autofill/AutofillFeatureFlags.java
@@ -156,6 +156,14 @@
             "trigger_fill_request_on_unimportant_view";
 
     /**
+     * Whether to apply heuristic check on important views.
+     *
+     * @hide
+     */
+    public static final String DEVICE_CONFIG_TRIGGER_FILL_REQUEST_ON_FILTERED_IMPORTANT_VIEWS =
+            "trigger_fill_request_on_filtered_important_views";
+
+    /**
      * Continas imeAction ids that is irrelevant for autofill. For example, ime_action_search. We
      * use this to avoid trigger fill request on unimportant views.
      *
@@ -167,6 +175,14 @@
     @SuppressLint("IntentName")
     public static final String DEVICE_CONFIG_NON_AUTOFILLABLE_IME_ACTION_IDS =
             "non_autofillable_ime_action_ids";
+
+    /**
+     * Whether to enable autofill on all view types (not just checkbox, spinner, datepicker etc...)
+     *
+     * @hide
+     */
+    public static final String DEVICE_CONFIG_SHOULD_ENABLE_AUTOFILL_ON_ALL_VIEW_TYPES =
+            "should_enable_autofill_on_all_view_types";
     // END AUTOFILL FOR ALL APPS FLAGS //
 
 
@@ -315,6 +331,28 @@
     }
 
     /**
+     * Whether to apply heuristic check on important views before triggering fill request
+     *
+     * @hide
+     */
+    public static boolean isTriggerFillRequestOnFilteredImportantViewsEnabled() {
+        return DeviceConfig.getBoolean(
+            DeviceConfig.NAMESPACE_AUTOFILL,
+            DEVICE_CONFIG_TRIGGER_FILL_REQUEST_ON_FILTERED_IMPORTANT_VIEWS, false);
+    }
+
+    /**
+     * Whether to enable autofill on all view types.
+     *
+     * @hide
+     */
+    public static boolean shouldEnableAutofillOnAllViewTypes(){
+        return DeviceConfig.getBoolean(
+            DeviceConfig.NAMESPACE_AUTOFILL,
+            DEVICE_CONFIG_SHOULD_ENABLE_AUTOFILL_ON_ALL_VIEW_TYPES, false);
+    }
+
+    /**
      * Get the non-autofillable ime actions from flag. This will be used in filtering
      * condition to trigger fill request.
      *
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index aef0e65..0deaa76 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -301,6 +301,14 @@
     public static final String EXTRA_AUGMENTED_AUTOFILL_CLIENT =
             "android.view.autofill.extra.AUGMENTED_AUTOFILL_CLIENT";
 
+    /**
+     * Autofill Hint to indicate that it can match any field.
+     *
+     * @hide
+     */
+    @TestApi
+    public static final String ANY_HINT = "any";
+
     private static final String SESSION_ID_TAG = "android:sessionId";
     private static final String STATE_TAG = "android:state";
     private static final String LAST_AUTOFILLED_DATA_TAG = "android:lastAutoFilledData";
@@ -666,6 +674,12 @@
     // Indicate whether trigger fill request on unimportant views is enabled
     private boolean mIsTriggerFillRequestOnUnimportantViewEnabled = false;
 
+    // Indicate whether to apply heuristic check on important views before trigger fill request
+    private boolean mIsTriggerFillRequestOnFilteredImportantViewsEnabled;
+
+    // Indicate whether to enable autofill for all view types
+    private boolean mShouldEnableAutofillOnAllViewTypes;
+
     // A set containing all non-autofillable ime actions passed by flag
     private Set<String> mNonAutofillableImeActionIdSet = new ArraySet<>();
 
@@ -683,6 +697,9 @@
     // Indicates whether called the showAutofillDialog() method.
     private boolean mShowAutofillDialogCalled = false;
 
+    // Cached autofill feature flag
+    private boolean mShouldIgnoreCredentialViews = false;
+
     private final String[] mFillDialogEnabledHints;
 
     // Tracked all views that have appeared, including views that there are no
@@ -830,6 +847,7 @@
 
         mIsFillDialogEnabled = AutofillFeatureFlags.isFillDialogEnabled();
         mFillDialogEnabledHints = AutofillFeatureFlags.getFillDialogEnabledHints();
+        mShouldIgnoreCredentialViews = AutofillFeatureFlags.shouldIgnoreCredentialViews();
         if (sDebug) {
             Log.d(TAG, "Fill dialog is enabled:" + mIsFillDialogEnabled
                     + ", hints=" + Arrays.toString(mFillDialogEnabledHints));
@@ -843,6 +861,12 @@
         mIsTriggerFillRequestOnUnimportantViewEnabled =
             AutofillFeatureFlags.isTriggerFillRequestOnUnimportantViewEnabled();
 
+        mIsTriggerFillRequestOnFilteredImportantViewsEnabled =
+            AutofillFeatureFlags.isTriggerFillRequestOnFilteredImportantViewsEnabled();
+
+        mShouldEnableAutofillOnAllViewTypes =
+            AutofillFeatureFlags.shouldEnableAutofillOnAllViewTypes();
+
         mNonAutofillableImeActionIdSet =
             AutofillFeatureFlags.getNonAutofillableImeActionIdSetFromFlag();
 
@@ -853,14 +877,39 @@
         mIsPackageFullyDeniedForAutofillForUnimportantView =
             isPackageFullyDeniedForAutofillForUnimportantView(denyListString, packageName);
 
-        mIsPackagePartiallyDeniedForAutofillForUnimportantView =
-            isPackagePartiallyDeniedForAutofillForUnimportantView(denyListString, packageName);
+        if (!mIsPackageFullyDeniedForAutofillForUnimportantView) {
+            mIsPackagePartiallyDeniedForAutofillForUnimportantView =
+                isPackagePartiallyDeniedForAutofillForUnimportantView(denyListString, packageName);
+        }
 
         if (mIsPackagePartiallyDeniedForAutofillForUnimportantView) {
             setDeniedActivitySetWithDenyList(denyListString, packageName);
         }
     }
 
+    /**
+     * Whether to apply heuristic check on important views before triggering fill request
+     *
+     * @hide
+     */
+    public boolean isTriggerFillRequestOnFilteredImportantViewsEnabled() {
+        return mIsTriggerFillRequestOnFilteredImportantViewsEnabled;
+    }
+
+    /**
+     * Whether view passes the imeAction check
+     *
+     * @hide
+     */
+    public boolean isPassingImeActionCheck(EditText editText) {
+        final int actionId = editText.getImeOptions();
+        if (mNonAutofillableImeActionIdSet.contains(String.valueOf(actionId))) {
+            // TODO: add a log to indicate what has filtered out the view
+            return false;
+        }
+        return true;
+    }
+
     private boolean isPackageFullyDeniedForAutofillForUnimportantView(
             @NonNull String denyListString, @NonNull String packageName) {
         // If "PackageName:;" is in the string, then it means the package name is in denylist
@@ -945,25 +994,32 @@
      *
      * @hide
      */
-    public final boolean isMatchingAutofillableHeuristics(@NonNull View view) {
+    public final boolean isMatchingAutofillableHeuristicsForNotImportantViews(@NonNull View view) {
         if (!mIsTriggerFillRequestOnUnimportantViewEnabled) {
             return false;
         }
+
+        // TODO: remove the autofill type check when this function is applied on both important and
+        // not important views.
+        // This check is needed here because once the view type check is lifted, addiditional
+        // unimportant views will be added to the assist structure which may cuase system health
+        // regression (viewGroup#populateChidlrenForAutofill() calls this function to decide whether
+        // to include child view)
+        if (view.getAutofillType() == View.AUTOFILL_TYPE_NONE) return false;
+
         if (view instanceof EditText) {
-            final int actionId = ((EditText) view).getImeOptions();
-            if (mNonAutofillableImeActionIdSet.contains(String.valueOf(actionId))) {
-                return false;
-            }
-            return true;
+            return isPassingImeActionCheck((EditText) view);
         }
+
         if (view instanceof CheckBox
-                || view instanceof Spinner
-                || view instanceof DatePicker
-                || view instanceof TimePicker
-                || view instanceof RadioGroup) {
+            || view instanceof Spinner
+            || view instanceof DatePicker
+            || view instanceof TimePicker
+            || view instanceof RadioGroup) {
             return true;
         }
-        return false;
+
+        return mShouldEnableAutofillOnAllViewTypes;
     }
 
 
@@ -2073,6 +2129,11 @@
     }
 
     /** @hide */
+    public boolean shouldIgnoreCredentialViews() {
+        return mShouldIgnoreCredentialViews;
+    }
+
+    /** @hide */
     public void onAuthenticationResult(int authenticationId, Intent data, View focusView) {
         if (!hasAutofillFeature()) {
             return;
diff --git a/core/java/android/view/autofill/OWNERS b/core/java/android/view/autofill/OWNERS
index 26c59a6..622b0e2 100644
--- a/core/java/android/view/autofill/OWNERS
+++ b/core/java/android/view/autofill/OWNERS
@@ -1,10 +1,6 @@
 # Bug component: 351486
 
-augale@google.com
-haoranzhang@google.com
-joannechung@google.com
-markpun@google.com
-lpeter@google.com
 simranjit@google.com
-tymtsai@google.com
+haoranzhang@google.com
+skxu@google.com
 yunicorn@google.com
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index b7f03e1..62044aa 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -182,6 +182,10 @@
     /** @hide */
     public static final int FLUSH_REASON_VIEW_TREE_APPEARED = 10;
 
+    /**
+     * After {@link UPSIDE_DOWN_CAKE}, {@link #notifyViewsDisappeared(AutofillId, long[])} wraps
+     * the virtual children with a pair of view tree appearing and view tree appeared events.
+     */
     @ChangeId
     @EnabledSince(targetSdkVersion = UPSIDE_DOWN_CAKE)
     static final long NOTIFY_NODES_DISAPPEAR_NOW_SENDS_TREE_EVENTS = 258825825L;
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index 6ddfcb8..8cff066 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -562,11 +562,11 @@
         final int numberEvents = mEvents.size();
         final String reasonString = getFlushReasonAsString(reason);
 
-        if (sDebug) {
+        if (sVerbose) {
             ContentCaptureEvent event = mEvents.get(numberEvents - 1);
             String forceString = (reason == FLUSH_REASON_FORCE_FLUSH) ? ". The force flush event "
                     + ContentCaptureEvent.getTypeAsString(event.getType()) : "";
-            Log.d(TAG, "Flushing " + numberEvents + " event(s) for " + getDebugState(reason)
+            Log.v(TAG, "Flushing " + numberEvents + " event(s) for " + getDebugState(reason)
                     + forceString);
         }
         if (mFlushHistory != null) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index fd8f549..1600a16 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -13221,10 +13221,10 @@
     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
         super.onPopulateAccessibilityEventInternal(event);
 
-        if (this.isAccessibilityDataPrivate() && !event.isAccessibilityDataPrivate()) {
-            // This view's accessibility data is private, but another view that generated this event
-            // is not, so don't append this view's text to the event in order to prevent sharing
-            // this view's contents with non-accessibility-tool services.
+        if (this.isAccessibilityDataSensitive() && !event.isAccessibilityDataSensitive()) {
+            // This view's accessibility data is sensitive, but another view that generated this
+            // event is not, so don't append this view's text to the event in order to prevent
+            // sharing this view's contents with non-accessibility-tool services.
             return;
         }
 
diff --git a/core/java/android/window/BackNavigationInfo.java b/core/java/android/window/BackNavigationInfo.java
index d7bca30..5140594 100644
--- a/core/java/android/window/BackNavigationInfo.java
+++ b/core/java/android/window/BackNavigationInfo.java
@@ -92,6 +92,8 @@
     @Nullable
     private final IOnBackInvokedCallback mOnBackInvokedCallback;
     private final boolean mPrepareRemoteAnimation;
+    @Nullable
+    private final CustomAnimationInfo mCustomAnimationInfo;
 
     /**
      * Create a new {@link BackNavigationInfo} instance.
@@ -104,11 +106,13 @@
     private BackNavigationInfo(@BackTargetType int type,
             @Nullable RemoteCallback onBackNavigationDone,
             @Nullable IOnBackInvokedCallback onBackInvokedCallback,
-            boolean isPrepareRemoteAnimation) {
+            boolean isPrepareRemoteAnimation,
+            @Nullable CustomAnimationInfo customAnimationInfo) {
         mType = type;
         mOnBackNavigationDone = onBackNavigationDone;
         mOnBackInvokedCallback = onBackInvokedCallback;
         mPrepareRemoteAnimation = isPrepareRemoteAnimation;
+        mCustomAnimationInfo = customAnimationInfo;
     }
 
     private BackNavigationInfo(@NonNull Parcel in) {
@@ -116,6 +120,7 @@
         mOnBackNavigationDone = in.readTypedObject(RemoteCallback.CREATOR);
         mOnBackInvokedCallback = IOnBackInvokedCallback.Stub.asInterface(in.readStrongBinder());
         mPrepareRemoteAnimation = in.readBoolean();
+        mCustomAnimationInfo = in.readTypedObject(CustomAnimationInfo.CREATOR);
     }
 
     /** @hide */
@@ -125,6 +130,7 @@
         dest.writeTypedObject(mOnBackNavigationDone, flags);
         dest.writeStrongInterface(mOnBackInvokedCallback);
         dest.writeBoolean(mPrepareRemoteAnimation);
+        dest.writeTypedObject(mCustomAnimationInfo, flags);
     }
 
     /**
@@ -172,6 +178,15 @@
         }
     }
 
+    /**
+     * Get customize animation info.
+     * @hide
+     */
+    @Nullable
+    public CustomAnimationInfo getCustomAnimationInfo() {
+        return mCustomAnimationInfo;
+    }
+
     /** @hide */
     @Override
     public int describeContents() {
@@ -197,6 +212,7 @@
                 + "mType=" + typeToString(mType) + " (" + mType + ")"
                 + ", mOnBackNavigationDone=" + mOnBackNavigationDone
                 + ", mOnBackInvokedCallback=" + mOnBackInvokedCallback
+                + ", mCustomizeAnimationInfo=" + mCustomAnimationInfo
                 + '}';
     }
 
@@ -223,6 +239,67 @@
     }
 
     /**
+     * Information for customize back animation.
+     * @hide
+     */
+    public static final class CustomAnimationInfo implements Parcelable {
+        private final String mPackageName;
+        private int mWindowAnimations;
+
+        /**
+         * The package name of the windowAnimations.
+         */
+        @NonNull
+        public String getPackageName() {
+            return mPackageName;
+        }
+
+        /**
+         * The resource Id of window animations.
+         */
+        public int getWindowAnimations() {
+            return mWindowAnimations;
+        }
+
+        public CustomAnimationInfo(@NonNull String packageName) {
+            this.mPackageName = packageName;
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
+            dest.writeString8(mPackageName);
+            dest.writeInt(mWindowAnimations);
+        }
+
+        private CustomAnimationInfo(@NonNull Parcel in) {
+            mPackageName = in.readString8();
+            mWindowAnimations = in.readInt();
+        }
+
+        @Override
+        public String toString() {
+            return "CustomAnimationInfo, package name= " + mPackageName;
+        }
+
+        @NonNull
+        public static final Creator<CustomAnimationInfo> CREATOR = new Creator<>() {
+            @Override
+            public CustomAnimationInfo createFromParcel(Parcel in) {
+                return new CustomAnimationInfo(in);
+            }
+
+            @Override
+            public CustomAnimationInfo[] newArray(int size) {
+                return new CustomAnimationInfo[size];
+            }
+        };
+    }
+    /**
      * @hide
      */
     @SuppressWarnings("UnusedReturnValue") // Builder pattern
@@ -233,6 +310,7 @@
         @Nullable
         private IOnBackInvokedCallback mOnBackInvokedCallback = null;
         private boolean mPrepareRemoteAnimation;
+        private CustomAnimationInfo mCustomAnimationInfo;
 
         /**
          * @see BackNavigationInfo#getType()
@@ -268,12 +346,22 @@
         }
 
         /**
+         * Set windowAnimations for customize animation.
+         */
+        public Builder setWindowAnimations(String packageName, int windowAnimations) {
+            mCustomAnimationInfo = new CustomAnimationInfo(packageName);
+            mCustomAnimationInfo.mWindowAnimations = windowAnimations;
+            return this;
+        }
+
+        /**
          * Builds and returns an instance of {@link BackNavigationInfo}
          */
         public BackNavigationInfo build() {
             return new BackNavigationInfo(mType, mOnBackNavigationDone,
                     mOnBackInvokedCallback,
-                    mPrepareRemoteAnimation);
+                    mPrepareRemoteAnimation,
+                    mCustomAnimationInfo);
         }
     }
 }
diff --git a/core/java/android/window/IBackAnimationRunner.aidl b/core/java/android/window/IBackAnimationRunner.aidl
index 1c67789..b1d7582 100644
--- a/core/java/android/window/IBackAnimationRunner.aidl
+++ b/core/java/android/window/IBackAnimationRunner.aidl
@@ -37,14 +37,13 @@
 
     /**
      * Called when the system is ready for the handler to start animating all the visible tasks.
-     * @param type The back navigation type.
      * @param apps The list of departing (type=MODE_CLOSING) and entering (type=MODE_OPENING)
                    windows to animate,
      * @param wallpapers The list of wallpapers to animate.
      * @param nonApps The list of non-app windows such as Bubbles to animate.
      * @param finishedCallback The callback to invoke when the animation is finished.
      */
-    void onAnimationStart(in int type,
+    void onAnimationStart(
             in RemoteAnimationTarget[] apps,
             in RemoteAnimationTarget[] wallpapers,
             in RemoteAnimationTarget[] nonApps,
diff --git a/core/java/android/window/SnapshotDrawerUtils.java b/core/java/android/window/SnapshotDrawerUtils.java
index 071c20f..52e17ca 100644
--- a/core/java/android/window/SnapshotDrawerUtils.java
+++ b/core/java/android/window/SnapshotDrawerUtils.java
@@ -34,6 +34,7 @@
 import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
 import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
 import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
+import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST;
@@ -223,6 +224,11 @@
                         PixelFormat.RGBA_8888,
                         GraphicBuffer.USAGE_HW_TEXTURE | GraphicBuffer.USAGE_HW_COMPOSER
                                 | GraphicBuffer.USAGE_SW_WRITE_RARELY);
+                if (background == null) {
+                    Log.e(TAG, "Unable to draw snapshot: failed to allocate graphic buffer for "
+                            + mTitle);
+                    return;
+                }
                 // TODO: Support this on HardwareBuffer
                 final Canvas c = background.lockCanvas();
                 drawBackgroundAndBars(c, frame);
@@ -410,6 +416,7 @@
         layoutParams.setFitInsetsIgnoringVisibility(attrs.isFitInsetsIgnoringVisibility());
 
         layoutParams.setTitle(title);
+        layoutParams.inputFeatures |= INPUT_FEATURE_NO_INPUT_CHANNEL;
         return layoutParams;
     }
 
diff --git a/core/java/android/window/SurfaceSyncGroup.java b/core/java/android/window/SurfaceSyncGroup.java
index 78de954..0672d63 100644
--- a/core/java/android/window/SurfaceSyncGroup.java
+++ b/core/java/android/window/SurfaceSyncGroup.java
@@ -22,6 +22,8 @@
 import android.os.Binder;
 import android.os.BinderProxy;
 import android.os.Debug;
+import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.Trace;
@@ -60,6 +62,7 @@
     private static final int MAX_COUNT = 100;
 
     private static final AtomicInteger sCounter = new AtomicInteger(0);
+    private static final int TRANSACTION_READY_TIMEOUT = 1000;
 
     private static Supplier<Transaction> sTransactionFactory = Transaction::new;
 
@@ -111,6 +114,13 @@
      */
     private final Binder mToken = new Binder();
 
+    private static final Object sHandlerThreadLock = new Object();
+    @GuardedBy("sHandlerThreadLock")
+    private static HandlerThread sHandlerThread;
+    private Handler mHandler;
+
+    private boolean mTimeoutAdded;
+
     private static boolean isLocalBinder(IBinder binder) {
         return !(binder instanceof BinderProxy);
     }
@@ -538,6 +548,11 @@
                             + transactionReadyCallback.hashCode());
         }
 
+        // Start the timeout when this SurfaceSyncGroup has been added to a parent SurfaceSyncGroup.
+        // This is because if the other SurfaceSyncGroup has bugs and doesn't complete, this SSG
+        // will get stuck. It's better to complete this SSG even if the parent SSG is broken.
+        addTimeout();
+
         boolean finished = false;
         Runnable addedToSyncListener = null;
         synchronized (mLock) {
@@ -641,6 +656,9 @@
         }
         mTransactionReadyConsumer.accept(mTransaction);
         mFinished = true;
+        if (mTimeoutAdded) {
+            mHandler.removeCallbacksAndMessages(this);
+        }
     }
 
     /**
@@ -701,6 +719,12 @@
             }
         }
 
+        // Start the timeout when another SSG has been added to this SurfaceSyncGroup. This is
+        // because if the other SurfaceSyncGroup has bugs and doesn't complete, it will affect this
+        // SSGs. So it's better to just add a timeout in case the other SSG doesn't invoke the
+        // callback and complete this SSG.
+        addTimeout();
+
         return transactionReadyCallback;
     }
 
@@ -731,6 +755,41 @@
         }
     }
 
+    private void addTimeout() {
+        synchronized (sHandlerThreadLock) {
+            if (sHandlerThread == null) {
+                sHandlerThread = new HandlerThread("SurfaceSyncGroupTimer");
+                sHandlerThread.start();
+            }
+        }
+
+        synchronized (mLock) {
+            if (mTimeoutAdded) {
+                // We only need one timeout for the entire SurfaceSyncGroup since we just want to
+                // ensure it doesn't stay stuck forever.
+                return;
+            }
+
+            if (mHandler == null) {
+                mHandler = new Handler(sHandlerThread.getLooper());
+            }
+
+            mTimeoutAdded = true;
+        }
+
+        Runnable runnable = () -> {
+            Log.e(TAG, "Failed to receive transaction ready in " + TRANSACTION_READY_TIMEOUT
+                    + "ms. Marking SurfaceSyncGroup as ready " + mName);
+            // Clear out any pending syncs in case the other syncs can't complete or timeout due to
+            // a crash.
+            synchronized (mLock) {
+                mPendingSyncs.clear();
+            }
+            markSyncReady();
+        };
+        mHandler.postDelayed(runnable, this, TRANSACTION_READY_TIMEOUT);
+    }
+
     /**
      * A frame callback that is used to synchronize SurfaceViews. The owner of the SurfaceView must
      * implement onFrameStarted when trying to sync the SurfaceView. This is to ensure the sync
diff --git a/core/java/android/window/TaskFragmentInfo.java b/core/java/android/window/TaskFragmentInfo.java
index a881a05..fa51957 100644
--- a/core/java/android/window/TaskFragmentInfo.java
+++ b/core/java/android/window/TaskFragmentInfo.java
@@ -66,6 +66,13 @@
     @NonNull
     private final List<IBinder> mActivities = new ArrayList<>();
 
+    /**
+     * List of Activity tokens that were explicitly requested to be launched in this TaskFragment.
+     * It only contains Activities that belong to the organizer process for security.
+     */
+    @NonNull
+    private final List<IBinder> mInRequestedTaskFragmentActivities = new ArrayList<>();
+
     /** Relative position of the fragment's top left corner in the parent container. */
     private final Point mPositionInParent = new Point();
 
@@ -99,15 +106,18 @@
     public TaskFragmentInfo(
             @NonNull IBinder fragmentToken, @NonNull WindowContainerToken token,
             @NonNull Configuration configuration, int runningActivityCount,
-            boolean isVisible, @NonNull List<IBinder> activities, @NonNull Point positionInParent,
-            boolean isTaskClearedForReuse, boolean isTaskFragmentClearedForPip,
-            boolean isClearedForReorderActivityToFront, @NonNull Point minimumDimensions) {
+            boolean isVisible, @NonNull List<IBinder> activities,
+            @NonNull List<IBinder> inRequestedTaskFragmentActivities,
+            @NonNull Point positionInParent, boolean isTaskClearedForReuse,
+            boolean isTaskFragmentClearedForPip, boolean isClearedForReorderActivityToFront,
+            @NonNull Point minimumDimensions) {
         mFragmentToken = requireNonNull(fragmentToken);
         mToken = requireNonNull(token);
         mConfiguration.setTo(configuration);
         mRunningActivityCount = runningActivityCount;
         mIsVisible = isVisible;
         mActivities.addAll(activities);
+        mInRequestedTaskFragmentActivities.addAll(inRequestedTaskFragmentActivities);
         mPositionInParent.set(positionInParent);
         mIsTaskClearedForReuse = isTaskClearedForReuse;
         mIsTaskFragmentClearedForPip = isTaskFragmentClearedForPip;
@@ -151,6 +161,11 @@
         return mActivities;
     }
 
+    @NonNull
+    public List<IBinder> getActivitiesRequestedInTaskFragment() {
+        return mInRequestedTaskFragmentActivities;
+    }
+
     /** Returns the relative position of the fragment's top left corner in the parent container. */
     @NonNull
     public Point getPositionInParent() {
@@ -215,6 +230,8 @@
                 && mIsVisible == that.mIsVisible
                 && getWindowingMode() == that.getWindowingMode()
                 && mActivities.equals(that.mActivities)
+                && mInRequestedTaskFragmentActivities.equals(
+                        that.mInRequestedTaskFragmentActivities)
                 && mPositionInParent.equals(that.mPositionInParent)
                 && mIsTaskClearedForReuse == that.mIsTaskClearedForReuse
                 && mIsTaskFragmentClearedForPip == that.mIsTaskFragmentClearedForPip
@@ -229,6 +246,7 @@
         mRunningActivityCount = in.readInt();
         mIsVisible = in.readBoolean();
         in.readBinderList(mActivities);
+        in.readBinderList(mInRequestedTaskFragmentActivities);
         mPositionInParent.readFromParcel(in);
         mIsTaskClearedForReuse = in.readBoolean();
         mIsTaskFragmentClearedForPip = in.readBoolean();
@@ -245,6 +263,7 @@
         dest.writeInt(mRunningActivityCount);
         dest.writeBoolean(mIsVisible);
         dest.writeBinderList(mActivities);
+        dest.writeBinderList(mInRequestedTaskFragmentActivities);
         mPositionInParent.writeToParcel(dest, flags);
         dest.writeBoolean(mIsTaskClearedForReuse);
         dest.writeBoolean(mIsTaskFragmentClearedForPip);
@@ -274,6 +293,7 @@
                 + " runningActivityCount=" + mRunningActivityCount
                 + " isVisible=" + mIsVisible
                 + " activities=" + mActivities
+                + " inRequestedTaskFragmentActivities" + mInRequestedTaskFragmentActivities
                 + " positionInParent=" + mPositionInParent
                 + " isTaskClearedForReuse=" + mIsTaskClearedForReuse
                 + " isTaskFragmentClearedForPip=" + mIsTaskFragmentClearedForPip
diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java
index 0b43eb5..4c482460 100644
--- a/core/java/android/window/TransitionInfo.java
+++ b/core/java/android/window/TransitionInfo.java
@@ -24,6 +24,7 @@
 import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN;
 import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP;
 import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
+import static android.view.Display.INVALID_DISPLAY;
 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
 import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_CLOSE;
@@ -58,6 +59,7 @@
  * @hide
  */
 public final class TransitionInfo implements Parcelable {
+    private static final String TAG = "TransitionInfo";
 
     /**
      * Modes are only a sub-set of all the transit-types since they are per-container
@@ -144,8 +146,11 @@
     /** The window should have no animation (by policy). */
     public static final int FLAG_NO_ANIMATION = 1 << 18;
 
+    /** The task is launching behind home. */
+    public static final int FLAG_TASK_LAUNCHING_BEHIND = 1 << 19;
+
     /** The first unused bit. This can be used by remotes to attach custom flags to this change. */
-    public static final int FLAG_FIRST_CUSTOM = 1 << 19;
+    public static final int FLAG_FIRST_CUSTOM = 1 << 20;
 
     /** The change belongs to a window that won't contain activities. */
     public static final int FLAGS_IS_NON_APP_WINDOW =
@@ -173,6 +178,7 @@
             FLAG_IS_SYSTEM_WINDOW,
             FLAG_BACK_GESTURE_ANIMATED,
             FLAG_NO_ANIMATION,
+            FLAG_TASK_LAUNCHING_BEHIND,
             FLAG_FIRST_CUSTOM
     })
     public @interface ChangeFlags {}
@@ -180,9 +186,7 @@
     private final @TransitionType int mType;
     private final @TransitionFlags int mFlags;
     private final ArrayList<Change> mChanges = new ArrayList<>();
-
-    private SurfaceControl mRootLeash;
-    private final Point mRootOffset = new Point();
+    private final ArrayList<Root> mRoots = new ArrayList<>();
 
     private AnimationOptions mOptions;
 
@@ -196,10 +200,7 @@
         mType = in.readInt();
         mFlags = in.readInt();
         in.readTypedList(mChanges, Change.CREATOR);
-        mRootLeash = new SurfaceControl();
-        mRootLeash.readFromParcel(in);
-        mRootLeash.setUnreleasedWarningCallSite("TransitionInfo");
-        mRootOffset.readFromParcel(in);
+        in.readTypedList(mRoots, Root.CREATOR);
         mOptions = in.readTypedObject(AnimationOptions.CREATOR);
     }
 
@@ -209,8 +210,7 @@
         dest.writeInt(mType);
         dest.writeInt(mFlags);
         dest.writeTypedList(mChanges);
-        mRootLeash.writeToParcel(dest, flags);
-        mRootOffset.writeToParcel(dest, flags);
+        dest.writeTypedList(mRoots, flags);
         dest.writeTypedObject(mOptions, flags);
     }
 
@@ -234,10 +234,15 @@
         return 0;
     }
 
-    /** @see #getRootLeash() */
-    public void setRootLeash(@NonNull SurfaceControl leash, int offsetLeft, int offsetTop) {
-        mRootLeash = leash;
-        mRootOffset.set(offsetLeft, offsetTop);
+    /** @see #getRoot */
+    public void addRootLeash(int displayId, @NonNull SurfaceControl leash,
+            int offsetLeft, int offsetTop) {
+        mRoots.add(new Root(displayId, leash, offsetLeft, offsetTop));
+    }
+
+    /** @see #getRoot */
+    public void addRoot(Root other) {
+        mRoots.add(other);
     }
 
     public void setAnimationOptions(AnimationOptions options) {
@@ -253,23 +258,52 @@
     }
 
     /**
+     * @return The number of animation roots. Most transitions should have 1, but there may be more
+     *         in some cases (such as a transition spanning multiple displays).
+     */
+    public int getRootCount() {
+        return mRoots.size();
+    }
+
+    /**
+     * @return the transition-root at a specific index.
+     */
+    @NonNull
+    public Root getRoot(int idx) {
+        return mRoots.get(idx);
+    }
+
+    /**
+     * @return the index of the transition-root associated with `displayId` or -1 if not found.
+     */
+    public int findRootIndex(int displayId) {
+        for (int i = 0; i < mRoots.size(); ++i) {
+            if (mRoots.get(i).mDisplayId == displayId) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
      * @return a surfacecontrol that can serve as a parent surfacecontrol for all the changing
      * participants to animate within. This will generally be placed at the highest-z-order
      * shared ancestor of all participants. While this is non-null, it's possible for the rootleash
      * to be invalid if the transition is a no-op.
+     *
+     * @deprecated Use {@link #getRoot} instead. This call assumes there is only one root.
      */
+    @Deprecated
     @NonNull
     public SurfaceControl getRootLeash() {
-        if (mRootLeash == null) {
-            throw new IllegalStateException("Trying to get a leash which wasn't set");
+        if (mRoots.isEmpty()) {
+            throw new IllegalStateException("Trying to get a root leash from a no-op transition.");
         }
-        return mRootLeash;
-    }
-
-    /** @return the offset (relative to the screen) of the root leash. */
-    @NonNull
-    public Point getRootOffset() {
-        return mRootOffset;
+        if (mRoots.size() > 1) {
+            android.util.Log.e(TAG, "Assuming one animation root when there are more.",
+                    new Throwable());
+        }
+        return mRoots.get(0).mLeash;
     }
 
     public AnimationOptions getAnimationOptions() {
@@ -316,8 +350,15 @@
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
-        sb.append("{t=" + transitTypeToString(mType) + " f=0x" + Integer.toHexString(mFlags)
-                + " ro=" + mRootOffset + " c=[");
+        sb.append("{t=").append(transitTypeToString(mType)).append(" f=0x")
+                .append(Integer.toHexString(mFlags)).append(" r=[");
+        for (int i = 0; i < mRoots.size(); ++i) {
+            if (i > 0) {
+                sb.append(',');
+            }
+            sb.append(mRoots.get(i).mDisplayId).append("@").append(mRoots.get(i).mOffset);
+        }
+        sb.append("] c=[");
         for (int i = 0; i < mChanges.size(); ++i) {
             if (i > 0) {
                 sb.append(',');
@@ -395,6 +436,9 @@
         if ((flags & FLAG_NO_ANIMATION) != 0) {
             sb.append(sb.length() == 0 ? "" : "|").append("NO_ANIMATION");
         }
+        if ((flags & FLAG_TASK_LAUNCHING_BEHIND) != 0) {
+            sb.append((sb.length() == 0 ? "" : "|") + "TASK_LAUNCHING_BEHIND");
+        }
         if ((flags & FLAG_FIRST_CUSTOM) != 0) {
             sb.append(sb.length() == 0 ? "" : "|").append("FIRST_CUSTOM");
         }
@@ -441,8 +485,8 @@
                 c.mSnapshot = null;
             }
         }
-        if (mRootLeash != null) {
-            mRootLeash.release();
+        for (int i = 0; i < mRoots.size(); ++i) {
+            mRoots.get(i).mLeash.release();
         }
     }
 
@@ -469,10 +513,11 @@
         for (int i = 0; i < mChanges.size(); ++i) {
             out.mChanges.add(mChanges.get(i).localRemoteCopy());
         }
-        out.mRootLeash = mRootLeash != null ? new SurfaceControl(mRootLeash, "localRemote") : null;
+        for (int i = 0; i < mRoots.size(); ++i) {
+            out.mRoots.add(mRoots.get(i).localRemoteCopy());
+        }
         // Doesn't have any native stuff, so no need for actual copy
         out.mOptions = mOptions;
-        out.mRootOffset.set(mRootOffset);
         return out;
     }
 
@@ -489,6 +534,8 @@
         private final Point mEndRelOffset = new Point();
         private ActivityManager.RunningTaskInfo mTaskInfo = null;
         private boolean mAllowEnterPip;
+        private int mStartDisplayId = INVALID_DISPLAY;
+        private int mEndDisplayId = INVALID_DISPLAY;
         private @Surface.Rotation int mStartRotation = ROTATION_UNDEFINED;
         private @Surface.Rotation int mEndRotation = ROTATION_UNDEFINED;
         /**
@@ -519,6 +566,8 @@
             mEndRelOffset.readFromParcel(in);
             mTaskInfo = in.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR);
             mAllowEnterPip = in.readBoolean();
+            mStartDisplayId = in.readInt();
+            mEndDisplayId = in.readInt();
             mStartRotation = in.readInt();
             mEndRotation = in.readInt();
             mEndFixedRotation = in.readInt();
@@ -539,6 +588,8 @@
             out.mEndRelOffset.set(mEndRelOffset);
             out.mTaskInfo = mTaskInfo;
             out.mAllowEnterPip = mAllowEnterPip;
+            out.mStartDisplayId = mStartDisplayId;
+            out.mEndDisplayId = mEndDisplayId;
             out.mStartRotation = mStartRotation;
             out.mEndRotation = mEndRotation;
             out.mEndFixedRotation = mEndFixedRotation;
@@ -601,6 +652,12 @@
         }
 
         /** Sets the start and end rotation of this container. */
+        public void setDisplayId(int start, int end) {
+            mStartDisplayId = start;
+            mEndDisplayId = end;
+        }
+
+        /** Sets the start and end rotation of this container. */
         public void setRotation(@Surface.Rotation int start, @Surface.Rotation int end) {
             mStartRotation = start;
             mEndRotation = end;
@@ -718,6 +775,14 @@
             return mAllowEnterPip;
         }
 
+        public int getStartDisplayId() {
+            return mStartDisplayId;
+        }
+
+        public int getEndDisplayId() {
+            return mEndDisplayId;
+        }
+
         @Surface.Rotation
         public int getStartRotation() {
             return mStartRotation;
@@ -769,6 +834,8 @@
             mEndRelOffset.writeToParcel(dest, flags);
             dest.writeTypedObject(mTaskInfo, flags);
             dest.writeBoolean(mAllowEnterPip);
+            dest.writeInt(mStartDisplayId);
+            dest.writeInt(mEndDisplayId);
             dest.writeInt(mStartRotation);
             dest.writeInt(mEndRotation);
             dest.writeInt(mEndFixedRotation);
@@ -815,6 +882,11 @@
             if (mEndRelOffset.x != 0 || mEndRelOffset.y != 0) {
                 sb.append(" eo="); sb.append(mEndRelOffset);
             }
+            sb.append(" d=");
+            if (mStartDisplayId != mEndDisplayId) {
+                sb.append(mStartDisplayId).append("->");
+            }
+            sb.append(mEndDisplayId);
             if (mStartRotation != mEndRotation) {
                 sb.append(" r="); sb.append(mStartRotation);
                 sb.append("->"); sb.append(mEndRotation);
@@ -1101,4 +1173,86 @@
                     };
         }
     }
+
+    /**
+     * An animation root in a transition. There is one of these for each display that contains
+     * participants. It will be placed, in z-order, right above the top-most participant and at the
+     * same position in the hierarchy. As a result, if all participants are animating within a
+     * part of the screen, the root-leash will only be in that part of the screen. In these cases,
+     * it's relative position (from the screen) is stored in {@link Root#getOffset}.
+     */
+    public static final class Root implements Parcelable {
+        private final int mDisplayId;
+        private final SurfaceControl mLeash;
+        private final Point mOffset = new Point();
+
+        public Root(int displayId, @NonNull SurfaceControl leash, int offsetLeft, int offsetTop) {
+            mDisplayId = displayId;
+            mLeash = leash;
+            mOffset.set(offsetLeft, offsetTop);
+        }
+
+        private Root(Parcel in) {
+            mDisplayId = in.readInt();
+            mLeash = new SurfaceControl();
+            mLeash.readFromParcel(in);
+            mLeash.setUnreleasedWarningCallSite("TransitionInfo.Root");
+            mOffset.readFromParcel(in);
+        }
+
+        private Root localRemoteCopy() {
+            return new Root(mDisplayId, new SurfaceControl(mLeash, "localRemote"),
+                    mOffset.x, mOffset.y);
+        }
+
+        /** @return the id of the display this root is on. */
+        public int getDisplayId() {
+            return mDisplayId;
+        }
+
+        /** @return the root's leash. Surfaces should be parented to this while animating. */
+        @NonNull
+        public SurfaceControl getLeash() {
+            return mLeash;
+        }
+
+        /** @return the offset (relative to its screen) of the root leash. */
+        @NonNull
+        public Point getOffset() {
+            return mOffset;
+        }
+
+        /** @hide */
+        @Override
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
+            dest.writeInt(mDisplayId);
+            mLeash.writeToParcel(dest, flags);
+            mOffset.writeToParcel(dest, flags);
+        }
+
+        @NonNull
+        public static final Creator<Root> CREATOR =
+                new Creator<Root>() {
+                    @Override
+                    public Root createFromParcel(Parcel in) {
+                        return new Root(in);
+                    }
+
+                    @Override
+                    public Root[] newArray(int size) {
+                        return new Root[size];
+                    }
+                };
+
+        /** @hide */
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public String toString() {
+            return mDisplayId + "@" + mOffset + ":" + mLeash;
+        }
+    }
 }
diff --git a/core/java/android/window/WindowInfosListener.java b/core/java/android/window/WindowInfosListener.java
index 8db5a5e..42bb674 100644
--- a/core/java/android/window/WindowInfosListener.java
+++ b/core/java/android/window/WindowInfosListener.java
@@ -16,6 +16,8 @@
 
 package android.window;
 
+import android.Manifest;
+import android.annotation.RequiresPermission;
 import android.graphics.Matrix;
 import android.util.Pair;
 import android.util.Size;
@@ -49,10 +51,13 @@
     /**
      * Register the WindowInfosListener.
      *
+     * Registering WindowInfosListeners should only be done within system_server and shell.
+     *
      * @return The cached values for InputWindowHandles and DisplayInfos. This is the last updated
      * value that was sent from SurfaceFlinger to this particular process. If there was nothing
      * registered previously, then the data can be empty.
      */
+    @RequiresPermission(Manifest.permission.ACCESS_SURFACE_FLINGER)
     public Pair<InputWindowHandle[], DisplayInfo[]> register() {
         return nativeRegister(mNativeListener);
     }
@@ -65,8 +70,12 @@
     }
 
     private static native long nativeCreate(WindowInfosListener thiz);
+
+    @RequiresPermission(Manifest.permission.ACCESS_SURFACE_FLINGER)
     private static native Pair<InputWindowHandle[], DisplayInfo[]> nativeRegister(long ptr);
+
     private static native void nativeUnregister(long ptr);
+
     private static native long nativeGetFinalizer();
 
     /**
diff --git a/core/java/android/window/WindowInfosListenerForTest.java b/core/java/android/window/WindowInfosListenerForTest.java
new file mode 100644
index 0000000..01e577f
--- /dev/null
+++ b/core/java/android/window/WindowInfosListenerForTest.java
@@ -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 android.window;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.TestApi;
+import android.graphics.Rect;
+import android.os.IBinder;
+import android.os.InputConfig;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.util.Pair;
+import android.view.InputWindowHandle;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.function.Consumer;
+
+/**
+ * Wrapper class to provide access to WindowInfosListener within tests.
+ *
+ * @hide
+ */
+@TestApi
+public class WindowInfosListenerForTest {
+
+    /**
+     * Window properties passed to {@code @WindowInfosListenerForTest#onWindowInfosChanged}.
+     */
+    public static class WindowInfo {
+        /**
+         * The window's token.
+         */
+        @NonNull
+        public final IBinder windowToken;
+
+        /**
+         * The window's name.
+         */
+        @NonNull
+        public final String name;
+
+        /**
+         * The window's position and size in display space.
+         */
+        @NonNull
+        public final Rect bounds;
+
+        /**
+         * True if the window is a trusted overlay.
+         */
+        public final boolean isTrustedOverlay;
+
+        WindowInfo(@NonNull IBinder windowToken, @NonNull String name, @NonNull Rect bounds,
+                int inputConfig) {
+            this.windowToken = windowToken;
+            this.name = name;
+            this.bounds = bounds;
+            this.isTrustedOverlay = (inputConfig & InputConfig.TRUSTED_OVERLAY) != 0;
+        }
+    }
+
+    private static final String TAG = "WindowInfosListenerForTest";
+
+    private ArrayMap<Consumer<List<WindowInfo>>, WindowInfosListener> mListeners;
+
+    public WindowInfosListenerForTest() {
+        mListeners = new ArrayMap<>();
+    }
+
+    /**
+     * Register a listener that is called when the system's list of visible windows has changes in
+     * position or visibility.
+     *
+     * @param consumer Consumer that is called with reverse Z ordered lists of WindowInfo instances
+     *                 where the first value is the topmost window.
+     */
+    @RequiresPermission(Manifest.permission.ACCESS_SURFACE_FLINGER)
+    public void addWindowInfosListener(
+            @NonNull Consumer<List<WindowInfo>> consumer) {
+        var calledWithInitialState = new CountDownLatch(1);
+        var listener = new WindowInfosListener() {
+            @Override
+            public void onWindowInfosChanged(InputWindowHandle[] windowHandles,
+                    DisplayInfo[] displayInfos) {
+                try {
+                    calledWithInitialState.await();
+                } catch (InterruptedException exception) {
+                    Log.e(TAG,
+                            "Exception thrown while waiting for listener to be called with "
+                                    + "initial state");
+                }
+                consumer.accept(buildWindowInfos(windowHandles));
+            }
+        };
+        mListeners.put(consumer, listener);
+        Pair<InputWindowHandle[], WindowInfosListener.DisplayInfo[]> initialState =
+                listener.register();
+        consumer.accept(buildWindowInfos(initialState.first));
+        calledWithInitialState.countDown();
+    }
+
+    /**
+     * Unregisters the listener.
+     */
+    public void removeWindowInfosListener(@NonNull Consumer<List<WindowInfo>> consumer) {
+        WindowInfosListener listener = mListeners.remove(consumer);
+        if (listener == null) {
+            return;
+        }
+        listener.unregister();
+    }
+
+    private static List<WindowInfo> buildWindowInfos(InputWindowHandle[] windowHandles) {
+        var windowInfos = new ArrayList<WindowInfo>(windowHandles.length);
+        for (var handle : windowHandles) {
+            if ((handle.inputConfig & InputConfig.NOT_VISIBLE) != 0) {
+                continue;
+            }
+            var bounds = new Rect(handle.frameLeft, handle.frameTop, handle.frameRight,
+                    handle.frameBottom);
+            windowInfos.add(new WindowInfo(handle.getWindowToken(), handle.name, bounds,
+                    handle.inputConfig));
+        }
+        return windowInfos;
+    }
+}
diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java
index a8c2b2f..8066f50 100644
--- a/core/java/android/window/WindowOnBackInvokedDispatcher.java
+++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java
@@ -357,6 +357,11 @@
         mImeDispatcher = imeDispatcher;
     }
 
+    /** Returns true if a non-null {@link ImeOnBackInvokedDispatcher} has been set. **/
+    public boolean hasImeOnBackInvokedDispatcher() {
+        return mImeDispatcher != null;
+    }
+
     /**
      * Class used to check whether a callback can be registered or not. This is meant to be
      * shared with {@link ProxyOnBackInvokedDispatcher} which needs to do the same checks.
diff --git a/core/java/com/android/internal/accessibility/dialog/AccessibilityActivityTarget.java b/core/java/com/android/internal/accessibility/dialog/AccessibilityActivityTarget.java
index 4c7d93b..063154d 100644
--- a/core/java/com/android/internal/accessibility/dialog/AccessibilityActivityTarget.java
+++ b/core/java/com/android/internal/accessibility/dialog/AccessibilityActivityTarget.java
@@ -26,6 +26,7 @@
 import android.view.accessibility.AccessibilityManager.ShortcutType;
 
 import com.android.internal.accessibility.common.ShortcutConstants.AccessibilityFragmentType;
+import com.android.internal.accessibility.common.ShortcutConstants.ShortcutMenuMode;
 
 /**
  * Base class for creating accessibility activity target.
@@ -40,8 +41,25 @@
                 isShortcutContained(context, shortcutType,
                         shortcutInfo.getComponentName().flattenToString()),
                 shortcutInfo.getComponentName().flattenToString(),
+                shortcutInfo.getActivityInfo().applicationInfo.uid,
                 shortcutInfo.getActivityInfo().loadLabel(context.getPackageManager()),
                 shortcutInfo.getActivityInfo().loadIcon(context.getPackageManager()),
                 convertToKey(convertToUserType(shortcutType)));
     }
+
+    @Override
+    public void updateActionItem(@NonNull TargetAdapter.ViewHolder holder,
+            @ShortcutMenuMode int shortcutMenuMode) {
+        super.updateActionItem(holder, shortcutMenuMode);
+
+        final boolean isAllowed = AccessibilityTargetHelper.isAccessibilityTargetAllowed(
+                getContext(), getComponentName().getPackageName(), getUid());
+        final boolean isEditMenuMode =
+                shortcutMenuMode == ShortcutMenuMode.EDIT;
+        final boolean enabled = isAllowed || (isEditMenuMode && isShortcutEnabled());
+        holder.mCheckBoxView.setEnabled(enabled);
+        holder.mIconView.setEnabled(enabled);
+        holder.mLabelView.setEnabled(enabled);
+        holder.mStatusView.setEnabled(enabled);
+    }
 }
diff --git a/core/java/com/android/internal/accessibility/dialog/AccessibilityServiceTarget.java b/core/java/com/android/internal/accessibility/dialog/AccessibilityServiceTarget.java
index e64f78a..6497409 100644
--- a/core/java/com/android/internal/accessibility/dialog/AccessibilityServiceTarget.java
+++ b/core/java/com/android/internal/accessibility/dialog/AccessibilityServiceTarget.java
@@ -26,6 +26,7 @@
 import android.view.accessibility.AccessibilityManager.ShortcutType;
 
 import com.android.internal.accessibility.common.ShortcutConstants.AccessibilityFragmentType;
+import com.android.internal.accessibility.common.ShortcutConstants.ShortcutMenuMode;
 
 /**
  * Base class for creating accessibility service target with various fragment types related to
@@ -42,8 +43,25 @@
                 isShortcutContained(context, shortcutType,
                         serviceInfo.getComponentName().flattenToString()),
                 serviceInfo.getComponentName().flattenToString(),
+                serviceInfo.getResolveInfo().serviceInfo.applicationInfo.uid,
                 serviceInfo.getResolveInfo().loadLabel(context.getPackageManager()),
                 serviceInfo.getResolveInfo().loadIcon(context.getPackageManager()),
                 convertToKey(convertToUserType(shortcutType)));
     }
+
+    @Override
+    public void updateActionItem(@NonNull TargetAdapter.ViewHolder holder,
+            @ShortcutMenuMode int shortcutMenuMode) {
+        super.updateActionItem(holder, shortcutMenuMode);
+
+        final boolean isAllowed = AccessibilityTargetHelper.isAccessibilityTargetAllowed(
+                getContext(), getComponentName().getPackageName(), getUid());
+        final boolean isEditMenuMode =
+                shortcutMenuMode == ShortcutMenuMode.EDIT;
+        final boolean enabled = isAllowed || (isEditMenuMode && isShortcutEnabled());
+        holder.mCheckBoxView.setEnabled(enabled);
+        holder.mIconView.setEnabled(enabled);
+        holder.mLabelView.setEnabled(enabled);
+        holder.mStatusView.setEnabled(enabled);
+    }
 }
diff --git a/core/java/com/android/internal/accessibility/dialog/AccessibilityShortcutChooserActivity.java b/core/java/com/android/internal/accessibility/dialog/AccessibilityShortcutChooserActivity.java
index 50afb3e..5dd558a 100644
--- a/core/java/com/android/internal/accessibility/dialog/AccessibilityShortcutChooserActivity.java
+++ b/core/java/com/android/internal/accessibility/dialog/AccessibilityShortcutChooserActivity.java
@@ -95,6 +95,13 @@
 
     private void onTargetSelected(AdapterView<?> parent, View view, int position, long id) {
         final AccessibilityTarget target = mTargets.get(position);
+        if (target instanceof AccessibilityServiceTarget
+                || target instanceof AccessibilityActivityTarget) {
+            if (sendRestrictedDialogIntentIfNeeded(target)) {
+                return;
+            }
+        }
+
         target.onSelected();
         mMenuDialog.dismiss();
     }
@@ -102,15 +109,41 @@
     private void onTargetChecked(AdapterView<?> parent, View view, int position, long id) {
         final AccessibilityTarget target = mTargets.get(position);
 
-        if ((target instanceof AccessibilityServiceTarget) && !target.isShortcutEnabled()) {
-            showPermissionDialogIfNeeded(this, (AccessibilityServiceTarget) target, mTargetAdapter);
-            return;
+        if (!target.isShortcutEnabled()) {
+            if (target instanceof AccessibilityServiceTarget
+                    || target instanceof AccessibilityActivityTarget) {
+                if (sendRestrictedDialogIntentIfNeeded(target)) {
+                    return;
+                }
+            }
+
+            if (target instanceof AccessibilityServiceTarget) {
+                showPermissionDialogIfNeeded(this, (AccessibilityServiceTarget) target,
+                        mTargetAdapter);
+                return;
+            }
         }
 
         target.onCheckedChanged(!target.isShortcutEnabled());
         mTargetAdapter.notifyDataSetChanged();
     }
 
+    /**
+     * Sends restricted dialog intent if the accessibility target is disallowed.
+     *
+     * @return true if sends restricted dialog intent, otherwise false.
+     */
+    private boolean sendRestrictedDialogIntentIfNeeded(AccessibilityTarget target) {
+        if (AccessibilityTargetHelper.isAccessibilityTargetAllowed(this,
+                target.getComponentName().getPackageName(), target.getUid())) {
+            return false;
+        }
+
+        AccessibilityTargetHelper.sendRestrictedDialogIntent(this,
+                target.getComponentName().getPackageName(), target.getUid());
+        return true;
+    }
+
     private void showPermissionDialogIfNeeded(Context context,
             AccessibilityServiceTarget serviceTarget, ShortcutTargetAdapter targetAdapter) {
         if (mPermissionDialog != null) {
diff --git a/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java b/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java
index b8446da..652cb52 100644
--- a/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java
+++ b/core/java/com/android/internal/accessibility/dialog/AccessibilityTarget.java
@@ -25,6 +25,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.ComponentName;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.view.View;
@@ -37,8 +38,11 @@
 import com.android.internal.annotations.VisibleForTesting;
 
 /**
- * Abstract base class for creating various target related to accessibility service,
- * accessibility activity, and allowlisting feature.
+ * Abstract base class for creating various target related to accessibility service, accessibility
+ * activity, and allowlisting features.
+ *
+ * <p> Disables accessibility features that are not permitted in adding a restricted padlock icon
+ * and showing admin support message dialog.
  */
 public abstract class AccessibilityTarget implements TargetOperations, OnTargetSelectedListener,
         OnTargetCheckedChangeListener {
@@ -49,6 +53,8 @@
     private int mFragmentType;
     private boolean mShortcutEnabled;
     private String mId;
+    private int mUid;
+    private ComponentName mComponentName;
     private CharSequence mLabel;
     private Drawable mIcon;
     private String mKey;
@@ -57,12 +63,14 @@
     @VisibleForTesting
     public AccessibilityTarget(Context context, @ShortcutType int shortcutType,
             @AccessibilityFragmentType int fragmentType, boolean isShortcutSwitched, String id,
-            CharSequence label, Drawable icon, String key) {
+            int uid, CharSequence label, Drawable icon, String key) {
         mContext = context;
         mShortcutType = shortcutType;
         mFragmentType = fragmentType;
         mShortcutEnabled = isShortcutSwitched;
         mId = id;
+        mUid = uid;
+        mComponentName = ComponentName.unflattenFromString(id);
         mLabel = label;
         mIcon = icon;
         mKey = key;
@@ -71,9 +79,14 @@
     @Override
     public void updateActionItem(@NonNull ViewHolder holder,
             @ShortcutConstants.ShortcutMenuMode int shortcutMenuMode) {
+        // Resetting the enable state of the item to avoid the previous wrong state of RecyclerView.
+        holder.mCheckBoxView.setEnabled(true);
+        holder.mIconView.setEnabled(true);
+        holder.mLabelView.setEnabled(true);
+        holder.mStatusView.setEnabled(true);
+
         final boolean isEditMenuMode =
                 shortcutMenuMode == ShortcutConstants.ShortcutMenuMode.EDIT;
-
         holder.mCheckBoxView.setChecked(isEditMenuMode && isShortcutEnabled());
         holder.mCheckBoxView.setVisibility(isEditMenuMode ? View.VISIBLE : View.GONE);
         holder.mIconView.setImageDrawable(getIcon());
@@ -145,6 +158,14 @@
         return mId;
     }
 
+    public int getUid() {
+        return mUid;
+    }
+
+    public ComponentName getComponentName() {
+        return mComponentName;
+    }
+
     public CharSequence getLabel() {
         return mLabel;
     }
diff --git a/core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java b/core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java
index a47a97c..0f85075 100644
--- a/core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java
+++ b/core/java/com/android/internal/accessibility/dialog/AccessibilityTargetHelper.java
@@ -35,6 +35,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.os.Build;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.text.BidiFormatter;
 import android.view.LayoutInflater;
@@ -202,12 +203,14 @@
     private static List<AccessibilityTarget> getAllowListingFeatureTargets(Context context,
             @ShortcutType int shortcutType) {
         final List<AccessibilityTarget> targets = new ArrayList<>();
+        final int uid = context.getApplicationInfo().uid;
 
         final InvisibleToggleAllowListingFeatureTarget magnification =
                 new InvisibleToggleAllowListingFeatureTarget(context,
                         shortcutType,
                         isShortcutContained(context, shortcutType, MAGNIFICATION_CONTROLLER_NAME),
                         MAGNIFICATION_CONTROLLER_NAME,
+                        uid,
                         context.getString(R.string.accessibility_magnification_chooser_text),
                         context.getDrawable(R.drawable.ic_accessibility_magnification),
                         Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED);
@@ -219,6 +222,7 @@
                         isShortcutContained(context, shortcutType,
                                 DALTONIZER_COMPONENT_NAME.flattenToString()),
                         DALTONIZER_COMPONENT_NAME.flattenToString(),
+                        uid,
                         context.getString(R.string.color_correction_feature_name),
                         context.getDrawable(R.drawable.ic_accessibility_color_correction),
                         Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED);
@@ -230,6 +234,7 @@
                         isShortcutContained(context, shortcutType,
                                 COLOR_INVERSION_COMPONENT_NAME.flattenToString()),
                         COLOR_INVERSION_COMPONENT_NAME.flattenToString(),
+                        uid,
                         context.getString(R.string.color_inversion_feature_name),
                         context.getDrawable(R.drawable.ic_accessibility_color_inversion),
                         Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
@@ -242,6 +247,7 @@
                             isShortcutContained(context, shortcutType,
                                     ONE_HANDED_COMPONENT_NAME.flattenToString()),
                             ONE_HANDED_COMPONENT_NAME.flattenToString(),
+                            uid,
                             context.getString(R.string.one_handed_mode_feature_name),
                             context.getDrawable(R.drawable.ic_accessibility_one_handed),
                             Settings.Secure.ONE_HANDED_MODE_ACTIVATED);
@@ -254,6 +260,7 @@
                         isShortcutContained(context, shortcutType,
                                 REDUCE_BRIGHT_COLORS_COMPONENT_NAME.flattenToString()),
                         REDUCE_BRIGHT_COLORS_COMPONENT_NAME.flattenToString(),
+                        uid,
                         context.getString(R.string.reduce_bright_colors_feature_name),
                         context.getDrawable(R.drawable.ic_accessibility_reduce_bright_colors),
                         Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED);
@@ -265,6 +272,7 @@
                         isShortcutContained(context, shortcutType,
                                 ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME.flattenToString()),
                         ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME.flattenToString(),
+                        uid,
                         context.getString(R.string.hearing_aids_feature_name),
                         context.getDrawable(R.drawable.ic_accessibility_hearing_aid),
                         /* key= */ null);
@@ -327,4 +335,21 @@
         final Locale locale = context.getResources().getConfiguration().getLocales().get(0);
         return BidiFormatter.getInstance(locale).unicodeWrap(label);
     }
+
+    /**
+     * Determines if the{@link AccessibilityTarget} is allowed.
+     */
+    public static boolean isAccessibilityTargetAllowed(Context context, String packageName,
+            int uid) {
+        final AccessibilityManager am = context.getSystemService(AccessibilityManager.class);
+        return am.isAccessibilityTargetAllowed(packageName, uid, UserHandle.myUserId());
+    }
+
+    /**
+     * Sends restricted dialog intent if the accessibility target is disallowed.
+     */
+    public static boolean sendRestrictedDialogIntent(Context context, String packageName, int uid) {
+        final AccessibilityManager am = context.getSystemService(AccessibilityManager.class);
+        return am.sendRestrictedDialogIntent(packageName, uid, UserHandle.myUserId());
+    }
 }
diff --git a/core/java/com/android/internal/accessibility/dialog/InvisibleToggleAllowListingFeatureTarget.java b/core/java/com/android/internal/accessibility/dialog/InvisibleToggleAllowListingFeatureTarget.java
index e78036d..c22f17d 100644
--- a/core/java/com/android/internal/accessibility/dialog/InvisibleToggleAllowListingFeatureTarget.java
+++ b/core/java/com/android/internal/accessibility/dialog/InvisibleToggleAllowListingFeatureTarget.java
@@ -29,8 +29,9 @@
 class InvisibleToggleAllowListingFeatureTarget extends AccessibilityTarget {
 
     InvisibleToggleAllowListingFeatureTarget(Context context, @ShortcutType int shortcutType,
-            boolean isShortcutSwitched, String id, CharSequence label, Drawable icon, String key) {
-        super(context, shortcutType, AccessibilityFragmentType.INVISIBLE_TOGGLE,
-                isShortcutSwitched, id, label, icon, key);
+            boolean isShortcutSwitched, String id, int uid, CharSequence label, Drawable icon,
+            String key) {
+        super(context, shortcutType, AccessibilityFragmentType.INVISIBLE_TOGGLE, isShortcutSwitched,
+                id, uid, label, icon, key);
     }
 }
diff --git a/core/java/com/android/internal/accessibility/dialog/ToggleAccessibilityServiceTarget.java b/core/java/com/android/internal/accessibility/dialog/ToggleAccessibilityServiceTarget.java
index 41a0ba2..a4ffef6 100644
--- a/core/java/com/android/internal/accessibility/dialog/ToggleAccessibilityServiceTarget.java
+++ b/core/java/com/android/internal/accessibility/dialog/ToggleAccessibilityServiceTarget.java
@@ -29,12 +29,22 @@
 import com.android.internal.accessibility.common.ShortcutConstants.ShortcutMenuMode;
 import com.android.internal.accessibility.dialog.TargetAdapter.ViewHolder;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Extension for {@link AccessibilityServiceTarget} with {@link AccessibilityFragmentType#TOGGLE}
  * type.
  */
 class ToggleAccessibilityServiceTarget extends AccessibilityServiceTarget {
 
+    /** Float enum for view alpha setting. */
+    @Retention(RetentionPolicy.SOURCE)
+    @interface StatusViewAlphaScale {
+        float OPAQUE = 1.0f;
+        float DISABLED = 0.5f;
+    }
+
     ToggleAccessibilityServiceTarget(Context context, @ShortcutType int shortcutType,
             @NonNull AccessibilityServiceInfo serviceInfo) {
         super(context,
@@ -53,9 +63,13 @@
             @ShortcutMenuMode int shortcutMenuMode) {
         super.updateActionItem(holder, shortcutMenuMode);
 
+        final boolean isAllowed = AccessibilityTargetHelper.isAccessibilityTargetAllowed(
+                getContext(), getComponentName().getPackageName(), getUid());
         final boolean isEditMenuMode =
                 shortcutMenuMode == ShortcutMenuMode.EDIT;
         holder.mStatusView.setVisibility(isEditMenuMode ? View.GONE : View.VISIBLE);
         holder.mStatusView.setText(getStateDescription());
+        holder.mStatusView.setAlpha(isAllowed
+                ? StatusViewAlphaScale.OPAQUE : StatusViewAlphaScale.DISABLED);
     }
 }
diff --git a/core/java/com/android/internal/accessibility/dialog/ToggleAllowListingFeatureTarget.java b/core/java/com/android/internal/accessibility/dialog/ToggleAllowListingFeatureTarget.java
index d2124a0..11e668f 100644
--- a/core/java/com/android/internal/accessibility/dialog/ToggleAllowListingFeatureTarget.java
+++ b/core/java/com/android/internal/accessibility/dialog/ToggleAllowListingFeatureTarget.java
@@ -35,9 +35,10 @@
 class ToggleAllowListingFeatureTarget extends AccessibilityTarget {
 
     ToggleAllowListingFeatureTarget(Context context, @ShortcutType int shortcutType,
-            boolean isShortcutSwitched, String id, CharSequence label, Drawable icon, String key) {
-        super(context, shortcutType, AccessibilityFragmentType.TOGGLE,
-                isShortcutSwitched, id, label, icon, key);
+            boolean isShortcutSwitched, String id, int uid, CharSequence label, Drawable icon,
+            String key) {
+        super(context, shortcutType, AccessibilityFragmentType.TOGGLE, isShortcutSwitched, id,
+                uid, label, icon, key);
 
         final int statusResId = isFeatureEnabled()
                 ? R.string.accessibility_shortcut_menu_item_status_on
diff --git a/core/java/com/android/internal/app/LocaleHelper.java b/core/java/com/android/internal/app/LocaleHelper.java
index 57bd3f9..d521866 100644
--- a/core/java/com/android/internal/app/LocaleHelper.java
+++ b/core/java/com/android/internal/app/LocaleHelper.java
@@ -20,6 +20,7 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.icu.text.CaseMap;
 import android.icu.text.ListFormatter;
+import android.icu.text.NumberingSystem;
 import android.icu.util.ULocale;
 import android.os.LocaleList;
 import android.text.TextUtils;
@@ -173,6 +174,21 @@
     }
 
     /**
+     * Returns numbering system value of a locale for display in the provided locale.
+     *
+     * @param locale The locale whose key value is displayed.
+     * @param displayLocale The locale in which to display the key value.
+     * @return The string of numbering system.
+     */
+    public static String getDisplayNumberingSystemKeyValue(
+            Locale locale, Locale displayLocale) {
+        ULocale uLocale = new ULocale.Builder()
+                .setUnicodeLocaleKeyword("nu", NumberingSystem.getInstance(locale).getName())
+                .build();
+        return uLocale.getDisplayKeywordValue("numbers", ULocale.forLocale(displayLocale));
+    }
+
+    /**
      * Adds the likely subtags for a provided locale ID.
      *
      * @param locale the locale to maximize.
diff --git a/core/java/com/android/internal/app/LocalePickerWithRegion.java b/core/java/com/android/internal/app/LocalePickerWithRegion.java
index 685bd9a..5dfc0ea 100644
--- a/core/java/com/android/internal/app/LocalePickerWithRegion.java
+++ b/core/java/com/android/internal/app/LocalePickerWithRegion.java
@@ -61,6 +61,7 @@
     private int mTopDistance = 0;
     private CharSequence mTitle = null;
     private OnActionExpandListener mOnActionExpandListener;
+    private boolean mIsNumberingSystem = false;
 
     /**
      * Other classes can register to be notified when a locale was selected.
@@ -90,6 +91,18 @@
         boolean hasSpecificPackageName();
     }
 
+    private static LocalePickerWithRegion createNumberingSystemPicker(
+            LocaleSelectedListener listener, LocaleStore.LocaleInfo parent,
+            boolean translatedOnly, OnActionExpandListener onActionExpandListener,
+            LocaleCollectorBase localePickerCollector) {
+        LocalePickerWithRegion localePicker = new LocalePickerWithRegion();
+        localePicker.setOnActionExpandListener(onActionExpandListener);
+        localePicker.setIsNumberingSystem(true);
+        boolean shouldShowTheList = localePicker.setListener(listener, parent,
+                translatedOnly, localePickerCollector);
+        return shouldShowTheList ? localePicker : null;
+    }
+
     private static LocalePickerWithRegion createCountryPicker(
             LocaleSelectedListener listener, LocaleStore.LocaleInfo parent,
             boolean translatedOnly, OnActionExpandListener onActionExpandListener,
@@ -128,6 +141,10 @@
         return localePicker;
     }
 
+    private void setIsNumberingSystem(boolean isNumberingSystem) {
+        mIsNumberingSystem = isNumberingSystem;
+    }
+
     /**
      * Sets the listener and initializes the locale list.
      *
@@ -184,6 +201,7 @@
         final boolean hasSpecificPackageName =
                 mLocalePickerCollector != null && mLocalePickerCollector.hasSpecificPackageName();
         mAdapter = new SuggestedLocaleAdapter(mLocaleList, countryMode, hasSpecificPackageName);
+        mAdapter.setNumberingSystemMode(mIsNumberingSystem);
         final LocaleHelper.LocaleInfoComparator comp =
                 new LocaleHelper.LocaleInfoComparator(sortingLocale, countryMode);
         mAdapter.sort(comp);
@@ -213,7 +231,6 @@
     @Override
     public void onResume() {
         super.onResume();
-
         if (mParentLocale != null) {
             getActivity().setTitle(mParentLocale.getFullNameNative());
         } else {
@@ -250,16 +267,28 @@
         // Special case for resetting the app locale to equal the system locale.
         boolean isSystemLocale = locale.isSystemLocale();
         boolean isRegionLocale = locale.getParent() != null;
+        boolean mayHaveDifferentNumberingSystem = locale.hasNumberingSystems();
 
-        if (isSystemLocale || isRegionLocale) {
+        if (isSystemLocale
+                || (isRegionLocale && !mayHaveDifferentNumberingSystem)
+                || mIsNumberingSystem) {
             if (mListener != null) {
                 mListener.onLocaleSelected(locale);
             }
             returnToParentFrame();
         } else {
-            LocalePickerWithRegion selector = LocalePickerWithRegion.createCountryPicker(
-                    mListener, locale, mTranslatedOnly /* translate only */,
-                    mOnActionExpandListener, this.mLocalePickerCollector);
+            LocalePickerWithRegion selector;
+            if (mayHaveDifferentNumberingSystem) {
+                selector =
+                        LocalePickerWithRegion.createNumberingSystemPicker(
+                        mListener, locale, mTranslatedOnly /* translate only */,
+                        mOnActionExpandListener, this.mLocalePickerCollector);
+            } else {
+                selector = LocalePickerWithRegion.createCountryPicker(
+                        mListener, locale, mTranslatedOnly /* translate only */,
+                        mOnActionExpandListener, this.mLocalePickerCollector);
+            }
+
             if (selector != null) {
                 getFragmentManager().beginTransaction()
                         .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
diff --git a/core/java/com/android/internal/app/LocaleStore.java b/core/java/com/android/internal/app/LocaleStore.java
index 8b41829..bcbfdc9 100644
--- a/core/java/com/android/internal/app/LocaleStore.java
+++ b/core/java/com/android/internal/app/LocaleStore.java
@@ -39,6 +39,9 @@
 import java.util.Set;
 
 public class LocaleStore {
+    private static final int TIER_LANGUAGE = 1;
+    private static final int TIER_REGION = 2;
+    private static final int TIER_NUMBERING = 3;
     private static final HashMap<String, LocaleInfo> sLocaleCache = new HashMap<>();
     private static final String TAG = LocaleStore.class.getSimpleName();
     private static boolean sFullyInitialized = false;
@@ -68,10 +71,13 @@
         private String mFullCountryNameNative;
         private String mLangScriptKey;
 
+        private boolean mHasNumberingSystems;
+
         private LocaleInfo(Locale locale) {
             this.mLocale = locale;
             this.mId = locale.toLanguageTag();
             this.mParent = getParent(locale);
+            this.mHasNumberingSystems = false;
             this.mIsChecked = false;
             this.mSuggestionFlags = SUGGESTION_TYPE_NONE;
             this.mIsTranslated = false;
@@ -93,6 +99,11 @@
                     .build();
         }
 
+        /** Return true if there are any same locales with different numbering system. */
+        public boolean hasNumberingSystems() {
+            return mHasNumberingSystems;
+        }
+
         @Override
         public String toString() {
             return mId;
@@ -195,6 +206,10 @@
             }
         }
 
+        String getNumberingSystem() {
+            return LocaleHelper.getDisplayNumberingSystemKeyValue(mLocale, mLocale);
+        }
+
         String getContentDescription(boolean countryMode) {
             if (countryMode) {
                 return getFullCountryNameInUiLanguage();
@@ -383,6 +398,12 @@
 
         final boolean isInDeveloperMode = Settings.Global.getInt(context.getContentResolver(),
                 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
+        Set<Locale> numberSystemLocaleList = new HashSet<>();
+        for (String localeId : LocalePicker.getSupportedLocales(context)) {
+            if (Locale.forLanguageTag(localeId).getUnicodeLocaleType("nu") != null) {
+                numberSystemLocaleList.add(Locale.forLanguageTag(localeId));
+            }
+        }
         for (String localeId : LocalePicker.getSupportedLocales(context)) {
             if (localeId.isEmpty()) {
                 throw new IllformedLocaleException("Bad locale entry in locale_config.xml");
@@ -403,6 +424,12 @@
             if (simCountries.contains(li.getLocale().getCountry())) {
                 li.mSuggestionFlags |= LocaleInfo.SUGGESTION_TYPE_SIM;
             }
+            numberSystemLocaleList.forEach(l -> {
+                if (li.getLocale().stripExtensions().equals(l.stripExtensions())) {
+                    li.mHasNumberingSystems = true;
+                }
+            });
+
             sLocaleCache.put(li.getId(), li);
             final Locale parent = li.getParent();
             if (parent != null) {
@@ -445,20 +472,43 @@
         sFullyInitialized = true;
     }
 
-    private static int getLevel(Set<String> ignorables, LocaleInfo li, boolean translatedOnly) {
-        if (ignorables.contains(li.getId())) return 0;
-        if (li.mIsPseudo) return 2;
-        if (translatedOnly && !li.isTranslated()) return 0;
-        if (li.getParent() != null) return 2;
-        return 0;
+    private static boolean isShallIgnore(
+            Set<String> ignorables, LocaleInfo li, boolean translatedOnly) {
+        if (ignorables.stream().anyMatch(tag ->
+                Locale.forLanguageTag(tag).stripExtensions()
+                        .equals(li.getLocale().stripExtensions()))) {
+            return true;
+        }
+        if (li.mIsPseudo) return false;
+        if (translatedOnly && !li.isTranslated()) return true;
+        if (li.getParent() != null) return false;
+        return true;
+    }
+
+    private static int getLocaleTier(LocaleInfo parent) {
+        if (parent == null) {
+            return TIER_LANGUAGE;
+        } else if (parent.getLocale().getCountry().isEmpty()) {
+            return TIER_REGION;
+        } else {
+            return TIER_NUMBERING;
+        }
     }
 
     /**
      * Returns a list of locales for language or region selection.
+     *
      * If the parent is null, then it is the language list.
+     *
      * If it is not null, then the list will contain all the locales that belong to that parent.
      * Example: if the parent is "ar", then the region list will contain all Arabic locales.
-     * (this is not language based, but language-script, so that it works for zh-Hant and so on.
+     * (this is not language based, but language-script, so that it works for zh-Hant and so on.)
+     *
+     * If it is not null and has country, then the list will contain all locales with that parent's
+     * language and country, i.e. containing alternate numbering systems.
+     *
+     * Example: if the parent is "ff-Adlm-BF", then the numbering list will contain all
+     * Fula (Adlam, Burkina Faso) i.e. "ff-Adlm-BF" and "ff-Adlm-BF-u-nu-latn"
      */
     @UnsupportedAppUsage
     public static Set<LocaleInfo> getLevelLocales(Context context, Set<String> ignorables,
@@ -478,28 +528,49 @@
      */
     public static Set<LocaleInfo> getLevelLocales(Context context, Set<String> ignorables,
             LocaleInfo parent, boolean translatedOnly, LocaleList explicitLocales) {
-        fillCache(context);
-        String parentId = parent == null ? null : parent.getId();
-        HashSet<LocaleInfo> result = new HashSet<>();
+        if (context != null) {
+            fillCache(context);
+        }
         HashMap<String, LocaleInfo> supportedLcoaleInfos =
                 explicitLocales == null
                         ? sLocaleCache
                         : convertExplicitLocales(explicitLocales, sLocaleCache.values());
+        return getTierLocales(ignorables, parent, translatedOnly, supportedLcoaleInfos);
+    }
 
+    private static Set<LocaleInfo> getTierLocales(
+            Set<String> ignorables,
+            LocaleInfo parent,
+            boolean translatedOnly,
+            HashMap<String, LocaleInfo> supportedLcoaleInfos) {
+
+        boolean hasTargetParent = parent != null;
+        String parentId = hasTargetParent ? parent.getId() : null;
+        HashSet<LocaleInfo> result = new HashSet<>();
         for (LocaleStore.LocaleInfo li : supportedLcoaleInfos.values()) {
-            int level = getLevel(ignorables, li, translatedOnly);
-            if (level == 2) {
-                if (parent != null) { // region selection
-                    if (parentId.equals(li.getParent().toLanguageTag())) {
-                        result.add(li);
-                    }
-                } else { // language selection
+            if (isShallIgnore(ignorables, li, translatedOnly)) {
+                continue;
+            }
+            switch(getLocaleTier(parent)) {
+                case TIER_LANGUAGE:
                     if (li.isSuggestionOfType(LocaleInfo.SUGGESTION_TYPE_SIM)) {
                         result.add(li);
                     } else {
-                        result.add(getLocaleInfo(li.getParent()));
+                        result.add(getLocaleInfo(li.getParent(), supportedLcoaleInfos));
                     }
-                }
+                    break;
+                case TIER_REGION:
+                    if (parentId.equals(li.getParent().toLanguageTag())) {
+                        result.add(getLocaleInfo(
+                                li.getLocale().stripExtensions(), supportedLcoaleInfos));
+                    }
+                    break;
+                case TIER_NUMBERING:
+                    if (parent.getLocale().stripExtensions()
+                            .equals(li.getLocale().stripExtensions())) {
+                        result.add(li);
+                    }
+                    break;
             }
         }
         return result;
@@ -538,18 +609,21 @@
     }
 
     private static LocaleList matchLocaleFromSupportedLocaleList(
-            LocaleList explicitLocales, Collection<LocaleInfo> localeinfo) {
+            LocaleList explicitLocales, Collection<LocaleInfo> localeInfos) {
+        if (localeInfos == null) {
+            return explicitLocales;
+        }
         //TODO: Adds a function for unicode extension if needed.
         Locale[] resultLocales = new Locale[explicitLocales.size()];
         for (int i = 0; i < explicitLocales.size(); i++) {
-            Locale locale = explicitLocales.get(i).stripExtensions();
+            Locale locale = explicitLocales.get(i);
             if (!TextUtils.isEmpty(locale.getCountry())) {
-                for (LocaleInfo localeInfo :localeinfo) {
+                for (LocaleInfo localeInfo :localeInfos) {
                     if (LocaleList.matchesLanguageAndScript(locale, localeInfo.getLocale())
                             && TextUtils.equals(locale.getCountry(),
                             localeInfo.getLocale().getCountry())) {
                         resultLocales[i] = localeInfo.getLocale();
-                        continue;
+                        break;
                     }
                 }
             }
@@ -562,18 +636,23 @@
 
     @UnsupportedAppUsage
     public static LocaleInfo getLocaleInfo(Locale locale) {
+        return getLocaleInfo(locale, sLocaleCache);
+    }
+
+    private static LocaleInfo getLocaleInfo(
+            Locale locale, HashMap<String, LocaleInfo> localeInfos) {
         String id = locale.toLanguageTag();
         LocaleInfo result;
-        if (!sLocaleCache.containsKey(id)) {
+        if (!localeInfos.containsKey(id)) {
             // Locale preferences can modify the language tag to current system languages, so we
             // need to check the input locale without extra u extension except numbering system.
             Locale filteredLocale = new Locale.Builder()
                     .setLocale(locale.stripExtensions())
                     .setUnicodeLocaleKeyword("nu", locale.getUnicodeLocaleType("nu"))
                     .build();
-            if (sLocaleCache.containsKey(filteredLocale.toLanguageTag())) {
+            if (localeInfos.containsKey(filteredLocale.toLanguageTag())) {
                 result = new LocaleInfo(locale);
-                LocaleInfo localeInfo = sLocaleCache.get(filteredLocale.toLanguageTag());
+                LocaleInfo localeInfo = localeInfos.get(filteredLocale.toLanguageTag());
                 // This locale is included in supported locales, so follow the settings
                 // of supported locales.
                 result.mIsPseudo = localeInfo.mIsPseudo;
@@ -582,9 +661,9 @@
                 return result;
             }
             result = new LocaleInfo(locale);
-            sLocaleCache.put(id, result);
+            localeInfos.put(id, result);
         } else {
-            result = sLocaleCache.get(id);
+            result = localeInfos.get(id);
         }
         return result;
     }
diff --git a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
index a61a6d7..08de4dfb 100644
--- a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
+++ b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
@@ -64,6 +64,7 @@
     protected ArrayList<LocaleStore.LocaleInfo> mOriginalLocaleOptions;
     protected int mSuggestionCount;
     protected final boolean mCountryMode;
+    protected boolean mIsNumberingMode;
     protected LayoutInflater mInflater;
 
     protected Locale mDisplayLocale = null;
@@ -89,6 +90,14 @@
         }
     }
 
+    public void setNumberingSystemMode(boolean isNumberSystemMode) {
+        mIsNumberingMode = isNumberSystemMode;
+    }
+
+    public boolean getIsForNumberingSystem() {
+        return mIsNumberingMode;
+    }
+
     @Override
     public boolean areAllItemsEnabled() {
         return false;
@@ -209,7 +218,6 @@
         if (convertView == null && mInflater == null) {
             mInflater = LayoutInflater.from(parent.getContext());
         }
-
         int itemType = getItemViewType(position);
         View itemView = getNewViewIfNeeded(convertView, parent, itemType, position);
         switch (itemType) {
@@ -217,13 +225,13 @@
             case TYPE_HEADER_ALL_OTHERS:
                 TextView textView = (TextView) itemView;
                 if (itemType == TYPE_HEADER_SUGGESTED) {
-                   if (mCountryMode) {
+                    if (mCountryMode && !mIsNumberingMode) {
                         setTextTo(textView, R.string.language_picker_regions_section_suggested);
                     } else {
                         setTextTo(textView, R.string.language_picker_section_suggested);
                     }
                 } else {
-                    if (mCountryMode) {
+                    if (mCountryMode && !mIsNumberingMode) {
                         setTextTo(textView, R.string.region_picker_section_all);
                     } else {
                         setTextTo(textView, R.string.language_picker_section_all);
@@ -419,9 +427,11 @@
 
     private void updateTextView(View convertView, TextView text, int position) {
         LocaleStore.LocaleInfo item = (LocaleStore.LocaleInfo) getItem(position);
-        text.setText(item.getLabel(mCountryMode));
+        text.setText(mIsNumberingMode
+                ? item.getNumberingSystem() : item.getLabel(mCountryMode));
         text.setTextLocale(item.getLocale());
-        text.setContentDescription(item.getContentDescription(mCountryMode));
+        text.setContentDescription(mIsNumberingMode
+                        ? item.getNumberingSystem() : item.getContentDescription(mCountryMode));
         if (mCountryMode) {
             int layoutDir = TextUtils.getLayoutDirectionFromLocale(item.getParent());
             //noinspection ResourceType
diff --git a/core/java/com/android/internal/app/procstats/UidState.java b/core/java/com/android/internal/app/procstats/UidState.java
index 8761b74..4911346 100644
--- a/core/java/com/android/internal/app/procstats/UidState.java
+++ b/core/java/com/android/internal/app/procstats/UidState.java
@@ -150,6 +150,7 @@
     public void resetSafely(long now) {
         mDurations.resetTable();
         mStartTime = now;
+        mProcesses.removeIf(p -> !p.isInUse());
     }
 
     /**
diff --git a/core/java/com/android/internal/infra/AbstractMultiplePendingRequestsRemoteService.java b/core/java/com/android/internal/infra/AbstractMultiplePendingRequestsRemoteService.java
index 6c01780..2a9025d 100644
--- a/core/java/com/android/internal/infra/AbstractMultiplePendingRequestsRemoteService.java
+++ b/core/java/com/android/internal/infra/AbstractMultiplePendingRequestsRemoteService.java
@@ -61,7 +61,7 @@
             final int size = mPendingRequests.size();
             if (mVerbose) Slog.v(mTag, "Sending " + size + " pending requests");
             for (int i = 0; i < size; i++) {
-                mPendingRequests.get(i).run();
+                handlePendingRequest(mPendingRequests.get(i));
             }
             mPendingRequests.clear();
         }
diff --git a/core/java/com/android/internal/infra/AbstractRemoteService.java b/core/java/com/android/internal/infra/AbstractRemoteService.java
index d5f7ba5..18414cf 100644
--- a/core/java/com/android/internal/infra/AbstractRemoteService.java
+++ b/core/java/com/android/internal/infra/AbstractRemoteService.java
@@ -107,7 +107,7 @@
     private int mServiceExitSubReason;
 
     /** Requests that have been scheduled, but that are not finished yet */
-    private final ArrayList<BasePendingRequest<S, I>> mUnfinishedRequests = new ArrayList<>();
+    protected final ArrayList<BasePendingRequest<S, I>> mUnfinishedRequests = new ArrayList<>();
 
     /**
      * Callback called when the service dies.
@@ -673,6 +673,11 @@
                 mCancelled = true;
             }
 
+            S service = mWeakService.get();
+            if (service != null) {
+                service.finishRequest(this);
+            }
+
             onCancel();
             return true;
         }
diff --git a/core/java/com/android/internal/inputmethod/ImeTracing.java b/core/java/com/android/internal/inputmethod/ImeTracing.java
index e6a9b54..db95012 100644
--- a/core/java/com/android/internal/inputmethod/ImeTracing.java
+++ b/core/java/com/android/internal/inputmethod/ImeTracing.java
@@ -62,11 +62,7 @@
             if (isSystemProcess()) {
                 sInstance = new ImeTracingServerImpl();
             } else {
-                try {
-                    sInstance = new ImeTracingClientImpl();
-                } catch (RuntimeException e) {
-                    Log.e(TAG, "Exception while creating ImeTracingClientImpl instance", e);
-                }
+                sInstance = new ImeTracingClientImpl();
             }
         }
         return sInstance;
diff --git a/core/java/com/android/internal/jank/EventLogTags.logtags b/core/java/com/android/internal/jank/EventLogTags.logtags
index 7af5d8f..ad47b81 100644
--- a/core/java/com/android/internal/jank/EventLogTags.logtags
+++ b/core/java/com/android/internal/jank/EventLogTags.logtags
@@ -3,8 +3,8 @@
 option java_package com.android.internal.jank;
 
 # Marks a request to start tracing a CUJ. Doesn't mean the request was executed.
-37001 jank_cuj_events_begin_request (CUJ Type|1|5),(Elapsed Time Ns|2|3),(Uptime Ns|2|3)
+37001 jank_cuj_events_begin_request (CUJ Type|1|5),(Unix Time Ns|2|3),(Elapsed Time Ns|2|3),(Uptime Ns|2|3)
 # Marks a request to end tracing a CUJ. Doesn't mean the request was executed.
-37002 jank_cuj_events_end_request (CUJ Type|1|5),(Elapsed Time Ns|2|3),(Uptime Time Ns|2|3)
+37002 jank_cuj_events_end_request (CUJ Type|1|5),(Unix Time Ns|2|3),(Elapsed Time Ns|2|3),(Uptime Time Ns|2|3)
 # Marks a request to cancel tracing a CUJ. Doesn't mean the request was executed.
-37003 jank_cuj_events_cancel_request (CUJ Type|1|5),(Elapsed Time Ns|2|3),(Uptime Time Ns|2|3)
+37003 jank_cuj_events_cancel_request (CUJ Type|1|5),(Unix Time Ns|2|3),(Elapsed Time Ns|2|3),(Uptime Time Ns|2|3)
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index 62f1599..7ae63b1 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -37,6 +37,7 @@
 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_QUICK_SWITCH;
 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;
@@ -127,6 +128,7 @@
 
 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;
@@ -240,6 +242,7 @@
     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_IME_INSETS_ANIMATION = 69;
+    public static final int CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION = 70;
 
     private static final int NO_STATSD_LOGGING = -1;
 
@@ -318,6 +321,7 @@
             UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_SWIPE,
             UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_TO_HOME,
             UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_ANIMATION,
+            UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_CLOCK_MOVE_ANIMATION,
     };
 
     private static class InstanceHolder {
@@ -412,6 +416,7 @@
             CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE,
             CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME,
             CUJ_IME_INSETS_ANIMATION,
+            CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface CujType {
@@ -574,8 +579,10 @@
     public boolean begin(@NonNull Configuration.Builder builder) {
         try {
             final Configuration config = builder.build();
-            EventLogTags.writeJankCujEventsBeginRequest(
-                    config.mCujType, SystemClock.elapsedRealtimeNanos(), SystemClock.uptimeNanos());
+            postEventLogToWorkerThread((unixNanos, elapsedNanos, realtimeNanos) -> {
+                EventLogTags.writeJankCujEventsBeginRequest(
+                        config.mCujType, unixNanos, elapsedNanos, realtimeNanos);
+            });
             final TrackerResult result = new TrackerResult();
             final boolean success = config.getHandler().runWithScissors(
                     () -> result.mResult = beginInternal(config), EXECUTOR_TASK_TIMEOUT);
@@ -649,8 +656,10 @@
      * @return boolean true if the tracker is ended successfully, false otherwise.
      */
     public boolean end(@CujType int cujType) {
-        EventLogTags.writeJankCujEventsEndRequest(cujType, SystemClock.elapsedRealtimeNanos(),
-                SystemClock.uptimeNanos());
+        postEventLogToWorkerThread((unixNanos, elapsedNanos, realtimeNanos) -> {
+            EventLogTags.writeJankCujEventsEndRequest(
+                    cujType, unixNanos, elapsedNanos, realtimeNanos);
+        });
         FrameTracker tracker = getTracker(cujType);
         // Skip this call since we haven't started a trace yet.
         if (tracker == null) return false;
@@ -688,8 +697,10 @@
      * @return boolean true if the tracker is cancelled successfully, false otherwise.
      */
     public boolean cancel(@CujType int cujType) {
-        EventLogTags.writeJankCujEventsCancelRequest(cujType, SystemClock.elapsedRealtimeNanos(),
-                SystemClock.uptimeNanos());
+        postEventLogToWorkerThread((unixNanos, elapsedNanos, realtimeNanos) -> {
+            EventLogTags.writeJankCujEventsCancelRequest(
+                    cujType, unixNanos, elapsedNanos, realtimeNanos);
+        });
         return cancel(cujType, REASON_CANCEL_NORMAL);
     }
 
@@ -946,6 +957,8 @@
                 return "LAUNCHER_CLOSE_ALL_APPS_TO_HOME";
             case CUJ_IME_INSETS_ANIMATION:
                 return "IME_INSETS_ANIMATION";
+            case CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION:
+                return "LOCKSCREEN_CLOCK_MOVE_ANIMATION";
         }
         return "UNKNOWN";
     }
@@ -1278,4 +1291,21 @@
             return mReason;
         }
     }
+
+    @FunctionalInterface
+    private interface TimeFunction {
+        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();
+
+        mWorker.getThreadHandler().post(() -> {
+            logFunction.invoke(unixNanos, elapsedNanos, realtimeNanos);
+        });
+    }
 }
diff --git a/core/java/com/android/internal/midi/EventScheduler.java b/core/java/com/android/internal/midi/EventScheduler.java
index 506902f6..426cd74 100644
--- a/core/java/com/android/internal/midi/EventScheduler.java
+++ b/core/java/com/android/internal/midi/EventScheduler.java
@@ -16,7 +16,6 @@
 
 package com.android.internal.midi;
 
-import java.util.Iterator;
 import java.util.SortedMap;
 import java.util.TreeMap;
 
@@ -26,11 +25,11 @@
  * And only one Thread can read from the buffer.
  */
 public class EventScheduler {
-    private static final long NANOS_PER_MILLI = 1000000;
+    public static final long NANOS_PER_MILLI = 1000000;
 
     private final Object mLock = new Object();
-    volatile private SortedMap<Long, FastEventQueue> mEventBuffer;
-    private FastEventQueue mEventPool = null;
+    protected volatile SortedMap<Long, FastEventQueue> mEventBuffer;
+    protected FastEventQueue mEventPool = null;
     private int mMaxPoolSize = 200;
     private boolean mClosed;
 
@@ -38,9 +37,13 @@
         mEventBuffer = new TreeMap<Long, FastEventQueue>();
     }
 
-    // If we keep at least one node in the list then it can be atomic
-    // and non-blocking.
-    private class FastEventQueue {
+    /**
+     * Class for a fast event queue.
+     *
+     * If we keep at least one node in the list then it can be atomic
+     * and non-blocking.
+     */
+    public static class FastEventQueue {
         // One thread takes from the beginning of the list.
         volatile SchedulableEvent mFirst;
         // A second thread returns events to the end of the list.
@@ -48,7 +51,7 @@
         volatile long mEventsAdded;
         volatile long mEventsRemoved;
 
-        FastEventQueue(SchedulableEvent event) {
+        public FastEventQueue(SchedulableEvent event) {
             mFirst = event;
             mLast = mFirst;
             mEventsAdded = 1;
@@ -149,7 +152,8 @@
      * @param event
      */
     public void add(SchedulableEvent event) {
-        synchronized (mLock) {
+        Object lock = getLock();
+        synchronized (lock) {
             FastEventQueue list = mEventBuffer.get(event.getTimestamp());
             if (list == null) {
                 long lowestTime = mEventBuffer.isEmpty() ? Long.MAX_VALUE
@@ -159,7 +163,7 @@
                 // If the event we added is earlier than the previous earliest
                 // event then notify any threads waiting for the next event.
                 if (event.getTimestamp() < lowestTime) {
-                    mLock.notify();
+                    lock.notify();
                 }
             } else {
                 list.add(event);
@@ -167,7 +171,7 @@
         }
     }
 
-    private SchedulableEvent removeNextEventLocked(long lowestTime) {
+    protected SchedulableEvent removeNextEventLocked(long lowestTime) {
         SchedulableEvent event;
         FastEventQueue list = mEventBuffer.get(lowestTime);
         // Remove list from tree if this is the last node.
@@ -186,7 +190,8 @@
      */
     public SchedulableEvent getNextEvent(long time) {
         SchedulableEvent event = null;
-        synchronized (mLock) {
+        Object lock = getLock();
+        synchronized (lock) {
             if (!mEventBuffer.isEmpty()) {
                 long lowestTime = mEventBuffer.firstKey();
                 // Is it time for this list to be processed?
@@ -209,7 +214,8 @@
      */
     public SchedulableEvent waitNextEvent() throws InterruptedException {
         SchedulableEvent event = null;
-        synchronized (mLock) {
+        Object lock = getLock();
+        synchronized (lock) {
             while (!mClosed) {
                 long millisToWait = Integer.MAX_VALUE;
                 if (!mEventBuffer.isEmpty()) {
@@ -231,7 +237,7 @@
                         }
                     }
                 }
-                mLock.wait((int) millisToWait);
+                lock.wait((int) millisToWait);
             }
         }
         return event;
@@ -242,10 +248,25 @@
         mEventBuffer = new TreeMap<Long, FastEventQueue>();
     }
 
+    /**
+     * Stops the EventScheduler.
+     * The subscriber calling waitNextEvent() will get one final SchedulableEvent returning null.
+     */
     public void close() {
-        synchronized (mLock) {
+        Object lock = getLock();
+        synchronized (lock) {
             mClosed = true;
-            mLock.notify();
+            lock.notify();
         }
     }
+
+    /**
+     * Gets the lock. This doesn't lock it in anyway.
+     * Subclasses can override this.
+     *
+     * @return Object
+     */
+    protected Object getLock() {
+        return mLock;
+    }
 }
diff --git a/core/java/com/android/internal/midi/MidiEventMultiScheduler.java b/core/java/com/android/internal/midi/MidiEventMultiScheduler.java
new file mode 100644
index 0000000..16e4abe
--- /dev/null
+++ b/core/java/com/android/internal/midi/MidiEventMultiScheduler.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.midi;
+
+/**
+ * Uses multiple MidiEventSchedulers for waiting for events.
+ *
+ */
+public class MidiEventMultiScheduler {
+    private MultiLockMidiEventScheduler[] mMidiEventSchedulers;
+    private int mNumEventSchedulers;
+    private int mNumClosedSchedulers = 0;
+    private final Object mMultiLock = new Object();
+
+    private class MultiLockMidiEventScheduler extends MidiEventScheduler {
+        @Override
+        public void close() {
+            synchronized (mMultiLock) {
+                mNumClosedSchedulers++;
+            }
+            super.close();
+        }
+
+        @Override
+        protected Object getLock() {
+            return mMultiLock;
+        }
+
+        public boolean isEventBufferEmptyLocked() {
+            return mEventBuffer.isEmpty();
+        }
+
+        public long getLowestTimeLocked() {
+            return mEventBuffer.firstKey();
+        }
+    }
+
+    /**
+     * MidiEventMultiScheduler constructor
+     *
+     * @param numSchedulers the number of schedulers to create
+     */
+    public MidiEventMultiScheduler(int numSchedulers) {
+        mNumEventSchedulers = numSchedulers;
+        mMidiEventSchedulers = new MultiLockMidiEventScheduler[numSchedulers];
+        for (int i = 0; i < numSchedulers; i++) {
+            mMidiEventSchedulers[i] = new MultiLockMidiEventScheduler();
+        }
+    }
+
+    /**
+     * Waits for the next MIDI event. This will return true when it receives it.
+     * If all MidiEventSchedulers have been closed, this will return false.
+     *
+     * @return true if a MIDI event is received and false if all schedulers are closed.
+     */
+    public boolean waitNextEvent() throws InterruptedException {
+        synchronized (mMultiLock) {
+            while (true) {
+                if (mNumClosedSchedulers >= mNumEventSchedulers) {
+                    return false;
+                }
+                long lowestTime = Long.MAX_VALUE;
+                long now = System.nanoTime();
+                for (MultiLockMidiEventScheduler eventScheduler : mMidiEventSchedulers) {
+                    if (!eventScheduler.isEventBufferEmptyLocked()) {
+                        lowestTime = Math.min(lowestTime,
+                                eventScheduler.getLowestTimeLocked());
+                    }
+                }
+                if (lowestTime <= now) {
+                    return true;
+                }
+                long nanosToWait = lowestTime - now;
+                // Add 1 millisecond so we don't wake up before it is
+                // ready.
+                long millisToWait = 1 + (nanosToWait / EventScheduler.NANOS_PER_MILLI);
+                // Clip 64-bit value to 32-bit max.
+                if (millisToWait > Integer.MAX_VALUE) {
+                    millisToWait = Integer.MAX_VALUE;
+                }
+                mMultiLock.wait(millisToWait);
+            }
+        }
+    }
+
+    /**
+     * Gets the number of MidiEventSchedulers.
+     *
+     * @return the number of MidiEventSchedulers.
+     */
+    public int getNumEventSchedulers() {
+        return mNumEventSchedulers;
+    }
+
+    /**
+     * Gets a specific MidiEventScheduler based on the index.
+     *
+     * @param index the zero indexed index of a MIDI event scheduler
+     * @return a MidiEventScheduler
+     */
+    public MidiEventScheduler getEventScheduler(int index) {
+        return mMidiEventSchedulers[index];
+    }
+
+    /**
+     * Closes all event schedulers.
+     */
+    public void close() {
+        for (MidiEventScheduler eventScheduler : mMidiEventSchedulers) {
+            eventScheduler.close();
+        }
+    }
+}
diff --git a/core/java/com/android/internal/midi/MidiEventScheduler.java b/core/java/com/android/internal/midi/MidiEventScheduler.java
index 7b01904..1b2934d 100644
--- a/core/java/com/android/internal/midi/MidiEventScheduler.java
+++ b/core/java/com/android/internal/midi/MidiEventScheduler.java
@@ -79,7 +79,7 @@
     /**
      * Create an event that contains the message.
      */
-    private MidiEvent createScheduledEvent(byte[] msg, int offset, int count,
+    public MidiEvent createScheduledEvent(byte[] msg, int offset, int count,
             long timestamp) {
         MidiEvent event;
         if (count > POOL_EVENT_SIZE) {
diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java
index 0489dc81..fef5e83 100644
--- a/core/java/com/android/internal/notification/SystemNotificationChannels.java
+++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java
@@ -17,7 +17,6 @@
 import static android.app.admin.DevicePolicyResources.Strings.Core.NOTIFICATION_CHANNEL_DEVICE_ADMIN;
 
 import android.app.INotificationManager;
-import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.admin.DevicePolicyManager;
@@ -25,7 +24,6 @@
 import android.content.pm.ParceledListSlice;
 import android.media.AudioAttributes;
 import android.os.RemoteException;
-import android.provider.Settings;
 
 import com.android.internal.R;
 
@@ -78,9 +76,7 @@
         final NotificationChannel physicalKeyboardChannel = new NotificationChannel(
                 PHYSICAL_KEYBOARD,
                 context.getString(R.string.notification_channel_physical_keyboard),
-                NotificationManager.IMPORTANCE_DEFAULT);
-        physicalKeyboardChannel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI,
-                Notification.AUDIO_ATTRIBUTES_DEFAULT);
+                NotificationManager.IMPORTANCE_LOW);
         physicalKeyboardChannel.setBlockable(true);
         channelsList.add(physicalKeyboardChannel);
 
diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java
index 65655b7..70514c3 100644
--- a/core/java/com/android/internal/os/ProcessCpuTracker.java
+++ b/core/java/com/android/internal/os/ProcessCpuTracker.java
@@ -80,10 +80,6 @@
     /** Stores user time and system time in jiffies. */
     private final long[] mProcessStatsData = new long[4];
 
-    /** Stores user time and system time in jiffies.  Used for
-     * public API to retrieve CPU use for a process.  Must lock while in use. */
-    private final long[] mSinglePidStatsData = new long[4];
-
     private static final int[] PROCESS_FULL_STATS_FORMAT = new int[] {
         PROC_SPACE_TERM,
         PROC_SPACE_TERM|PROC_PARENS|PROC_OUT_STRING,    // 2: name
@@ -629,17 +625,15 @@
      * executing in both user and system code. Safe to call without lock held.
      */
     public long getCpuTimeForPid(int pid) {
-        synchronized (mSinglePidStatsData) {
-            final String statFile = "/proc/" + pid + "/stat";
-            final long[] statsData = mSinglePidStatsData;
-            if (Process.readProcFile(statFile, PROCESS_STATS_FORMAT,
-                    null, statsData, null)) {
-                long time = statsData[PROCESS_STAT_UTIME]
+        final String statFile = "/proc/" + pid + "/stat";
+        final long[] statsData = new long[4];
+        if (Process.readProcFile(statFile, PROCESS_STATS_FORMAT,
+                null, statsData, null)) {
+            long time = statsData[PROCESS_STAT_UTIME]
                         + statsData[PROCESS_STAT_STIME];
-                return time * mJiffyMillis;
-            }
-            return 0;
+            return time * mJiffyMillis;
         }
+        return 0;
     }
 
     /**
@@ -647,15 +641,13 @@
      * in the runqueue. Safe to call without lock held.
      */
     public long getCpuDelayTimeForPid(int pid) {
-        synchronized (mSinglePidStatsData) {
-            final String statFile = "/proc/" + pid + "/schedstat";
-            final long[] statsData = mSinglePidStatsData;
-            if (Process.readProcFile(statFile, PROCESS_SCHEDSTATS_FORMAT,
-                    null, statsData, null)) {
-                return statsData[PROCESS_SCHEDSTAT_CPU_DELAY_TIME] / 1_000_000;
-            }
-            return 0;
+        final String statFile = "/proc/" + pid + "/schedstat";
+        final long[] statsData = new long[4];
+        if (Process.readProcFile(statFile, PROCESS_SCHEDSTATS_FORMAT,
+                null, statsData, null)) {
+            return statsData[PROCESS_SCHEDSTAT_CPU_DELAY_TIME] / 1_000_000;
         }
+        return 0;
     }
 
     /**
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 8a9445d..28b98d6 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -16,14 +16,10 @@
 
 package com.android.internal.os;
 
-import static com.android.internal.os.SafeZipPathValidatorCallback.VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL;
-
-import android.annotation.TestApi;
 import android.app.ActivityManager;
 import android.app.ActivityThread;
 import android.app.ApplicationErrorReport;
 import android.app.IActivityManager;
-import android.app.compat.CompatChanges;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.type.DefaultMimeMapFactory;
 import android.net.TrafficStats;
@@ -40,7 +36,6 @@
 
 import dalvik.system.RuntimeHooks;
 import dalvik.system.VMRuntime;
-import dalvik.system.ZipPathValidator;
 
 import libcore.content.type.MimeMap;
 
@@ -265,31 +260,10 @@
          */
         TrafficStats.attachSocketTagger();
 
-        /*
-         * Initialize the zip path validator callback depending on the targetSdk.
-         */
-        initZipPathValidatorCallback();
-
         initialized = true;
     }
 
     /**
-     * If targetSDK >= U: set the safe zip path validator callback which disallows dangerous zip
-     * entry names.
-     * Otherwise: clear the callback to the default validation.
-     *
-     * @hide
-     */
-    @TestApi
-    public static void initZipPathValidatorCallback() {
-        if (CompatChanges.isChangeEnabled(VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL)) {
-            ZipPathValidator.setCallback(new SafeZipPathValidatorCallback());
-        } else {
-            ZipPathValidator.clearCallback();
-        }
-    }
-
-    /**
      * Returns an HTTP user agent of the form
      * "Dalvik/1.1.0 (Linux; U; Android Eclair Build/MAIN)".
      */
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index c41b822..9b9e010 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -295,6 +295,7 @@
     private boolean mClosingActionMenu;
 
     private int mVolumeControlStreamType = AudioManager.USE_DEFAULT_STREAM_TYPE;
+    private int mAudioMode = AudioManager.MODE_NORMAL;
     private MediaController mMediaController;
 
     private AudioManager mAudioManager;
@@ -317,6 +318,8 @@
         }
     };
 
+    private AudioManager.OnModeChangedListener mOnModeChangedListener;
+
     private Transition mEnterTransition = null;
     private Transition mReturnTransition = USE_DEFAULT_TRANSITION;
     private Transition mExitTransition = null;
@@ -1944,7 +1947,7 @@
             case KeyEvent.KEYCODE_VOLUME_MUTE: {
                 // If we have a session and no active phone call send it the volume command,
                 // otherwise use the suggested stream.
-                if (mMediaController != null && !isActivePhoneCallKnown()) {
+                if (mMediaController != null && !isActivePhoneCallOngoing()) {
                     getMediaSessionManager().dispatchVolumeKeyEventToSessionAsSystemService(event,
                             mMediaController.getSessionToken());
                 } else {
@@ -1995,16 +1998,9 @@
         return false;
     }
 
-    private boolean isActivePhoneCallKnown() {
-        boolean isActivePhoneCallKnown = false;
-        AudioManager audioManager =
-                (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
-        int audioManagerMode = audioManager.getMode();
-        if (audioManagerMode == AudioManager.MODE_IN_CALL
-                || audioManagerMode == AudioManager.MODE_IN_COMMUNICATION) {
-            isActivePhoneCallKnown = true;
-        }
-        return isActivePhoneCallKnown;
+    private boolean isActivePhoneCallOngoing() {
+        return mAudioMode == AudioManager.MODE_IN_CALL
+                || mAudioMode == AudioManager.MODE_IN_COMMUNICATION;
     }
 
     private KeyguardManager getKeyguardManager() {
@@ -2331,6 +2327,14 @@
         }
     }
 
+    @Override
+    protected void onDestroy() {
+        if (mOnModeChangedListener != null) {
+            getAudioManager().removeOnModeChangedListener(mOnModeChangedListener);
+            mOnModeChangedListener = null;
+        }
+    }
+
     private class PanelMenuPresenterCallback implements MenuPresenter.Callback {
         @Override
         public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
@@ -3229,6 +3233,15 @@
     @Override
     public void setMediaController(MediaController controller) {
         mMediaController = controller;
+        if (controller != null && mOnModeChangedListener == null) {
+            mAudioMode = getAudioManager().getMode();
+            mOnModeChangedListener = mode -> mAudioMode = mode;
+            getAudioManager().addOnModeChangedListener(getContext().getMainExecutor(),
+                    mOnModeChangedListener);
+        } else if (mOnModeChangedListener != null) {
+            getAudioManager().removeOnModeChangedListener(mOnModeChangedListener);
+            mOnModeChangedListener = null;
+        }
     }
 
     @Override
diff --git a/core/java/com/android/internal/policy/TransitionAnimation.java b/core/java/com/android/internal/policy/TransitionAnimation.java
index 600ae50..5cab674 100644
--- a/core/java/com/android/internal/policy/TransitionAnimation.java
+++ b/core/java/com/android/internal/policy/TransitionAnimation.java
@@ -265,6 +265,34 @@
         }
         return null;
     }
+
+    /** Get animation resId by attribute Id from specific LayoutParams */
+    public int getAnimationResId(LayoutParams lp, int animAttr, int transit) {
+        int resId = Resources.ID_NULL;
+        if (animAttr >= 0) {
+            AttributeCache.Entry ent = getCachedAnimations(lp);
+            if (ent != null) {
+                resId = ent.array.getResourceId(animAttr, 0);
+            }
+        }
+        resId = updateToTranslucentAnimIfNeeded(resId, transit);
+        return resId;
+    }
+
+    /** Get default animation resId */
+    public int getDefaultAnimationResId(int animAttr, int transit) {
+        int resId = Resources.ID_NULL;
+        if (animAttr >= 0) {
+            AttributeCache.Entry ent = getCachedAnimations(DEFAULT_PACKAGE,
+                    mDefaultWindowAnimationStyleResId);
+            if (ent != null) {
+                resId = ent.array.getResourceId(animAttr, 0);
+            }
+        }
+        resId = updateToTranslucentAnimIfNeeded(resId, transit);
+        return resId;
+    }
+
     /**
      * Load animation by attribute Id from a specific AnimationStyle resource.
      *
diff --git a/core/java/com/android/internal/protolog/BaseProtoLogImpl.java b/core/java/com/android/internal/protolog/BaseProtoLogImpl.java
index cd55d32..abe6c7c 100644
--- a/core/java/com/android/internal/protolog/BaseProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/BaseProtoLogImpl.java
@@ -72,11 +72,13 @@
     private static final String TAG = "ProtoLog";
     private static final long MAGIC_NUMBER_VALUE = ((long) MAGIC_NUMBER_H << 32) | MAGIC_NUMBER_L;
     static final String PROTOLOG_VERSION = "1.0.0";
+    private static final int DEFAULT_PER_CHUNK_SIZE = 0;
 
     private final File mLogFile;
     private final String mViewerConfigFilename;
     private final TraceBuffer mBuffer;
     protected final ProtoLogViewerConfigReader mViewerConfig;
+    private final int mPerChunkSize;
 
     private boolean mProtoLogEnabled;
     private boolean mProtoLogEnabledLockFree;
@@ -160,7 +162,7 @@
             return;
         }
         try {
-            ProtoOutputStream os = new ProtoOutputStream();
+            ProtoOutputStream os = new ProtoOutputStream(mPerChunkSize);
             long token = os.start(LOG);
             os.write(MESSAGE_HASH, messageHash);
             os.write(ELAPSED_REALTIME_NANOS, SystemClock.elapsedRealtimeNanos());
@@ -219,10 +221,16 @@
 
     public BaseProtoLogImpl(File file, String viewerConfigFilename, int bufferCapacity,
             ProtoLogViewerConfigReader viewerConfig) {
+        this(file, viewerConfigFilename, bufferCapacity, viewerConfig, DEFAULT_PER_CHUNK_SIZE);
+    }
+
+    public BaseProtoLogImpl(File file, String viewerConfigFilename, int bufferCapacity,
+            ProtoLogViewerConfigReader viewerConfig, int perChunkSize) {
         mLogFile = file;
         mBuffer = new TraceBuffer(bufferCapacity);
         mViewerConfigFilename = viewerConfigFilename;
         mViewerConfig = viewerConfig;
+        mPerChunkSize = perChunkSize;
     }
 
     /**
@@ -259,6 +267,7 @@
             if (writeToFile) {
                 writeProtoLogToFileLocked();
                 logAndPrintln(pw, "Log written to " + mLogFile + ".");
+                mBuffer.resetBuffer();
             }
             if (mProtoLogEnabled) {
                 logAndPrintln(pw, "ERROR: logging was re-enabled while waiting for flush.");
@@ -367,7 +376,7 @@
         try {
             long offset =
                     (System.currentTimeMillis() - (SystemClock.elapsedRealtimeNanos() / 1000000));
-            ProtoOutputStream proto = new ProtoOutputStream();
+            ProtoOutputStream proto = new ProtoOutputStream(mPerChunkSize);
             proto.write(MAGIC_NUMBER, MAGIC_NUMBER_VALUE);
             proto.write(VERSION, PROTOLOG_VERSION);
             proto.write(REAL_TIME_TO_ELAPSED_TIME_OFFSET_MILLIS, offset);
diff --git a/core/java/com/android/internal/protolog/ProtoLogImpl.java b/core/java/com/android/internal/protolog/ProtoLogImpl.java
index 353c6c0..527cfdd 100644
--- a/core/java/com/android/internal/protolog/ProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/ProtoLogImpl.java
@@ -30,6 +30,7 @@
     private static final int BUFFER_CAPACITY = 1024 * 1024;
     private static final String LOG_FILENAME = "/data/misc/wmtrace/wm_log.winscope";
     private static final String VIEWER_CONFIG_FILENAME = "/system/etc/protolog.conf.json.gz";
+    private static final int PER_CHUNK_SIZE = 1024;
 
     private static ProtoLogImpl sServiceInstance = null;
 
@@ -94,7 +95,10 @@
     public static synchronized ProtoLogImpl getSingleInstance() {
         if (sServiceInstance == null) {
             sServiceInstance = new ProtoLogImpl(
-                    new File(LOG_FILENAME), BUFFER_CAPACITY, new ProtoLogViewerConfigReader());
+                    new File(LOG_FILENAME)
+                    , BUFFER_CAPACITY
+                    , new ProtoLogViewerConfigReader()
+                    , PER_CHUNK_SIZE);
         }
         return sServiceInstance;
     }
@@ -105,8 +109,8 @@
     }
 
     public ProtoLogImpl(File logFile, int bufferCapacity,
-            ProtoLogViewerConfigReader viewConfigReader) {
-        super(logFile, VIEWER_CONFIG_FILENAME, bufferCapacity, viewConfigReader);
-    }
+            ProtoLogViewerConfigReader viewConfigReader, int perChunkSize) {
+        super(logFile, VIEWER_CONFIG_FILENAME, bufferCapacity, viewConfigReader, perChunkSize);
+  }
 }
 
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index a646df3..a781454 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -18,7 +18,7 @@
 
 import android.app.PendingIntent;
 import android.app.RemoteLockscreenValidationResult;
-import android.app.StartLockscreenValidationRequest;
+import android.app.RemoteLockscreenValidationSession;
 import android.app.trust.IStrongAuthTracker;
 import android.os.Bundle;
 import android.security.keystore.recovery.WrappedApplicationKey;
@@ -95,7 +95,7 @@
             in byte[] recoveryKeyBlob,
             in List<WrappedApplicationKey> applicationKeys);
     void closeSession(in String sessionId);
-    StartLockscreenValidationRequest startRemoteLockscreenValidation();
+    RemoteLockscreenValidationSession startRemoteLockscreenValidation();
     RemoteLockscreenValidationResult validateRemoteLockscreen(in byte[] encryptedCredential);
     boolean hasSecureLockScreen();
     boolean tryUnlockWithCachedUnifiedChallenge(int userId);
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index f72c4c3..4d91410 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -29,7 +29,7 @@
 import android.annotation.UserIdInt;
 import android.app.PropertyInvalidatedCache;
 import android.app.RemoteLockscreenValidationResult;
-import android.app.StartLockscreenValidationRequest;
+import android.app.RemoteLockscreenValidationSession;
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.PasswordMetrics;
 import android.app.trust.IStrongAuthTracker;
@@ -133,6 +133,21 @@
     })
     public @interface CredentialType {}
 
+    public static String credentialTypeToString(int credentialType) {
+        switch (credentialType) {
+            case CREDENTIAL_TYPE_NONE:
+                return "NONE";
+            case CREDENTIAL_TYPE_PATTERN:
+                return "PATTERN";
+            case CREDENTIAL_TYPE_PIN:
+                return "PIN";
+            case CREDENTIAL_TYPE_PASSWORD:
+                return "PASSWORD";
+            default:
+                return "UNKNOWN_" + credentialType;
+        }
+    }
+
     /**
      * Flag provided to {@link #verifyCredential(LockscreenCredential, int, int)} . If set, the
      * method will return a handle to the Gatekeeper Password in the
@@ -170,6 +185,8 @@
     private static final String LOCK_SCREEN_OWNER_INFO_ENABLED =
             Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED;
 
+    private static final String LOCK_PIN_ENHANCED_PRIVACY = "pin_enhanced_privacy";
+
     private static final String LOCK_SCREEN_DEVICE_OWNER_INFO = "lockscreen.device_owner_info";
 
     private static final String ENABLED_TRUST_AGENTS = "lockscreen.enabledtrustagents";
@@ -1037,6 +1054,27 @@
     }
 
     /**
+     * @return Whether enhanced pin privacy is enabled.
+     */
+    public boolean isPinEnhancedPrivacyEnabled(int userId) {
+        return getBoolean(LOCK_PIN_ENHANCED_PRIVACY, false, userId);
+    }
+
+    /**
+     * Set whether enhanced pin privacy is enabled.
+     */
+    public void setPinEnhancedPrivacyEnabled(boolean enabled, int userId) {
+        setBoolean(LOCK_PIN_ENHANCED_PRIVACY, enabled, userId);
+    }
+
+    /**
+     * @return Whether enhanced pin privacy was ever chosen.
+     */
+    public boolean isPinEnhancedPrivacyEverChosen(int userId) {
+        return getString(LOCK_PIN_ENHANCED_PRIVACY, userId) != null;
+    }
+
+    /**
      * Set whether the visible password is enabled for cryptkeeper screen.
      */
     public void setVisiblePasswordEnabled(boolean enabled, int userId) {
@@ -1837,7 +1875,7 @@
      * Starts a session to verify lockscreen credentials provided by a remote device.
      */
     @NonNull
-    public StartLockscreenValidationRequest startRemoteLockscreenValidation() {
+    public RemoteLockscreenValidationSession startRemoteLockscreenValidation() {
         try {
             return getLockSettings().startRemoteLockscreenValidation();
         } catch (RemoteException e) {
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 939a0e4..9c6a534 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -266,7 +266,8 @@
 }
 
 static jint nativeCreateDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
-        jlong size, jint channelType, jint fd, jobject hardwareBufferObj) {
+                                      jint deviceId, jlong size, jint channelType, jint fd,
+                                      jobject hardwareBufferObj) {
     const native_handle_t *nativeHandle = nullptr;
     NATIVE_HANDLE_DECLARE_STORAGE(ashmemHandle, 1, 0);
 
@@ -287,7 +288,7 @@
     }
 
     SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
-    return mgr->createDirectChannel(size, channelType, nativeHandle);
+    return mgr->createDirectChannel(deviceId, size, channelType, nativeHandle);
 }
 
 static void nativeDestroyDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
@@ -532,7 +533,7 @@
 
         {"nativeIsDataInjectionEnabled", "(J)Z", (void *)nativeIsDataInjectionEnabled},
 
-        {"nativeCreateDirectChannel", "(JJIILandroid/hardware/HardwareBuffer;)I",
+        {"nativeCreateDirectChannel", "(JIJIILandroid/hardware/HardwareBuffer;)I",
          (void *)nativeCreateDirectChannel},
 
         {"nativeDestroyDirectChannel", "(JI)V", (void *)nativeDestroyDirectChannel},
diff --git a/core/jni/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp
index b09a9c3..739055e 100644
--- a/core/jni/android_view_DisplayEventReceiver.cpp
+++ b/core/jni/android_view_DisplayEventReceiver.cpp
@@ -50,12 +50,22 @@
 
     struct {
         jclass clazz;
+
         jmethodID init;
+
+        jfieldID vsyncId;
+        jfieldID expectedPresentationTime;
+        jfieldID deadline;
     } frameTimelineClassInfo;
 
     struct {
         jclass clazz;
+
         jmethodID init;
+
+        jfieldID frameInterval;
+        jfieldID preferredFrameTimelineIndex;
+        jfieldID frameTimelines;
     } vsyncEventDataClassInfo;
 
 } gDisplayEventReceiverClassInfo;
@@ -63,7 +73,7 @@
 
 class NativeDisplayEventReceiver : public DisplayEventDispatcher {
 public:
-    NativeDisplayEventReceiver(JNIEnv* env, jobject receiverWeak,
+    NativeDisplayEventReceiver(JNIEnv* env, jobject receiverWeak, jobject vsyncEventDataWeak,
                                const sp<MessageQueue>& messageQueue, jint vsyncSource,
                                jint eventRegistration, jlong layerHandle);
 
@@ -74,6 +84,7 @@
 
 private:
     jobject mReceiverWeakGlobal;
+    jobject mVsyncEventDataWeakGlobal;
     sp<MessageQueue> mMessageQueue;
 
     void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count,
@@ -87,6 +98,7 @@
 };
 
 NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env, jobject receiverWeak,
+                                                       jobject vsyncEventDataWeak,
                                                        const sp<MessageQueue>& messageQueue,
                                                        jint vsyncSource, jint eventRegistration,
                                                        jlong layerHandle)
@@ -98,6 +110,7 @@
                                                           reinterpret_cast<IBinder*>(layerHandle))
                                                 : nullptr),
         mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
+        mVsyncEventDataWeakGlobal(env->NewGlobalRef(vsyncEventDataWeak)),
         mMessageQueue(messageQueue) {
     ALOGV("receiver %p ~ Initializing display event receiver.", this);
 }
@@ -144,12 +157,39 @@
     JNIEnv* env = AndroidRuntime::getJNIEnv();
 
     ScopedLocalRef<jobject> receiverObj(env, GetReferent(env, mReceiverWeakGlobal));
-    if (receiverObj.get()) {
+    ScopedLocalRef<jobject> vsyncEventDataObj(env, GetReferent(env, mVsyncEventDataWeakGlobal));
+    if (receiverObj.get() && vsyncEventDataObj.get()) {
         ALOGV("receiver %p ~ Invoking vsync handler.", this);
 
-        jobject javaVsyncEventData = createJavaVsyncEventData(env, vsyncEventData);
+        env->SetIntField(vsyncEventDataObj.get(),
+                         gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo
+                                 .preferredFrameTimelineIndex,
+                         vsyncEventData.preferredFrameTimelineIndex);
+        env->SetLongField(vsyncEventDataObj.get(),
+                          gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.frameInterval,
+                          vsyncEventData.frameInterval);
+
+        jobjectArray frameTimelinesObj = reinterpret_cast<jobjectArray>(
+                env->GetObjectField(vsyncEventDataObj.get(),
+                                    gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo
+                                            .frameTimelines));
+        for (int i = 0; i < VsyncEventData::kFrameTimelinesLength; i++) {
+            VsyncEventData::FrameTimeline& frameTimeline = vsyncEventData.frameTimelines[i];
+            jobject frameTimelineObj = env->GetObjectArrayElement(frameTimelinesObj, i);
+            env->SetLongField(frameTimelineObj,
+                              gDisplayEventReceiverClassInfo.frameTimelineClassInfo.vsyncId,
+                              frameTimeline.vsyncId);
+            env->SetLongField(frameTimelineObj,
+                              gDisplayEventReceiverClassInfo.frameTimelineClassInfo
+                                      .expectedPresentationTime,
+                              frameTimeline.expectedPresentationTime);
+            env->SetLongField(frameTimelineObj,
+                              gDisplayEventReceiverClassInfo.frameTimelineClassInfo.deadline,
+                              frameTimeline.deadlineTimestamp);
+        }
+
         env->CallVoidMethod(receiverObj.get(), gDisplayEventReceiverClassInfo.dispatchVsync,
-                            timestamp, displayId.value, count, javaVsyncEventData);
+                            timestamp, displayId.value, count);
         ALOGV("receiver %p ~ Returned from vsync handler.", this);
     }
 
@@ -217,8 +257,9 @@
     mMessageQueue->raiseAndClearException(env, "dispatchModeChanged");
 }
 
-static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak, jobject messageQueueObj,
-                        jint vsyncSource, jint eventRegistration, jlong layerHandle) {
+static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak, jobject vsyncEventDataWeak,
+                        jobject messageQueueObj, jint vsyncSource, jint eventRegistration,
+                        jlong layerHandle) {
     sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
     if (messageQueue == NULL) {
         jniThrowRuntimeException(env, "MessageQueue is not initialized.");
@@ -226,8 +267,8 @@
     }
 
     sp<NativeDisplayEventReceiver> receiver =
-            new NativeDisplayEventReceiver(env, receiverWeak, messageQueue, vsyncSource,
-                                           eventRegistration, layerHandle);
+            new NativeDisplayEventReceiver(env, receiverWeak, vsyncEventDataWeak, messageQueue,
+                                           vsyncSource, eventRegistration, layerHandle);
     status_t status = receiver->initialize();
     if (status) {
         String8 message;
@@ -274,7 +315,9 @@
 
 static const JNINativeMethod gMethods[] = {
         /* name, signature, funcPtr */
-        {"nativeInit", "(Ljava/lang/ref/WeakReference;Landroid/os/MessageQueue;IIJ)J",
+        {"nativeInit",
+         "(Ljava/lang/ref/WeakReference;Ljava/lang/ref/WeakReference;Landroid/os/"
+         "MessageQueue;IIJ)J",
          (void*)nativeInit},
         {"nativeGetDisplayEventReceiverFinalizer", "()J",
          (void*)nativeGetDisplayEventReceiverFinalizer},
@@ -291,8 +334,7 @@
     gDisplayEventReceiverClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
 
     gDisplayEventReceiverClassInfo.dispatchVsync =
-            GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.clazz, "dispatchVsync",
-                             "(JJILandroid/view/DisplayEventReceiver$VsyncEventData;)V");
+            GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.clazz, "dispatchVsync", "(JJI)V");
     gDisplayEventReceiverClassInfo.dispatchHotplug = GetMethodIDOrDie(env,
             gDisplayEventReceiverClassInfo.clazz, "dispatchHotplug", "(JJZ)V");
     gDisplayEventReceiverClassInfo.dispatchModeChanged =
@@ -318,6 +360,15 @@
     gDisplayEventReceiverClassInfo.frameTimelineClassInfo.init =
             GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.frameTimelineClassInfo.clazz,
                              "<init>", "(JJJ)V");
+    gDisplayEventReceiverClassInfo.frameTimelineClassInfo.vsyncId =
+            GetFieldIDOrDie(env, gDisplayEventReceiverClassInfo.frameTimelineClassInfo.clazz,
+                            "vsyncId", "J");
+    gDisplayEventReceiverClassInfo.frameTimelineClassInfo.expectedPresentationTime =
+            GetFieldIDOrDie(env, gDisplayEventReceiverClassInfo.frameTimelineClassInfo.clazz,
+                            "expectedPresentationTime", "J");
+    gDisplayEventReceiverClassInfo.frameTimelineClassInfo.deadline =
+            GetFieldIDOrDie(env, gDisplayEventReceiverClassInfo.frameTimelineClassInfo.clazz,
+                            "deadline", "J");
 
     jclass vsyncEventDataClazz =
             FindClassOrDie(env, "android/view/DisplayEventReceiver$VsyncEventData");
@@ -329,6 +380,17 @@
                              "([Landroid/view/"
                              "DisplayEventReceiver$VsyncEventData$FrameTimeline;IJ)V");
 
+    gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.preferredFrameTimelineIndex =
+            GetFieldIDOrDie(env, gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.clazz,
+                            "preferredFrameTimelineIndex", "I");
+    gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.frameInterval =
+            GetFieldIDOrDie(env, gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.clazz,
+                            "frameInterval", "J");
+    gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.frameTimelines =
+            GetFieldIDOrDie(env, gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.clazz,
+                            "frameTimelines",
+                            "[Landroid/view/DisplayEventReceiver$VsyncEventData$FrameTimeline;");
+
     return res;
 }
 
diff --git a/core/jni/android_view_InputEventSender.cpp b/core/jni/android_view_InputEventSender.cpp
index 4bc567a..ad54004 100644
--- a/core/jni/android_view_InputEventSender.cpp
+++ b/core/jni/android_view_InputEventSender.cpp
@@ -20,20 +20,21 @@
 
 #include <android_runtime/AndroidRuntime.h>
 #include <input/InputTransport.h>
+#include <inttypes.h>
 #include <log/log.h>
 #include <nativehelper/JNIHelp.h>
 #include <nativehelper/ScopedLocalRef.h>
 #include <utils/Looper.h>
+
+#include <optional>
+#include <unordered_map>
+
 #include "android_os_MessageQueue.h"
 #include "android_view_InputChannel.h"
 #include "android_view_KeyEvent.h"
 #include "android_view_MotionEvent.h"
 #include "core_jni_helpers.h"
 
-#include <inttypes.h>
-#include <unordered_map>
-
-
 using android::base::Result;
 
 namespace android {
@@ -67,7 +68,7 @@
     jobject mSenderWeakGlobal;
     InputPublisher mInputPublisher;
     sp<MessageQueue> mMessageQueue;
-    std::unordered_map<uint32_t, uint32_t> mPublishedSeqMap;
+    std::unordered_map<uint32_t, std::optional<uint32_t>> mPublishedSeqMap;
 
     uint32_t mNextPublishedSeq;
 
@@ -165,8 +166,14 @@
                     getInputChannelName().c_str(), status);
             return status;
         }
+        // mPublishedSeqMap tracks all sequences published from this sender. Only the last
+        // sequence number is used to signal this motion event is finished.
+        if (i == event->getHistorySize()) {
+            mPublishedSeqMap.emplace(publishedSeq, seq);
+        } else {
+            mPublishedSeqMap.emplace(publishedSeq, std::nullopt);
+        }
     }
-    mPublishedSeqMap.emplace(publishedSeq, seq);
     return OK;
 }
 
@@ -277,8 +284,16 @@
         // does something wrong and sends bad data. Just ignore and process other events.
         return true;
     }
-    const uint32_t seq = it->second;
+
+    const std::optional<uint32_t> seqOptional = it->second;
     mPublishedSeqMap.erase(it);
+    // If this optional does not have a value, it means we are processing an event that had history
+    // and was split. There are more events coming, so we can't call 'dispatchInputEventFinished'
+    // yet. The final split event will have a valid sequence number.
+    if (!seqOptional.has_value()) {
+        return true;
+    }
+    const uint32_t seq = seqOptional.value();
 
     if (kDebugDispatchCycle) {
         ALOGD("channel '%s' ~ Received finished signal, seq=%u, handled=%s, pendingEvents=%zu.",
diff --git a/core/jni/android_view_MotionPredictor.cpp b/core/jni/android_view_MotionPredictor.cpp
index 2c232fa..de3e81c 100644
--- a/core/jni/android_view_MotionPredictor.cpp
+++ b/core/jni/android_view_MotionPredictor.cpp
@@ -20,7 +20,6 @@
 #include <input/MotionPredictor.h>
 
 #include "android_view_MotionEvent.h"
-#include "core_jni_converters.h"
 #include "core_jni_helpers.h"
 
 /**
@@ -30,14 +29,6 @@
 
 namespace android {
 
-// ----------------------------------------------------------------------------
-
-static struct {
-    jclass clazz;
-} gMotionEventClassInfo;
-
-// ----------------------------------------------------------------------------
-
 static void release(void* ptr) {
     delete reinterpret_cast<MotionPredictor*>(ptr);
 }
@@ -57,14 +48,20 @@
                                                       jobject event) {
     MotionPredictor* predictor = reinterpret_cast<MotionPredictor*>(ptr);
     MotionEvent* motionEvent = android_view_MotionEvent_getNativePtr(env, event);
-    predictor->record(*motionEvent);
+
+    android::base::Result<void> result = predictor->record(*motionEvent);
+    if (!result.ok()) {
+        jniThrowException(env, "java/lang/IllegalArgumentException",
+                          result.error().message().c_str());
+    }
 }
 
 static jobject android_view_MotionPredictor_nativePredict(JNIEnv* env, jclass clazz, jlong ptr,
                                                           jlong predictionTimeNanos) {
     MotionPredictor* predictor = reinterpret_cast<MotionPredictor*>(ptr);
-    return toJavaArray(env, predictor->predict(static_cast<nsecs_t>(predictionTimeNanos)),
-                       gMotionEventClassInfo.clazz, &android_view_MotionEvent_obtainFromNative);
+    return android_view_MotionEvent_obtainFromNative(env,
+                                                     predictor->predict(static_cast<nsecs_t>(
+                                                             predictionTimeNanos)));
 }
 
 static jboolean android_view_MotionPredictor_nativeIsPredictionAvailable(JNIEnv* env, jclass clazz,
@@ -84,15 +81,13 @@
          (void*)android_view_MotionPredictor_nativeGetNativeMotionPredictorFinalizer},
         {"nativeRecord", "(JLandroid/view/MotionEvent;)V",
          (void*)android_view_MotionPredictor_nativeRecord},
-        {"nativePredict", "(JJ)[Landroid/view/MotionEvent;",
+        {"nativePredict", "(JJ)Landroid/view/MotionEvent;",
          (void*)android_view_MotionPredictor_nativePredict},
         {"nativeIsPredictionAvailable", "(JII)Z",
          (void*)android_view_MotionPredictor_nativeIsPredictionAvailable},
 }};
 
 int register_android_view_MotionPredictor(JNIEnv* env) {
-    jclass motionEventClazz = FindClassOrDie(env, "android/view/MotionEvent");
-    gMotionEventClassInfo.clazz = MakeGlobalRefOrDie(env, motionEventClazz);
     return RegisterMethodsOrDie(env, "android/view/MotionPredictor", gMotionPredictorMethods.data(),
                                 gMotionPredictorMethods.size());
 }
diff --git a/core/jni/android_view_SurfaceControlHdrLayerInfoListener.cpp b/core/jni/android_view_SurfaceControlHdrLayerInfoListener.cpp
index adbd791..443f99a 100644
--- a/core/jni/android_view_SurfaceControlHdrLayerInfoListener.cpp
+++ b/core/jni/android_view_SurfaceControlHdrLayerInfoListener.cpp
@@ -42,12 +42,12 @@
         LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&mVm) != JNI_OK, "Failed to GetJavaVm");
     }
 
-    binder::Status onHdrLayerInfoChanged(int numberOfHdrLayers, int maxW, int maxH,
-                                         int flags) override {
+    binder::Status onHdrLayerInfoChanged(int numberOfHdrLayers, int maxW, int maxH, int flags,
+                                         float maxDesiredHdrSdrRatio) override {
         JNIEnv* env = requireEnv();
 
         env->CallVoidMethod(mListener, gListenerClassInfo.mOnHdrInfoChanged, mDisplayToken,
-                            numberOfHdrLayers, maxW, maxH, flags);
+                            numberOfHdrLayers, maxW, maxH, flags, maxDesiredHdrSdrRatio);
 
         if (env->ExceptionCheck()) {
             ALOGE("SurfaceControlHdrLayerInfoListener.onHdrInfoChanged() failed.");
@@ -129,7 +129,7 @@
     jclass clazz = env->FindClass("android/view/SurfaceControlHdrLayerInfoListener");
     gListenerClassInfo.mClass = MakeGlobalRefOrDie(env, clazz);
     gListenerClassInfo.mOnHdrInfoChanged =
-            env->GetMethodID(clazz, "onHdrInfoChanged", "(Landroid/os/IBinder;IIII)V");
+            env->GetMethodID(clazz, "onHdrInfoChanged", "(Landroid/os/IBinder;IIIIF)V");
     return 0;
 }
 
diff --git a/core/jni/android_window_WindowInfosListener.cpp b/core/jni/android_window_WindowInfosListener.cpp
index f2cbe8a..850755a 100644
--- a/core/jni/android_window_WindowInfosListener.cpp
+++ b/core/jni/android_window_WindowInfosListener.cpp
@@ -134,6 +134,7 @@
 
 void destroyNativeService(void* ptr) {
     WindowInfosListener* listener = reinterpret_cast<WindowInfosListener*>(ptr);
+    SurfaceComposerClient::getDefault()->removeWindowInfosListener(listener);
     listener->decStrong((void*)nativeCreate);
 }
 
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 1b812d1..d62f1cf 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -1805,10 +1805,15 @@
     if (!is_system_server && getuid() == 0) {
         const int rc = createProcessGroup(uid, getpid());
         if (rc != 0) {
-            fail_fn(rc == -EROFS ? CREATE_ERROR("createProcessGroup failed, kernel missing "
-                                                "CONFIG_CGROUP_CPUACCT?")
-                                 : CREATE_ERROR("createProcessGroup(%d, %d) failed: %s", uid,
-                                                /* pid= */ 0, strerror(-rc)));
+            if (rc == -ESRCH) {
+                // If process is dead, treat this as a non-fatal error
+                ALOGE("createProcessGroup(%d, %d) failed: %s", uid, /* pid= */ 0, strerror(-rc));
+            } else {
+                fail_fn(rc == -EROFS ? CREATE_ERROR("createProcessGroup failed, kernel missing "
+                                                    "CONFIG_CGROUP_CPUACCT?")
+                                     : CREATE_ERROR("createProcessGroup(%d, %d) failed: %s", uid,
+                                                    /* pid= */ 0, strerror(-rc)));
+            }
         }
     }
 
diff --git a/core/proto/android/nfc/Android.bp b/core/proto/android/nfc/Android.bp
new file mode 100644
index 0000000..6a62c91
--- /dev/null
+++ b/core/proto/android/nfc/Android.bp
@@ -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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+filegroup {
+    name: "srcs_nfc_proto",
+    srcs: [
+        "*.proto",
+    ],
+}
+
+// Will be statically linked by `framework-nfc`.
+java_library {
+    name: "nfc-proto-java-gen",
+    installable: false,
+    proto: {
+        type: "stream",
+        include_dirs: [
+            "external/protobuf/src",
+        ],
+    },
+    srcs: [
+        ":srcs_nfc_proto",
+    ],
+    sdk_version: "current",
+    min_sdk_version: "current",
+}
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index 8caf127..a5d287c 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -95,6 +95,8 @@
         optional SettingProto hearing_aid_media_routing = 48 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto hearing_aid_system_sounds_routing = 49 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto accessibility_magnification_joystick_enabled = 50 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        // Settings for font scaling
+        optional SettingProto accessibility_font_scaling_has_been_changed = 51 [ (android.privacy).dest = DEST_AUTOMATIC ];
     }
     optional Accessibility accessibility = 2;
 
diff --git a/core/proto/android/providers/settings/system.proto b/core/proto/android/providers/settings/system.proto
index 146ac9d..7503dde4 100644
--- a/core/proto/android/providers/settings/system.proto
+++ b/core/proto/android/providers/settings/system.proto
@@ -115,6 +115,9 @@
         optional SettingProto sound_cache = 2;
         optional SettingProto light_pulse = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto vibration_intensity = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        optional SettingProto camera_flash_notification = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        optional SettingProto screen_flash_notification = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        optional SettingProto screen_flash_notification_color_global = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
     }
     optional Notification notification = 17;
 
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index ab7b0ab..ed612a0 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -142,6 +142,7 @@
         optional int64 finish_clock_time_ms = 4;
     }
     repeated BroadcastSummary historical_broadcasts_summary = 6;
+    repeated BroadcastRecordProto pending_broadcasts = 7;
 }
 
 message MemInfoDumpProto {
@@ -439,6 +440,7 @@
 
         optional int32 id = 1;
         optional .android.app.NotificationProto notification = 2;
+        optional int32 foregroundServiceType = 3;
     }
     optional Foreground foreground = 13;
 
diff --git a/core/proto/android/service/notification.proto b/core/proto/android/service/notification.proto
index e029af4..f87d910 100644
--- a/core/proto/android/service/notification.proto
+++ b/core/proto/android/service/notification.proto
@@ -285,22 +285,24 @@
     repeated PackageRemoteViewInfoProto package_remote_view_info = 1;
 }
 
+// Enum used in DNDModeProto to specify the zen mode setting.
+enum LoggedZenMode {
+    ROOT_CONFIG = -1;  // Used to distinguish config (one per user) from the rules.
+    OFF = 0;
+    IMPORTANT_INTERRUPTIONS = 1;
+    NO_INTERRUPTIONS = 2;
+    ALARMS = 3;
+}
+
 /**
  * Atom that represents an item in the list of Do Not Disturb rules, pulled from
  * NotificationManagerService.java.
  */
 message DNDModeProto {
-    enum Mode {
-        ROOT_CONFIG = -1;  // Used to distinguish the config (one per user) from the rules.
-        ZEN_MODE_OFF = 0;
-        ZEN_MODE_IMPORTANT_INTERRUPTIONS = 1;
-        ZEN_MODE_NO_INTERRUPTIONS = 2;
-        ZEN_MODE_ALARMS = 3;
-    }
     optional int32 user = 1;  // Android user ID (0, 1, 10, ...)
     optional bool enabled = 2;  // true for ROOT_CONFIG if a manualRule is enabled
     optional bool channels_bypassing = 3; // only valid for ROOT_CONFIG
-    optional Mode zen_mode = 4;
+    optional LoggedZenMode zen_mode = 4;
     // id is one of the system default rule IDs, or empty
     // May also be "MANUAL_RULE" to indicate app-activation of the manual rule.
     optional string id = 5;
@@ -308,15 +310,34 @@
     optional DNDPolicyProto policy = 7;
 }
 
+// Enum used in DNDPolicyProto for a particular policy parameter's state.
+enum State {
+    STATE_UNSET = 0;
+    STATE_ALLOW = 1;
+    STATE_DISALLOW = 2;
+}
+
+// Enum used in DNDPolicyProto for which people are allowed to break through.
+enum PeopleType {
+    PEOPLE_UNSET = 0;
+    PEOPLE_ANYONE = 1;
+    PEOPLE_CONTACTS = 2;
+    PEOPLE_STARRED = 3;
+    PEOPLE_NONE = 4;
+}
+
+// Enum used in DNDPolicyProto for conversation types allowed to break through.
+enum ConversationType {
+    CONV_UNSET = 0;
+    CONV_ANYONE = 1;
+    CONV_IMPORTANT = 2;
+    CONV_NONE = 3;
+}
+
 /**
- * Atom that represents a Do Not Disturb policy, an optional detail proto for DNDModeProto.
+ * Message that represents a Do Not Disturb policy, an optional detail proto for DNDModeProto.
  */
 message DNDPolicyProto {
-    enum State {
-        STATE_UNSET = 0;
-        STATE_ALLOW = 1;
-        STATE_DISALLOW = 2;
-    }
     optional State calls = 1;
     optional State repeat_callers = 2;
     optional State messages = 3;
@@ -334,23 +355,8 @@
     optional State ambient = 15;
     optional State notification_list = 16;
 
-    enum PeopleType {
-        PEOPLE_UNSET = 0;
-        PEOPLE_ANYONE = 1;
-        PEOPLE_CONTACTS = 2;
-        PEOPLE_STARRED = 3;
-        PEOPLE_NONE = 4;
-    }
-
     optional PeopleType allow_calls_from = 17;
     optional PeopleType allow_messages_from = 18;
 
-    enum ConversationType {
-        CONV_UNSET = 0;
-        CONV_ANYONE = 1;
-        CONV_IMPORTANT = 2;
-        CONV_NONE = 3;
-    }
-
     optional ConversationType allow_conversations_from = 19;
 }
diff --git a/core/res/Android.bp b/core/res/Android.bp
index 3c4bac8..b71995f 100644
--- a/core/res/Android.bp
+++ b/core/res/Android.bp
@@ -178,3 +178,12 @@
         " > $(out)",
     tools: ["xmllint"],
 }
+
+filegroup {
+    name: "frameworks-base-core-AndroidManifest.xml",
+    srcs: ["AndroidManifest.xml"],
+    visibility: [
+        "//frameworks/base",
+        "//frameworks/base/api",
+    ],
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 85d1765..611035e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -822,6 +822,8 @@
     <protected-broadcast android:name="com.android.internal.telephony.cat.SMS_SENT_ACTION" />
     <protected-broadcast android:name="com.android.internal.telephony.cat.SMS_DELIVERY_ACTION" />
     <protected-broadcast android:name="android.companion.virtual.action.VIRTUAL_DEVICE_REMOVED" />
+    <protected-broadcast android:name="com.android.internal.intent.action.FLASH_NOTIFICATION_START_PREVIEW" />
+    <protected-broadcast android:name="com.android.internal.intent.action.FLASH_NOTIFICATION_STOP_PREVIEW" />
 
     <!-- ====================================================================== -->
     <!--                          RUNTIME PERMISSIONS                           -->
@@ -3159,7 +3161,7 @@
     <!-- @SystemApi @hide Allows an application to call APIs that allow it to query users on the
          device. -->
     <permission android:name="android.permission.QUERY_USERS"
-                android:protectionLevel="signature|role" />
+                android:protectionLevel="signature|privileged|role" />
 
     <!-- Allows an application to access data blobs across users. -->
     <permission android:name="android.permission.ACCESS_BLOBS_ACROSS_USERS"
@@ -3707,7 +3709,8 @@
 
     <!-- @SystemApi @hide Allows an application to set a device owner on retail demo devices.-->
     <permission android:name="android.permission.PROVISION_DEMO_DEVICE"
-                android:protectionLevel="signature|setup" />
+                android:protectionLevel="signature|setup|knownSigner"
+                android:knownCerts="@array/demo_device_provisioning_known_signers" />
 
     <!-- @TestApi @hide Allows an application to reset the record of previous system update freeze
          periods. -->
@@ -3769,10 +3772,9 @@
     <permission android:name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND"
                 android:protectionLevel="signature|privileged|vendorPrivileged|oem|verifier|role"/>
 
-    <!-- Allows an application to hint that a component lifecycle operation such as sending
-         a broadcast is associated with an "interactive" usage scenario.
+    <!-- Allows an application to request interactive options when sending a broadcast.
          @hide -->
-    <permission android:name="android.permission.COMPONENT_OPTION_INTERACTIVE"
+    <permission android:name="android.permission.BROADCAST_OPTION_INTERACTIVE"
                 android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Must be required by activities that handle the intent action
@@ -4201,6 +4203,16 @@
     <permission android:name="android.permission.WRITE_DEVICE_CONFIG"
         android:protectionLevel="signature|verifier|configurator"/>
 
+    <!-- @SystemApi @TestApi @hide Allows an application to read/write sync disabled mode config.
+    <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.READ_WRITE_SYNC_DISABLED_MODE_CONFIG"
+        android:protectionLevel="signature|verifier|configurator"/>
+
+    <!-- @SystemApi @TestApi @hide Allows an application to modify only allowlisted settings.
+    <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.ALLOWLISTED_WRITE_DEVICE_CONFIG"
+        android:protectionLevel="signature|verifier|configurator"/>
+
     <!-- @SystemApi @hide Allows an application to read config settings.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.READ_DEVICE_CONFIG"
@@ -4481,8 +4493,8 @@
     <!-- Allows an application to be able to store and retrieve credentials from a remote
          device.
          @hide @SystemApi -->
-    <permission android:name="android.permission.PROVIDE_HYBRID_CREDENTIAL_SERVICE"
-                android:protectionLevel="signature|privileged" />
+    <permission android:name="android.permission.PROVIDE_REMOTE_CREDENTIALS"
+                android:protectionLevel="signature|privileged|role" />
 
     <!-- ========================================= -->
     <!-- Permissions for special development tools -->
@@ -7608,8 +7620,8 @@
 
     <!-- @SystemApi Allows to call APIs that log process lifecycle events
          @hide -->
-    <permission android:name="android.permission.LOG_PROCESS_ACTIVITIES"
-                android:protectionLevel="signature|privileged" />
+    <permission android:name="android.permission.LOG_FOREGROUND_RESOURCE_USE"
+                android:protectionLevel="signature|module" />
 
     <!-- @hide Allows an application to get type of any provider uri.
          <p>Not for use by third-party applications.
@@ -8166,6 +8178,10 @@
                  android:permission="android.permission.BIND_JOB_SERVICE" >
         </service>
 
+        <service android:name="com.android.server.healthconnect.migration.MigrationBroadcastJobService"
+            android:permission="android.permission.BIND_JOB_SERVICE">
+        </service>
+
         <service android:name="com.android.server.pm.PackageManagerShellCommandDataLoader"
             android:exported="false">
             <intent-filter>
diff --git a/core/res/res/layout/transient_notification.xml b/core/res/res/layout/transient_notification.xml
index 3259201..8bedb89 100644
--- a/core/res/res/layout/transient_notification.xml
+++ b/core/res/res/layout/transient_notification.xml
@@ -25,7 +25,7 @@
     android:orientation="horizontal"
     android:gravity="center_vertical"
     android:maxWidth="@dimen/toast_width"
-    android:background="?android:attr/toastFrameBackground"
+    android:background="?android:attr/colorBackground"
     android:elevation="@dimen/toast_elevation"
     android:layout_marginEnd="16dp"
     android:layout_marginStart="16dp"
diff --git a/core/res/res/layout/transient_notification_with_icon.xml b/core/res/res/layout/transient_notification_with_icon.xml
index e9b17df..0dfb3ad 100644
--- a/core/res/res/layout/transient_notification_with_icon.xml
+++ b/core/res/res/layout/transient_notification_with_icon.xml
@@ -22,7 +22,7 @@
     android:orientation="horizontal"
     android:gravity="center_vertical"
     android:maxWidth="@dimen/toast_width"
-    android:background="?android:attr/toastFrameBackground"
+    android:background="?android:attr/colorBackground"
     android:elevation="@dimen/toast_elevation"
     android:layout_marginEnd="16dp"
     android:layout_marginStart="16dp"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 82591a5..f78844f 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Kies invoermetode"</string>
     <string name="show_ime" msgid="6406112007347443383">"Hou dit op die skerm terwyl fisieke sleutelbord aktief is"</string>
     <string name="hardware" msgid="1800597768237606953">"Wys virtuele sleutelbord"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Stel fisieke sleutelbord op"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Tik om taal en uitleg te kies"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Gehoortoestelle"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Het volumesleutels ingehou. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aangeskakel."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Het volumesleutels ingehou. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> is afgeskakel"</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Druk en hou albei volumesleutels drie sekondes lank om <xliff:g id="SERVICE_NAME">%1$s</xliff:g> te gebruik"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Kies \'n kenmerk om te gebruik wanneer jy op die toeganklikheidknoppie tik:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Kies \'n kenmerk om te gebruik saam met die toeganklikheidgebaar (swiep met twee vingers op van die onderkant van die skerm af):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Kies \'n kenmerk om te gebruik saam met die toeganklikheidgebaar (swiep met drie vingers op van die onderkant van die skerm af):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Toestel is te warm"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dubbelskerm is nie beskikbaar nie omdat jou foon tans te warm word"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Skakel af"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index ab5a9c7..12c25eb 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"የግቤት ስልት ምረጥ"</string>
     <string name="show_ime" msgid="6406112007347443383">"አካላዊ የቁልፍ ሰሌዳ ገቢር ሆኖ ሳለ በማያ ገጽ ላይ አቆየው"</string>
     <string name="hardware" msgid="1800597768237606953">"ምናባዊ የቁልፍ ሰሌዳን አሳይ"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"አካላዊ ቁልፍ ሰሌዳን ያዋቅሩ"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"ቋንቋ እና አቀማመጥን ለመምረጥ መታ ያድርጉ"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"የመስሚያ መሣሪያዎች"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"የድምፅ ቁልፎችን ይዟል። <xliff:g id="SERVICE_NAME">%1$s</xliff:g> በርቷል።"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"የድምፅ ቁልፎችን ይዟል። <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ጠፍተዋል።"</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>ን ለመጠቀም ለሦስት ሰከንዶች ሁለቱንም የድምፅ ቁልፎች ተጭነው ይያዙ"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"የተደራሽነት አዝራርን መታ በሚያደርጉበት ጊዜ ጥቅም ላይ የሚውለውን ባሕሪ ይምረጡ፦"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"ከተደራሽነት ጣት ምልክት ጋር የሚጠቀሙበት ባሕሪ ይምረጡ (በሁለት ጣቶች ከማያ ገጹ ግርጌ ወደ ላይ ይጥረጉ)፦"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"ከተደራሽነት ጣት ምልክት ጋር አብረው የሚጠቀሙበት ባሕሪ ይምረጡ (በሦስት ጣቶች ከማያ ገጹ ግርጌ ወደ ላይ ይጥረጉ)፦"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"መሣሪያ በጣም ሞቋል"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"ስልክዎ በጣም እየሞቀ ስለሆነ ባለሁለት ማያ ገጽ አይገኝም"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"አጥፋ"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index b9fc266..6443401 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1397,7 +1397,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"اختيار أسلوب الإدخال"</string>
     <string name="show_ime" msgid="6406112007347443383">"استمرار عرضها على الشاشة أثناء نشاط لوحة المفاتيح الفعلية"</string>
     <string name="hardware" msgid="1800597768237606953">"إظهار لوحة المفاتيح الافتراضية"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"إعداد لوحة المفاتيح الفعلية"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"انقر لاختيار لغة وتنسيق"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" أ ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789 أ ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي"</string>
@@ -1722,7 +1725,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"سماعات الأذن الطبية"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"تم الضغط مع الاستمرار على مفتاحَي التحكّم في مستوى الصوت. تم تفعيل <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"تم الضغط مع الاستمرار على مفتاحَي التحكّم في مستوى الصوت. تم إيقاف <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"اضغط مع الاستمرار على مفتاحي مستوى الصوت لمدة 3 ثوانٍ لاستخدام <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"يمكنك اختيار إحدى الميزات لاستخدامها عند النقر على زر أدوات تمكين الوصول:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"يمكنك اختيار إحدى الميزات لاستخدامها مع إيماءة أدوات تمكين الوصول (مرّر سريعًا إلى الأعلى من أسفل الشاشة باستخدام إصبعين):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"يمكنك اختيار إحدى الميزات التالية لاستخدامها مع إيماءة أدوات تمكين الوصول (مرّر سريعًا إلى الأعلى من أسفل الشاشة باستخدام ثلاثة أصابع):"</string>
@@ -2327,4 +2331,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"الجهاز ساخن للغاية"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"ميزة \"استخدام الشاشتين\" غير متاحة لأن هاتفك ساخن للغاية."</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"إيقاف"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 1354ad4..3d1a7b3 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"ইনপুট পদ্ধতি বাছনি কৰক"</string>
     <string name="show_ime" msgid="6406112007347443383">"কায়িক কীব’ৰ্ড সক্ৰিয় হৈ থাকোঁতে ইয়াক স্ক্ৰীনত ৰাখক"</string>
     <string name="hardware" msgid="1800597768237606953">"ভাৰ্শ্বুৱল কীব\'ৰ্ড দেখুৱাওক"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"কায়িক কীব’ৰ্ড কনফিগাৰ কৰক"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"ভাষা আৰু চানেকি বাছনি কৰিবলৈ ইয়াত টিপক"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"শুনাৰ ডিভাইচ"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ভলিউম কীসমূহ ধৰি ৰাখক। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> অন কৰা হ\'ল।"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ভলিউম কী ধৰি ৰাখিছিল। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> অফ কৰা হ\'ল।"</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ব্যৱহাৰ কৰিবলৈ দুয়োটা ভলিউম বুটাম তিনি ছেকেণ্ডৰ বাবে হেঁচি ৰাখক"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"আপুনি সাধ্য-সুবিধাৰ বুটামটো টিপিলে ব্যৱহাৰ কৰিবলৈ এটা সুবিধা বাছনি কৰক:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"সাধ্য-সুবিধাৰ নির্দেশৰ জৰিয়তে ব্যৱহাৰ কৰিবলৈ এটা সুবিধা বাছনি কৰক (দুটা আঙুলিৰে স্ক্রীনখনৰ একেবাৰে তলিৰ পৰা ওপৰলৈ ছোৱাইপ কৰক):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"সাধ্য-সুবিধাৰ নির্দেশৰ জৰিয়তে ব্যৱহাৰ কৰিবলৈ এটা সুবিধা বাছনি কৰক (তিনিটা আঙুলিৰে স্ক্রীনখনৰ একেবাৰে তলিৰ পৰা ওপৰলৈ ছোৱাইপ কৰক):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"ডিভাইচটো অতি বেছি গৰম হৈছে"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"আপোনাৰ ফ’নটো অতি বেছি গৰম হোৱাৰ বাবে ডুৱেল স্ক্ৰীন উপলব্ধ নহয়"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"অফ কৰক"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 3d3b717..c8443b9 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Daxiletmə metodunu seçin"</string>
     <string name="show_ime" msgid="6406112007347443383">"Fiziki klaviatura aktiv olanda görünsün"</string>
     <string name="hardware" msgid="1800597768237606953">"Virtual klaviaturanı göstərin"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Fiziki klaviaturanı konfiqurasiya edin"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Dil və tərtibatı seçmək üçün tıklayın"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCÇDEƏFGĞHXIİJKQLMNOÖPRSŞTUÜVYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCÇDEƏFGĞHİIJKLMNOÖPQRSŞTUÜVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Eşitmə cihazları"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Səs səviyyəsi düymələrinə basıb saxlayın. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aktiv edildi."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Səs səviyyəsi düymələrinə basılaraq saxlanıb. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> deaktiv edilib."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> istifadə etmək üçün hər iki səs düyməsini üç saniyə basıb saxlayın"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Xüsusi imkanlar düyməsinə toxunanda istədiyiniz funksiyanı seçin:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Əlçatımlılıq jesti (iki barmağınızla ekranın aşağısından yuxarı doğru sürüşdürün) ilə istifadə edəcəyiniz funksiyanı seçin:"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Əlçatımlılıq jesti (üç barmağınızla ekranın aşağısından yuxarı doğru sürüşdürün) ilə istifadə edəcəyiniz funksiyanı seçin:"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Cihaz çox isinib"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Telefonunuz çox isindiyi üçün İkili Ekran əlçatan deyil"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Deaktiv edin"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 719be37..a5575e6 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1394,7 +1394,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Izbor metoda unosa"</string>
     <string name="show_ime" msgid="6406112007347443383">"Zadržava se na ekranu dok je fizička tastatura aktivna"</string>
     <string name="hardware" msgid="1800597768237606953">"Prikaži virtuelnu tastaturu"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Konfigurišite fizičku tastaturu"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Dodirnite da biste izabrali jezik i raspored"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1719,7 +1722,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Slušni aparati"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Držali ste tastere 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 tastere za jačinu zvuka. Usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je isključena."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Pritisnite i zadržite oba tastera za jačinu zvuka tri sekunde da biste koristili <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Izaberite funkciju koja će se koristiti kada dodirnete dugme Pristupačnost:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Odaberite funkciju koja će se koristiti pomoću pokreta za pristupačnost (pomoću dva prsta prevucite nagore od dna ekrana):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Odaberite funkciju koja će se koristiti pomoću pokreta za pristupačnost (pomoću tri prsta prevucite nagore od dna ekrana):"</string>
@@ -2324,4 +2328,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Uređaj je previše zagrejan"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dvojni ekran je nedostupan jer je telefon previše zagrejan"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Isključi"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 741c7ff..9c17d06 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1395,7 +1395,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Выберыце метад уводу"</string>
     <string name="show_ime" msgid="6406112007347443383">"Захоўваць яе на экране ў той час, калі фізічная клавіятура актыўная"</string>
     <string name="hardware" msgid="1800597768237606953">"Паказаць віртуальную клавіятуру"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Наладжванне фізічнай клавіятуры"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Дакраніцеся, каб выбраць мову і раскладку"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" АБВГДЕЁЖЗІЙКЛМНОПРСТУЎФХЦЧШ\'ЫЬЭЮЯ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1720,7 +1723,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Слыхавыя апараты"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Клавішы гучнасці ўтрымліваліся націснутымі. Уключана служба \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\"."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Клавішы гучнасці ўтрымліваліся націснутымі. Служба \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\" выключана."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Каб карыстацца сэрвісам \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\", націсніце і ўтрымлівайце на працягу трох секунд абедзве клавішы гучнасці"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Выберыце функцыю, якую будзеце выкарыстоўваць пры націску кнопкі спецыяльных магчымасцей:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Выберыце функцыю, якую будзеце выкарыстоўваць з жэстам спецыяльных магчымасцей (правесці двума пальцамі па экране знізу ўверх):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Выберыце функцыю, якую будзеце выкарыстоўваць з жэстам спецыяльных магчымасцей (правесці трыма пальцамі па экране знізу ўверх):"</string>
@@ -2325,4 +2329,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Прылада моцна нагрэлася"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Функцыя \"Двайны экран\" недаступная, бо тэлефон моцна награваецца"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Выключыць"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 4218549..a07e04e 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Избор на метод на въвеждане"</string>
     <string name="show_ime" msgid="6406112007347443383">"Показване на екрана, докато физическата клавиатура е активна"</string>
     <string name="hardware" msgid="1800597768237606953">"Показване на вирт. клавиатура"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Конфигуриране на физическата клавиатура"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Докоснете, за да изберете език и подредба"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Слухови апарати"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Задържахте бутоните за силата на звука. Услугата <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е включена."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Задържахте бутоните за силата на звука. Услугата <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е изключена."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"За да използвате <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, натиснете двата бутона за силата на звука и ги задръжте за 3 секунди"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Изберете функция, която да използвате, когато докоснете бутона за достъпност:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Изберете коя функция да се използва с жеста за достъпност (прекарване на два пръста нагоре от долната част на екрана):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Изберете коя функция да се използва с жеста за достъпност (прекарване на три пръста нагоре от долната част на екрана):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Устройството е твърде топло"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Функцията за двоен екран не е налице, защото телефонът ви е твърде топъл"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Изключване"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 6df2dfb..d6af185 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"ইনপুট পদ্ধতি বেছে নিন"</string>
     <string name="show_ime" msgid="6406112007347443383">"ফিজিক্যাল কীবোর্ড সক্রিয় থাকার সময় এটিকে স্ক্রীনে রাখুন"</string>
     <string name="hardware" msgid="1800597768237606953">"ভার্চুয়াল কীবোর্ড দেখুন"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"ফিজিক্যাল কীবোর্ড কনফিগার করুন"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"ভাষা এবং লেআউট বেছে নিন আলতো চাপ দিন"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"হিয়ারিং ডিভাইস"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ভলিউম কী ধরে ছিলেন। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> চালু করা হয়েছে।"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ভলিউম কী ধরে ছিলেন। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> বন্ধ করা হয়েছে।"</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ব্যবহার করতে ভলিউম কী বোতাম ৩ সেকেন্ডের জন্য চেপে ধরে রাখুন"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"অ্যাক্সেসিবিলিটি বোতামে ট্যাপ করে আপনি যে ফিচার ব্যবহার করতে চান সেটি বেছে নিন:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"অ্যাক্সেসিবিলিটি জেসচারের (দুটি আঙ্গুল দিয়ে স্ক্রিনের নিচে থেকে উপরের দিকে সোয়াইপ করুন) সাহায্যে আপনি যে ফিচার ব্যবহার করতে চান সেটি বেছে নিন:"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"অ্যাক্সেসিবিলিটি জেসচারের (তিনটি আঙ্গুল দিয়ে স্ক্রিনের নিচে থেকে উপরের দিকে সোয়াইপ করুন) সাহায্যে আপনি যে ফিচার ব্যবহার করতে চান সেটি বেছে নিন:"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"ডিভাইস খুব গরম হয়ে গেছে"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"আপনার ফোন খুব বেশি গরম হয়ে যাচ্ছে বলে \'ডুয়াল স্ক্রিন\' উপলভ্য নেই"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"বন্ধ করুন"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 2bb7912..8aaa6ae 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -1394,7 +1394,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Odaberite način unosa"</string>
     <string name="show_ime" msgid="6406112007347443383">"Prikaži na ekranu dok je fizička tastatura aktivna"</string>
     <string name="hardware" msgid="1800597768237606953">"Prikaz virtuelne tastature"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Konfigurirajte fizičku tastaturu"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Dodirnite za odabir jezika i rasporeda"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1719,7 +1722,8 @@
     <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>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Pritisnite obje tipke za podešavanje jačine zvuka i držite ih pritisnutim tri sekunde da koristite uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Odaberite funkciju koja će se koristiti kada dodirnete dugme Pristupačnost:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Odaberite funkciju koju ćete koristiti kada izvedete pokret za pristupačnost (s dva prsta prevucite prema gore s dna ekrana):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Odaberite funkciju koju ćete koristiti kada izvedete pokret za pristupačnost (s tri prsta prevucite prema gore s dna ekrana):"</string>
@@ -2324,4 +2328,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Uređaj je previše zagrijan"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dupli ekran nije dostupan je se telefon previše zagrijava"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Isključi"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index e9a0d8c..5145cbb 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1328,8 +1328,8 @@
     <string name="sms_control_yes" msgid="4858845109269524622">"Permet"</string>
     <string name="sms_control_no" msgid="4845717880040355570">"Denega"</string>
     <string name="sms_short_code_confirm_message" msgid="1385416688897538724">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vol enviar un missatge a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
-    <string name="sms_short_code_details" msgid="2723725738333388351">"Aquesta acció "<b>"pot produir càrrecs"</b>" al teu compte per a mòbils."</string>
-    <string name="sms_premium_short_code_details" msgid="1400296309866638111"><b>"Aquesta acció produirà càrrecs al teu compte per a mòbils."</b></string>
+    <string name="sms_short_code_details" msgid="2723725738333388351">"Aquesta acció "<b>"pot produir càrrecs"</b>" al teu compte mòbil."</string>
+    <string name="sms_premium_short_code_details" msgid="1400296309866638111"><b>"Aquesta acció produirà càrrecs al teu compte mòbil."</b></string>
     <string name="sms_short_code_confirm_allow" msgid="920477594325526691">"Envia"</string>
     <string name="sms_short_code_confirm_deny" msgid="1356917469323768230">"Cancel·la"</string>
     <string name="sms_short_code_remember_choice" msgid="1374526438647744862">"Recorda la meva selecció"</string>
@@ -1369,7 +1369,7 @@
     <string name="usb_power_notification_message" msgid="7284765627437897702">"S\'està carregant el dispositiu connectat. Toca per veure més opcions."</string>
     <string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"S\'ha detectat un accessori d\'àudio analògic"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"El dispositiu connectat no és compatible amb aquest telèfon. Toca per obtenir més informació."</string>
-    <string name="adb_active_notification_title" msgid="408390247354560331">"Depuració per USB activada"</string>
+    <string name="adb_active_notification_title" msgid="408390247354560331">"Depuració per USB connectada"</string>
     <string name="adb_active_notification_message" msgid="5617264033476778211">"Toca per desactivar la depuració per USB"</string>
     <string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Selecciona per desactivar la depuració per USB"</string>
     <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"S\'ha connectat la depuració sense fil"</string>
@@ -1394,7 +1394,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Selecciona un mètode d\'introducció"</string>
     <string name="show_ime" msgid="6406112007347443383">"Mantén-lo en pantalla mentre el teclat físic està actiu"</string>
     <string name="hardware" msgid="1800597768237606953">"Mostra el teclat virtual"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Configura el teclat físic"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Toca per seleccionar l\'idioma i la disposició"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1719,7 +1722,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Audiòfons"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"S\'han mantingut premudes les tecles de volum. S\'ha activat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"S\'han mantingut premudes les tecles de volum. S\'ha desactivat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Mantén premudes les dues tecles de volum durant 3 segons per fer servir <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Tria la funció que vols utilitzar quan toquis el botó d\'accessibilitat:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Tria la funció que vols utilitzar amb el gest d\'accessibilitat (llisca cap amunt amb dos dits des de la part inferior de la pantalla):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Tria la funció que vols utilitzar amb el gest d\'accessibilitat (fes lliscar tres dits cap amunt des de la part inferior de la pantalla):"</string>
@@ -2324,4 +2328,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"El dispositiu està massa calent"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"La pantalla dual no està disponible perquè el telèfon està massa calent"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Desactiva"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index a3d49ae..4aa1192 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1395,7 +1395,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Vybrat metodu zadávání"</string>
     <string name="show_ime" msgid="6406112007347443383">"Ponechat na obrazovce, když je aktivní fyzická klávesnice"</string>
     <string name="hardware" msgid="1800597768237606953">"Zobrazit virtuální klávesnici"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Konfigurace fyzické klávesnice"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Klepnutím vyberte jazyk a rozvržení"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" AÁBCČDĎEÉĚFGHCHIÍJKLMNŇOÓPQRŘSŠTŤUÚVWXYÝZŽ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789AÁBCČDĎEÉĚFGHCHIÍJKLMNŇOÓPQRŘSŠTŤUÚVWXYÝZŽ"</string>
@@ -1720,7 +1723,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Naslouchátka"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Byla podržena tlačítka hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je zapnutá."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Byla podržena tlačítka hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> byla vypnuta."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Chcete-li používat službu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, tři sekundy podržte stisknutá obě tlačítka hlasitosti"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Určete, jakou funkci aktivujete klepnutím na tlačítko přístupnosti:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Určete, jakou funkci aktivujete pomocí gesta přístupnosti (přejetí dvěma prsty ze spodní části obrazovky nahoru):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Určete, jakou funkci aktivujete pomocí gesta přístupnosti (přejetí třemi prsty ze spodní části obrazovky nahoru):"</string>
@@ -2325,4 +2329,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Zařízení je příliš horké"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dvojitá obrazovka není k dispozici, protože se telefon příliš zahřívá"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Vypnout"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index ab0b6c4..44abefb 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Vælg inputmetode"</string>
     <string name="show_ime" msgid="6406112007347443383">"Behold den på skærmen, mens det fysiske tastatur er aktivt"</string>
     <string name="hardware" msgid="1800597768237606953">"Vis virtuelt tastatur"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Konfigurer fysisk tastatur"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Tryk for at vælge sprog og layout"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Høreapparater"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Lydstyrkeknapperne blev holdt nede. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> er aktiveret."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Lydstyrkeknapperne blev holdt nede. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> er deaktiveret."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Hold begge lydstyrkeknapper nede i tre sekunder for at bruge <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Vælg, hvilken funktion du vil bruge, når du trykker på knappen til hjælpefunktioner:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Vælg, hvilken funktion du vil bruge, når du laver bevægelsen for hjælpefunktioner (stryger opad fra bunden af skærmen med to fingre):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Vælg, hvilken funktion du vil bruge, når du laver bevægelsen for hjælpefunktioner (stryger opad fra bunden af skærmen med tre fingre):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Enheden er for varm"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dobbeltskærm er ikke tilgængelig, fordi din telefon er for varm"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Deaktiver"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 96feac3..2f485bb 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Eingabemethode wählen"</string>
     <string name="show_ime" msgid="6406112007347443383">"Bildschirmtastatur auch dann anzeigen, wenn physische Tastatur aktiv ist"</string>
     <string name="hardware" msgid="1800597768237606953">"Virtuelle Tastatur einblenden"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Physische Tastatur konfigurieren"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Zum Auswählen von Sprache und Layout tippen"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hörgeräte"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Lautstärketasten wurden gedrückt gehalten. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ist aktiviert."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Lautstärketasten wurden gedrückt gehalten. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ist deaktiviert."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Halten Sie beide Lautstärketasten drei Sekunden lang gedrückt, um <xliff:g id="SERVICE_NAME">%1$s</xliff:g> zu verwenden"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Wähle eine Funktion aus, die verwendet wird, wenn du auf die Schaltfläche \"Bedienungshilfen\" tippst:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Wähle die Funktion aus, die mit der Touch-Geste für die Bedienungshilfen verwendet werden soll (mit zwei Fingern vom unteren Bildschirmrand nach oben wischen):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Wähle eine Funktion aus, die mit der Touch-Geste für die Bedienungshilfen verwendet werden soll (mit drei Fingern vom unteren Bildschirmrand nach oben wischen):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Gerät ist zu warm"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dual Screen ist nicht verfügbar, weil dein Smartphone zu warm ist"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Deaktivieren"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index de19837..34d7188 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Επιλογή μεθόδου εισόδου"</string>
     <string name="show_ime" msgid="6406112007347443383">"Να παραμένει στην οθόνη όταν είναι ενεργό το κανονικό πληκτρολόγιο"</string>
     <string name="hardware" msgid="1800597768237606953">"Εμφάνιση εικονικού πληκτρολ."</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Διαμόρφωση φυσικού πληκτρολογίου"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Πατήστε για να επιλέξετε γλώσσα και διάταξη"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Συσκευές ακοής"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Τα πλήκτρα έντασης είναι πατημένα. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ενεργοποιήθηκε."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Τα πλήκτρα έντασης είναι πατημένα. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>: απενεργοποιημένο"</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Πατήστε παρατεταμένα και τα δύο κουμπιά έντασης ήχου για τρία δευτερόλεπτα, ώστε να χρησιμοποιήσετε την υπηρεσία <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Επιλέξτε μια λειτουργία που θα χρησιμοποιείται κατά το πάτημα του κουμπιού προσβασιμότητας:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Επιλέξτε μια λειτουργία που θα χρησιμοποιείται με την κίνηση προσβασιμότητας (σύρετε με δύο δάχτυλα προς τα επάνω από το κάτω μέρος της οθόνης):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Επιλέξτε μια λειτουργία που θα χρησιμοποιείται με την κίνηση προσβασιμότητας (σύρετε με τρία δάχτυλα προς τα επάνω από το κάτω μέρος της οθόνης):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Η θερμοκρασία της συσκευής είναι πολύ υψηλή"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Η λειτουργία διπλής οθόνης δεν είναι διαθέσιμη επειδή η θερμοκρασία του τηλεφώνου αυξάνεται υπερβολικά"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Απενεργοποίηση"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 73d6bfd..c83e2a7 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Choose input method"</string>
     <string name="show_ime" msgid="6406112007347443383">"Keep it on screen while physical keyboard is active"</string>
     <string name="hardware" msgid="1800597768237606953">"Show virtual keyboard"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Configure physical keyboard"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Tap to select language and layout"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hearing devices"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Choose a feature to use when you tap the Accessibility button:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Choose a feature to use with the accessibility gesture (swipe up from the bottom of the screen with two fingers):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Choose a feature to use with the accessibility gesture (swipe up from the bottom of the screen with three fingers):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Device is too warm"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dual Screen is unavailable because your phone is getting too warm"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Turn off"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 02f76c2..ff34dca 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -1393,7 +1393,8 @@
     <string name="select_input_method" msgid="3971267998568587025">"Choose input method"</string>
     <string name="show_ime" msgid="6406112007347443383">"Keep it on screen while physical keyboard is active"</string>
     <string name="hardware" msgid="1800597768237606953">"Show virtual keyboard"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Configure physical keyboard"</string>
+    <string name="select_keyboard_layout_notification_title" msgid="5823199895322205589">"Configure <xliff:g id="DEVICE_NAME">%s</xliff:g>"</string>
+    <string name="select_multiple_keyboards_layout_notification_title" msgid="6999491025126641938">"Configure physical keyboards"</string>
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Tap to select language and layout"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1719,7 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hearing devices"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Release the volume keys. To turn on <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, press and hold both volume keys again for 3 seconds."</string>
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Choose a feature to use when you tap the accessibility button:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Choose a feature to use with the accessibility gesture (swipe up from the bottom of the screen with two fingers):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Choose a feature to use with the accessibility gesture (swipe up from the bottom of the screen with three fingers):"</string>
@@ -2323,4 +2324,11 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Device is too warm"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dual Screen is unavailable because your phone is getting too warm"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Turn off"</string>
+    <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"<xliff:g id="DEVICE_NAME">%s</xliff:g> configured"</string>
+    <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"Keyboard layout set to <xliff:g id="LAYOUT_1">%s</xliff:g>. Tap to change."</string>
+    <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"Keyboard layout set to <xliff:g id="LAYOUT_1">%1$s</xliff:g>, <xliff:g id="LAYOUT_2">%2$s</xliff:g>. Tap to change."</string>
+    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"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_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>
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 19570b1..3fc4540 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Choose input method"</string>
     <string name="show_ime" msgid="6406112007347443383">"Keep it on screen while physical keyboard is active"</string>
     <string name="hardware" msgid="1800597768237606953">"Show virtual keyboard"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Configure physical keyboard"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Tap to select language and layout"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hearing devices"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Choose a feature to use when you tap the Accessibility button:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Choose a feature to use with the accessibility gesture (swipe up from the bottom of the screen with two fingers):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Choose a feature to use with the accessibility gesture (swipe up from the bottom of the screen with three fingers):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Device is too warm"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dual Screen is unavailable because your phone is getting too warm"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Turn off"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index dfa965c..93d45c7 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Choose input method"</string>
     <string name="show_ime" msgid="6406112007347443383">"Keep it on screen while physical keyboard is active"</string>
     <string name="hardware" msgid="1800597768237606953">"Show virtual keyboard"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Configure physical keyboard"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Tap to select language and layout"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hearing devices"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Choose a feature to use when you tap the Accessibility button:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Choose a feature to use with the accessibility gesture (swipe up from the bottom of the screen with two fingers):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Choose a feature to use with the accessibility gesture (swipe up from the bottom of the screen with three fingers):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Device is too warm"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dual Screen is unavailable because your phone is getting too warm"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Turn off"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 7e74c19..d55ee16 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -1393,7 +1393,8 @@
     <string name="select_input_method" msgid="3971267998568587025">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‏‏‏‎‎‏‏‎‎‎‏‏‏‎‎‏‏‎‏‎‎‎‎‏‏‏‎‏‎‏‎‎‎‏‏‏‎‏‎‎‏‏‏‏‏‎‎‎‏‎‎‎‏‎Choose input method‎‏‎‎‏‎"</string>
     <string name="show_ime" msgid="6406112007347443383">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‏‎‎‏‏‏‎‎‎‏‎‏‎‎‏‏‏‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‏‎‎‎‏‎‏‏‎‏‎‏‏‎‏‏‏‎Keep it on screen while physical keyboard is active‎‏‎‎‏‎"</string>
     <string name="hardware" msgid="1800597768237606953">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‎‏‎‎‎‏‎‎‎‎‏‎‏‎‏‎‏‏‏‎‎‏‎‏‎‎‏‏‏‏‎‏‎‎‎‎‎‏‎‏‎‎‏‎Show virtual keyboard‎‏‎‎‏‎"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‏‎‎‏‎‎‎‏‎‎‏‏‎‏‎‏‎‎‎‏‏‏‎‎‏‎‎‏‎‏‎‎‏‏‎‏‎‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‎Configure physical keyboard‎‏‎‎‏‎"</string>
+    <string name="select_keyboard_layout_notification_title" msgid="5823199895322205589">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‎‏‎‎‎‎‎‎‏‎‏‎‎‏‎‏‏‏‎‎‏‏‏‏‎‎‎‎‎‎‏‏‎‎‎‏‎‏‏‎‎‏‏‏‎‏‏‎‎‏‎‏‎‏‎Configure ‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="select_multiple_keyboards_layout_notification_title" msgid="6999491025126641938">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‎‎‎‏‏‎‎‏‏‎‎‎‎‎‎‎‎‎‎‎‎‏‎‏‎‎‎‎‏‎‎‏‏‎‏‎‏‎‏‎‏‎‎‎‏‎‎‎‏‎‎‏‎‎Configure physical keyboards‎‏‎‎‏‎"</string>
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‎‏‏‎‎‏‎‎‏‏‎‎‏‏‏‎‏‏‎‎‎‎‏‎‎‏‏‎‎‏‏‎‏‎‎‏‎‏‏‏‎‎‎‎‎‏‎‏‎‎Tap to select language and layout‎‏‎‎‏‎"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‏‎‏‎‎‎‏‏‎‏‎‎‏‎‏‏‏‎‏‏‏‎‏‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎ ABCDEFGHIJKLMNOPQRSTUVWXYZ‎‏‎‎‏‎"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" ‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‎‏‏‎‏‎‏‎‏‏‏‎‏‏‎‎‏‎‏‏‎‏‏‎‏‎‎‏‎‎‎‎‎‎‎‎‏‏‎‏‎‎‏‏‏‎‎‏‎‏‎‎‎‏‎ 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ‎‏‎‎‏‎"</string>
@@ -1718,7 +1719,7 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‏‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‏‏‏‏‎‎‎‎‏‎‎‎‏‎‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‎Hearing devices‎‏‎‎‏‎"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‎‎‎‏‏‎‏‎‏‎‎‏‏‏‏‏‎‏‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‎‏‏‏‎Held volume keys. ‎‏‎‎‏‏‎<xliff:g id="SERVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ turned on.‎‏‎‎‏‎"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‎‎‏‎‏‎‏‎‎‎‏‎‎‏‏‎‏‎‏‏‎‎‏‏‏‎‎‏‎‏‎‏‏‏‏‎‏‎‏‏‏‎‎‏‎‎‏‎‏‏‎Held volume keys. ‎‏‎‎‏‏‎<xliff:g id="SERVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ turned off.‎‏‎‎‏‎"</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‏‎‎‎‎‎‏‏‎‏‎‏‎‎‏‏‎‎‏‏‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‎‏‎‎Press and hold both volume keys for three seconds to use ‎‏‎‎‏‏‎<xliff:g id="SERVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‏‏‎‎‎‏‏‏‎‎‎‎‎‎‏‏‎‎‏‏‎‎‎‏‎‏‎‎‎‏‎‎‎‏‏‎‎‏‏‎‎‎‏‎‎‏‏‎‎‏‏‎‏‎‎Release the volume keys. To turn on ‎‏‎‎‏‏‎<xliff:g id="SERVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎, press and hold both volume keys again for 3 seconds.‎‏‎‎‏‎"</string>
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‎‎‏‎‎‎‎‏‏‎‎‏‎‎‏‎‏‏‎‎‎‎‏‎‎‎‎‎‏‎‎‏‏‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‎‎‏‎Choose a feature to use when you tap the accessibility button:‎‏‎‎‏‎"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‎‏‏‏‎‏‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎‎‎‏‏‏‎‏‏‏‎‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‏‎‎‎‎‎Choose a feature to use with the accessibility gesture (swipe up from the bottom of the screen with two fingers):‎‏‎‎‏‎"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‎‏‎‏‎‎‎‎‏‎‎‎‎‏‏‏‎‏‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‏‎‎‎‎‎‎‏‏‎‏‎‎‏‏‎‏‎‏‏‎Choose a feature to use with the accessibility gesture (swipe up from the bottom of the screen with three fingers):‎‏‎‎‏‎"</string>
@@ -2323,4 +2324,11 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‎‏‏‎‏‏‏‎‎‏‎‎‎‎‏‏‎‎‎‎‏‎‎‏‎‎‏‏‎‎‏‏‏‎‏‏‎‎‏‎‎‏‎‎‎‏‎‎‏‏‏‎‏‎Device is too warm‎‏‎‎‏‎"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‏‎‏‏‎‎‏‏‎‏‎‎‏‏‏‎‏‏‎‎‏‏‎‎‎‎‏‏‏‏‏‎‎‎‎‎‎‎‏‎‏‎‏‏‏‏‎‎‏‏‏‎Dual Screen is unavailable because your phone is getting too warm‎‏‎‎‏‎"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‏‎‎‎‎‎‎‎‏‏‎‎‏‏‏‎‎‏‎‏‏‎‏‎‎‎‎‏‎‎‎‎‎‎‎‏‏‎‎‏‎‎‎‎‎Turn off‎‏‎‎‏‎"</string>
+    <string name="keyboard_layout_notification_selected_title" msgid="1202560174252421219">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‏‎‏‏‎‎‎‎‎‏‎‏‏‎‏‎‎‎‎‏‏‎‏‏‎‏‏‎‎‏‏‏‎‏‎‏‏‎‎‎‏‏‏‏‎‎‎‎‎‏‏‎‎‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%s</xliff:g>‎‏‎‎‏‏‏‎ configured‎‏‎‎‏‎"</string>
+    <string name="keyboard_layout_notification_one_selected_message" msgid="4314216053129257197">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‏‏‎‏‏‏‏‏‎‎‏‎‏‏‎‎‏‎‏‎‎‏‎‎‏‎‎‎‎‎‏‏‎‎‎‎‏‏‏‎‏‎‏‎‎‎‎‎‏‏‏‎‏‏‎‏‎Keyboard layout set to ‎‏‎‎‏‏‎<xliff:g id="LAYOUT_1">%s</xliff:g>‎‏‎‎‏‏‏‎. Tap to change.‎‏‎‎‏‎"</string>
+    <string name="keyboard_layout_notification_two_selected_message" msgid="1876349944065922950">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‎‏‎‏‎‎‎‏‎‎‎‏‎‎‏‎‏‎‏‎‏‎‎‏‏‎‎‏‎‎‏‎‏‏‏‏‏‏‎‎‏‎‏‏‏‏‎‎‎‎‏‏‎‎Keyboard layout set to ‎‏‎‎‏‏‎<xliff:g id="LAYOUT_1">%1$s</xliff:g>‎‏‎‎‏‏‏‎, ‎‏‎‎‏‏‎<xliff:g id="LAYOUT_2">%2$s</xliff:g>‎‏‎‎‏‏‏‎. Tap to change.‎‏‎‎‏‎"</string>
+    <string name="keyboard_layout_notification_three_selected_message" msgid="280734264593115419">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‏‏‏‎‎‏‎‏‎‏‎‏‏‏‏‎‎‏‎‏‎‎‏‏‏‎‎‎‎‏‎‏‎‏‎‏‏‎‏‎‎‏‏‎‏‎‎‏‎‎‎‏‏‎‏‏‎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_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>
 </resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 4cf1fbb..f32279a 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1369,7 +1369,7 @@
     <string name="usb_power_notification_message" msgid="7284765627437897702">"Cargando el dispositivo conectado. Presiona para ver más opciones."</string>
     <string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Se detectó un accesorio de audio analógico"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"El dispositivo adjunto no es compatible con este teléfono. Presiona para obtener más información."</string>
-    <string name="adb_active_notification_title" msgid="408390247354560331">"Depuración por USB conectada"</string>
+    <string name="adb_active_notification_title" msgid="408390247354560331">"Depuración por USB activada"</string>
     <string name="adb_active_notification_message" msgid="5617264033476778211">"Presiona para desactivar"</string>
     <string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Seleccionar para desactivar la depuración por USB"</string>
     <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Se conectó la depuración inalámbrica"</string>
@@ -1394,7 +1394,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Selecciona el método de entrada"</string>
     <string name="show_ime" msgid="6406112007347443383">"Mientras el teclado físico está activo"</string>
     <string name="hardware" msgid="1800597768237606953">"Mostrar teclado virtual"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Configura el teclado físico"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Presiona para seleccionar el idioma y el diseño"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1719,7 +1722,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Dispositivos auditivos"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Como mantuviste presionadas las teclas de volumen, se activó <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Se presionaron las teclas de volumen. Se desactivó <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Mantén presionadas ambas teclas de volumen durante tres segundos para usar <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Elige una función para usar cuando pulses el botón accesibilidad:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Elige la función que se usará cuando realices el gesto de accesibilidad (deslizar dos dedos hacia arriba desde la parte inferior de la pantalla):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Elige la función que se usará cuando realices el gesto de accesibilidad (deslizar tres dedos hacia arriba desde la parte inferior de la pantalla):"</string>
@@ -2324,4 +2328,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"El dispositivo está muy caliente"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"La Pantalla dual no está disponible porque el teléfono se está calentando demasiado"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Desactivar"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index a03449d..ffc018f 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1369,9 +1369,9 @@
     <string name="usb_power_notification_message" msgid="7284765627437897702">"Cargando el dispositivo conectado. Toca para ver más opciones."</string>
     <string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Se ha detectado un accesorio de audio analógico"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"El dispositivo adjunto no es compatible con este teléfono. Toca para obtener más información."</string>
-    <string name="adb_active_notification_title" msgid="408390247354560331">"Depuración USB habilitada"</string>
-    <string name="adb_active_notification_message" msgid="5617264033476778211">"Toca para desactivar la depuración USB"</string>
-    <string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Seleccionar para inhabilitar la depuración USB"</string>
+    <string name="adb_active_notification_title" msgid="408390247354560331">"Depuración por USB activa"</string>
+    <string name="adb_active_notification_message" msgid="5617264033476778211">"Toca para desactivar la depuración por USB"</string>
+    <string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Seleccionar para inhabilitar la depuración por USB"</string>
     <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Depuración inalámbrica conectada"</string>
     <string name="adbwifi_active_notification_message" msgid="930987922852867972">"Toca para desactivar la depuración inalámbrica"</string>
     <string name="adbwifi_active_notification_message" product="tv" msgid="8633421848366915478">"Toca para desactivar la depuración inalámbrica."</string>
@@ -1394,7 +1394,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Selecciona un método de entrada"</string>
     <string name="show_ime" msgid="6406112007347443383">"Mientras el teclado físico está activo"</string>
     <string name="hardware" msgid="1800597768237606953">"Mostrar teclado virtual"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Configurar el teclado físico"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Toca para seleccionar el idioma y el diseño"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1719,7 +1722,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Dispositivos auditivos"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Al mantener pulsadas las teclas de volumen, se ha activado <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Se han mantenido pulsadas las teclas de volumen. Se ha desactivado <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Para utilizar <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, mantén pulsadas ambas teclas de volumen durante 3 segundos"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Selecciona la función que se utilizará cuando toques el botón de accesibilidad:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Elige la función que se utilizará con el gesto de accesibilidad (deslizar dos dedos hacia arriba desde la parte inferior de la pantalla):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Elige la función que se utilizará con el gesto de accesibilidad (deslizar tres dedos hacia arriba desde la parte inferior de la pantalla):"</string>
@@ -2324,4 +2328,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"El dispositivo está demasiado caliente"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Cámara Dual no está disponible porque el teléfono se está calentando demasiado"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Desactivar"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 6d26022..d84db73 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Valige sisestusmeetod"</string>
     <string name="show_ime" msgid="6406112007347443383">"Hoia seda ekraanil, kui füüsiline klaviatuur on aktiivne"</string>
     <string name="hardware" msgid="1800597768237606953">"Virtuaalse klaviatuuri kuvam."</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Füüsilise klaviatuuri seadistamine"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Puudutage keele ja paigutuse valimiseks"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜXY"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜXY"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Kuuldeseadmed"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Helitugevuse klahve hoiti all. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> lülitati sisse."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Helitugevuse klahve hoiti all. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> lülitati välja."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Teenuse <xliff:g id="SERVICE_NAME">%1$s</xliff:g> kasutamiseks hoidke kolm sekundit all mõlemat helitugevuse klahvi"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Valige, millist funktsiooni kasutada, kui vajutate juurdepääsetavuse nuppu:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Valige, millist funktsiooni juurdepääsetavuse liigutusega (kahe sõrmega ekraanikuval alt üles pühkimine) kasutada:"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Valige, millist funktsiooni juurdepääsetavuse liigutusega (kolme sõrmega ekraanikuval alt üles pühkimine) kasutada:"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Seade on liiga kuum"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Kahe ekraani režiim pole saadaval, kuna teie telefon läheb liiga kuumaks"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Lülita välja"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 76b39bb..e7aabd8 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -207,12 +207,9 @@
     <string name="personal_apps_suspension_text" msgid="6115455688932935597">"Aplikazio pertsonalak blokeatuta egongo dira laneko profila aktibatzen duzun arte"</string>
     <string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Aplikazio pertsonalak egun eta ordu honetan blokeatuko dira: <xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>. IKT saileko administratzaileak ez dizu ematen baimenik laneko profila <xliff:g id="NUMBER">%3$d</xliff:g> egunez baino gehiagoz desaktibatuta edukitzeko."</string>
     <string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Aktibatu"</string>
-    <!-- no translation found for work_profile_telephony_paused_title (7690804479291839519) -->
-    <skip />
-    <!-- no translation found for work_profile_telephony_paused_text (8065762301100978221) -->
-    <skip />
-    <!-- no translation found for work_profile_telephony_paused_turn_on_button (7542632318337068821) -->
-    <skip />
+    <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Deiak eta mezuak desaktibatuta daude"</string>
+    <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Laneko aplikazioak pausatu dituzu. Ez duzu jasoko telefono-deirik edo testu-mezurik."</string>
+    <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Berraktibatu laneko aplikazioak"</string>
     <string name="me" msgid="6207584824693813140">"Ni"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tabletaren aukerak"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV gailuaren aukerak"</string>
@@ -1396,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Aukeratu idazketa-metodoa"</string>
     <string name="show_ime" msgid="6406112007347443383">"Erakutsi pantailan teklatu fisikoa aktibo dagoen bitartean"</string>
     <string name="hardware" msgid="1800597768237606953">"Erakutsi teklatu birtuala"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Konfiguratu teklatu fisikoa"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Hizkuntza eta diseinua hautatzeko, sakatu hau"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1721,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Audifonoak"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Bolumen-botoiak sakatuta eduki direnez, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aktibatu egin da."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Bolumen-botoiak sakatuta eduki direnez, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desaktibatu egin da."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> erabiltzeko, eduki sakatuta bi bolumen-botoiak hiru segundoz"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Aukeratu zein eginbide erabili nahi duzun Erabilerraztasuna botoia sakatzean:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Aukeratu zein eginbide erabili nahi duzun erabilerraztasun-keinuarekin (hau da, bi hatz pantailaren behealdetik gora pasatzean):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Aukeratu zein eginbide erabili nahi duzun erabilerraztasun-keinuarekin (hau da, hiru hatz pantailaren behealdetik gora pasatzean):"</string>
@@ -1873,8 +1874,8 @@
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Administratzaileak eguneratu du"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Administratzaileak ezabatu du"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"Ados"</string>
-    <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Bateria-aurreztaileak gai iluna aktibatzen du, eta murriztu edo desaktibatu egiten ditu atzeko planoko jarduerak, zenbait efektu bisual, eta eginbide jakin eta sareko konexio batzuk."</string>
-    <string name="battery_saver_description" msgid="8518809702138617167">"Bateria-aurreztaileak gai iluna aktibatzen du, eta atzeko planoko jarduerak, zenbait efektu bisual, eta eginbide jakin eta sareko konexio batzuk murrizten edo desaktibatzen ditu."</string>
+    <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Bateria-aurreztaileak gai iluna aktibatzen du, eta atzeko planoko jarduerak, zenbait efektu bisual, eta eginbide jakin eta sareko konexio batzuk mugatzen edo desaktibatzen ditu."</string>
+    <string name="battery_saver_description" msgid="8518809702138617167">"Bateria-aurreztaileak gai iluna aktibatzen du, eta atzeko planoko jarduerak, zenbait efektu bisual, eta eginbide jakin eta sareko konexio batzuk mugatzen edo desaktibatzen ditu."</string>
     <string name="data_saver_description" msgid="4995164271550590517">"Datu-erabilera murrizteko, atzeko planoan datuak bidaltzea eta jasotzea galarazten die datu-aurreztaileak aplikazio batzuei. Erabiltzen ari zaren aplikazioek datuak atzitu ahalko dituzte, baina baliteke maiztasun txikiagoarekin atzitzea. Ondorioz, adibidez, baliteke irudiak ez erakustea haiek sakatu arte."</string>
     <string name="data_saver_enable_title" msgid="7080620065745260137">"Datu-aurreztailea aktibatu nahi duzu?"</string>
     <string name="data_saver_enable_button" msgid="4399405762586419726">"Aktibatu"</string>
@@ -2326,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Gailua beroegi dago"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Bi pantailako modua ez dago erabilgarri telefonoa berotzen ari delako"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Desaktibatu"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index dfb0b2e..4b98194 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -296,7 +296,7 @@
     <string name="safeMode" msgid="8974401416068943888">"حالت ایمن"</string>
     <string name="android_system_label" msgid="5974767339591067210">"‏سیستم Android"</string>
     <string name="user_owner_label" msgid="8628726904184471211">"جابه‌جا شدن به نمایه شخصی"</string>
-    <string name="managed_profile_label" msgid="7316778766973512382">"جابه‌جا شدن به نمایه کاری"</string>
+    <string name="managed_profile_label" msgid="7316778766973512382">"رفتن به نمایه کاری"</string>
     <string name="permgrouplab_contacts" msgid="4254143639307316920">"مخاطبین"</string>
     <string name="permgroupdesc_contacts" msgid="9163927941244182567">"دسترسی به مخاطبین شما"</string>
     <string name="permgrouplab_location" msgid="1858277002233964394">"مکان"</string>
@@ -634,7 +634,7 @@
     <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"حرکت انگشت خیلی آهسته بود. لطفاً دوباره امتحان کنید."</string>
     <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"اثر انگشت دیگری را امتحان کنید"</string>
     <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"خیلی روشن است"</string>
-    <string name="fingerprint_acquired_power_press" msgid="3107864151278434961">"فشردن دکمه روشن/ خاموش شناسایی شد"</string>
+    <string name="fingerprint_acquired_power_press" msgid="3107864151278434961">"فشردن دکمه روشن/خاموش شناسایی شد"</string>
     <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"اثر انگشت را تنظیم کنید"</string>
     <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"هربار موقعیت انگشتتان را کمی تغییر دهید"</string>
   <string-array name="fingerprint_acquired_vendor">
@@ -656,7 +656,7 @@
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"این دستگاه حسگر اثر انگشت ندارد."</string>
     <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"حسگر به‌طور موقت غیرفعال است."</string>
     <string name="fingerprint_error_bad_calibration" msgid="4385512597740168120">"امکان استفاده از حسگر اثر انگشت وجود ندارد. به ارائه‌دهنده خدمات تعمیر مراجعه کنید"</string>
-    <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"دکمه روشن/ خاموش فشار داده شد"</string>
+    <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"دکمه روشن/خاموش فشار داده شد"</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"انگشت <xliff:g id="FINGERID">%d</xliff:g>"</string>
     <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"استفاده از اثر انگشت"</string>
     <string name="fingerprint_or_screen_lock_app_setting_name" msgid="3501743523487644907">"استفاده از اثر انگشت یا قفل صفحه"</string>
@@ -1254,11 +1254,11 @@
     <string name="android_preparing_apk" msgid="589736917792300956">"آماده‌سازی <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"درحال آغاز کردن برنامه‌ها."</string>
     <string name="android_upgrading_complete" msgid="409800058018374746">"درحال اتمام راه‌اندازی."</string>
-    <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"دکمه روشن/ خاموش را فشار دادید — این کار معمولاً صفحه‌نمایش را خاموش می‌کند.\n\nهنگام راه‌اندازی اثر انگشت، آرام ضربه بزنید."</string>
+    <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"دکمه روشن/خاموش را فشار دادید — این کار معمولاً صفحه‌نمایش را خاموش می‌کند.\n\nهنگام راه‌اندازی اثر انگشت، آرام ضربه بزنید."</string>
     <string name="fp_power_button_enrollment_title" msgid="6976841690455338563">"برای اتمام راه‌اندازی، صفحه را خاموش کنید"</string>
     <string name="fp_power_button_enrollment_button_text" msgid="3199783266386029200">"خاموش کردن"</string>
     <string name="fp_power_button_bp_title" msgid="5585506104526820067">"تأیید اثر انگشت را ادامه می‌دهید؟"</string>
-    <string name="fp_power_button_bp_message" msgid="2983163038168903393">"دکمه روشن/ خاموش را فشار دادید — این کار معمولاً صفحه‌نمایش را خاموش می‌کند.\n\nبرای تأیید اثر انگشتتان، آرام ضربه بزنید."</string>
+    <string name="fp_power_button_bp_message" msgid="2983163038168903393">"دکمه روشن/خاموش را فشار دادید — این کار معمولاً صفحه‌نمایش را خاموش می‌کند.\n\nبرای تأیید اثر انگشتتان، آرام ضربه بزنید."</string>
     <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"خاموش کردن صفحه"</string>
     <string name="fp_power_button_bp_negative_button" msgid="3971364246496775178">"ادامه"</string>
     <string name="heavy_weight_notification" msgid="8382784283600329576">"<xliff:g id="APP">%1$s</xliff:g> در حال اجرا"</string>
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"انتخاب روش ورودی"</string>
     <string name="show_ime" msgid="6406112007347443383">"وقتی صفحه‌کلید فیزیکی فعال است این ویرایشگر را روی صفحه نگه‌می‌دارد"</string>
     <string name="hardware" msgid="1800597768237606953">"نمایش صفحه‌کلید مجازی"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"پیکربندی صفحه‌کلید فیزیکی"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"برای انتخاب زبان و چیدمان ضربه بزنید"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"دستگاه‌های کمک‌شنوایی"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"کلیدهای میزان صدا پایین نگه داشته شد. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> روشن شد."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"کلیدهای میزان صدا پایین نگه داشته شد. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> خاموش شد."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"برای استفاده از <xliff:g id="SERVICE_NAME">%1$s</xliff:g>، هر دو کلید صدا را فشار دهید و سه ثانیه نگه دارید"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"ویژگی را انتخاب کنید که هنگام ضربه زدن روی دکمه دسترس‌پذیری استفاده می‌شود:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"ویژگی را برای استفاده با اشاره دسترس‌پذیری انتخاب کنید (با دو انگشت صفحه را از پایین تند به‌بالا بکشید):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"ویزگی را برای استفاده با اشاره دسترس‌پذیری انتخاب کنید (با سه انگشت صفحه را از پایین تند به‌بالا بکشید):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"دستگاه بیش‌ازحد گرم شده است"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"«صفحه دوتایی» دردسترس نیست زیرا تلفن بیش‌ازحد گرم شده است"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"خاموش کردن"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 4803bc0..487082d 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Valitse syöttötapa"</string>
     <string name="show_ime" msgid="6406112007347443383">"Pidä näytöllä, kun fyysinen näppäimistö on aktiivinen"</string>
     <string name="hardware" msgid="1800597768237606953">"Näytä virtuaalinen näppäimistö"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Määritä fyysinen näppäimistö"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Valitse kieli ja asettelu koskettamalla."</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Kuulolaitteet"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Äänenvoimakkuuspainikkeita painettiin pitkään. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> laitettiin päälle."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Äänenvoimakkuuspainikkeita painettiin pitkään. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> laitettiin pois päältä."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Voit käyttää palvelua <xliff:g id="SERVICE_NAME">%1$s</xliff:g> painamalla molempia äänenvoimakkuuspainikkeita kolmen sekunnin ajan"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Valitse ominaisuus, jonka esteettömyyspainike aktivoi:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Valitse ominaisuus, jota käytetään esteettömyyseleellä (pyyhkäise näytön alalaidasta ylös kahdella sormella):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Valitse ominaisuus, jota käytetään esteettömyyseleellä (pyyhkäise näytön alalaidasta ylös kolmella sormella):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Laite on liian lämmin"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Kaksoisnäyttö ei ole käytettävissä, koska puhelin on liian lämmin"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Laita pois päältä"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 0c4dfae..f0d5528 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -208,12 +208,9 @@
     <string name="personal_apps_suspension_text" msgid="6115455688932935597">"Vos applications personnelles sont bloquées jusqu\'à ce que vous activiez votre profil professionnel"</string>
     <string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Les applications personnelles seront bloquées le <xliff:g id="DATE">%1$s</xliff:g> à <xliff:g id="TIME">%2$s</xliff:g>. Votre administrateur informatique ne vous autorise pas à laisser votre profil professionnel désactivé pendant plus de <xliff:g id="NUMBER">%3$d</xliff:g> jours."</string>
     <string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Activer"</string>
-    <!-- no translation found for work_profile_telephony_paused_title (7690804479291839519) -->
-    <skip />
-    <!-- no translation found for work_profile_telephony_paused_text (8065762301100978221) -->
-    <skip />
-    <!-- no translation found for work_profile_telephony_paused_turn_on_button (7542632318337068821) -->
-    <skip />
+    <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Les appels et messages sont désactivés"</string>
+    <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Vous avez mis en pause les applications professionnelles. Vous ne recevrez aucun appel téléphonique ni message texte."</string>
+    <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Réact. applis prof."</string>
     <string name="me" msgid="6207584824693813140">"Moi"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Options de la tablette"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Options d\'Android TV"</string>
@@ -1397,7 +1394,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Sélectionnez le mode de saisie"</string>
     <string name="show_ime" msgid="6406112007347443383">"Afficher lorsque le clavier physique est activé"</string>
     <string name="hardware" msgid="1800597768237606953">"Afficher le clavier virtuel"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Configurer le clavier physique"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Touchez pour sélectionner la langue et la configuration du clavier"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1722,7 +1722,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Appareils auditifs"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Touches de volume maintenues enfoncées. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> activé."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Touches de volume maintenues enfoncées. Service <xliff:g id="SERVICE_NAME">%1$s</xliff:g> désactivé."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Maintenez les deux touches de volume enfoncées pendant trois secondes pour utiliser <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Choisissez une fonctionnalité à utiliser lorsque vous touchez le bouton d\'accessibilité :"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Choisissez une fonctionnalité à utiliser lorsque vous utilisez le geste d\'accessibilité (balayer l\'écran de bas en haut avec deux doigts) :"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Choisissez une fonctionnalité à utiliser lorsque vous utilisez le geste d\'accessibilité (balayer l\'écran de bas en haut avec trois doigts) :"</string>
@@ -2327,4 +2328,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"L\'appareil est trop chaud"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Le double écran n\'est pas accessible, car votre téléphone est trop chaud"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Désactiver"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 29b86bc..60c61fb 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1394,7 +1394,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Sélectionnez le mode de saisie"</string>
     <string name="show_ime" msgid="6406112007347443383">"Afficher le clavier virtuel même lorsque le clavier physique est actif"</string>
     <string name="hardware" msgid="1800597768237606953">"Afficher le clavier virtuel"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Configurer le clavier physique"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Appuyer pour sélectionner la langue et la disposition"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1719,7 +1722,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Prothèses auditives"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Touches de volume appuyées de manière prolongée. Service <xliff:g id="SERVICE_NAME">%1$s</xliff:g> activé."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Touches de volume appuyées de manière prolongée. Service <xliff:g id="SERVICE_NAME">%1$s</xliff:g> désactivé."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Appuyez de manière prolongée sur les deux touches de volume pendant trois secondes pour utiliser <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Choisissez une fonctionnalité à utiliser lorsque vous appuyez sur le bouton Accessibilité :"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Choisissez une fonctionnalité à utiliser avec le geste d\'accessibilité (balayez l\'écran de bas en haut avec deux doigts) :"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Choisissez une fonctionnalité à utiliser avec le geste d\'accessibilité (balayer l\'écran de bas en haut avec trois doigts) :"</string>
@@ -2324,4 +2328,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"L\'appareil est trop chaud"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Double écran n\'est pas disponible, car votre téléphone surchauffe"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Désactiver"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 355acf4..8d1aac3 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -1327,8 +1327,8 @@
     <string name="sms_control_yes" msgid="4858845109269524622">"Permitir"</string>
     <string name="sms_control_no" msgid="4845717880040355570">"Rexeitar"</string>
     <string name="sms_short_code_confirm_message" msgid="1385416688897538724">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; quere enviar unha mensaxe a &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
-    <string name="sms_short_code_details" msgid="2723725738333388351">"Esta acción "<b>"pode supoñer custos"</b>" na túa conta de teléfono móbil."</string>
-    <string name="sms_premium_short_code_details" msgid="1400296309866638111"><b>"Esta acción suporá custos na túa conta de teléfono móbil."</b></string>
+    <string name="sms_short_code_details" msgid="2723725738333388351">"Esta acción "<b>"pode supoñer custos"</b>" na conta do teu operador móbil."</string>
+    <string name="sms_premium_short_code_details" msgid="1400296309866638111"><b>"Esta acción suporá custos na conta do teu operador móbil."</b></string>
     <string name="sms_short_code_confirm_allow" msgid="920477594325526691">"Enviar"</string>
     <string name="sms_short_code_confirm_deny" msgid="1356917469323768230">"Cancelar"</string>
     <string name="sms_short_code_remember_choice" msgid="1374526438647744862">"Lembrar a miña opción"</string>
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Escoller método de introdución de texto"</string>
     <string name="show_ime" msgid="6406112007347443383">"Móstrase na pantalla mentres o teclado físico estea activo"</string>
     <string name="hardware" msgid="1800597768237606953">"Mostrar teclado virtual"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Configura o teclado físico"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Toca para seleccionar o idioma e o deseño"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Dispositivos auditivos"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas de volume premidas. Activouse o servizo <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume premidas. Desactivouse <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Mantén premidas as teclas do volume durante tres segudos para usar <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Escolle a función que queres utilizar cando toques o botón Accesibilidade:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Escolle a función que queres usar co xesto de accesibilidade (pasa dous dedos cara arriba desde a parte inferior da pantalla):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Escolle a función que queres usar co xesto de accesibilidade (pasa tres dedos cara arriba desde a parte inferior da pantalla):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"O dispositivo está demasiado quente"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"A pantalla dual non está dispoñible porque o teléfono está quentando demasiado"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Desactivar"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 64ca834..687ad2f 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"ઇનપુટ પદ્ધતિ પસંદ કરો"</string>
     <string name="show_ime" msgid="6406112007347443383">"જ્યારે ભૌતિક કીબોર્ડ સક્રિય હોય ત્યારે તેને સ્ક્રીન પર રાખો"</string>
     <string name="hardware" msgid="1800597768237606953">"વર્ચ્યુઅલ કીબોર્ડ બતાવો"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"ભૌતિક કીબોર્ડ ગોઠવો"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"ભાષા અને લેઆઉટ પસંદ કરવા માટે ટૅપ કરો"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"સાંભળવામાં સહાય કરતા ડિવાઇસ"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"વૉલ્યૂમ કી દબાવી રાખો. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ચાલુ કરી."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"વૉલ્યૂમ કી દબાવી રાખો. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> બંધ કરી."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>નો ઉપયોગ કરવા માટે બન્ને વૉલ્યૂમ કીને ત્રણ સેકન્ડ સુધી દબાવી રાખો"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"જ્યારે તમે ઍક્સેસિબિલિટી બટન પર ટૅપ કરો, ત્યારે ઉપયોગ કરવાની સુવિધા પસંદ કરો:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"ઍક્સેસિબિલિટી સંકેત સાથે ઉપયોગ કરવાની સુવિધા પસંદ કરો (બે આંગળીઓ વડે સ્ક્રીનના નીચેના ભાગથી ઉપરની તરફ સ્વાઇપ કરવા માટે):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"ઍક્સેસિબિલિટી સંકેત સાથે ઉપયોગ કરવાની સુવિધા પસંદ કરો (ત્રણ આંગળીઓ વડે સ્ક્રીનના નીચેના ભાગથી ઉપરની તરફ સ્વાઇપ કરવા માટે):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"ડિવાઇસ ખૂબ જ ગરમ છે"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"ડ્યૂઅલ સ્ક્રીન અનુપલબ્ધ છે કારણ કે તમારો ફોન ખૂબ જ ગરમ થઈ રહ્યો છે"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"બંધ કરો"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 277b7a0..c0df6ca 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"इनपुट का तरीका चुनें"</string>
     <string name="show_ime" msgid="6406112007347443383">"सामान्य कीबोर्ड के सक्रिय होने के दौरान इसे स्‍क्रीन पर बनाए रखें"</string>
     <string name="hardware" msgid="1800597768237606953">"वर्चुअल कीबोर्ड दिखाएं"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"सामान्य कीबोर्ड कॉन्फ़िगर करें"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"भाषा और लेआउट चुनने के लिए टैप करें"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"सुनने में मदद करने वाले डिवाइस"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"आवाज़ कम-ज़्यादा करने वाले दोनों बटन दबाकर रखें. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> को चालू कर दिया गया."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"आवाज़ कम-ज़्यादा करने वाले दोनों बटन दबाकर रखें. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> को बंद कर दिया गया."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> इस्तेमाल करने के लिए आवाज़ वाले दोनों बटन तीन सेकंड तक दबाकर रखें"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"सुलभता बटन पर टैप करके, इस्तेमाल करने के लिए सुविधा चुनें:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"सुलभता वाले हाथ के जेस्चर (हाव-भाव) के साथ इस्तेमाल करने के लिए सुविधा चुनें (दो उंगलियों से स्क्रीन पर सबसे नीचे से ऊपर की ओर स्वाइप करें):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"सुलभता वाले हाथ के जेस्चर (हाव-भाव) के साथ इस्तेमाल करने के लिए सुविधा चुनें (तीन उंगलियों से स्क्रीन पर सबसे नीचे से ऊपर की ओर स्वाइप करें):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"आपका फ़ोन बहुत गर्म हो गया है"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"ड्यूअल स्क्रीन की सुविधा अभी उपलब्ध नहीं है, क्योंकि आपका फ़ोन बहुत गर्म हो रहा है"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"बंद करें"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index e752c8e..56220ce 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1394,7 +1394,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Odabir načina unosa"</string>
     <string name="show_ime" msgid="6406112007347443383">"Zadrži na zaslonu dok je fizička tipkovnica aktivna"</string>
     <string name="hardware" msgid="1800597768237606953">"Prikaži virtualnu tipkovnicu"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Konfigurirajte fizičku tipkovnicu"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Dodirnite da biste odabrali jezik i raspored"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1719,7 +1722,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Slušni uređaji"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Držali ste tipke za glasnoću. Uključila se usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Držali ste tipke za glasnoću. Isključila se usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Pritisnite i zadržite tipke za glasnoću na tri sekunde da biste koristili uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Odaberite značajku koju ćete upotrebljavati kada dodirnete gumb za Pristupačnost:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Odaberite za koju će se značajku upotrebljavati pokret pristupačnosti (prelazak s dva prsta prema gore od dna zaslona):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Odaberite za koju će se značajku upotrebljavati pokret pristupačnosti (prelazak s tri prsta prema gore od dna zaslona):"</string>
@@ -2324,4 +2328,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Uređaj se pregrijao"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dvostruki zaslon nije podržan jer se vaš telefon pregrijao"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Isključi"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index b0333bf..4d781d9 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Beviteli mód kiválasztása"</string>
     <string name="show_ime" msgid="6406112007347443383">"Maradjon a képernyőn, amíg a billentyűzet aktív"</string>
     <string name="hardware" msgid="1800597768237606953">"Virtuális billentyűzet"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Állítsa be a fizikai billentyűzetet"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Koppintson a nyelv és a billentyűzetkiosztás kiválasztásához"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hallásjavító eszközök"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Nyomva tartotta a hangerőgombokat. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> bekapcsolva."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Nyomva tartotta a hangerőgombokat. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> kikapcsolva."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"A(z) <xliff:g id="SERVICE_NAME">%1$s</xliff:g> használatához tartsa lenyomva három másodpercig a két hangerőgombot"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Válassza ki a Kisegítő lehetőségek gombra koppintáskor használni kívánt funkciót:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Válassza ki a kisegítő kézmozdulattal (felfelé csúsztatás két ujjal a képernyő aljáról) használni kívánt funkciót:"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Válassza ki a kisegítő kézmozdulattal (felfelé csúsztatás három ujjal a képernyő aljáról) használni kívánt funkciót:"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Az eszköz túl meleg"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"A Két képernyő funkció nem áll rendelkezésre, mert a telefon melegedni kezdett"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Kikapcsolás"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 706e920..fdad595c 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Ընտրեք ներածման եղանակը"</string>
     <string name="show_ime" msgid="6406112007347443383">"Պահել էկրանին, երբ ֆիզիկական ստեղնաշարն ակտիվ է"</string>
     <string name="hardware" msgid="1800597768237606953">"Ցույց տալ վիրտուալ ստեղնաշարը"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Կազմաձևեք ֆիզիկական ստեղնաշարը"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Հպեք՝ լեզուն և դասավորությունն ընտրելու համար"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉՊՋՌՍՎՏՐՑՈՒՓՔԵւՕՖ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Լսողական սարքեր"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ձայնի կարգավորման կոճակները սեղմվեցին։ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ծառայությունը միացավ։"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ձայնի կարգավորման կոճակները սեղմվեցին։ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ծառայությունն անջատվեց։"</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"«<xliff:g id="SERVICE_NAME">%1$s</xliff:g>» ծառայությունն օգտագործելու համար սեղմեք և 3 վայրկյան պահեք ձայնի ուժգնության երկու կոճակները"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Ընտրեք գործառույթը, որը կգործարկվի «Հատուկ գործառույթներ» կոճակին հպելու դեպքում՝"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Ընտրեք գործառույթը, որը կգործարկվի հատուկ գործառույթների ժեստը (երկու մատը էկրանի ներքևից սահեցրեք վերև) անելու դեպքում՝"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Ընտրեք գործառույթը, որը կգործարկվի հատուկ գործառույթների ժեստը (երեք մատը էկրանի ներքևից սահեցրեք վերև) անելու դեպքում՝"</string>
@@ -1960,7 +1964,7 @@
     <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g>՝ անհասանելի է"</string>
     <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Անհրաժեշտ է թույլտվություն"</string>
     <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Տեսախցիկն անհասանելի է"</string>
-    <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Շարունակեք հեռախոսով"</string>
+    <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Շարու­նակեք հեռախոսով"</string>
     <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Խոսափողն անհասանելի է"</string>
     <string name="app_streaming_blocked_title_for_playstore_dialog" msgid="8149823099822897538">"Play Խանութը հասանելի չէ"</string>
     <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV-ի կարգավորումներն անհասանելի են"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Սարքը գերտաքացել է"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Կրկնակի էկրանն անհասանելի է, քանի որ ձեր հեռախոսը գերտաքանում է"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Անջատել"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 5836b5a..577e9a2 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Pilih metode masukan"</string>
     <string name="show_ime" msgid="6406112007347443383">"Biarkan di layar meski keyboard fisik aktif"</string>
     <string name="hardware" msgid="1800597768237606953">"Tampilkan keyboard virtual"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Mengonfigurasi keyboard fisik"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Ketuk untuk memilih bahasa dan tata letak"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Alat bantu dengar"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tombol volume ditahan. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> diaktifkan."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tombol volume ditahan. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> dinonaktifkan."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Tekan dan tahan kedua tombol volume selama tiga detik untuk menggunakan <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Pilih fitur yang akan digunakan saat mengetuk tombol aksesibilitas:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Pilih fitur yang akan digunakan dengan gestur aksesibilitas (geser ke atas dari bawah layar dengan dua jari):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Pilih fitur yang akan digunakan dengan gestur aksesibilitas (geser ke atas dari bawah layar dengan tiga jari):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Suhu perangkat terlalu panas"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Layar ganda tidak tersedia karena suhu ponsel terlalu panas"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Nonaktifkan"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 5edf2e6..bbccc75 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Veldu innsláttaraðferð"</string>
     <string name="show_ime" msgid="6406112007347443383">"Halda því á skjánum meðan vélbúnaðarlyklaborðið er virkt"</string>
     <string name="hardware" msgid="1800597768237606953">"Sýna sýndarlyklaborð"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Stilla vélbúnaðarlyklaborð"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Ýttu til að velja tungumál og útlit"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" AÁBCDÐEÉFGHIÍJKLMNOÓPQRSTUÚVWXYÝZÞÆÖ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789AÁBCDÐEÉFGHIÍJKLMNOÓPQRSTUÚVWXYÝZÞÆÖ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Heyrnartæki"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Hljóðstyrkstökkum haldið inni. Kveikt á <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Hljóðstyrkstökkum haldið inni. Slökkt á <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Haltu báðum hljóðstyrkstökkunum inni í þrjár sekúndur til að nota <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Veldu eiginleika sem á að nota þegar ýtt er á aðgengishnappinn:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Veldu eiginleika sem á að nota með aðgengisbendingunni (strjúka upp frá neðri hluta skjásins með tveimur fingrum):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Veldu eiginleika sem á að nota með aðgengisbendingunni (strjúka upp frá neðri hluta skjásins með þremur fingrum):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Tækið er of heitt"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Tveir skjáir eru ekki í boði vegna þess að síminn er of heitur"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Slökkva"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index bd29ffb..d97254d 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -297,7 +297,7 @@
     <string name="safeMode" msgid="8974401416068943888">"Modalità provvisoria"</string>
     <string name="android_system_label" msgid="5974767339591067210">"Sistema Android"</string>
     <string name="user_owner_label" msgid="8628726904184471211">"Passa al profilo personale"</string>
-    <string name="managed_profile_label" msgid="7316778766973512382">"Passa a profilo di lavoro"</string>
+    <string name="managed_profile_label" msgid="7316778766973512382">"Passa al profilo di lavoro"</string>
     <string name="permgrouplab_contacts" msgid="4254143639307316920">"Contatti"</string>
     <string name="permgroupdesc_contacts" msgid="9163927941244182567">"Possono accedere ai contatti"</string>
     <string name="permgrouplab_location" msgid="1858277002233964394">"Posizione"</string>
@@ -1394,7 +1394,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Scegli il metodo di immissione"</string>
     <string name="show_ime" msgid="6406112007347443383">"Tieni sullo schermo quando è attiva la tastiera fisica"</string>
     <string name="hardware" msgid="1800597768237606953">"Mostra tastiera virtuale"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Configura la tastiera fisica"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Tocca per selezionare la lingua e il layout"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1719,7 +1722,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Apparecchi acustici"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tieni premuti i tasti del volume. Servizio <xliff:g id="SERVICE_NAME">%1$s</xliff:g> attivato."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tieni premuti i tasti del volume. Servizio <xliff:g id="SERVICE_NAME">%1$s</xliff:g> disattivato."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Tieni premuti entrambi i tasti del volume per tre secondi per utilizzare <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Scegli una funzionalità da usare quando tocchi il pulsante Accessibilità:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Scegli una funzionalità da usare con il gesto di accessibilità (scorrimento verso l\'alto dalla parte inferiore dello schermo con due dita):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Scegli una funzionalità da usare con il gesto di accessibilità (scorrimento verso l\'alto dalla parte inferiore dello schermo con tre dita):"</string>
@@ -1985,7 +1989,7 @@
     <string name="profile_encrypted_message" msgid="1128512616293157802">"Tocca per sbloc. prof. di lav."</string>
     <string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Connesso a <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
     <string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Tocca per visualizzare i file"</string>
-    <string name="pin_target" msgid="8036028973110156895">"Blocca"</string>
+    <string name="pin_target" msgid="8036028973110156895">"Fissa"</string>
     <string name="pin_specific_target" msgid="7824671240625957415">"Blocca <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="unpin_target" msgid="3963318576590204447">"Sgancia"</string>
     <string name="unpin_specific_target" msgid="3859828252160908146">"Sblocca <xliff:g id="LABEL">%1$s</xliff:g>"</string>
@@ -2324,4 +2328,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Il dispositivo è troppo caldo"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Il doppio schermo non è disponibile perché il telefono si sta surriscaldando"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Disattiva"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 85984f0..c8ce531 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1394,7 +1394,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"בחירה של שיטת הזנה"</string>
     <string name="show_ime" msgid="6406112007347443383">"להשאיר במסך בזמן שהמקלדת הפיזית פעילה"</string>
     <string name="hardware" msgid="1800597768237606953">"הצגת מקלדת וירטואלית"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"הגדרת מקלדת פיזית"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"יש להקיש כדי לבחור שפה ופריסה"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1719,7 +1722,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"מכשירי שמיעה"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"לחצני עוצמת הקול נלחצו בלחיצה ארוכה. שירות <xliff:g id="SERVICE_NAME">%1$s</xliff:g> הופעל."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"לחצני עוצמת הקול נלחצו בלחיצה ארוכה. שירות <xliff:g id="SERVICE_NAME">%1$s</xliff:g> הושבת."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"יש ללחוץ לחיצה ארוכה על שני לחצני עוצמת הקול למשך שלוש שניות כדי להשתמש בשירות <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"צריך לבחור תכונה שתופעל כשלוחצים על לחצן הנגישות:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"יש לבחור תכונה שתופעל באמצעות תנועת הנגישות (החלקה למעלה מתחתית המסך בעזרת שתי אצבעות):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"יש לבחור תכונה שתופעל באמצעות תנועת הנגישות (החלקה למעלה מתחתית המסך בעזרת שלוש אצבעות):"</string>
@@ -2324,4 +2328,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"המכשיר חם מדי"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"מצב שני מסכים לא זמין כי הטלפון נהיה חם מדי"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"השבתה"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 70d84ca..44ba18e 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"入力方法の選択"</string>
     <string name="show_ime" msgid="6406112007347443383">"物理キーボードが有効になっていても画面に表示させます"</string>
     <string name="hardware" msgid="1800597768237606953">"仮想キーボードの表示"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"物理キーボードの設定"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"タップして言語とレイアウトを選択してください"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"補聴器"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"音量ボタンを長押ししました。<xliff:g id="SERVICE_NAME">%1$s</xliff:g> が ON になりました。"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"音量ボタンを長押ししました。<xliff:g id="SERVICE_NAME">%1$s</xliff:g> が OFF になりました。"</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> を使用するには、音量大と音量小の両方のボタンを 3 秒間長押ししてください"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"ユーザー補助機能ボタンをタップした場合に使用する機能を選択してください。"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"ユーザー補助操作(2 本の指で画面の下から上にスワイプ)で使用する機能を選択してください。"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"ユーザー補助操作(3 本の指で画面の下から上にスワイプ)で使用する機能を選択してください。"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"デバイスが熱くなりすぎています"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"スマートフォンが熱くなりすぎているため、デュアル スクリーンを使用できません"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"オフにする"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index c8162c4..e472973 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"აირჩიეთ შეყვანის მეთოდი"</string>
     <string name="show_ime" msgid="6406112007347443383">"აქტიური ფიზიკური კლავიატურისას ეკრანზე შენარჩუნება"</string>
     <string name="hardware" msgid="1800597768237606953">"ვირტუალური კლავიატურის ჩვენება"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"მოახდინეთ ფიზიკური კლავიატურის კონფიგურაცია"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"შეეხეთ ენისა და განლაგების ასარჩევად"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"სმენის აპარატები"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ხანგრძლივად დააჭირეთ ხმის ღილაკებს. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ჩართულია."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ხანგრძლივად დააჭირეთ ხმის ღილაკებს. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> გამორთულია."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> რომ გამოიყენოთ, დააჭირეთ ხმის ორივე ღილაკზე 3 წამის განმავლობაში"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"აირჩიეთ მარტივი წვდომის ღილაკზე შეხებისას გამოსაყენებელი ფუნქცია:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"აირჩიეთ მარტივი წვდომის ჟესტთან (ორი თითით გადაფურცვლა ეკრანის ქვედა კიდიდან ზემოთ) გამოსაყენებელი ფუნქცია:"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"აირჩიეთ მარტივი წვდომის ჟესტთან (სამი თითით გადაფურცვლა ეკრანის ქვედა კიდიდან ზემოთ) გამოსაყენებელი ფუნქცია:"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"მოწყობილობა ძალიან თბილია"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"ორმაგი ეკრანი მიუწვდომელია, რადგან თქვენი ტელეფონი ძალიან თბება"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"გამორთვა"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 73adb51..2959b25 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Енгізу әдісін таңдау"</string>
     <string name="show_ime" msgid="6406112007347443383">"Физикалық пернетақта қосулы кезде оны экранға шығару"</string>
     <string name="hardware" msgid="1800597768237606953">"Виртуалдық пернетақтаны көрсету"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Физикалық пернетақтаны конфигурациялау"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Тіл мен пернетақта схемасын таңдау үшін түртіңіз"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Есту аппараттары"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Пайдаланушы дыбыс деңгейі пернелерін басып ұстап тұрды. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> қосулы."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Дыбыс деңгейі пернелерін басып тұрған соң, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> өшірілді."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> қызметін пайдалану үшін дыбыс деңгейін реттейтін екі түймені де 3 секунд басып тұрыңыз"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"\"Арнайы мүмкіндіктер\" түймесін түрткенде пайдаланатын функцияны таңдаңыз:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Арнайы мүмкіндіктер қимылымен (екі саусақпен экранның төменгі жағынан жоғары қарай сырғытыңыз) пайдаланатын функцияны таңдаңыз:"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Арнайы мүмкіндіктер қимылымен (үш саусақпен экранның төменгі жағынан жоғары қарай сырғытыңыз) пайдаланатын функцияны таңдаңыз:"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Құрылғы қатты қызып кетті."</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Қос экран функциясы істемейді, себебі телефон қатты қызып кетеді."</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Өшіру"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index ede615b..abe3213 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"ជ្រើស​វិធីសាស្ត្រ​បញ្ចូល"</string>
     <string name="show_ime" msgid="6406112007347443383">"ទុកវានៅលើអេក្រង់ខណៈពេលក្តារចុចពិតប្រាកដកំពុងសកម្ម"</string>
     <string name="hardware" msgid="1800597768237606953">"បង្ហាញក្ដារចុចនិម្មិត"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"កំណត់រចនាសម្ព័ន្ធក្តារចុច​រូបវន្ត"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"ប៉ះដើម្បីជ្រើសភាសា និងប្លង់"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"ឧបករណ៍ស្តាប់"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"បានសង្កត់​គ្រាប់ចុច​កម្រិតសំឡេង​ជាប់។ បាន​បើក <xliff:g id="SERVICE_NAME">%1$s</xliff:g>។"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"បានសង្កត់​គ្រាប់ចុច​កម្រិតសំឡេង​ជាប់។ បាន​បិទ <xliff:g id="SERVICE_NAME">%1$s</xliff:g>។"</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"ចុចគ្រាប់ចុច​កម្រិត​សំឡេងទាំងពីរ​ឱ្យជាប់រយៈពេលបីវិនាទី ដើម្បីប្រើ <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"ជ្រើសរើស​មុខងារ​ដែលត្រូវប្រើ នៅពេល​ដែល​អ្នកចុច​ប៊ូតុង​ភាពងាយស្រួល៖"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"ជ្រើសរើស​មុខងារ ដើម្បី​ប្រើជាមួយចលនា​ភាពងាយស្រួល (អូស​ឡើងលើ​ពី​ផ្នែកខាងក្រោម​នៃ​អេក្រង់​ដោយប្រើ​ម្រាមដៃ​ពីរ)៖"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"ជ្រើសរើស​មុខងារ ដើម្បី​ប្រើជាមួយ​ចលនា​ភាពងាយស្រួល (អូស​ឡើងលើ​ពី​ផ្នែកខាងក្រោម​នៃ​អេក្រង់​ដោយប្រើ​ម្រាមដៃ​បី)៖"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"ឧបករណ៍ក្តៅពេក"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"អេក្រង់ពីរមិនអាចប្រើបានទេ ដោយសារទូរសព្ទរបស់អ្នកឡើងក្តៅពេក"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"បិទ"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index a673417..1f24e7d 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"ಇನ್‌ಪುಟ್‌‌ ವಿಧಾನವನ್ನು ಆರಿಸಿ"</string>
     <string name="show_ime" msgid="6406112007347443383">"ಭೌತಿಕ ಕೀಬೋರ್ಡ್ ಸಕ್ರಿಯವಾಗಿರುವಾಗ ಅದನ್ನು ಪರದೆಯ ಮೇಲಿರಿಸಿ"</string>
     <string name="hardware" msgid="1800597768237606953">"ವರ್ಚುವಲ್ ಕೀಬೋರ್ಡ್ ತೋರಿಸಿ"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"ಭೌತಿಕ ಕೀಬೋರ್ಡ್ ಕಾನ್ಫಿಗರ್ ಮಾಡಿ"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"ಭಾಷೆ ಮತ್ತು ವಿನ್ಯಾಸವನ್ನು ಆಯ್ಕೆ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"ಶ್ರವಣ ಸಾಧನಗಳು"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಹಿಡಿದುಕೊಳ್ಳಿ. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ಅನ್ನು ಆನ್ ಮಾಡಲಾಗಿದೆ."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳಲಾಗಿದೆ. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, ಆಫ್ ಮಾಡಲಾಗಿದೆ."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ಅನ್ನು ಬಳಸಲು ಎರಡೂ ಧ್ವನಿ ಕೀಗಳನ್ನು ಮೂರು ಸೆಕೆಂಡ್‌ಗಳ ಕಾಲ ಒತ್ತಿ ಹಿಡಿದುಕೊಳ್ಳಿ"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"ನೀವು ಪ್ರವೇಶಿಸುವಿಕೆ ಬಟನ್ ಟ್ಯಾಪ್ ಮಾಡಿದಾಗ ಬಳಸುವುದಕ್ಕಾಗಿ ವೈಶಿಷ್ಟ್ಯವೊಂದನ್ನು ಆರಿಸಿ:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"ಪ್ರವೇಶಿಸುವಿಕೆ ಗೆಸ್ಚರ್‌ನೊಂದಿಗೆ ಬಳಸಲು ವೈಶಿಷ್ಟ್ಯವೊಂದನ್ನು ಆಯ್ಕೆಮಾಡಿ (ಎರಡು ಬೆರಳುಗಳನ್ನು ಬಳಸಿ ಪರದೆಯ ಕೆಳಭಾಗದಿಂದ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"ಪ್ರವೇಶಿಸುವಿಕೆ ಗೆಸ್ಚರ್‌ನೊಂದಿಗೆ ಬಳಸಲು ವೈಶಿಷ್ಟ್ಯವೊಂದನ್ನು ಆಯ್ಕೆಮಾಡಿ (ಮೂರು ಬೆರಳುಗಳನ್ನು ಬಳಸಿ ಪರದೆಯ ಕೆಳಭಾಗದಿಂದ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"ಸಾಧನವು ತುಂಬಾ ಬಿಸಿಯಾಗಿದೆ"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"ನಿಮ್ಮ ಫೋನ್ ತುಂಬಾ ಬಿಸಿಯಾಗುವುದರಿಂದ ಡ್ಯೂಯಲ್ ಸ್ಕ್ರೀನ್ ಲಭ್ಯವಿಲ್ಲ"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"ಆಫ್ ಮಾಡಿ"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 8064eb0..02b797c 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -207,12 +207,9 @@
     <string name="personal_apps_suspension_text" msgid="6115455688932935597">"직장 프로필을 사용 설정할 때까지 개인 앱이 차단됩니다."</string>
     <string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"개인 앱이 <xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g>에 차단됩니다. IT 관리자가 <xliff:g id="NUMBER">%3$d</xliff:g>일 넘게 직장 프로필을 중지하도록 허용하지 않습니다."</string>
     <string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"사용 설정"</string>
-    <!-- no translation found for work_profile_telephony_paused_title (7690804479291839519) -->
-    <skip />
-    <!-- no translation found for work_profile_telephony_paused_text (8065762301100978221) -->
-    <skip />
-    <!-- no translation found for work_profile_telephony_paused_turn_on_button (7542632318337068821) -->
-    <skip />
+    <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"전화 및 메시지 사용 중지됨"</string>
+    <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"직장 앱을 일시중지했습니다. 전화나 문자 메시지를 수신하지 않습니다."</string>
+    <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"직장 앱 일시중지 해제"</string>
     <string name="me" msgid="6207584824693813140">"나"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"태블릿 옵션"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV 옵션"</string>
@@ -1396,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"입력 방법 선택"</string>
     <string name="show_ime" msgid="6406112007347443383">"물리적 키보드가 활성 상태인 경우 화면에 켜 둠"</string>
     <string name="hardware" msgid="1800597768237606953">"가상 키보드 표시"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"물리적 키보드 설정"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"탭하여 언어와 레이아웃을 선택하세요."</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1721,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"보청기"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"볼륨 키를 길게 눌렀습니다. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>이(가) 사용 설정되었습니다."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"볼륨 키를 길게 눌렀습니다. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>이(가) 사용 중지되었습니다."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> 서비스를 사용하려면 두 볼륨 키를 3초 동안 길게 누르세요"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"접근성 버튼을 탭할 때 사용할 기능을 선택하세요."</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"접근성 동작(두 손가락을 사용하여 화면 하단에서 위로 스와이프)으로 실행할 기능을 선택하세요."</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"접근성 동작(세 손가락을 사용하여 화면 하단에서 위로 스와이프)으로 실행할 기능을 선택하세요."</string>
@@ -2326,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"기기 온도가 너무 높음"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"휴대전화 온도가 너무 높아지고 있으므로 듀얼 스크린을 사용할 수 없습니다."</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"사용 중지"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 90d60e6..f87be7c 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Дайын киргизүү ыкмасын тандаңыз"</string>
     <string name="show_ime" msgid="6406112007347443383">"Баскычтоп иштетилгенде экранда көрүнүп турат"</string>
     <string name="hardware" msgid="1800597768237606953">"Виртуалдык баскычтоп"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Аппараттык баскычтопту конфигурациялоо"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Тил жана калып тандоо үчүн таптап коюңуз"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1419,7 +1422,7 @@
     <string name="ext_media_unmountable_notification_message" product="automotive" msgid="2274596120715020680">"Түзмөктү форматташыңыз керек болушу мүмкүн. Чыгаруу үчүн таптап коюңуз."</string>
     <string name="ext_media_unsupported_notification_title" msgid="3487534182861251401">"<xliff:g id="NAME">%s</xliff:g> аныкталды"</string>
     <string name="ext_media_unsupported_notification_title" product="automotive" msgid="6004193172658722381">"<xliff:g id="NAME">%s</xliff:g> иштебей жатат"</string>
-    <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Тууралоо үчүн таптаңыз."</string>
+    <string name="ext_media_unsupported_notification_message" msgid="8463636521459807981">"Орнотуу үчүн басыңыз."</string>
     <string name="ext_media_unsupported_notification_message" product="tv" msgid="1595482802187036532">"Колдоого алынуучу форматта орнотуу үчүн <xliff:g id="NAME">%s</xliff:g> тандаңыз."</string>
     <string name="ext_media_unsupported_notification_message" product="automotive" msgid="3412494732736336330">"Түзмөктү форматташыңыз керек болушу мүмкүн"</string>
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> күтүүсүздөн өчүрүлдү"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Угуу түзмөктөрү"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Үндү катуулатуу/акырындатуу баскычтары басылып, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> күйгүзүлдү."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Үндү катуулатуу/акырындатуу баскычтары басылып, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> өчүрүлдү."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> кызматын колдонуу үчүн үнүн чоңойтуп/кичирейтүү баскычтарын үч секунд коё бербей басып туруңуз"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Атайын мүмкүнчүлүктөр баскычын таптаганыңызда иштей турган функцияны тандаңыз:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Атайын мүмкүнчүлүктөр жаңсоосу үчүн функцияны тандаңыз (эки манжаңыз менен экранды ылдыйдан өйдө сүрүңүз):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Атайын мүмкүнчүлүктөр жаңсоосу аркылуу иштетиле турган функцияны тандаңыз (үч манжаңыз менен экранды ылдыйдан өйдө сүрүңүз):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Түзмөк ысып кетти"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Телефонуңуз ысып кеткендиктен, Кош экран функциясы жеткиликсиз"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Өчүрүү"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 63854c3..9366586 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"ເລືອກຮູບແບບການປ້ອນ"</string>
     <string name="show_ime" msgid="6406112007347443383">"ເປີດໃຊ້ໃຫ້ມັນຢູ່ໃນໜ້າຈໍໃນຂະນະທີ່ໃຊ້ແປ້ນພິມພາຍນອກຢູ່"</string>
     <string name="hardware" msgid="1800597768237606953">"ສະແດງແປ້ນພິມສະເໝືອນ"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"ຕັ້ງຄ່າແປ້ນພິມພາຍນອກ"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"ແຕະເພື່ອເລືອກພາສາ ແລະ ໂຄງແປ້ນພິມ"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"ອຸປະກອນຊ່ວຍຟັງ"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ກົດປຸ່ມລະດັບສຽງຄ້າງໄວ້. ເປີດໃຊ້ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ແລ້ວ."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ກົດປຸ່ມລະດັບສຽງຄ້າງໄວ້. ປິດ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ໄວ້ແລ້ວ."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"ກົດປຸ່ມສຽງທັງສອງພ້ອມກັນຄ້າງໄວ້ສາມວິນາທີເພື່ອໃຊ້ <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"ເລືອກຄຸນສົມບັດທີ່ຈະໃຊ້ເມື່ອທ່ານແຕະປຸ່ມການຊ່ວຍເຂົ້າເຖິງ:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"ເລືອກຄຸນສົມບັດເພື່ອໃຊ້ກັບທ່າທາງການຊ່ວຍເຂົ້າເຖິງ (ປັດຂຶ້ນຈາກລຸ່ມສຸດຂອງໜ້າຈໍດ້ວຍສອງນິ້ວ):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"ເລືອກຄຸນສົມບັດເພື່ອໃຊ້ກັບທ່າທາງການຊ່ວຍເຂົ້າເຖິງ (ປັດຂຶ້ນຈາກລຸ່ມສຸດຂອງໜ້າຈໍດ້ວຍສາມນິ້ວ):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"ອຸປະກອນຮ້ອນເກີນໄປ"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"ໜ້າຈໍຄູ່ບໍ່ພ້ອມໃຫ້ນຳໃຊ້ເນື່ອງຈາກໂທລະສັບຂອງທ່ານຮ້ອນເກີນໄປ"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"ປິດໄວ້"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 8460325..35a2715 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1395,7 +1395,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Pasirinkite įvesties metodą"</string>
     <string name="show_ime" msgid="6406112007347443383">"Palikti ekrane, kol fizinė klaviatūra aktyvi"</string>
     <string name="hardware" msgid="1800597768237606953">"Rodyti virtualiąją klaviatūrą"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Fizinės klaviatūros konfigūravimas"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Palieskite, kad pasirinktumėte kalbą ir išdėstymą"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ"</string>
@@ -1720,7 +1723,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Klausos įrenginiai"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Laikomi garsumo klavišai. „<xliff:g id="SERVICE_NAME">%1$s</xliff:g>“ įjungta."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Laikomi garsumo klavišai. „<xliff:g id="SERVICE_NAME">%1$s</xliff:g>“ išjungta."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Jei norite naudoti „<xliff:g id="SERVICE_NAME">%1$s</xliff:g>“, paspauskite abu garsumo klavišus ir palaikykite tris sekundes"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Pasirinkite funkciją, kuri bus naudojama, kai paliesite pritaikomumo mygtuką:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Pasirinkite funkciją, kuri bus naudojama su pritaikomumo gestu (perbraukimas aukštyn dviem pirštais iš ekrano apačios):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Pasirinkite funkciją, kuri bus naudojama su pritaikomumo gestu (perbraukimas aukštyn trimis pirštais iš ekrano apačios):"</string>
@@ -2325,4 +2329,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Įrenginys per daug kaista"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dvigubas ekranas nepasiekiamas, nes telefonas per daug kaista"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Išjungti"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 5d3d46f..b27c3d3 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1394,7 +1394,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Ievades metodes izvēle"</string>
     <string name="show_ime" msgid="6406112007347443383">"Paturēt ekrānā, kamēr ir aktīva fiziskā tastatūra"</string>
     <string name="hardware" msgid="1800597768237606953">"Virtuālās tastatūras rādīšana"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Fiziskās tastatūras konfigurēšana"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Pieskarieties, lai atlasītu valodu un izkārtojumu"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" AĀBCČDEĒFGĢHIĪJKĶLĻMNŅOPRSŠTUŪVZŽ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789AĀBCČDEĒFGĢHIĪJKĶLĻMNŅOPRSŠTUŪVZŽ"</string>
@@ -1719,7 +1722,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Dzirdes aparāti"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Turējāt nospiestas skaļuma pogas. Pakalpojums <xliff:g id="SERVICE_NAME">%1$s</xliff:g> tika ieslēgts."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Turējāt nospiestas skaļuma pogas. Pakalpojums <xliff:g id="SERVICE_NAME">%1$s</xliff:g> tika izslēgts."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Lai izmantotu pakalpojumu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, nospiediet abus skaļuma pogas un turiet tos trīs sekundes."</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Izvēlieties funkciju, ko izmantot, kad pieskaraties pieejamības pogai."</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Izvēlieties funkciju, ko izmantot ar pieejamības žestu (vilkšana ar diviem pirkstiem augšup no ekrāna apakšdaļas)."</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Izvēlieties funkciju, ko izmantot ar pieejamības žestu (vilkšana ar trīs pirkstiem augšup no ekrāna apakšdaļas)."</string>
@@ -2324,4 +2328,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Ierīce ir pārāk sakarsusi"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Divu ekrānu režīms nav pieejams, jo tālrunis sāk pārāk sakarst."</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Izslēgt"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-mcc334-mnc020-th/strings.xml b/core/res/res/values-mcc334-mnc020-th/strings.xml
index e4e62f0..dfd73ab 100644
--- a/core/res/res/values-mcc334-mnc020-th/strings.xml
+++ b/core/res/res/values-mcc334-mnc020-th/strings.xml
@@ -20,7 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string>
-    <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"การตรวจสอบสิทธิ์ล้มเหลว -29-"</string>
+    <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"การตรวจสอบสิทธิ์ไม่สำเร็จ -29-"</string>
     <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ไม่ได้สมัครใช้บริการ -33-"</string>
     <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"ไม่อนุญาตการเชื่อมต่อ PDN หลายรายการสำหรับ APN ที่กำหนด -55-"</string>
 </resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index ff1db65..2179895 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Одбери метод на внес"</string>
     <string name="show_ime" msgid="6406112007347443383">"Прикажувај ја на екранот додека е активна физичката тастатура"</string>
     <string name="hardware" msgid="1800597768237606953">"Прикажи виртуелна тастатура"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Конфигурирајте физичка тастатура"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Допрете за избирање јазик и распоред"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Слушни помагала"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ги задржавте копчињата за јачина на звук. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е вклучена."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ги задржавте копчињата за јачина на звук. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е исклучена."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Притиснете ги и задржете ги двете копчиња за јачина на звукот во траење од три секунди за да користите <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Изберете функција за користење кога ќе го допрете копчето за пристапност:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Изберете ја функцијата што ќе ја користите со движењето за пристапност (повлекување нагоре од дното на екранот со два прста):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Изберете ја функцијата што ќе ја користите со движењето за пристапност (повлекување нагоре од дното на екранот со три прста):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Уредот е претопол"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Двојниот екран е недостапен бидејќи вашиот телефон станува претопол"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Исклучи"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 51e8c59..d568bb8 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"ഇൻപുട്ട് രീതി തിരഞ്ഞെടുക്കുക"</string>
     <string name="show_ime" msgid="6406112007347443383">"ഫിസിക്കൽ കീബോർഡ് സജീവമായിരിക്കുമ്പോൾ സ്ക്രീനിൽ നിലനിർത്തുക"</string>
     <string name="hardware" msgid="1800597768237606953">"വെർച്വൽ കീബോർഡ് കാണിക്കുക"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"ഫിസിക്കൽ കീബോർഡ് കോൺഫിഗർ ചെയ്യുക"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"ഭാഷയും ലേഔട്ടും തിരഞ്ഞെടുക്കുന്നതിന് ടാപ്പ് ചെയ്യുക"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"ശ്രവണ ഉപകരണങ്ങൾ"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"വോളിയം കീകൾ പിടിച്ചു. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഓണാക്കി."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"വോളിയം കീകൾ അമർത്തിപ്പിടിച്ചു. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഓഫാക്കി."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഉപയോഗിക്കാൻ, രണ്ട് വോളിയം കീകളും മൂന്ന് സെക്കൻഡ് അമർത്തിപ്പിടിക്കുക"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"നിങ്ങൾ ഉപയോഗസഹായി ബട്ടൺ ടാപ്പ് ചെയ്യുമ്പോൾ ഉപയോഗിക്കുന്നതിന് ഒരു ഫീച്ചർ തിരഞ്ഞെടുക്കുക:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"ഉപയോഗസഹായി വിരൽചലനത്തോടൊപ്പം ഉപയോഗിക്കാൻ ഒരു ഫീച്ചർ തിരഞ്ഞെടുക്കുക (രണ്ട് വിരലുകളുപയോഗിച്ച് സ്‌ക്രീനിന്റെ താഴെ നിന്ന് മുകളിലോട്ട് സ്വൈപ്പ് ചെയ്യുക):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"ഉപയോഗസഹായി വിരൽചലനത്തോടൊപ്പം ഉപയോഗിക്കാൻ ഒരു ഫീച്ചർ തിരഞ്ഞെടുക്കുക (മൂന്ന് വിരലുകളുപയോഗിച്ച് സ്‌ക്രീനിന്റെ താഴെ നിന്ന് മുകളിലോട്ട് സ്വൈപ്പ് ചെയ്യുക):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"ഉപകരണത്തിന് ചൂട് കൂടുതലാണ്"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"നിങ്ങളുടെ ഫോൺ വളരെയധികം ചൂടാകുന്നതിനാൽ ഡ്യുവൽ സ്‌ക്രീൻ ലഭ്യമല്ല"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"ഓഫാക്കുക"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 760cb14..f924dd7 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Оруулах аргыг сонгоно уу"</string>
     <string name="show_ime" msgid="6406112007347443383">"Биет гар идэвхтэй үед үүнийг дэлгэцэд харуулна уу"</string>
     <string name="hardware" msgid="1800597768237606953">"Хийсвэр гарыг харуулах"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Биет гарыг хэлбэрт оруулах"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Хэл болон бүдүүвчийг сонгохын тулд дарна уу"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Сонсголын төхөөрөмжүүд"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Дууны түвшний түлхүүрийг удаан дарсан. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>-г асаалаа."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Дууны түвшний түлхүүрийг удаан дарсан. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>-г унтраалаа."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>-г ашиглахын тулд дууны түвшнийг ихэсгэх, багасгах түлхүүрийг 3 секундийн турш зэрэг дарна уу"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Хандалтын товчлуурыг товшихдоо ашиглах онцлогийг сонгоно уу:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Хандалтын зангаагаар ашиглах үйлчилгээг сонгоно уу (хоёр хуруугаараа дэлгэцийн доороос дээш хоёр хуруугаар шударна уу):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Хандалтын зангаагаар ашиглах онцлогийг сонгоно уу (гурван хуруугаар дэлгэцийн доороос дээш шударна уу):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Төхөөрөмж хэт халуун байна"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Таны утас хэт халж байгаа тул Хоёр дэлгэц боломжгүй байна"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Унтраах"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 73b19aa..48df544 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"इनपुट पद्धत निवडा"</string>
     <string name="show_ime" msgid="6406112007347443383">"भौतिक कीबोर्ड सक्रिय असताना त्यास स्क्रीनवर ठेवा"</string>
     <string name="hardware" msgid="1800597768237606953">"व्हर्च्युअल कीबोर्ड दर्शवा"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"वास्तविक कीबोर्ड कॉंफिगर करा"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"भाषा आणि लेआउट निवडण्यासाठी टॅप करा"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"श्रवणयंत्र डिव्हाइस"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"धरून ठेवलेल्या व्हॉल्यूम की. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> सुरू केला आहे."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"धरून ठेवलेल्या व्हॉल्यूम की. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> बंद केले आहे."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> वापरण्यासाठी दोन्ही व्हॉल्युम की तीन सेकंद दाबा आणि धरून ठेवा"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"तुम्ही अ‍ॅक्सेसिबिलिटी बटणावर टॅप केल्यास वापरण्यासाठी एक वैशिष्ट्य निवडा:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"अ‍ॅक्सेसिबिलिटी जेश्चरसोबत वापराचे असलेले वैशिष्‍ट्य निवडा (दोन बोटांनी स्क्रीनच्या तळापासून वर स्वाइप करा):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"अ‍ॅक्सेसिबिलिटी जेश्चरसोबत वापराचे असलेले वैशिष्‍ट्य निवडा (तीनन बोटांनी स्क्रीनच्या तळापासून वर स्वाइप करा):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"डिव्हाइस खूप गरम आहे"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"तुमचा फोन खूप गरम होत असल्यामुळे ड्युअल स्क्रीन उपलब्ध नाही"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"बंद करा"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 231d6ad..cc41127f 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Pilih kaedah input"</string>
     <string name="show_ime" msgid="6406112007347443383">"Pastikannya pada skrin, semasa papan kekunci fizikal aktif"</string>
     <string name="hardware" msgid="1800597768237606953">"Tunjukkan papan kekunci maya"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Konfigurasikan papan kekunci fizikal"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Ketik untuk memilih bahasa dan susun atur"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Peranti pendengaran"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Kekunci kelantangan ditahan. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> dihidupkan."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Kekunci kelantangan ditahan. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> dimatikan."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Tekan dan tahan kedua-dua kekunci kelantangan selama tiga saat untuk menggunakan <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Pilih ciri yang hendak digunakan apabila anda mengetik butang kebolehaksesan:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Pilih ciri untuk digunakan dengan gerak isyarat kebolehaksesan (leret ke atas dari bahagian bawah skrin menggunakan dua jari):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Pilih ciri untuk digunakan dengan gerak isyarat kebolehaksesan (leret ke atas dari bahagian bawah skrin menggunakan tiga jari):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Peranti terlalu panas"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dwiskrin tidak tersedia kerana telefon anda terlalu panas"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Matikan"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index f7cb067..9a37e10 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"ထည့်သွင်းရေး နည်းကို ရွေးရန်"</string>
     <string name="show_ime" msgid="6406112007347443383">"စက်၏ကီးဘုတ် ဖွင့်ထားစဉ်တွင် ၎င်းကို ဖန်သားပြင်ပေါ်တွင် ဆက်ထားပါ"</string>
     <string name="hardware" msgid="1800597768237606953">"ပကတိအသွင်ကီးဘုတ်ပြရန်"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"စက်၏ ကီးဘုတ်ကို ပြင်ဆင်သတ်မှတ်ပါ"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"ဘာသာစကားနှင့် အသွင်အပြင်ရွေးချယ်ရန် တို့ပါ"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"နားကြားကိရိယာ"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"အသံခလုတ်များကို ဖိထားသည်။ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ဖွင့်လိုက်သည်။"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"အသံခလုတ်များကို ဖိထားသည်။ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ပိတ်လိုက်သည်။"</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ကို သုံးရန် အသံအတိုးအလျှော့ ခလုတ်နှစ်ခုလုံးကို သုံးစက္ကန့်ကြာ ဖိထားပါ"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"သုံးနိုင်မှုခလုတ်ကို တို့ပြီးလျှင် ဝန်ဆောင်မှုတစ်ခု ရွေးပါ−"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"သုံးနိုင်မှုလက်ဟန်ဖြင့် အသုံးပြုရန် ဝန်ဆောင်မှုတစ်ခုကို ရွေးပါ (ဖန်သားပြင်အောက်ခြေမှနေ၍ လက်နှစ်ချောင်းဖြင့် အပေါ်သို့ ပွတ်ဆွဲပါ)-"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"သုံးနိုင်မှုလက်ဟန်ဖြင့် အသုံးပြုရန် ဝန်ဆောင်မှုတစ်ခုကို ရွေးပါ (ဖန်သားပြင်အောက်ခြေမှနေ၍ လက်သုံးချောင်းဖြင့် အပေါ်သို့ ပွတ်ဆွဲပါ)-"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"စက်ပစ္စည်း အလွန်ပူနေသည်"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"သင့်ဖုန်း အလွန်ပူနေသဖြင့် ‘စခရင်နှစ်ခု’ သုံး၍မရပါ"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"ပိတ်ရန်"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index e5e8629..826ff49 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Velg inndatametode"</string>
     <string name="show_ime" msgid="6406112007347443383">"Ha den på skjermen mens det fysiske tastaturet er aktivt"</string>
     <string name="hardware" msgid="1800597768237606953">"Vis det virtuelle tastaturet"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Konfigurer et fysisk tastatur"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Trykk for å velge språk og layout"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Høreapparater"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Volumtastene holdes inne. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> er slått på."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Volumtastene holdes inne. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> er slått av."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Trykk og hold inne begge volumtastene i tre sekunder for å bruke <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Velg en funksjon du vil bruke når du trykker på Tilgjengelighet-knappen:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Velg en funksjon du vil bruke med tilgjengelighetsbevegelsen (sveip opp fra bunnen av skjermen med to fingre):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Velg en funksjon du vil bruke med tilgjengelighetsbevegelsen (sveip opp fra bunnen av skjermen med tre fingre):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Enheten er for varm"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dobbel skjerm er ikke tilgjengelig fordi telefonen begynner å bli for varm"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Slå av"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index d91ad08..2624a39 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"निवेश विधि छान्नुहोस्"</string>
     <string name="show_ime" msgid="6406112007347443383">"फिजिकल किबोर्ड सक्रिय हुँदा यसलाई स्क्रिनमा राखियोस्"</string>
     <string name="hardware" msgid="1800597768237606953">"भर्चुअल किबोर्ड देखाउनुहोस्"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"फिजिकल किबोर्ड कन्फिगर गर्नुहोस्"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"भाषा र लेआउट चयन गर्न ट्याप गर्नुहोस्"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"हियरिङ डिभाइसहरू"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"तपाईंले भोल्युम बटनहरू थिचिराख्नुभयो। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> अन भयो।"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"तपाईंले भोल्युम बटनहरू थिचिराख्नुभयो। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> अफ भयो।"</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> प्रयोग गर्न दुवै भोल्युम कुञ्जीहरूलाई तीन सेकेन्डसम्म थिचिराख्नुहोस्"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"तपाईंले एक्सेसिबिलिटी बटन ट्याप गर्दा प्रयोग गर्न चाहनुभएको सुविधा छनौट गर्नुहोस्:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"तपाईंले पहुँचको इसारामार्फत प्रयोग गर्न चाहनुभएको सुविधा छनौट गर्नुहोस् (दुईवटा औँलाले स्क्रिनको फेदबाट माथितिर स्वाइप गर्नुहोस्):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"तपाईंले पहुँचको इसारामार्फत प्रयोग गर्न चाहनुभएको सुविधा छनौट गर्नुहोस् (तीनवटा औँलाले स्क्रिनको फेदबाट माथितिर स्वाइप गर्नुहोस्):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"डिभाइस ज्यादै तातेको छ"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"तपाईंको फोन ज्यादै तातिरहेको हुनाले डुअल स्क्रिन उपलब्ध छैन"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"अफ गर्नुहोस्"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 2955a35..b56efb5 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Invoermethode selecteren"</string>
     <string name="show_ime" msgid="6406112007347443383">"Toon op het scherm terwijl het fysieke toetsenbord actief is"</string>
     <string name="hardware" msgid="1800597768237606953">"Virtueel toetsenbord tonen"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Fysiek toetsenbord instellen"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Tik om een taal en indeling te selecteren"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hoortoestellen"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Volumetoetsen ingedrukt gehouden. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> staat aan."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Volumetoetsen ingedrukt gehouden. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> staat uit."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Houd beide volumetoetsen drie seconden ingedrukt om <xliff:g id="SERVICE_NAME">%1$s</xliff:g> te gebruiken"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Kies een functie om te gebruiken als je op de knop Toegankelijkheid tikt:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Kies een functie om te gebruiken met het toegankelijkheidsgebaar (met twee vingers omhoog swipen vanaf de onderkant van het scherm):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Kies een functie om te gebruiken met het toegankelijkheidsgebaar (met drie vingers omhoog swipen vanaf de onderkant van het scherm):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Het apparaat is te warm"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dubbel scherm is niet beschikbaar, omdat je telefoon te warm wordt"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Uitzetten"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 8b0df2e..15fb22a 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"ଇନପୁଟ୍ ପଦ୍ଧତି ବାଛନ୍ତୁ"</string>
     <string name="show_ime" msgid="6406112007347443383">"ଫିଜିକାଲ୍‌ କୀବୋର୍ଡ ସକ୍ରିୟ ଥିବାବେଳେ ଏହାକୁ ସ୍କ୍ରିନ୍‌ ଉପରେ ରଖନ୍ତୁ"</string>
     <string name="hardware" msgid="1800597768237606953">"ଭର୍ଚୁଆଲ୍ କୀ’ବୋର୍ଡ ଦେଖାନ୍ତୁ"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"ଫିଜିକଲ୍ କୀ\'ବୋର୍ଡ କନଫିଗର୍‍ କରନ୍ତୁ"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"ଭାଷା ଓ ଲେଆଉଟ୍‍ ଚୟନ କରିବା ପାଇଁ ଟାପ୍‍ କରନ୍ତୁ"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"ହିଅରିଂ ଡିଭାଇସଗୁଡ଼ିକ"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ଭଲ୍ୟୁମ୍ କୀ\'ଗୁଡ଼ିକୁ ଧରି ରଖାଯାଇଛି। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ଚାଲୁ ହୋଇଛି।"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ଭଲ୍ୟୁମ୍ କୀ\'ଗୁଡ଼ିକୁ ଧରି ରଖାଯାଇଛି। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ବନ୍ଦ ହୋଇଛି।"</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ବ୍ୟବହାର କରିବାକୁ ତିନି ସେକେଣ୍ଡ ପାଇଁ ଉଭୟ ଭଲ୍ୟୁମ୍‍ କୀ ଦବାଇ ଧରି ରଖନ୍ତୁ"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"ଆପଣ ଆକ୍ସେସିବିଲିଟୀ ବଟନ୍ ଟାପ୍ କରିବା ବେଳେ ଏକ ଫିଚର୍ ବ୍ୟବହାର କରିବାକୁ ବାଛନ୍ତୁ:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"ଆକ୍ସେସିବିଲିଟୀ ଜେଶ୍ଚର୍ ସହିତ ବ୍ୟବହାର କରିବାକୁ ଏକ ଫିଚର୍ ବାଛନ୍ତୁ (ଦୁଇଟି ଆଙ୍ଗୁଠିରେ ସ୍କ୍ରିନର ତଳୁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"ଆକ୍ସେସିବିଲିଟୀ ଜେଶ୍ଚର୍ ସହିତ ବ୍ୟବହାର କରିବାକୁ ଏକ ଫିଚର୍ ବାଛନ୍ତୁ (ତିନୋଟି ଆଙ୍ଗୁଠିରେ ସ୍କ୍ରିନର ତଳୁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ):"</string>
@@ -1870,7 +1874,7 @@
     <string name="package_updated_device_owner" msgid="7560272363805506941">"ଆପଣଙ୍କ ଆଡମିନ୍‌‌ ଅପଡେଟ୍‍ କରିଛନ୍ତି"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"ଆପଣଙ୍କ ଆଡମିନ୍‌‌ ଡିଲିଟ୍‍ କରିଛନ୍ତି"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"ଠିକ୍ ଅଛି"</string>
-    <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"ବ୍ୟାଟେରୀ ସେଭର୍ ଗାଢ଼ା ଥିମକୁ ଚାଲୁ କରେ ଏବଂ ପୃଷ୍ଠପଟ କାର୍ଯ୍ୟକଳାପ, କିଛି ଭିଜୁଆଲ୍ ଇଫେକ୍ଟ, କିଛି ଫିଚର୍ ଏବଂ କିଛି ନେଟୱାର୍କ ସଂଯୋଗକୁ ସୀମିତ କିମ୍ବା ବନ୍ଦ କରେ।"</string>
+    <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"ବେଟେରୀ ସେଭର ଗାଢ଼ା ଥିମକୁ ଚାଲୁ କରେ ଏବଂ ପୃଷ୍ଠପଟ କାର୍ଯ୍ୟକଳାପ, କିଛି ଭିଜୁଆଲ ଇଫେକ୍ଟ, କିଛି ଫିଚର ଏବଂ କିଛି ନେଟୱାର୍କ ସଂଯୋଗକୁ ସୀମିତ କିମ୍ବା ବନ୍ଦ କରେ।"</string>
     <string name="battery_saver_description" msgid="8518809702138617167">"ବ୍ୟାଟେରୀ ସେଭର୍ ଗାଢ଼ା ଥିମକୁ ଚାଲୁ କରେ ଏବଂ ପୃଷ୍ଠପଟ କାର୍ଯ୍ୟକଳାପ, କିଛି ଭିଜୁଆଲ୍ ଇଫେକ୍ଟ, କିଛି ଫିଚର୍ ଏବଂ କିଛି ନେଟୱାର୍କ ସଂଯୋଗକୁ ସୀମିତ କିମ୍ବା ବନ୍ଦ କରେ।"</string>
     <string name="data_saver_description" msgid="4995164271550590517">"ଡାଟା ବ୍ୟବହାର କମ୍‍ କରିବାରେ ସାହାଯ୍ୟ କରିବାକୁ, ଡାଟା ସେଭର୍‍ ବ୍ୟାକ୍‌ଗ୍ରାଉଣ୍ଡରେ ଡାଟା ପଠାଇବା କିମ୍ବା ପ୍ରାପ୍ତ କରିବାକୁ କିଛି ଆପ୍‍କୁ ବାରଣ କରେ। ଆପଣ ବର୍ତ୍ତମାନ ବ୍ୟବହାର କରୁଥିବା ଆପ୍‍, ଡାଟା ଆକ୍ସେସ୍‍ କରିପାରେ, କିନ୍ତୁ ଏହା କମ୍‍ ଥର କରିପାରେ। ଏହାର ଅର୍ଥ ହୋଇପାରେ ଯେମିତି ଆପଣ ଇମେଜଗୁଡ଼ିକୁ ଟାପ୍‍ ନକରିବା ପର୍ଯ୍ୟନ୍ତ ସେଗୁଡ଼ିକ ଡିସପ୍ଲେ ହୁଏ ନାହିଁ।"</string>
     <string name="data_saver_enable_title" msgid="7080620065745260137">"ଡାଟା ସେଭର୍‌ ଚାଲୁ କରିବେ?"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"ଡିଭାଇସ ବହୁତ ଗରମ ଅଛି"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"ଆପଣଙ୍କ ଫୋନ ବହୁତ ଗରମ ହେଉଥିବା ଯୋଗୁଁ ଡୁଆଲ ସ୍କ୍ରିନ ଉପଲବ୍ଧ ନାହିଁ"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"ବନ୍ଦ କରନ୍ତୁ"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index d5414e3..f0c0521 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"ਇਨਪੁਟ ਵਿਧੀ ਚੁਣੋ"</string>
     <string name="show_ime" msgid="6406112007347443383">"ਭੌਤਿਕ ਕੀ-ਬੋਰਡ ਸਰਗਰਮ ਹੋਣ ਦੌਰਾਨ ਇਸ ਨੂੰ ਸਕ੍ਰੀਨ \'ਤੇ ਬਣਾਈ ਰੱਖੋ"</string>
     <string name="hardware" msgid="1800597768237606953">"ਆਭਾਸੀ ਕੀ-ਬੋਰਡ ਦਿਖਾਓ"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"ਭੌਤਿਕ ਕੀ-ਬੋਰਡ ਦਾ ਸੰਰੂਪਣ ਕਰੋ"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"ਭਾਸ਼ਾ ਅਤੇ ਖਾਕਾ ਚੁਣਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"ਸੁਣਨ ਵਾਲੇ ਡੀਵਾਈਸ"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ਅਵਾਜ਼ੀ ਕੁੰਜੀਆਂ ਦਬਾ ਕੇ ਰੱਖੀਆਂ ਗਈਆਂ। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਗਿਆ।"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ਅਵਾਜ਼ੀ ਕੁੰਜੀਆਂ ਦਬਾ ਕੇ ਰੱਖੀਆਂ ਗਈਆਂ। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਨੂੰ ਬੰਦ ਕੀਤਾ ਗਿਆ।"</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰਨ ਲਈ ਦੋਵੇਂ ਅਵਾਜ਼ ਕੁੰਜੀਆਂ ਨੂੰ 3 ਸਕਿੰਟਾਂ ਲਈ ਦਬਾਈ ਰੱਖੋ"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਪਹੁੰਚਯੋਗਤਾ ਬਟਨ ਨੂੰ ਟੈਪ ਕੀਤੇ ਜਾਣ \'ਤੇ ਵਰਤਣ ਲਈ ਕੋਈ ਵਿਸ਼ੇਸ਼ਤਾ ਚੁਣੋ:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"ਪਹੁੰਚਯੋਗਤਾ ਸੰਕੇਤ ਨਾਲ ਵਰਤਣ ਲਈ ਕੋਈ ਵਿਸ਼ੇਸ਼ਤਾ ਚੁਣੋ (ਦੋ ਉਂਗਲਾਂ ਨਾਲ ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"ਪਹੁੰਚਯੋਗਤਾ ਸੰਕੇਤ ਨਾਲ ਵਰਤਣ ਲਈ ਕੋਈ ਵਿਸ਼ੇਸ਼ਤਾ ਚੁਣੋ (ਤਿੰਨ ਉਂਗਲਾਂ ਨਾਲ ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"ਡੀਵਾਈਸ ਬਹੁਤ ਗਰਮ ਹੈ"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"ਦੋਹਰੀ ਸਕ੍ਰੀਨ ਵਿਸ਼ੇਸ਼ਤਾ ਉਪਲਬਧ ਨਹੀਂ ਹੈ ਕਿਉਂਕਿ ਤੁਹਾਡਾ ਫ਼ੋਨ ਬਹੁਤ ਗਰਮ ਹੋ ਰਿਹਾ ਹੈ"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"ਬੰਦ ਕਰੋ"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 8c13803..2f5aa5a 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1395,7 +1395,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Wybierz metodę wprowadzania"</string>
     <string name="show_ime" msgid="6406112007347443383">"Pozostaw na ekranie, gdy aktywna jest klawiatura fizyczna"</string>
     <string name="hardware" msgid="1800597768237606953">"Pokaż klawiaturę wirtualną"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Skonfiguruj klawiaturę fizyczną"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Kliknij, by wybrać język i układ"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" AĄBCĆDEĘFGHIJKLŁMNŃOÓPQRSŚTUVWXYZŹŻ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1720,7 +1723,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Urządzenia słuchowe"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Przytrzymano klawisze głośności. Usługa <xliff:g id="SERVICE_NAME">%1$s</xliff:g> została włączona."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Przytrzymano klawisze głośności. Usługa <xliff:g id="SERVICE_NAME">%1$s</xliff:g> została wyłączona."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Naciśnij i przytrzymaj oba przyciski głośności przez trzy sekundy, by użyć usługi <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Wybierz funkcję używaną po kliknięciu przycisku ułatwień dostępu:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Wybierz funkcję, której chcesz używać w przypadku gestu ułatwień dostępu (przesunięcie dwoma palcami w górę od dołu ekranu):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Wybierz funkcję, której chcesz używać w przypadku gestu ułatwień dostępu (przesunięcie trzema palcami w górę od dołu ekranu):"</string>
@@ -2325,4 +2329,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Urządzenie jest za ciepłe"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Podwójny ekran jest niedostępny, ponieważ telefon za bardzo się nagrzewa"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Wyłącz"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 896362a..5eb7a46 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1394,7 +1394,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Selecione o método de entrada"</string>
     <string name="show_ime" msgid="6406112007347443383">"Mantém o teclado virtual na tela enquanto o teclado físico está ativo"</string>
     <string name="hardware" msgid="1800597768237606953">"Mostrar teclado virtual"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Configurar teclado físico"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Toque para selecionar o idioma e o layout"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1719,7 +1722,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Aparelhos auditivos"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas de volume pressionadas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ativado."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume pressionadas. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desativado."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Toque nos dois botões de volume e os mantenha pressionados por três segundo para usar o <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Escolha um recurso a ser usado quando você toca no botão de acessibilidade:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Escolha um recurso para usar com o gesto de acessibilidade (deslizar de baixo para cima na tela com dois dedos):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Escolha um recurso para usar com o gesto de acessibilidade (deslizar de baixo para cima na tela com três dedos):"</string>
@@ -2324,4 +2328,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"O dispositivo está muito quente"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"A tela dupla está indisponível porque o smartphone está ficando muito quente"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Desativar"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 78eff13..18df66e 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -600,7 +600,7 @@
     <string name="permdesc_postNotification" msgid="5974977162462877075">"Permite à app mostrar notificações"</string>
     <string name="permlab_turnScreenOn" msgid="219344053664171492">"ativar o ecrã"</string>
     <string name="permdesc_turnScreenOn" msgid="4394606875897601559">"Permite que a app ative o ecrã."</string>
-    <string name="permlab_useBiometric" msgid="6314741124749633786">"Utilizar hardware biométrico"</string>
+    <string name="permlab_useBiometric" msgid="6314741124749633786">"Usar hardware biométrico"</string>
     <string name="permdesc_useBiometric" msgid="7502858732677143410">"Permite que a app utilize hardware biométrico para autenticação."</string>
     <string name="permlab_manageFingerprint" msgid="7432667156322821178">"gerir o hardware de impressão digital"</string>
     <string name="permdesc_manageFingerprint" msgid="2025616816437339865">"Permite que a app invoque métodos para adicionar e eliminar modelos de impressão digital para utilização."</string>
@@ -614,8 +614,8 @@
     <string name="permdesc_imagesWrite" msgid="5195054463269193317">"Permite que a app modifique a sua coleção de fotos."</string>
     <string name="permlab_mediaLocation" msgid="7368098373378598066">"ler as localizações a partir da sua coleção de multimédia"</string>
     <string name="permdesc_mediaLocation" msgid="597912899423578138">"Permite que a app leia as localizações a partir da sua coleção de multimédia."</string>
-    <string name="biometric_app_setting_name" msgid="3339209978734534457">"Utilizar a biometria"</string>
-    <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Utilizar a biometria ou o bloqueio de ecrã"</string>
+    <string name="biometric_app_setting_name" msgid="3339209978734534457">"Usar a biometria"</string>
+    <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Usar a biometria ou o bloqueio de ecrã"</string>
     <string name="biometric_dialog_default_title" msgid="55026799173208210">"Confirme a sua identidade"</string>
     <string name="biometric_dialog_default_subtitle" msgid="8457232339298571992">"Utilize a biometria para continuar."</string>
     <string name="biometric_or_screen_lock_dialog_default_subtitle" msgid="159539678371552009">"Utilize a biometria ou o bloqueio de ecrã para continuar"</string>
@@ -625,7 +625,7 @@
     <string name="biometric_error_canceled" msgid="8266582404844179778">"Autenticação cancelada"</string>
     <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"Nenhum PIN, padrão ou palavra-passe definidos."</string>
     <string name="biometric_error_generic" msgid="6784371929985434439">"Erro ao autenticar."</string>
-    <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Utilizar o bloqueio de ecrã"</string>
+    <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Usar o bloqueio de ecrã"</string>
     <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Introduza o bloqueio de ecrã para continuar"</string>
     <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Prima firmemente o sensor"</string>
     <string name="fingerprint_acquired_insufficient" msgid="623888149088216458">"Não é possível reconhecer a impressão digital. Tente novamente."</string>
@@ -659,8 +659,8 @@
     <string name="fingerprint_error_bad_calibration" msgid="4385512597740168120">"Não é possível usar o sensor de impressões digitais. Visite um fornecedor de serviços de reparação"</string>
     <string name="fingerprint_error_power_pressed" msgid="5479524500542129414">"Botão ligar/desligar premido"</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
-    <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Utilizar a impressão digital"</string>
-    <string name="fingerprint_or_screen_lock_app_setting_name" msgid="3501743523487644907">"Utilizar o bloqueio de ecrã ou a impressão digital"</string>
+    <string name="fingerprint_app_setting_name" msgid="4253767877095495844">"Usar a impressão digital"</string>
+    <string name="fingerprint_or_screen_lock_app_setting_name" msgid="3501743523487644907">"Usar o bloqueio de ecrã ou a impressão digital"</string>
     <string name="fingerprint_dialog_default_subtitle" msgid="3879832845486835905">"Utilize a sua impressão digital para continuar."</string>
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Utilize a impressão digital ou o bloqueio de ecrã para continuar"</string>
   <string-array name="fingerprint_error_vendor">
@@ -720,8 +720,8 @@
     <string name="face_error_hw_not_present" msgid="7940978724978763011">"O Desbloqueio facial não é suportado neste dispositivo"</string>
     <string name="face_error_security_update_required" msgid="5076017208528750161">"Sensor temporariamente desativado."</string>
     <string name="face_name_template" msgid="3877037340223318119">"Rosto <xliff:g id="FACEID">%d</xliff:g>"</string>
-    <string name="face_app_setting_name" msgid="5854024256907828015">"Utilizar o Desbloqueio facial"</string>
-    <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Utilizar o bloqueio através do rosto ou de ecrã"</string>
+    <string name="face_app_setting_name" msgid="5854024256907828015">"Usar o Desbloqueio facial"</string>
+    <string name="face_or_screen_lock_app_setting_name" msgid="1603149075605709106">"Usar o bloqueio através do rosto ou de ecrã"</string>
     <string name="face_dialog_default_subtitle" msgid="6620492813371195429">"Utilize o rosto para continuar"</string>
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Utilize o rosto ou o bloqueio de ecrã para continuar"</string>
   <string-array name="face_error_vendor">
@@ -1200,13 +1200,13 @@
     <string name="whichSendToApplicationNamed" msgid="3385686512014670003">"Enviar com %1$s"</string>
     <string name="whichSendToApplicationLabel" msgid="3543240188816513303">"Enviar"</string>
     <string name="whichHomeApplication" msgid="8276350727038396616">"Selecione uma app Página inicial"</string>
-    <string name="whichHomeApplicationNamed" msgid="5855990024847433794">"Utilizar %1$s como Página inicial"</string>
+    <string name="whichHomeApplicationNamed" msgid="5855990024847433794">"Usar %1$s como Página inicial"</string>
     <string name="whichHomeApplicationLabel" msgid="8907334282202933959">"Capturar imagem"</string>
     <string name="whichImageCaptureApplication" msgid="2737413019463215284">"Capturar imagem com"</string>
     <string name="whichImageCaptureApplicationNamed" msgid="8820702441847612202">"Capturar imagem com o %1$s"</string>
     <string name="whichImageCaptureApplicationLabel" msgid="6505433734824988277">"Capturar imagem"</string>
-    <string name="alwaysUse" msgid="3153558199076112903">"Utilizar por predefinição para esta ação."</string>
-    <string name="use_a_different_app" msgid="4987790276170972776">"Utilizar outra app"</string>
+    <string name="alwaysUse" msgid="3153558199076112903">"Usar por predefinição para esta ação."</string>
+    <string name="use_a_different_app" msgid="4987790276170972776">"Usar outra app"</string>
     <string name="clearDefaultHintMsg" msgid="1325866337702524936">"Limpar a predefinição nas Definições do Sistema &gt; Apps &gt; Transferidas."</string>
     <string name="chooseActivity" msgid="8563390197659779956">"Escolha uma ação"</string>
     <string name="chooseUsbActivity" msgid="2096269989990986612">"Escolher uma app para o dispositivo USB"</string>
@@ -1394,7 +1394,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Escolher o método de entrada"</string>
     <string name="show_ime" msgid="6406112007347443383">"Manter no ecrã enquanto o teclado físico estiver ativo"</string>
     <string name="hardware" msgid="1800597768237606953">"Mostrar o teclado virtual"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Configurar teclado físico"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Toque para selecionar o idioma e o esquema"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1711,7 +1714,7 @@
     <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar atalhos"</string>
     <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Concluído"</string>
     <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desativar atalho"</string>
-    <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilizar atalho"</string>
+    <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Usar atalho"</string>
     <string name="color_inversion_feature_name" msgid="2672824491933264951">"Inversão de cores"</string>
     <string name="color_correction_feature_name" msgid="7975133554160979214">"Correção da cor"</string>
     <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modo para uma mão"</string>
@@ -1719,7 +1722,7 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Dispositivos auditivos"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas do volume premidas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ativado."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume premidas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desativado."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"prima sem soltar as teclas de volume durante três segundos para usar o serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
+    <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Solte as teclas de volume. Para ativar o serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, prima sem soltar ambas as teclas de volume novamente durante 3 segundos."</string>
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Escolha uma funcionalidade para utilizar quando tocar no botão Acessibilidade:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Escolha a funcionalidade a utilizar com o gesto de acessibilidade (deslize rapidamente com dois dedos para cima a partir da parte inferior do ecrã):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Escolha a funcionalidade a utilizar com o gesto de acessibilidade (deslize rapidamente com três dedos para cima a partir da parte inferior do ecrã):"</string>
@@ -2167,8 +2170,8 @@
     <string name="resolver_no_personal_apps_available" msgid="6284837227019594881">"Sem apps pessoais"</string>
     <string name="miniresolver_open_in_personal" msgid="3874522693661065566">"Abrir a app <xliff:g id="APP">%s</xliff:g> no seu perfil pessoal?"</string>
     <string name="miniresolver_open_in_work" msgid="4415223793669536559">"Abrir a app <xliff:g id="APP">%s</xliff:g> no seu perfil de trabalho?"</string>
-    <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Utilizar navegador pessoal"</string>
-    <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Utilizar navegador de trabalho"</string>
+    <string name="miniresolver_use_personal_browser" msgid="776072682871133308">"Usar navegador pessoal"</string>
+    <string name="miniresolver_use_work_browser" msgid="543575306251952994">"Usar navegador de trabalho"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_ENTRY" msgid="8050953231914637819">"PIN para desbloqueio de rede do cartão SIM"</string>
     <string name="PERSOSUBSTATE_SIM_NETWORK_SUBSET_ENTRY" msgid="7164399703751688214">"PIN para desbloqueio do subconjunto da rede do cartão SIM"</string>
     <string name="PERSOSUBSTATE_SIM_CORPORATE_ENTRY" msgid="4447629474818217364">"PIN para desbloqueio empresarial do cartão SIM"</string>
@@ -2324,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"O dispositivo está a ficar demasiado quente"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"A funcionalidade Dois ecrãs está indisponível porque o seu telemóvel está a ficar demasiado quente"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Desativar"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 896362a..5eb7a46 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1394,7 +1394,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Selecione o método de entrada"</string>
     <string name="show_ime" msgid="6406112007347443383">"Mantém o teclado virtual na tela enquanto o teclado físico está ativo"</string>
     <string name="hardware" msgid="1800597768237606953">"Mostrar teclado virtual"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Configurar teclado físico"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Toque para selecionar o idioma e o layout"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1719,7 +1722,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Aparelhos auditivos"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas de volume pressionadas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ativado."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume pressionadas. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desativado."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Toque nos dois botões de volume e os mantenha pressionados por três segundo para usar o <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Escolha um recurso a ser usado quando você toca no botão de acessibilidade:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Escolha um recurso para usar com o gesto de acessibilidade (deslizar de baixo para cima na tela com dois dedos):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Escolha um recurso para usar com o gesto de acessibilidade (deslizar de baixo para cima na tela com três dedos):"</string>
@@ -2324,4 +2328,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"O dispositivo está muito quente"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"A tela dupla está indisponível porque o smartphone está ficando muito quente"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Desativar"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 6c6fc32..f477049 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1394,7 +1394,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Alege metoda de introducere de text"</string>
     <string name="show_ime" msgid="6406112007347443383">"Se păstrează pe ecran cât timp este activată tastatura fizică"</string>
     <string name="hardware" msgid="1800597768237606953">"Afișează tastatura virtuală"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Configurează tastatura fizică"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Atinge pentru a selecta limba și aspectul"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1719,7 +1722,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Aparate auditive"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"S-au apăsat lung tastele de volum. S-a activat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"S-au apăsat lung tastele de volum. S-a dezactivat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Apasă ambele butoane de volum timp de trei secunde pentru a folosi <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Alege o funcție pe care să o folosești când atingi butonul de accesibilitate:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Alege o funcție pe care să o folosești cu gestul de accesibilitate (glisează în sus cu două degete din partea de jos a ecranului):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Alege o funcție pe care să o folosești cu gestul de accesibilitate (glisează în sus cu trei degete din partea de jos a ecranului):"</string>
@@ -2324,4 +2328,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Dispozitivul este prea cald"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Funcția Dual Screen este indisponibilă, deoarece telefonul s-a încălzit prea tare"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Dezactivează"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 3888e0c..70cc882 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1172,8 +1172,8 @@
     <string name="no" msgid="5122037903299899715">"Отмена"</string>
     <string name="dialog_alert_title" msgid="651856561974090712">"Внимание!"</string>
     <string name="loading" msgid="3138021523725055037">"Загрузка…"</string>
-    <string name="capital_on" msgid="2770685323900821829">"I"</string>
-    <string name="capital_off" msgid="7443704171014626777">"O"</string>
+    <string name="capital_on" msgid="2770685323900821829">"Включено"</string>
+    <string name="capital_off" msgid="7443704171014626777">"Выключено"</string>
     <string name="checked" msgid="9179896827054513119">"отмечено"</string>
     <string name="not_checked" msgid="7972320087569023342">"не отмечено"</string>
     <string name="selected" msgid="6614607926197755875">"выбрано"</string>
@@ -1395,7 +1395,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Выберите способ ввода"</string>
     <string name="show_ime" msgid="6406112007347443383">"Не скрывать экранную клавиатуру, когда включена физическая"</string>
     <string name="hardware" msgid="1800597768237606953">"Виртуальная клавиатура"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Настройка физической клавиатуры"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Нажмите, чтобы выбрать язык и раскладку"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1720,7 +1723,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Слуховые аппараты"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Использован жест с кнопками регулировки громкости. Функция \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\" включена."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Использован жест с кнопками регулировки громкости. Функция \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\" отключена."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Чтобы использовать сервис \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\", нажмите и удерживайте обе клавиши громкости в течение трех секунд."</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Выберите функцию, которая будет запускаться при нажатии кнопки специальных возможностей:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Выберите функцию, которая будет запускаться с помощью жеста (провести по экрану снизу вверх двумя пальцами):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Выберите функцию, которая будет запускаться с помощью жеста (провести по экрану снизу вверх тремя пальцами):"</string>
@@ -1872,8 +1876,8 @@
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Обновлено администратором"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Удалено администратором"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"ОК"</string>
-    <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"В режиме энергосбережения включается тёмная тема, ограничиваются или отключаются фоновые процессы, а также некоторые визуальные эффекты, функции и сетевые подключения."</string>
-    <string name="battery_saver_description" msgid="8518809702138617167">"В режиме энергосбережения включается тёмная тема, ограничиваются или отключаются фоновые процессы, а также некоторые визуальные эффекты, функции и сетевые подключения."</string>
+    <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"В режиме энергосбережения включается тёмная тема, ограничиваются или отключаются фоновые процессы, а также некоторые визуальные эффекты, часть функций и сетевых подключений."</string>
+    <string name="battery_saver_description" msgid="8518809702138617167">"В режиме энергосбережения включается тёмная тема, ограничиваются или отключаются фоновые процессы, а также некоторые визуальные эффекты, часть функций и сетевых подключений."</string>
     <string name="data_saver_description" msgid="4995164271550590517">"В режиме экономии трафика фоновая передача данных для некоторых приложений отключена. Приложение, которым вы пользуетесь, может получать и отправлять данные, но реже, чем обычно. Например, изображения могут не загружаться, пока вы не нажмете на них."</string>
     <string name="data_saver_enable_title" msgid="7080620065745260137">"Включить экономию трафика?"</string>
     <string name="data_saver_enable_button" msgid="4399405762586419726">"Включить"</string>
@@ -2325,4 +2329,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Устройство перегрелось"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Двойной экран недоступен из-за перегрева телефона."</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Отключить"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index e58ca73..7f9a6cb 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"ආදාන ක්‍රමයක් තෝරන්න"</string>
     <string name="show_ime" msgid="6406112007347443383">"භෞතික යතුරු පුවරුව සක්‍රිය අතරතුර එය තිරය මත තබා ගන්න"</string>
     <string name="hardware" msgid="1800597768237606953">"අතථ්‍ය යතුරු පුවරුව පෙන්වන්න"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"භෞතික යතුරු පුවරුව වින්‍යාස කරන්න"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"භාෂාව හා පිරිසැලසුම තේරීමට තට්ටු කරන්න"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"ශ්‍රවණ උපාංග"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"හඬ පරිමා යතුරු අල්ලා ගන්න <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ක්‍රියාත්මකයි."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"හඬ පරිමා යතුරු අල්ලා ගන්න <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ක්‍රියාවිරහිතයි."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> භාවිත කිරීමට හඬ පරිමා යතුරු දෙකම තත්පර තුනකට ඔබාගෙන සිටින්න"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"ඔබ ප්‍රවේශ්‍යතා බොත්තම තට්ටු කරන විට භාවිත කිරීමට විශේෂාංගයක් තෝරා ගන්න:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"ප්‍රවේශ්‍යතා ඉංගිතය සමඟ භාවිතයට විශේෂාංගයක් තෝරා ගන්න (ඇඟිලි දෙකකින් තිරයේ පහළ සිට ඉහළට ස්වයිප් කරන්න):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"ප්‍රවේශ්‍යතා ඉංගිතය සමඟ භාවිතයට විශේෂාංගයක් තෝරා ගන්න (ඇඟිලි තුනකින් තිරයේ පහළ සිට ඉහළට ස්වයිප් කරන්න):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"උපාංගය ඉතා උණුසුම් වේ"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"ඔබේ දුරකථනය ඉතා උණුසුම් නිසා ද්විත්ව තිරය ලබා ගත නොහැක"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"අක්‍රිය කරන්න"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index d56b390..9c481a9 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1370,7 +1370,7 @@
     <string name="usb_power_notification_message" msgid="7284765627437897702">"Pripojené zariadenie sa nabíja. Ďalšie možností získate klepnutím."</string>
     <string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Bolo zistené analógové zvukové príslušenstvo"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"Pripojené zariadenie nie je kompatibilné s týmto telefónom. Ďalšie informácie zobrazíte klepnutím."</string>
-    <string name="adb_active_notification_title" msgid="408390247354560331">"Ladenie cez USB pripojené"</string>
+    <string name="adb_active_notification_title" msgid="408390247354560331">"Ladenie cez USB je pripojené"</string>
     <string name="adb_active_notification_message" msgid="5617264033476778211">"Klepnutím vypnite ladenie cez USB"</string>
     <string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Vyberte, ak chcete zakázať ladenie cez USB."</string>
     <string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Bezdrôtové ladenie je pripojené"</string>
@@ -1395,7 +1395,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Zvoliť metódu vstupu"</string>
     <string name="show_ime" msgid="6406112007347443383">"Ponechať na obrazovke, keď je aktívna fyzická klávesnica"</string>
     <string name="hardware" msgid="1800597768237606953">"Zobraziť virtuálnu klávesnicu"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Konfigurácia fyzickej klávesnice"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Klepnutím vyberte jazyk a rozloženie"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" AÁÄBCČDĎDZDŽEÉFGHCHIÍJKLĽMNŇOÓÔPRŔSŠTŤUÚVWXYÝZŽ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1720,7 +1723,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Načúvacie zariadenia"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Pridržali ste tlačidlá hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je zapnutá."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Pridržali ste tlačidlá hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je vypnutá."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Ak chcete používať službu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, pridržte tri sekundy oba klávesy hlasitosti"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Klepnutím na tlačidlo dostupnosti vyberte požadovanú funkciu:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Vyberte funkciu, ktorú chcete používať s daným gestom dostupnosti (potiahnutím dvoma prstami z dolnej časti obrazovky nahor):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Vyberte funkciu aktivovanú daným gestom dostupnosti (potiahnutím troma prstami z dolnej časti obrazovky nahor):"</string>
@@ -2325,4 +2329,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Zariadenie je príliš horúce"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dvojitá obrazovka nie je k dispozícii, pretože telefón sa prehrieva"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Vypnúť"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 2e582fd..39a722d 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1395,7 +1395,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Izberite način vnosa"</string>
     <string name="show_ime" msgid="6406112007347443383">"Ohrani na zaslonu, dokler je aktivna fizična tipkovnica"</string>
     <string name="hardware" msgid="1800597768237606953">"Pokaži navidezno tipkovnico"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Konfiguriranje fizične tipkovnice"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Dotaknite se, če želite izbrati jezik in postavitev."</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1720,7 +1723,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Slušni aparati"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tipki za glasnost sta pridržani. Storitev <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je vklopljena."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tipki za glasnost sta pridržani. Storitev <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je izklopljena."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Za uporabo storitve <xliff:g id="SERVICE_NAME">%1$s</xliff:g> pritisnite obe tipki za glasnost in ju pridržite tri sekunde"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Izberite funkcijo, ki jo želite uporabljati, ko se dotaknete gumba za funkcije za ljudi s posebnimi potrebami:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Izberite funkcijo, ki jo želite zagnati s potezo za ljudi s posebnimi potrebami (vlečenje z dvema prstoma z dna zaslona navzgor):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Izberite funkcijo, ki jo želite zagnati s potezo za ljudi s posebnimi potrebami (vlečenje s tremi prsti z dna zaslona navzgor):"</string>
@@ -2325,4 +2329,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Naprava se pregreva"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dvojni zaslon ni na voljo, ker se telefon pregreva."</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Izklopi"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 3688c5f..d8494b4 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Zgjidh metodën e hyrjes"</string>
     <string name="show_ime" msgid="6406112007347443383">"Mbaje në ekran ndërsa tastiera fizike është aktive"</string>
     <string name="hardware" msgid="1800597768237606953">"Shfaq tastierën virtuale"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Konfiguro tastierën fizike"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Trokit për të zgjedhur gjuhën dhe strukturën"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Pajisjet e dëgjimit"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tastet e volumit të mbajtura shtypur. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> i aktivizuar."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tastet e volumit të mbajtura shtypur. U çaktivizua \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\"."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Shtyp dhe mbaj shtypur të dy butonat e volumit për tre sekonda për të përdorur <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Zgjidh një funksion për ta përdorur kur troket butonin e qasshmërisë:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Zgjidh një veçori për ta përdorur me gjestin e qasshmërisë (rrëshqit shpejt lart nga fundi i ekranit me dy gishta):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Zgjidh një veçori për ta përdorur me gjestin e qasshmërisë (rrëshqit shpejt lart nga fundi i ekranit me tre gishta):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Pajisja është shumë e nxehtë"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"\"Ekrani i dyfishtë\" nuk ofrohet sepse telefoni yt po nxehet shumë"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Çaktivizoje"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 43f17fd..2e4c4ea 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1394,7 +1394,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Избор метода уноса"</string>
     <string name="show_ime" msgid="6406112007347443383">"Задржава се на екрану док је физичка тастатура активна"</string>
     <string name="hardware" msgid="1800597768237606953">"Прикажи виртуелну тастатуру"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Конфигуришите физичку тастатуру"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Додирните да бисте изабрали језик и распоред"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1719,7 +1722,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Слушни апарати"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Држали сте тастере за јачину звука. Услуга <xliff:g id="SERVICE_NAME">%1$s</xliff:g> је укључена."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Држали сте тастере за јачину звука. Услуга <xliff:g id="SERVICE_NAME">%1$s</xliff:g> је искључена."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Притисните и задржите оба тастера за јачину звука три секунде да бисте користили <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Изаберите функцију која ће се користити када додирнете дугме Приступачност:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Одаберите функцију која ће се користити помоћу покрета за приступачност (помоћу два прста превуците нагоре од дна екрана):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Одаберите функцију која ће се користити помоћу покрета за приступачност (помоћу три прста превуците нагоре од дна екрана):"</string>
@@ -2324,4 +2328,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Уређај је превише загрејан"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Двојни екран је недоступан јер је телефон превише загрејан"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Искључи"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 98c5aef..098b32f 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -299,7 +299,7 @@
     <string name="managed_profile_label" msgid="7316778766973512382">"Byt till jobbprofilen"</string>
     <string name="permgrouplab_contacts" msgid="4254143639307316920">"Kontakter"</string>
     <string name="permgroupdesc_contacts" msgid="9163927941244182567">"få tillgång till dina kontakter"</string>
-    <string name="permgrouplab_location" msgid="1858277002233964394">"Plats"</string>
+    <string name="permgrouplab_location" msgid="1858277002233964394">"plats"</string>
     <string name="permgroupdesc_location" msgid="1995955142118450685">"komma åt enhetens platsuppgifter"</string>
     <string name="permgrouplab_calendar" msgid="6426860926123033230">"Kalender"</string>
     <string name="permgroupdesc_calendar" msgid="6762751063361489379">"få tillgång till din kalender"</string>
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Välj inmatningsmetod"</string>
     <string name="show_ime" msgid="6406112007347443383">"Ha kvar det på skärmen när det fysiska tangentbordet används"</string>
     <string name="hardware" msgid="1800597768237606953">"Visa virtuellt tangentbord"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Konfigurera fysiskt tangentbord"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Tryck om du vill välja språk och layout"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hörapparater"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Volymknapparna har tryckts ned. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> har aktiverats."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Volymknapparna har tryckts ned. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> har inaktiverats."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Tryck och håll båda volymknapparna i tre sekunder för att använda <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Välj en funktion som ska användas när du trycker på tillgänglighetsknappen:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Välj en funktion som ska användas med tillgänglighetsrörelsen (svepa uppåt med två fingrar från skärmens nederkant):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Välj en funktion som ska användas med tillgänglighetsrörelsen (svepa uppåt med tre fingrar från skärmens nederkant):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Enheten är för varm"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Dubbel skärm kan inte användas eftersom telefonen börjar bli för varm"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Stäng av"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 67f6ca2..0d7b9da 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Chagua njia ya ingizo"</string>
     <string name="show_ime" msgid="6406112007347443383">"Ionyeshe kwenye skrini wakati kibodi halisi inatumika"</string>
     <string name="hardware" msgid="1800597768237606953">"Onyesha kibodi pepe"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Sanidi kibodi halisi"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Gusa ili uchague lugha na muundo"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Vifaa vya kusaidia kusikia"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Vitufe vya sauti vilivyoshikiliwa. Umewasha <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Vitufe vya sauti vimeshikiliwa. Umezima <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Bonyeza na ushikilie vitufe vyote viwili vya sauti kwa sekunde tatu ili utumie <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Chagua kipengele utakachotumia ukigusa kitufe cha ufikivu:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Chagua kipengele cha kutumia pamoja na ishara ya ufikivu (telezesha vidole viwili kutoka chini kwenda juu kwenye skrini):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Chagua kipengele cha kutumia pamoja na ishara ya ufikivu (telezesha vidole vitatu kutoka chini kwenda juu kwenye skrini):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Kifaa kina joto sana"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Kipengele cha Hali ya Skrini Mbili hakipatikani kwa sababu simu yako inapata joto sana"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Zima"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index ddf1393..e1f709e6 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"உள்ளீட்டு முறையைத் தேர்வுசெய்க"</string>
     <string name="show_ime" msgid="6406112007347443383">"கைமுறை கீபோர்டு இயக்கத்தில் இருக்கும் போது IMEஐ திரையில் வைத்திரு"</string>
     <string name="hardware" msgid="1800597768237606953">"விர்ச்சுவல் கீபோர்டை காட்டு"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"கைமுறை கீபோர்டை உள்ளமைக்கவும்"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"மொழியையும் தளவமைப்பையும் தேர்ந்தெடுக்க, தட்டவும்"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"செவித்துணைக் கருவிகள்"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ஒலியளவுக்கான விசைகளைப் பிடித்திருந்தீர்கள். <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ஆன் செய்யப்பட்டது."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ஒலியளவுக்கான விசைகளைப் பிடித்திருந்தீர்கள். <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ஆஃப் செய்யப்பட்டது."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>ஐப் பயன்படுத்த 3 விநாடிகளுக்கு இரண்டு ஒலியளவு பட்டன்களையும் அழுத்திப் பிடிக்கவும்"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"அணுகல்தன்மை பட்டனைத் தட்டுவதன் மூலம் பயன்படுத்த விரும்பும் அம்சத்தைத் தேர்ந்தெடுக்கவும்:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"அணுகல்தன்மை சைகைக்கான அம்சத்தைத் தேர்வுசெய்யவும் (இரண்டு விரல்களால் திரையின் கீழிருந்து மேல் நோக்கி ஸ்வைப் செய்யவும்):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"அணுகல்தன்மை சைகைக்கான அம்சத்தைத் தேர்வுசெய்யவும் (மூன்று விரல்களால் திரையின் கீழிருந்து மேல் நோக்கி ஸ்வைப் செய்யவும்):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"சாதனம் மிகவும் சூடாக உள்ளது"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"உங்கள் மொபைல் மிகவும் சூடாக இருப்பதால் இரட்டைத் திரை அம்சத்தைப் பயன்படுத்த முடியாது"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"முடக்கு"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 33f5d24..4d66751 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"ఇన్‌పుట్ పద్ధతిని ఎంచుకోండి"</string>
     <string name="show_ime" msgid="6406112007347443383">"దీన్ని భౌతిక కీబోర్డ్ యాక్టివ్‌గా ఉన్నప్పుడు స్క్రీన్‌పై ఉంచుతుంది"</string>
     <string name="hardware" msgid="1800597768237606953">"వర్చువల్ కీబోర్డ్‌ను చూపు"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"భౌతిక కీబోర్డుని కాన్ఫిగర్ చేయండి"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"భాష మరియు లేఅవుట్‌ను ఎంచుకోవడానికి నొక్కండి"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"వినికిడి పరికరం"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"వాల్యూమ్ కీలు నొక్కి ఉంచబడ్డాయి. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ఆన్ చేయబడింది"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"వాల్యూమ్ కీలు నొక్కి ఉంచబడ్డాయి. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ఆఫ్ చేయబడింది"</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>ని ఉపయోగించడానికి వాల్యూమ్ కీలు రెండింటినీ 3 సెకన్లు నొక్కి ఉంచండి"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"యాక్సెస్ సామర్థ్య బటన్‌ను మీరు నొక్కినప్పుడు ఉపయోగించాల్సిన ఒక ఫీచర్‌ను ఎంచుకోండి:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"యాక్సెసిబిలిటీ సంజ్ఞతో ఉపయోగించడానికి ఒక ఫీచర్‌ని ఎంచుకోండి (రెండు వేళ్లతో స్క్రీన్‌ను కింద నుండి పైకి స్వైప్ చేయండి):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"యాక్సెసిబిలిటీ సంజ్ఞతో ఉపయోగించడానికి ఒక ఫీచర్‌ను ఎంచుకోండి (మూడు చేతి వేళ్లతో స్క్రీన్‌ను కింద నుండి పైకి స్వైప్ చేయండి):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"పరికరం చాలా వేడిగా ఉంది"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"మీ ఫోన్ చాలా వేడిగా అవుతున్నందున, డ్యూయల్ స్క్రీన్ అందుబాటులో లేదు"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"ఆఫ్ చేయండి"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 8032880..2d00d89f 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"เลือกวิธีการป้อนข้อมูล"</string>
     <string name="show_ime" msgid="6406112007347443383">"เปิดทิ้งไว้บนหน้าจอในระหว่างใช้งานแป้นพิมพ์จริง"</string>
     <string name="hardware" msgid="1800597768237606953">"แสดงแป้นพิมพ์เสมือน"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"กำหนดค่าแป้นพิมพ์จริง"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"แตะเพื่อเลือกภาษาและรูปแบบ"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"เครื่องช่วยฟัง"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"กดปุ่มปรับระดับเสียงค้างไว้แล้ว เปิด <xliff:g id="SERVICE_NAME">%1$s</xliff:g> แล้ว"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"กดปุ่มปรับระดับเสียงค้างไว้แล้ว ปิด <xliff:g id="SERVICE_NAME">%1$s</xliff:g> แล้ว"</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"กดปุ่มปรับระดับเสียงทั้ง 2 ปุ่มค้างไว้ 3 วินาทีเพื่อใช้ <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"เลือกฟีเจอร์ที่จะใช้เมื่อคุณแตะปุ่มการช่วยเหลือพิเศษดังต่อไปนี้"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"เลือกฟีเจอร์ที่จะใช้กับท่าทางสัมผัสการช่วยเหลือพิเศษ (ใช้ 2 นิ้วเลื่อนขึ้นจากด้านล่างของหน้าจอ) ดังต่อไปนี้"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"เลือกฟีเจอร์ที่จะใช้กับท่าทางสัมผัสการช่วยเหลือพิเศษ (ใช้ 3 นิ้วเลื่อนขึ้นจากด้านล่างของหน้าจอ) ดังต่อไปนี้"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"อุปกรณ์ร้อนเกินไป"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"หน้าจอคู่ไม่พร้อมให้ใช้งานเนื่องจากโทรศัพท์ของคุณร้อนเกินไป"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"ปิด"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index d1383df..238cbfb 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Pumili ng pamamaraan ng pag-input"</string>
     <string name="show_ime" msgid="6406112007347443383">"Panatilihin ito sa screen habang aktibo ang pisikal na keyboard"</string>
     <string name="hardware" msgid="1800597768237606953">"Ipakita ang virtual keyboard"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"I-configure ang pisikal na keyboard"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"I-tap upang pumili ng wika at layout"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Mga hearing device"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Pinindot nang matagal ang volume keys. Na-on ang <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Pinindot nang matagal ang volume keys. Na-off ang <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Pindutin nang matagal ang parehong volume key sa loob ng tatlong segundo para magamit ang <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Pumili ng feature na gagana sa pamamagitan ng pag-tap mo sa button ng accessibility:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Pumili ng feature na gagana sa pamamagitan ng galaw ng accessibility (pag-swipe pataas mula sa ibaba ng screen gamit ang dalawang daliri):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Pumili ng feature na gagana sa pamamagitan ng galaw ng accessibility (pag-swipe pataas mula sa ibaba ng screen gamit ang tatlong daliri):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Masyadong mainit ang device"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Hindi available ang Dual Screen dahil masyado nang umiinit ang telepono mo"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"I-off"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 2e7b3c7..834bd47 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Giriş yöntemini seçin"</string>
     <string name="show_ime" msgid="6406112007347443383">"Fiziksel klavye etkin durumdayken ekranda tut"</string>
     <string name="hardware" msgid="1800597768237606953">"Sanal klavyeyi göster"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Fiziksel klavyeyi yapılandırın"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Dili ve düzeni seçmek için dokunun"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"İşitme cihazları"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ses tuşlarını basılı tuttunuz. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> açıldı."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ses tuşlarını basılı tuttunuz. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> kapatıldı."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> hizmetini kullanmak için her iki ses tuşunu basılı tutun"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Erişilebilirlik düğmesine dokunduğunuzda kullanmak için bir özellik seçin:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Erişilebilirlik hareketiyle (iki parmakla ekranın altından yukarı kaydırma) kullanılacak bir özellik seçin:"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Erişilebilirlik hareketiyle (üç parmakla ekranın altından yukarı kaydırma) kullanılacak bir özellik seçin:"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Cihaz çok ısındı"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Telefonunuz çok ısındığı için Çift Ekran kullanılamıyor"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Kapat"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 5ce099c..d9eef0d 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1395,7 +1395,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Вибрати метод введення"</string>
     <string name="show_ime" msgid="6406112007347443383">"Утримуйте на екрані, коли активна фізична клавіатура"</string>
     <string name="hardware" msgid="1800597768237606953">"Показати віртуальну клавіатуру"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Налаштуйте фізичну клавіатуру"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Торкніться, щоб вибрати мову та розкладку"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ"</string>
@@ -1720,7 +1723,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Слухові апарати"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Утримано клавіші гучності. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> увімкнено."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Утримано клавіші гучності. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> вимкнено."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Щоб скористатися службою <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, утримуйте обидві клавіші гучності впродовж трьох секунд"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Виберіть функцію для кнопки спеціальних можливостей:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Виберіть функцію для жесту спеціальних можливостей (проведення двома пальцями знизу вгору):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Виберіть функцію для жесту спеціальних можливостей (проведення трьома пальцями знизу вгору):"</string>
@@ -2325,4 +2329,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Пристрій сильно нагрівається"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Подвійний екран недоступний, оскільки телефон сильно нагрівається"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Вимкнути"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 101cec07..ac30a26 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"ان پٹ کا طریقہ منتخب کریں"</string>
     <string name="show_ime" msgid="6406112007347443383">"‏جب فزیکل کی بورڈ فعال ہو تو IME کو اسکرین پر رکھیں"</string>
     <string name="hardware" msgid="1800597768237606953">"ورچوئل کی بورڈ دکھائیں"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"فزیکل کی بورڈ کنفیگر کریں"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"زبان اور لے آؤٹ منتخب کرنے کیلئے تھپتھپائیں"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"سماعتی آلات"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"والیوم کی کلیدوں کو دبائے رکھا گیا۔ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> آن ہے۔"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"والیوم کی کلیدوں کو دبائے رکھا گیا۔ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> آف ہے۔"</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> کا استعمال کرنے کے لیے 3 سیکنڈ تک والیوم کی دونوں کلیدوں کو چھوئیں اور دبائے رکھیں"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"ایکسیسبیلٹی بٹن پر تھپتھپانے وقت استعمال کرنے کیلئے ایک خصوصیت منتخب کریں:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"ایکسیسبیلٹی اشارہ کے ساتھ استعمال کرنے کے لیے ایک خصوصیت چنیں (دو انگلیوں سے اسکرین کے نیچے سے اوپر کی طرف سوائپ کریں):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"ایکسیسبیلٹی اشارہ کے ساتھ استعمال کرنے کے لیے ایک خصوصیت چنیں (تین انگلیوں سے اسکرین کے نیچے سے اوپر کی طرف سوائپ کریں):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"آلہ بہت زیادہ گرم ہے"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"دوہری اسکرین دستیاب نہیں ہے کیونکہ آپ کا فون بہت زیادہ گرم ہو رہا ہے"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"آف کریں"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 1c08daa..0f7a9ef 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Matn kiritish usulini tanlang"</string>
     <string name="show_ime" msgid="6406112007347443383">"Tashqi klaviatura ulanganida ekranda chiqib turadi"</string>
     <string name="hardware" msgid="1800597768237606953">"Virtual klaviatura"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Tashqi klaviaturani sozlash"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Til va sxemani belgilash uchun bosing"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Eshitish qurilmalari"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tovush tugmalari bosib turildi. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> yoqildi."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tovush tugmalari bosib turildi. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> faolsizlantirildi."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> xizmatidan foydalanish uchun ikkala ovoz balandligi tugmalarini uzoq bosib turing"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Maxsus imkoniyatlar tugmasi bosilganda ishga tushadigan funksiyani tanlang:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Maxsus imkoniyatlar ishorasi bilan ishga tushadigan funksiyani tanlang (ikkita barmoq bilan ekranning pastidan tepaga surib tortilganda):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Maxsus imkoniyatlar ishorasi bilan ishga tushadigan funksiyani tanlang (uchta barmoq bilan ekranning pastidan tepaga surib tortilganda):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Qurilma qizib ketdi"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Telefon qizib ketgani uchun hozir ikki ekranli rejim ishlamaydi"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Faolsizlantirish"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 6a863a1..2bcadcc 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Chọn phương thức nhập"</string>
     <string name="show_ime" msgid="6406112007347443383">"Hiện bàn phím ảo trên màn hình trong khi bàn phím vật lý đang hoạt động"</string>
     <string name="hardware" msgid="1800597768237606953">"Hiện bàn phím ảo"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Định cấu hình bàn phím vật lý"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Nhấn để chọn ngôn ngữ và bố cục"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Thiết bị trợ thính"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Bạn đã giữ các phím âm lượng. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> đã bật."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Bạn đã giữ các phím âm lượng. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> đã tắt."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Nhấn và giữ đồng thời cả hai phím âm lượng trong 3 giây để sử dụng <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Chọn một tính năng để dùng khi bạn nhấn nút hỗ trợ tiếp cận:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Chọn một tính năng để dùng với cử chỉ hỗ trợ tiếp cận (dùng 2 ngón tay vuốt lên từ cuối màn hình):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Chọn một tính năng để dùng với cử chỉ hỗ trợ tiếp cận (dùng 3 ngón tay vuốt lên từ cuối màn hình):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Thiết bị quá nóng"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Không bật được chế độ Màn hình đôi vì điện thoại của bạn quá nóng"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Tắt"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 1f0e170..2ca846e 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"选择输入法"</string>
     <string name="show_ime" msgid="6406112007347443383">"开启后,连接到实体键盘时,它会一直显示在屏幕上"</string>
     <string name="hardware" msgid="1800597768237606953">"显示虚拟键盘"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"配置实体键盘"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"点按即可选择语言和布局"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"助听设备"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"已按住音量键。<xliff:g id="SERVICE_NAME">%1$s</xliff:g>已开启。"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"已按住音量键。<xliff:g id="SERVICE_NAME">%1$s</xliff:g>已关闭。"</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"同时按住两个音量键 3 秒钟即可使用 <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"选择点按“无障碍”按钮后要使用的功能:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"选择要搭配无障碍手势(用两根手指从屏幕底部向上滑动)使用的功能:"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"选择要搭配无障碍手势(用三根手指从屏幕底部向上滑动)使用的功能:"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"设备过热"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"手机过热,因此无法使用双屏幕功能"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"关闭"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 4f6d8e2..080165c 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"選擇輸入法"</string>
     <string name="show_ime" msgid="6406112007347443383">"在實體鍵盤處於連接狀態時保持顯示"</string>
     <string name="hardware" msgid="1800597768237606953">"顯示虛擬鍵盤"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"設定實體鍵盤"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"輕按即可選取語言和鍵盤配置"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"助聽器"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"已按住音量鍵。<xliff:g id="SERVICE_NAME">%1$s</xliff:g> 已開啟。"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"已按住音量鍵。<xliff:g id="SERVICE_NAME">%1$s</xliff:g> 已關閉。"</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"㩒住兩個音量鍵 3 秒就可以用 <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"請選擇輕按「無障礙功能」按鈕時使用的功能:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"請選擇要配搭無障礙手勢 (使用兩隻手指從螢幕底部向上滑動) 使用的功能:"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"請選擇要配搭無障礙手勢 (使用三隻手指從螢幕底部向上滑動) 使用的功能:"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"裝置過熱"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"由於手機過熱,雙螢幕功能無法使用"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"關閉"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 7896196..460bc73 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"選擇輸入法"</string>
     <string name="show_ime" msgid="6406112007347443383">"使用實體鍵盤時仍繼續顯示虛擬鍵盤"</string>
     <string name="hardware" msgid="1800597768237606953">"顯示虛擬鍵盤"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"設定實體鍵盤"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"輕觸即可選取語言和版面配置"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"助聽器"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"已按住音量鍵。「<xliff:g id="SERVICE_NAME">%1$s</xliff:g>」已開啟。"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"已按住音量鍵。「<xliff:g id="SERVICE_NAME">%1$s</xliff:g>」已關閉。"</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"同時按住調低及調高音量鍵三秒即可使用「<xliff:g id="SERVICE_NAME">%1$s</xliff:g>」"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"輕觸無障礙工具按鈕後,選擇你想使用的功能:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"選擇要搭配無障礙手勢 (用兩指從螢幕底部向上滑動) 使用的功能:"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"選擇要搭配無障礙手勢 (用三指從螢幕底部向上滑動) 使用的功能:"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"裝置過熱"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"手機過熱,因此無法使用雙螢幕功能"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"停用"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 1fcbbe2..363660d 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1393,7 +1393,10 @@
     <string name="select_input_method" msgid="3971267998568587025">"Khetha indlela yokufaka"</string>
     <string name="show_ime" msgid="6406112007347443383">"Yigcine kusikrini ngenkathi kusebenza ikhibhodi ephathekayo"</string>
     <string name="hardware" msgid="1800597768237606953">"Bonisa ikhibhodi ebonakalayo"</string>
-    <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"Lungisa ikhibhodi yoqobo"</string>
+    <!-- no translation found for select_keyboard_layout_notification_title (5823199895322205589) -->
+    <skip />
+    <!-- no translation found for select_multiple_keyboards_layout_notification_title (6999491025126641938) -->
+    <skip />
     <string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"Thepha ukuze ukhethe ulimi nesakhiwo"</string>
     <string name="fast_scroll_alphabet" msgid="8854435958703888376">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
@@ -1718,7 +1721,8 @@
     <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Amadivayizi okuzwa"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ubambe okhiye bevolumu. I-<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ivuliwe."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ubambe okhiye bevolumu. I-<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ivaliwe."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Cindezela uphinde ubambe bobabili okhiye bevolumu ngamasekhondi amathathu ukuze usebenzise i-<xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <!-- no translation found for accessibility_shortcut_spoken_feedback (3760999147597564314) -->
+    <skip />
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Khetha isici ozosisebenzisa uma uthepha inkinobho yokufinyelela:"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Khetha isici ozosisebenzisa ngokuthinta kokufinyeleleka (swayiphela phezulu kusukela ngaphansi kwesikrini ngeminwe emibili):"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Khetha isici ozosisebenzisa ngokuthinta kokufinyeleleka (swayiphela phezulu kusukela phansi esikrinini ngeminwe emithathu):"</string>
@@ -2323,4 +2327,18 @@
     <string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Idivayisi ifudumele kakhulu"</string>
     <string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"I-Dual Screen ayitholakali ngoba ifoni yakho iqala ukufudumala kakhulu"</string>
     <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Vala"</string>
+    <!-- no translation found for keyboard_layout_notification_selected_title (1202560174252421219) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_one_selected_message (4314216053129257197) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_two_selected_message (1876349944065922950) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_three_selected_message (280734264593115419) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_more_than_three_selected_message (1581834181578206937) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_title (5242444914367024499) -->
+    <skip />
+    <!-- no translation found for keyboard_layout_notification_multiple_selected_message (6576533454124419202) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 4468ebe..b35481d 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -227,4 +227,10 @@
     <string-array name="device_state_notification_thermal_contents">
         <item>@string/concurrent_display_notification_thermal_content</item>
     </string-array>
+
+    <!-- Certificate digests for trusted apps that will be allowed to obtain the knownSigner of the
+         demo device provisioning permissions. -->
+    <string-array name="demo_device_provisioning_known_signers">
+        <item>@string/config_retailDemoPackageSignature</item>
+    </string-array>
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 9252b14..2a67b44 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3201,8 +3201,8 @@
 
         <!-- Describes whether this view should allow interactions from AccessibilityServices only
              if the service sets the isAccessibilityTool property. -->
-        <attr name="accessibilityDataPrivate" format="integer">
-            <!-- The system determines whether the view's accessibility data is private
+        <attr name="accessibilityDataSensitive" format="integer">
+            <!-- The system determines whether the view's accessibility data is sensitive
                  - default (recommended). -->
             <enum name="auto" value="0" />
             <!-- Allow interactions from AccessibilityServices only if the service sets the
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 209c785..2ed1817 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -711,6 +711,9 @@
          mode. -->
     <integer name="config_unfoldTransitionHalfFoldedTimeout">1000</integer>
 
+    <!-- Timeout for receiving the keyguard drawn event from System UI.  -->
+    <integer name="config_keyguardDrawnTimeout">1000</integer>
+
     <!-- Indicates that the device supports having more than one internal display on at the same
          time. Only applicable to devices with more than one internal display. If this option is
          set to false, DisplayManager will make additional effort to ensure no more than 1 internal
@@ -1158,14 +1161,25 @@
     <integer name="config_triplePressOnStemPrimaryBehavior">0</integer>
 
     <!-- Control the behavior when the user short presses the stem primary button.
-        Stem primary button is only used on watch form factor. If a device is not
-        a watch, setting this config is no-op.
-           0 - Nothing
-           1 - Go to launch all apps
+         Stem primary button is only used on watch form factor. If a device is not
+         a watch, setting this config is no-op.
+            0 - Nothing
+            1 - Go to launch all apps
     -->
     <integer name="config_shortPressOnStemPrimaryBehavior">0</integer>
 
 
+    <!-- Control the behavior of the search key.
+            0 - Launch default search activity
+            1 - Launch target activity defined by config_searchKeyTargetActivity
+    -->
+    <integer name="config_searchKeyBehavior">0</integer>
+
+    <!-- Component name for the default target activity to be launched when user
+         presses the global search key. [DO NOT TRANSLATE]
+    -->
+    <string name="config_searchKeyTargetActivity" translatable="false"></string>
+
     <!-- Time to wait while a button is pressed before triggering a very long press. -->
     <integer name="config_veryLongPressTimeout">3500</integer>
 
@@ -2761,7 +2775,8 @@
 
     <!-- Whether the device allows users to start in background visible on the default display.
          Should be false for most devices, except passenger-only automotive build (i.e., when
-         Android runs in a separate system in the back seat to manage the passenger displays) -->
+         Android runs in a separate system in the back seat to manage the passenger displays).
+         When set to true, config_multiuserVisibleBackgroundUsers must also be true. -->
     <bool name="config_multiuserVisibleBackgroundUsersOnDefaultDisplay">false</bool>
 
     <!-- Whether to automatically switch to the designated Dock User (the user chosen for
@@ -2787,8 +2802,10 @@
     <integer name="config_userTypePackageWhitelistMode">13</integer> <!-- 1+4+8 -->
 
     <!-- Whether the main user is a permanent admin user. If the main user is a permanent admin user
-     it can't be deleted or downgraded to non-admin status. -->
-    <bool name="config_isMainUserPermanentAdmin">false</bool>
+     it can't be deleted or downgraded to non-admin status.
+     This is generally only relevant on headless system user mode devices; on other devices, the
+     main user is the system user which is always a permanent admin anyway. -->
+    <bool name="config_isMainUserPermanentAdmin">true</bool>
 
     <!-- Whether switch to headless system user is allowed. If allowed,
     headless system user can run in the foreground even though it is not a full user. -->
@@ -3007,10 +3024,18 @@
             >com.android.systemui/com.android.systemui.wifi.WifiDebuggingSecondaryUserActivity</string>
 
     <!-- Package name of the system service that implements the shared connectivity service -->
-    <string translatable="false" name="shared_connectivity_service_package"></string>
+    <string translatable="false" name="config_sharedConnectivityServicePackage"></string>
 
     <!-- Intent action used when binding to the shared connectivity service -->
-    <string translatable="false" name="shared_connectivity_service_intent_action"></string>
+    <string translatable="false" name="config_sharedConnectivityServiceIntentAction"></string>
+
+    <!-- The system and settings UI can support all the features of instant tether. If set to false,
+     instant tether will run in notifications mode -->
+    <bool name="config_hotspotNetworksEnabledForService">false</bool>
+
+    <!-- The system and settings UI can support all the features of known networks. If set to false,
+         known networks will run in notifications mode -->
+    <bool name="config_knownNetworksEnabledForService">false</bool>
 
     <!-- Component name of the activity that shows the usb containment status. -->
     <string name="config_usbContaminantActivity" translatable="false"
@@ -3975,7 +4000,7 @@
     <!-- Whether the device supports non-resizable activity in multi windowing modes.
          -1: The device doesn't support non-resizable in multi windowing modes.
           0: The device supports non-resizable in multi windowing modes only if this is a large
-             screen (smallest width >= {@link config_largeScreenSmallestScreenWidthDp}).
+             screen (smallest width >= {@link WindowManager#LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP}).
           1: The device always supports non-resizable in multi windowing modes.
     -->
     <integer name="config_supportsNonResizableMultiWindow">0</integer>
@@ -3985,9 +4010,9 @@
          -1: The device ignores the activity min width/height when determining if it can be shown in
              multi windowing modes.
           0: If this is a small screen (smallest width <
-             {@link config_largeScreenSmallestScreenWidthDp}), the device compares the activity min
-             width/height with the min multi windowing modes dimensions the device supports to
-             determine if the activity can be shown in multi windowing modes
+             {@link WindowManager#LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP}), the device compares the
+             activity min width/height with the min multi windowing modes dimensions the device
+             supports to determine if the activity can be shown in multi windowing modes
           1: The device always compare the activity min width/height with the min multi windowing
              modes dimensions {@link config_minPercentageMultiWindowSupportWidth} the device
              supports to determine if the activity can be shown in multi windowing modes.
@@ -4010,11 +4035,6 @@
     -->
     <item name="config_minPercentageMultiWindowSupportWidth" format="float" type="dimen">0.5</item>
 
-    <!-- If the display smallest screen width is greater or equal to this value, we will treat it
-         as a large screen device, which will have some multi window features enabled by default.
-    -->
-    <integer name="config_largeScreenSmallestScreenWidthDp">600</integer>
-
     <!-- True if the device is using legacy split. -->
     <bool name="config_useLegacySplit">false</bool>
 
@@ -6338,4 +6358,8 @@
     <bool name="config_batteryStatsResetOnUnplugHighBatteryLevel">true</bool>
     <!-- Whether to reset Battery Stats on unplug if the battery was significantly charged -->
     <bool name="config_batteryStatsResetOnUnplugAfterSignificantCharge">true</bool>
+
+    <!-- Whether we should persist the brightness value in nits for the default display even if
+         the underlying display device changes. -->
+    <bool name="config_persistBrightnessNitsForDefaultDisplay">false</bool>
 </resources>
diff --git a/core/res/res/values/config_telephony.xml b/core/res/res/values/config_telephony.xml
index 24a7d85..c0f2157 100644
--- a/core/res/res/values/config_telephony.xml
+++ b/core/res/res/values/config_telephony.xml
@@ -52,6 +52,16 @@
     <integer name="config_delay_for_ims_dereg_millis">0</integer>
     <java-symbol type="integer" name="config_delay_for_ims_dereg_millis" />
 
+    <!-- Define the bar of considering the availability of a subscription is stable in milliseconds,
+         where 0 means immediate switch, and negative milliseconds indicates the auto data switch
+         feature is disabled.-->
+    <integer name="auto_data_switch_availability_stability_time_threshold_millis">10000</integer>
+    <java-symbol type="integer" name="auto_data_switch_availability_stability_time_threshold_millis" />
+
+    <!-- Define the maximum retry times when a validation for switching failed.-->
+    <integer name="auto_data_switch_validation_max_retry">7</integer>
+    <java-symbol type="integer" name="auto_data_switch_validation_max_retry" />
+
     <!-- Boolean indicating whether the Iwlan data service supports persistence of iwlan ipsec
          tunnels across service restart. If iwlan tunnels are not persisted across restart,
          Framework will clean up dangling data connections when service restarts -->
@@ -110,6 +120,15 @@
     <string name="config_satellite_service_package" translatable="false"></string>
     <java-symbol type="string" name="config_satellite_service_package" />
 
+    <!-- Telephony pointing UI package name to be launched. -->
+    <string name="config_pointing_ui_package" translatable="false"></string>
+    <java-symbol type="string" name="config_pointing_ui_package" />
+
+    <!-- Telephony resends received satellite datagram to listener
+         if ack is not received within this timeout -->
+    <integer name="config_timeout_to_receive_delivered_ack_millis">300000</integer>
+    <java-symbol type="integer" name="config_timeout_to_receive_delivered_ack_millis" />
+
     <!-- Whether enhanced IWLAN handover check is enabled. If enabled, telephony frameworks
          will not perform handover if the target transport is out of service, or VoPS not
          supported. The network will be torn down on the source transport, and will be
@@ -119,7 +138,7 @@
     <java-symbol type="bool" name="config_enhanced_iwlan_handover_check" />
 
     <!-- Whether using the new SubscriptionManagerService or the old SubscriptionController -->
-    <bool name="config_using_subscription_manager_service">false</bool>
+    <bool name="config_using_subscription_manager_service">true</bool>
     <java-symbol type="bool" name="config_using_subscription_manager_service" />
 
     <!-- Whether asynchronously update the subscription database or not. Async mode increases
diff --git a/core/res/res/values/public-staging.xml b/core/res/res/values/public-staging.xml
index ee02100..69d5fef 100644
--- a/core/res/res/values/public-staging.xml
+++ b/core/res/res/values/public-staging.xml
@@ -114,7 +114,7 @@
     <public name="handwritingBoundsOffsetTop" />
     <public name="handwritingBoundsOffsetRight" />
     <public name="handwritingBoundsOffsetBottom" />
-    <public name="accessibilityDataPrivate" />
+    <public name="accessibilityDataSensitive" />
     <public name="enableTextStylingShortcuts" />
     <public name="requiredDisplayCategory"/>
     <public name="removed_maxConcurrentSessionsCount" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 2f33092..d8e69d7 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3790,8 +3790,10 @@
     <!-- Title of the physical keyboard category in the input method selector [CHAR LIMIT=30] -->
     <string name="hardware">Show virtual keyboard</string>
 
-    <!-- Title of the notification to prompt the user to configure physical keyboard settings. -->
-    <string name="select_keyboard_layout_notification_title">Configure physical keyboard</string>
+    <!-- Title of the notification to prompt the user to configure physical keyboard settings. [CHAR LIMIT=NOTIF_TITLE] -->
+    <string name="select_keyboard_layout_notification_title">Configure <xliff:g id="device_name" example="Foobar USB Keyboard">%s</xliff:g></string>
+    <!-- Title of the notification to prompt the user to configure physical keyboard settings when multiple keyboards connected. [CHAR LIMIT=NOTIF_TITLE] -->
+    <string name="select_multiple_keyboards_layout_notification_title">Configure physical keyboards</string>
     <!-- Message of the notification to prompt the user to configure physical keyboard settings
          where the user can associate language with physical keyboard layout. -->
     <string name="select_keyboard_layout_notification_message">Tap to select language and layout</string>
@@ -4749,8 +4751,7 @@
     <string name="accessibility_shortcut_disabling_service">Held volume keys. <xliff:g id="service_name" example="TalkBack">%1$s</xliff:g> turned off.</string>
 
     <!-- Text spoken when accessibility shortcut warning dialog is shown. [CHAR LIMIT=none] -->
-    <string name="accessibility_shortcut_spoken_feedback">Press and hold both volume keys for three seconds to use
-        <xliff:g id="service_name" example="TalkBack">%1$s</xliff:g></string>
+    <string name="accessibility_shortcut_spoken_feedback">Release the volume keys. To turn on <xliff:g id="service_name" example="TalkBack">%1$s</xliff:g>, press and hold both volume keys again for 3 seconds.</string>
 
     <!-- Text appearing in a prompt at the top of UI allowing the user to select a target service or feature to be assigned to the Accessibility button in the navigation bar. [CHAR LIMIT=none]-->
     <string name="accessibility_button_prompt_text">Choose a feature to use when you tap the accessibility button:</string>
@@ -6268,4 +6269,19 @@
     <string name="concurrent_display_notification_thermal_content">Dual Screen is unavailable because your phone is getting too warm</string>
     <!-- Text of device state notification turn off button. [CHAR LIMIT=NONE] -->
     <string name="device_state_notification_turn_off_button">Turn off</string>
+
+    <!-- Notification title when a keyboard has been configured [CHAR LIMIT=NOTIF_TITLE] -->
+    <string name="keyboard_layout_notification_selected_title"><xliff:g id="device_name" example="Foobar USB Keyboard">%s</xliff:g> configured</string>
+    <!-- Notification message shown when one layout was configured for a physical keyboard [CHAR LIMIT=NOTIF_BODY] -->
+    <string name="keyboard_layout_notification_one_selected_message">Keyboard layout set to <xliff:g id="layout_1" example="English (US)">%s</xliff:g>. Tap to change.</string>
+    <!-- Notification message shown when two layout were configured for a physical keyboard [CHAR LIMIT=NOTIF_BODY] -->
+    <string name="keyboard_layout_notification_two_selected_message">Keyboard layout set to <xliff:g id="layout_1" example="English (US)">%1$s</xliff:g>, <xliff:g id="layout_2" example="German">%2$s</xliff:g>. Tap to change.</string>
+    <!-- Notification message shown when three layout were configured for a physical keyboard [CHAR LIMIT=NOTIF_BODY] -->
+    <string name="keyboard_layout_notification_three_selected_message">Keyboard layout set to <xliff:g id="layout_1" example="English (US)">%1$s</xliff:g>, <xliff:g id="layout_2" example="German">%2$s</xliff:g>, <xliff:g id="layout_3" example="French">%3$s</xliff:g>. Tap to change.</string>
+    <!-- Notification message shown when more than three layout were configured for a physical keyboard [CHAR LIMIT=NOTIF_BODY] -->
+    <string name="keyboard_layout_notification_more_than_three_selected_message">Keyboard layout set to <xliff:g id="layout_1" example="English (US)">%1$s</xliff:g>, <xliff:g id="layout_2" example="English (US)">%2$s</xliff:g>, <xliff:g id="layout_3" example="French">%3$s</xliff:g>\u2026 Tap to change.</string>
+    <!-- Notification title when multiple keyboards with selected layouts have been connected the first time simultaneously [CHAR LIMIT=NOTIF_TITLE] -->
+    <string name="keyboard_layout_notification_multiple_selected_title">Physical keyboards configured</string>
+    <!-- Notification message when multiple keyboards with selected layouts have been connected the first time simultaneously [CHAR LIMIT=NOTIF_BODY] -->
+    <string name="keyboard_layout_notification_multiple_selected_message">Tap to view keyboards</string>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 8d56e7a..c10612e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -405,7 +405,6 @@
   <java-symbol type="integer" name="config_respectsActivityMinWidthHeightMultiWindow" />
   <java-symbol type="dimen" name="config_minPercentageMultiWindowSupportHeight" />
   <java-symbol type="dimen" name="config_minPercentageMultiWindowSupportWidth" />
-  <java-symbol type="integer" name="config_largeScreenSmallestScreenWidthDp" />
   <java-symbol type="bool" name="config_useLegacySplit" />
   <java-symbol type="bool" name="config_noHomeScreen" />
   <java-symbol type="bool" name="config_supportsSystemDecorsOnSecondaryDisplays" />
@@ -464,6 +463,8 @@
   <java-symbol type="integer" name="config_doublePressOnStemPrimaryBehavior" />
   <java-symbol type="integer" name="config_triplePressOnStemPrimaryBehavior" />
   <java-symbol type="string" name="config_doublePressOnPowerTargetActivity" />
+  <java-symbol type="integer" name="config_searchKeyBehavior" />
+  <java-symbol type="string" name="config_searchKeyTargetActivity" />
   <java-symbol type="integer" name="config_windowOutsetBottom" />
   <java-symbol type="integer" name="db_connection_pool_size" />
   <java-symbol type="integer" name="db_journal_size_limit" />
@@ -1938,6 +1939,7 @@
   <java-symbol type="bool" name="config_allowTheaterModeWakeFromDock" />
   <java-symbol type="bool" name="config_allowTheaterModeWakeFromWindowLayout" />
   <java-symbol type="bool" name="config_keepDreamingWhenUndocking" />
+  <java-symbol type="integer" name="config_keyguardDrawnTimeout" />
   <java-symbol type="bool" name="config_goToSleepOnButtonPressTheaterMode" />
   <java-symbol type="bool" name="config_supportLongPressPowerWhenNonInteractive" />
   <java-symbol type="bool" name="config_wimaxEnabled" />
@@ -2137,6 +2139,7 @@
   <java-symbol type="string" name="report" />
   <java-symbol type="string" name="select_input_method" />
   <java-symbol type="string" name="select_keyboard_layout_notification_title" />
+  <java-symbol type="string" name="select_multiple_keyboards_layout_notification_title" />
   <java-symbol type="string" name="select_keyboard_layout_notification_message" />
   <java-symbol type="string" name="smv_application" />
   <java-symbol type="string" name="smv_process" />
@@ -2228,6 +2231,7 @@
   <java-symbol type="bool" name="config_preventImeStartupUnlessTextEditor" />
   <java-symbol type="array" name="config_nonPreemptibleInputMethods" />
   <java-symbol type="bool" name="config_enhancedConfirmationModeEnabled" />
+  <java-symbol type="bool" name="config_persistBrightnessNitsForDefaultDisplay" />
 
   <java-symbol type="layout" name="resolver_list" />
   <java-symbol type="id" name="resolver_list" />
@@ -4957,16 +4961,27 @@
   <java-symbol type="bool" name="config_stopSystemPackagesByDefault"/>
   <java-symbol type="string" name="config_wearServiceComponent" />
 
-  <java-symbol type="string" name="shared_connectivity_service_package" />
-  <java-symbol type="string" name="shared_connectivity_service_intent_action" />
+  <java-symbol type="string" name="config_sharedConnectivityServicePackage" />
+  <java-symbol type="string" name="config_sharedConnectivityServiceIntentAction" />
+  <java-symbol type="bool" name="config_hotspotNetworksEnabledForService"/>
+  <java-symbol type="bool" name="config_knownNetworksEnabledForService"/>
 
   <!-- Whether to show weather on the lockscreen by default. -->
   <java-symbol type="bool" name="config_lockscreenWeatherEnabledByDefault" />
 
+  <!-- For keyboard notification -->
+  <java-symbol type="string" name="keyboard_layout_notification_selected_title"/>
+  <java-symbol type="string" name="keyboard_layout_notification_one_selected_message"/>
+  <java-symbol type="string" name="keyboard_layout_notification_two_selected_message"/>
+  <java-symbol type="string" name="keyboard_layout_notification_three_selected_message"/>
+  <java-symbol type="string" name="keyboard_layout_notification_more_than_three_selected_message"/>
+  <java-symbol type="string" name="keyboard_layout_notification_multiple_selected_title"/>
+  <java-symbol type="string" name="keyboard_layout_notification_multiple_selected_message"/>
+
   <java-symbol type="bool" name="config_batteryStatsResetOnUnplugHighBatteryLevel" />
   <java-symbol type="bool" name="config_batteryStatsResetOnUnplugAfterSignificantCharge" />
 
-  
+
   <java-symbol name="materialColorOnSecondaryFixedVariant" type="attr"/>
   <java-symbol name="materialColorOnTertiaryFixedVariant" type="attr"/>
   <java-symbol name="materialColorSurfaceContainerLowest" type="attr"/>
diff --git a/core/res/res/xml/irq_device_map.xml b/core/res/res/xml/irq_device_map.xml
index 86a44d6..4fae8fb 100644
--- a/core/res/res/xml/irq_device_map.xml
+++ b/core/res/res/xml/irq_device_map.xml
@@ -17,14 +17,15 @@
 */
 -->
 <irq-device-map>
-  <!--  This file maps devices (chips) that can send IRQs to the CPU (and bring it out of sleep) to
-        logical subsystems in userspace code. Since each Android device has its own uniquely
-        designed chipset, this mapping is expected to be empty by default and should be overridden
-        by device specific configs.
+  <!--  This file maps devices (chips) that can send interrupts to the main processor (and bring it
+        out of sleep) to logical subsystems in userspace code. Since each Android device has its own
+        uniquely designed chipset, this mapping is expected to be empty by default and should be
+        overridden by device-specific configs.
         This mapping helps the system to meaningfully attribute CPU wakeups to logical work that
         happened on the device. The devices are referred to by their names as defined in the kernel.
-        Currently defined subsystems are:
+        Currently, defined subsystems are:
         - Alarm: Use this to denote wakeup alarms requested by apps via the AlarmManager API.
+        - Wifi: Use this to denote network traffic that uses the wifi transport.
 
         The overlay should use tags <device> and <subsystem> to describe this mapping in the
         following way:
diff --git a/core/tests/coretests/src/android/app/backup/BackupRestoreEventLoggerTest.java b/core/tests/coretests/src/android/app/backup/BackupRestoreEventLoggerTest.java
index b176307..6e1c580 100644
--- a/core/tests/coretests/src/android/app/backup/BackupRestoreEventLoggerTest.java
+++ b/core/tests/coretests/src/android/app/backup/BackupRestoreEventLoggerTest.java
@@ -23,7 +23,6 @@
 
 import static junit.framework.Assert.fail;
 
-import android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType;
 import android.app.backup.BackupRestoreEventLogger.DataTypeResult;
 import android.os.Parcel;
 import android.platform.test.annotations.Presubmit;
@@ -78,7 +77,7 @@
 
         mLogger.logItemsBackedUp(DATA_TYPE_1, /* count */ 5);
         mLogger.logItemsBackupFailed(DATA_TYPE_1, /* count */ 5, ERROR_1);
-        mLogger.logBackupMetaData(DATA_TYPE_1, /* metadata */ "metadata");
+        mLogger.logBackupMetadata(DATA_TYPE_1, /* metadata */ "metadata");
 
         assertThat(getResultForDataTypeIfPresent(mLogger, DATA_TYPE_1)).isEqualTo(Optional.empty());
     }
@@ -91,7 +90,7 @@
             String dataType = DATA_TYPE_1 + i;
             mLogger.logItemsBackedUp(dataType, /* count */ 5);
             mLogger.logItemsBackupFailed(dataType, /* count */ 5, /* error */ null);
-            mLogger.logBackupMetaData(dataType, METADATA_1);
+            mLogger.logBackupMetadata(dataType, METADATA_1);
 
             assertThat(getResultForDataTypeIfPresent(mLogger, dataType)).isNotEqualTo(
                     Optional.empty());
@@ -127,8 +126,8 @@
     public void testLogBackupMetadata_repeatedCalls_recordsLatestMetadataHash() {
         mLogger = new BackupRestoreEventLogger(BACKUP);
 
-        mLogger.logBackupMetaData(DATA_TYPE_1, METADATA_1);
-        mLogger.logBackupMetaData(DATA_TYPE_1, METADATA_2);
+        mLogger.logBackupMetadata(DATA_TYPE_1, METADATA_1);
+        mLogger.logBackupMetadata(DATA_TYPE_1, METADATA_2);
 
         byte[] recordedHash = getResultForDataType(mLogger, DATA_TYPE_1).getMetadataHash();
         byte[] expectedHash = getMetaDataHash(METADATA_2);
@@ -315,7 +314,7 @@
     }
 
     private static DataTypeResult getResultForDataType(
-            BackupRestoreEventLogger logger, @BackupRestoreDataType String dataType) {
+            BackupRestoreEventLogger logger, String dataType) {
         Optional<DataTypeResult> result = getResultForDataTypeIfPresent(logger, dataType);
         if (result.isEmpty()) {
             fail("Failed to find result for data type: " + dataType);
@@ -324,7 +323,7 @@
     }
 
     private static Optional<DataTypeResult> getResultForDataTypeIfPresent(
-            BackupRestoreEventLogger logger, @BackupRestoreDataType String dataType) {
+            BackupRestoreEventLogger logger, String dataType) {
         List<DataTypeResult> resultList = logger.getLoggingResults();
         return resultList.stream()
                 .filter(dataTypeResult -> dataTypeResult.getDataType().equals(dataType))
diff --git a/core/tests/coretests/src/android/companion/virtual/sensor/VirtualSensorConfigTest.java b/core/tests/coretests/src/android/companion/virtual/sensor/VirtualSensorConfigTest.java
deleted file mode 100644
index f97099d..0000000
--- a/core/tests/coretests/src/android/companion/virtual/sensor/VirtualSensorConfigTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.companion.virtual.sensor;
-
-import static android.hardware.Sensor.TYPE_ACCELEROMETER;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.os.Parcel;
-import android.platform.test.annotations.Presubmit;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@Presubmit
-@RunWith(AndroidJUnit4.class)
-public class VirtualSensorConfigTest {
-
-    private static final String SENSOR_NAME = "VirtualSensorName";
-    private static final String SENSOR_VENDOR = "VirtualSensorVendor";
-
-    @Test
-    public void parcelAndUnparcel_matches() {
-        final VirtualSensorConfig originalConfig =
-                new VirtualSensorConfig.Builder(TYPE_ACCELEROMETER, SENSOR_NAME)
-                        .setVendor(SENSOR_VENDOR)
-                        .build();
-        final Parcel parcel = Parcel.obtain();
-        originalConfig.writeToParcel(parcel, /* flags= */ 0);
-        parcel.setDataPosition(0);
-        final VirtualSensorConfig recreatedConfig =
-                VirtualSensorConfig.CREATOR.createFromParcel(parcel);
-        assertThat(recreatedConfig.getType()).isEqualTo(originalConfig.getType());
-        assertThat(recreatedConfig.getName()).isEqualTo(originalConfig.getName());
-        assertThat(recreatedConfig.getVendor()).isEqualTo(originalConfig.getVendor());
-    }
-
-    @Test
-    public void sensorConfig_onlyRequiredFields() {
-        final VirtualSensorConfig config =
-                new VirtualSensorConfig.Builder(TYPE_ACCELEROMETER, SENSOR_NAME).build();
-        assertThat(config.getVendor()).isNull();
-    }
-}
diff --git a/core/tests/coretests/src/android/companion/virtual/sensor/VirtualSensorEventTest.java b/core/tests/coretests/src/android/companion/virtual/sensor/VirtualSensorEventTest.java
deleted file mode 100644
index c260ef9..0000000
--- a/core/tests/coretests/src/android/companion/virtual/sensor/VirtualSensorEventTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.companion.virtual.sensor;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.testng.Assert.assertThrows;
-
-import android.os.Parcel;
-import android.os.SystemClock;
-import android.platform.test.annotations.Presubmit;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@Presubmit
-@RunWith(AndroidJUnit4.class)
-public class VirtualSensorEventTest {
-
-    private static final long TIMESTAMP_NANOS = SystemClock.elapsedRealtimeNanos();
-    private static final float[] SENSOR_VALUES = new float[] {1.2f, 3.4f, 5.6f};
-
-    @Test
-    public void parcelAndUnparcel_matches() {
-        final VirtualSensorEvent originalEvent = new VirtualSensorEvent.Builder(SENSOR_VALUES)
-                .setTimestampNanos(TIMESTAMP_NANOS)
-                .build();
-        final Parcel parcel = Parcel.obtain();
-        originalEvent.writeToParcel(parcel, /* flags= */ 0);
-        parcel.setDataPosition(0);
-        final VirtualSensorEvent recreatedEvent =
-                VirtualSensorEvent.CREATOR.createFromParcel(parcel);
-        assertThat(recreatedEvent.getValues()).isEqualTo(originalEvent.getValues());
-        assertThat(recreatedEvent.getTimestampNanos()).isEqualTo(originalEvent.getTimestampNanos());
-    }
-
-    @Test
-    public void sensorEvent_nullValues() {
-        assertThrows(
-                IllegalArgumentException.class, () -> new VirtualSensorEvent.Builder(null).build());
-    }
-
-    @Test
-    public void sensorEvent_noValues() {
-        assertThrows(
-                IllegalArgumentException.class,
-                () -> new VirtualSensorEvent.Builder(new float[0]).build());
-    }
-
-    @Test
-    public void sensorEvent_noTimestamp_usesCurrentTime() {
-        final VirtualSensorEvent event = new VirtualSensorEvent.Builder(SENSOR_VALUES).build();
-        assertThat(event.getValues()).isEqualTo(SENSOR_VALUES);
-        assertThat(TIMESTAMP_NANOS).isLessThan(event.getTimestampNanos());
-        assertThat(event.getTimestampNanos()).isLessThan(SystemClock.elapsedRealtimeNanos());
-    }
-
-    @Test
-    public void sensorEvent_created() {
-        final VirtualSensorEvent event = new VirtualSensorEvent.Builder(SENSOR_VALUES)
-                .setTimestampNanos(TIMESTAMP_NANOS)
-                .build();
-        assertThat(event.getTimestampNanos()).isEqualTo(TIMESTAMP_NANOS);
-        assertThat(event.getValues()).isEqualTo(SENSOR_VALUES);
-    }
-}
diff --git a/core/tests/coretests/src/android/content/AbstractCrossUserContentResolverTest.java b/core/tests/coretests/src/android/content/AbstractCrossUserContentResolverTest.java
index 90bb627..92b1c04 100644
--- a/core/tests/coretests/src/android/content/AbstractCrossUserContentResolverTest.java
+++ b/core/tests/coretests/src/android/content/AbstractCrossUserContentResolverTest.java
@@ -18,6 +18,7 @@
 
 import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeTrue;
+import org.junit.Ignore;
 
 import android.app.ActivityManager;
 import android.app.activity.LocalProvider;
@@ -123,6 +124,7 @@
      * Register an observer for an URI in another user and verify that it receives
      * onChange callback when data at the URI changes.
      */
+    @Ignore("b/272733874")
     @Test
     public void testRegisterContentObserver() throws Exception {
         Context crossUserContext = null;
@@ -152,6 +154,7 @@
      * Register an observer for an URI in the current user and verify that another user can
      * notify changes for this URI.
      */
+    @Ignore("b/272733874")
     @Test
     public void testNotifyChange() throws Exception {
         final CountDownLatch notifyLatch = new CountDownLatch(1);
diff --git a/core/tests/coretests/src/android/content/pm/TEST_MAPPING b/core/tests/coretests/src/android/content/pm/TEST_MAPPING
index 15e04d1..978d80c 100644
--- a/core/tests/coretests/src/android/content/pm/TEST_MAPPING
+++ b/core/tests/coretests/src/android/content/pm/TEST_MAPPING
@@ -1,5 +1,5 @@
 {
-  "presubmit-large": [
+  "presubmit": [
     {
       "name": "FrameworksCoreTests",
       "options": [
diff --git a/core/tests/coretests/src/android/content/pm/UserPackageTest.java b/core/tests/coretests/src/android/content/pm/UserPackageTest.java
new file mode 100644
index 0000000..5114e2cf
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/UserPackageTest.java
@@ -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 android.content.pm;
+
+import android.platform.test.annotations.Presubmit;
+
+import junit.framework.TestCase;
+
+@Presubmit
+public class UserPackageTest extends TestCase {
+    public void testCacheLimit() {
+        UserPackage.setValidUserIds(new int[]{0});
+        for (int i = 0; i < UserPackage.MAX_NUM_CACHED_ENTRIES_PER_USER; ++i) {
+            UserPackage.of(0, "app" + i);
+            assertEquals(i + 1, UserPackage.numEntriesForUser(0));
+        }
+
+        for (int i = 0; i < UserPackage.MAX_NUM_CACHED_ENTRIES_PER_USER; ++i) {
+            UserPackage.of(0, "appOverLimit" + i);
+            final int numCached = UserPackage.numEntriesForUser(0);
+            assertTrue(numCached >= 1);
+            assertTrue(numCached <= UserPackage.MAX_NUM_CACHED_ENTRIES_PER_USER);
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt b/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
index ef106bc..a0d8dcf 100644
--- a/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
+++ b/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
@@ -28,6 +28,7 @@
 import kotlin.math.floor
 import org.junit.Test
 import org.junit.runner.RunWith
+import kotlin.random.Random.Default.nextFloat
 
 @Presubmit
 @RunWith(AndroidJUnit4::class)
@@ -43,14 +44,56 @@
         assertThat(table.convertSpToDp(0F)).isWithin(CONVERSION_TOLERANCE).of(0f)
     }
 
-    @SmallTest
-    fun missingLookupTableReturnsNull() {
-        assertThat(FontScaleConverterFactory.forScale(3F)).isNull()
+    @LargeTest
+    @Test
+    fun missingLookupTablePastEnd_returnsLinear() {
+        val table = FontScaleConverterFactory.forScale(3F)!!
+        generateSequenceOfFractions(-10000f..10000f, step = 0.01f)
+            .map {
+                assertThat(table.convertSpToDp(it)).isWithin(CONVERSION_TOLERANCE).of(it * 3f)
+            }
+        assertThat(table.convertSpToDp(1F)).isWithin(CONVERSION_TOLERANCE).of(3f)
+        assertThat(table.convertSpToDp(8F)).isWithin(CONVERSION_TOLERANCE).of(24f)
+        assertThat(table.convertSpToDp(10F)).isWithin(CONVERSION_TOLERANCE).of(30f)
+        assertThat(table.convertSpToDp(5F)).isWithin(CONVERSION_TOLERANCE).of(15f)
+        assertThat(table.convertSpToDp(0F)).isWithin(CONVERSION_TOLERANCE).of(0f)
+        assertThat(table.convertSpToDp(50F)).isWithin(CONVERSION_TOLERANCE).of(150f)
+        assertThat(table.convertSpToDp(100F)).isWithin(CONVERSION_TOLERANCE).of(300f)
     }
 
     @SmallTest
-    fun missingLookupTable105ReturnsNull() {
-        assertThat(FontScaleConverterFactory.forScale(1.05F)).isNull()
+    fun missingLookupTable110_returnsInterpolated() {
+        val table = FontScaleConverterFactory.forScale(1.1F)!!
+
+        assertThat(table.convertSpToDp(1F)).isWithin(CONVERSION_TOLERANCE).of(1.1f)
+        assertThat(table.convertSpToDp(8F)).isWithin(CONVERSION_TOLERANCE).of(8f * 1.1f)
+        assertThat(table.convertSpToDp(10F)).isWithin(CONVERSION_TOLERANCE).of(11f)
+        assertThat(table.convertSpToDp(5F)).isWithin(CONVERSION_TOLERANCE).of(5f * 1.1f)
+        assertThat(table.convertSpToDp(0F)).isWithin(CONVERSION_TOLERANCE).of(0f)
+        assertThat(table.convertSpToDp(50F)).isLessThan(50f * 1.1f)
+        assertThat(table.convertSpToDp(100F)).isLessThan(100f * 1.1f)
+    }
+
+    @Test
+    fun missingLookupTable199_returnsInterpolated() {
+        val table = FontScaleConverterFactory.forScale(1.9999F)!!
+        assertThat(table.convertSpToDp(1F)).isWithin(CONVERSION_TOLERANCE).of(2f)
+        assertThat(table.convertSpToDp(8F)).isWithin(CONVERSION_TOLERANCE).of(16f)
+        assertThat(table.convertSpToDp(10F)).isWithin(CONVERSION_TOLERANCE).of(20f)
+        assertThat(table.convertSpToDp(5F)).isWithin(CONVERSION_TOLERANCE).of(10f)
+        assertThat(table.convertSpToDp(0F)).isWithin(CONVERSION_TOLERANCE).of(0f)
+    }
+
+    @Test
+    fun missingLookupTable160_returnsInterpolated() {
+        val table = FontScaleConverterFactory.forScale(1.6F)!!
+        assertThat(table.convertSpToDp(1F)).isWithin(CONVERSION_TOLERANCE).of(1f * 1.6F)
+        assertThat(table.convertSpToDp(8F)).isWithin(CONVERSION_TOLERANCE).of(8f * 1.6F)
+        assertThat(table.convertSpToDp(10F)).isWithin(CONVERSION_TOLERANCE).of(10f * 1.6F)
+        assertThat(table.convertSpToDp(20F)).isLessThan(20f * 1.6F)
+        assertThat(table.convertSpToDp(100F)).isLessThan(100f * 1.6F)
+        assertThat(table.convertSpToDp(5F)).isWithin(CONVERSION_TOLERANCE).of(5f * 1.6F)
+        assertThat(table.convertSpToDp(0F)).isWithin(CONVERSION_TOLERANCE).of(0f)
     }
 
     @SmallTest
@@ -82,17 +125,23 @@
     @LargeTest
     @Test
     fun allFeasibleScalesAndConversionsDoNotCrash() {
-        generateSequenceOfFractions(-10f..10f, step = 0.01f)
+        generateSequenceOfFractions(-10f..10f, step = 0.1f)
+            .fuzzFractions()
             .mapNotNull{ FontScaleConverterFactory.forScale(it) }
             .flatMap{ table ->
-                generateSequenceOfFractions(-2000f..2000f, step = 0.01f)
+                generateSequenceOfFractions(-2000f..2000f, step = 0.1f)
+                    .fuzzFractions()
                     .map{ Pair(table, it) }
             }
             .forEach { (table, sp) ->
                 try {
-                    assertWithMessage("convertSpToDp(%s) on table: %s", sp, table)
-                        .that(table.convertSpToDp(sp))
-                        .isFinite()
+                    // Truth is slow because it creates a bunch of
+                    // objects. Don't use it unless we need to.
+                    if (!table.convertSpToDp(sp).isFinite()) {
+                        assertWithMessage("convertSpToDp(%s) on table: %s", sp, table)
+                            .that(table.convertSpToDp(sp))
+                            .isFinite()
+                    }
                 } catch (e: Exception) {
                     throw AssertionError("Exception during convertSpToDp($sp) on table: $table", e)
                 }
@@ -126,6 +175,30 @@
         assertThat(fractions).doesNotContain(-.35f)
     }
 
+    @Test
+    fun testFuzzFractions() {
+        val numFuzzedFractions = 6
+        val fractions = generateSequenceOfFractions(-1000f..1000f, step = 0.1f)
+            .fuzzFractions()
+            .toList()
+        fractions.forEach {
+            assertThat(it).isAtLeast(-1000f)
+            assertThat(it).isLessThan(1001f)
+        }
+
+        val numGeneratedFractions = 1000 * 2 * 10 + 1 // Don't forget the 0 in the middle!
+        assertThat(fractions).hasSize(numGeneratedFractions * numFuzzedFractions)
+
+        assertThat(fractions).contains(100f)
+        assertThat(fractions).contains(500.1f)
+        assertThat(fractions).contains(500.2f)
+        assertThat(fractions).contains(0.2f)
+        assertThat(fractions).contains(0f)
+        assertThat(fractions).contains(-10f)
+        assertThat(fractions).contains(-10f)
+        assertThat(fractions).contains(-10.3f)
+    }
+
     companion object {
         private const val CONVERSION_TOLERANCE = 0.05f
     }
@@ -142,3 +215,9 @@
         .takeWhile { it <= endInclusive }
         .map{ it.toFloat() / multiplier }
 }
+
+private fun Sequence<Float>.fuzzFractions(): Sequence<Float> {
+    return flatMap { i ->
+        listOf(i, i + 0.01f, i + 0.054f, i + 0.099f, i + nextFloat(), i + nextFloat())
+    }
+}
diff --git a/core/tests/coretests/src/android/credentials/CredentialManagerTest.java b/core/tests/coretests/src/android/credentials/CredentialManagerTest.java
index 25664fb..e31d5ae 100644
--- a/core/tests/coretests/src/android/credentials/CredentialManagerTest.java
+++ b/core/tests/coretests/src/android/credentials/CredentialManagerTest.java
@@ -30,6 +30,7 @@
 import android.app.Activity;
 import android.app.slice.Slice;
 import android.content.Context;
+import android.content.pm.ServiceInfo;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.CancellationSignal;
@@ -47,6 +48,7 @@
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
 
+import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 import java.util.concurrent.Executor;
@@ -59,6 +61,17 @@
     @Mock
     private Activity mMockActivity;
 
+    private static final int TEST_USER_ID = 1;
+    private static final CredentialProviderInfo TEST_CREDENTIAL_PROVIDER_INFO =
+                new CredentialProviderInfo.Builder(new ServiceInfo())
+                        .setSystemProvider(true)
+                        .setOverrideLabel("test")
+                        .addCapabilities(Arrays.asList("passkey"))
+                        .setEnabled(true)
+                        .build();
+    private static final List<CredentialProviderInfo> TEST_CREDENTIAL_PROVIDER_INFO_LIST =
+                Arrays.asList(TEST_CREDENTIAL_PROVIDER_INFO);
+
     private GetCredentialRequest mGetRequest;
     private CreateCredentialRequest mCreateRequest;
 
@@ -101,8 +114,9 @@
         mGetRequest = new GetCredentialRequest.Builder(Bundle.EMPTY).addCredentialOption(
                 new CredentialOption(Credential.TYPE_PASSWORD_CREDENTIAL, Bundle.EMPTY,
                         Bundle.EMPTY, false)).build();
-        mCreateRequest = new CreateCredentialRequest.Builder(Bundle.EMPTY, Bundle.EMPTY)
-                .setType(Credential.TYPE_PASSWORD_CREDENTIAL)
+        mCreateRequest = new CreateCredentialRequest.Builder(
+                Credential.TYPE_PASSWORD_CREDENTIAL,
+                Bundle.EMPTY, Bundle.EMPTY)
                 .setIsSystemProviderRequired(false)
                 .setAlwaysSendAppInfoToProvider(false)
                 .build();
@@ -437,95 +451,53 @@
     }
 
     @Test
-    public void testListEnabledProviders_nullExecutor() {
-        assertThrows(NullPointerException.class,
-                () -> mCredentialManager.listEnabledProviders(null, null, result -> {
-                }));
-
+    public void testGetCredentialProviderServices_allProviders() throws RemoteException {
+        verifyGetCredentialProviderServices(CredentialManager.PROVIDER_FILTER_ALL_PROVIDERS);
     }
 
     @Test
-    public void testListEnabledProviders_nullCallback() {
-        assertThrows(NullPointerException.class,
-                () -> mCredentialManager.listEnabledProviders(null, mExecutor, null));
-
+    public void testGetCredentialProviderServices_userProviders() throws RemoteException {
+        verifyGetCredentialProviderServices(CredentialManager.PROVIDER_FILTER_USER_PROVIDERS_ONLY);
     }
 
     @Test
-    public void testListEnabledProviders_alreadyCancelled() throws RemoteException {
-        final CancellationSignal cancellation = new CancellationSignal();
-        cancellation.cancel();
-
-        mCredentialManager.listEnabledProviders(cancellation, mExecutor, result -> {
-        });
-
-        verify(mMockCredentialManagerService, never()).listEnabledProviders(any());
+    public void testGetCredentialProviderServices_systemProviders() throws RemoteException {
+        verifyGetCredentialProviderServices(CredentialManager.PROVIDER_FILTER_SYSTEM_PROVIDERS_ONLY);
     }
 
     @Test
-    public void testListEnabledProviders_cancel() throws RemoteException {
-        final ICancellationSignal serviceSignal = mock(ICancellationSignal.class);
-        final CancellationSignal cancellation = new CancellationSignal();
-
-        OutcomeReceiver<ListEnabledProvidersResponse, ListEnabledProvidersException> callback =
-                mock(OutcomeReceiver.class);
-
-        when(mMockCredentialManagerService.listEnabledProviders(any())).thenReturn(serviceSignal);
-
-        mCredentialManager.listEnabledProviders(cancellation, mExecutor, callback);
-
-        verify(mMockCredentialManagerService).listEnabledProviders(any());
-
-        cancellation.cancel();
-        verify(serviceSignal).cancel();
+    public void testGetCredentialProviderServicesForTesting_allProviders() throws RemoteException {
+        verifyGetCredentialProviderServicesForTesting(CredentialManager.PROVIDER_FILTER_ALL_PROVIDERS);
     }
 
     @Test
-    public void testListEnabledProviders_failed() throws RemoteException {
-        ArgumentCaptor<IListEnabledProvidersCallback> callbackCaptor = ArgumentCaptor.forClass(
-                IListEnabledProvidersCallback.class);
-        ArgumentCaptor<ListEnabledProvidersException> errorCaptor = ArgumentCaptor.forClass(
-                ListEnabledProvidersException.class);
-
-        OutcomeReceiver<ListEnabledProvidersResponse, ListEnabledProvidersException> callback =
-                mock(OutcomeReceiver.class);
-
-        when(mMockCredentialManagerService.listEnabledProviders(
-                callbackCaptor.capture())).thenReturn(mock(ICancellationSignal.class));
-        mCredentialManager.listEnabledProviders(null, mExecutor, callback);
-        verify(mMockCredentialManagerService).listEnabledProviders(any());
-
-        final String errorType = "type";
-        callbackCaptor.getValue().onError("type", "unknown error");
-        verify(callback).onError(errorCaptor.capture());
-
-        assertThat(errorCaptor.getValue().getType()).isEqualTo(errorType);
+    public void testGetCredentialProviderServicesForTesting_userProviders() throws RemoteException {
+        verifyGetCredentialProviderServicesForTesting(CredentialManager.PROVIDER_FILTER_USER_PROVIDERS_ONLY);
     }
 
     @Test
-    public void testListEnabledProviders_success() throws RemoteException {
-        ListEnabledProvidersResponse response = ListEnabledProvidersResponse.create(
-                List.of("foo", "bar", "baz"));
+    public void testGetCredentialProviderServicesForTesting_systemProviders() throws RemoteException {
+        verifyGetCredentialProviderServicesForTesting(CredentialManager.PROVIDER_FILTER_SYSTEM_PROVIDERS_ONLY);
+    }
 
-        OutcomeReceiver<ListEnabledProvidersResponse, ListEnabledProvidersException> callback =
-                mock(OutcomeReceiver.class);
+    private void verifyGetCredentialProviderServices(int testFilter) throws RemoteException {
+        when(mMockCredentialManagerService.getCredentialProviderServices(
+                TEST_USER_ID, testFilter)).thenReturn(TEST_CREDENTIAL_PROVIDER_INFO_LIST);
 
-        ArgumentCaptor<IListEnabledProvidersCallback> callbackCaptor = ArgumentCaptor.forClass(
-                IListEnabledProvidersCallback.class);
-        ArgumentCaptor<ListEnabledProvidersResponse> responseCaptor = ArgumentCaptor.forClass(
-                ListEnabledProvidersResponse.class);
+        List<CredentialProviderInfo> output =
+                mCredentialManager.getCredentialProviderServices(TEST_USER_ID, testFilter);
 
-        when(mMockCredentialManagerService.listEnabledProviders(
-                callbackCaptor.capture())).thenReturn(mock(ICancellationSignal.class));
-        mCredentialManager.listEnabledProviders(null, mExecutor, callback);
+        assertThat(output).containsExactlyElementsIn(TEST_CREDENTIAL_PROVIDER_INFO_LIST);
+    }
 
-        verify(mMockCredentialManagerService).listEnabledProviders(any());
+    private void verifyGetCredentialProviderServicesForTesting(int testFilter) throws RemoteException {
+        when(mMockCredentialManagerService.getCredentialProviderServicesForTesting(
+                testFilter)).thenReturn(TEST_CREDENTIAL_PROVIDER_INFO_LIST);
 
-        callbackCaptor.getValue().onResponse(response);
+        List<CredentialProviderInfo> output =
+                mCredentialManager.getCredentialProviderServicesForTesting(testFilter);
 
-        verify(callback).onResult(responseCaptor.capture());
-        assertThat(responseCaptor.getValue().getProviderComponentNames()).containsExactlyElementsIn(
-                response.getProviderComponentNames());
+        assertThat(output).containsExactlyElementsIn(TEST_CREDENTIAL_PROVIDER_INFO_LIST);
     }
 
     @Test
diff --git a/core/tests/coretests/src/android/provider/NameValueCacheTest.java b/core/tests/coretests/src/android/provider/NameValueCacheTest.java
index 2e31bb5..54a3817 100644
--- a/core/tests/coretests/src/android/provider/NameValueCacheTest.java
+++ b/core/tests/coretests/src/android/provider/NameValueCacheTest.java
@@ -28,20 +28,23 @@
 import android.content.ContentProvider;
 import android.content.IContentProvider;
 import android.os.Bundle;
+import android.os.Parcel;
 import android.platform.test.annotations.Presubmit;
 import android.test.mock.MockContentResolver;
 import android.util.MemoryIntArray;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.io.IOException;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
@@ -59,42 +62,63 @@
     private static final String NAMESPACE = "namespace";
     private static final String NAMESPACE2 = "namespace2";
 
+    private static final String SETTING = "test_setting";
+    private static final String SETTING2 = "test_setting2";
+
     @Mock
     private IContentProvider mMockIContentProvider;
     @Mock
     private ContentProvider mMockContentProvider;
     private MockContentResolver mMockContentResolver;
-    private MemoryIntArray mCacheGenerationStore;
-    private int mCurrentGeneration = 123;
+    private MemoryIntArray mConfigsCacheGenerationStore;
+    private MemoryIntArray mSettingsCacheGenerationStore;
 
-    private HashMap<String, HashMap<String, String>> mStorage;
+    private HashMap<String, HashMap<String, String>> mConfigsStorage;
+    private HashMap<String, String> mSettingsStorage;
+
 
     @Before
     public void setUp() throws Exception {
         Settings.Config.clearProviderForTest();
+        Settings.Secure.clearProviderForTest();
         MockitoAnnotations.initMocks(this);
         when(mMockContentProvider.getIContentProvider()).thenReturn(mMockIContentProvider);
-        mMockContentResolver = new MockContentResolver(InstrumentationRegistry
-                .getInstrumentation().getContext());
+        mMockContentResolver = new MockContentResolver(
+                InstrumentationRegistry.getInstrumentation().getContext());
         mMockContentResolver.addProvider(Settings.Config.CONTENT_URI.getAuthority(),
                 mMockContentProvider);
-        mCacheGenerationStore = new MemoryIntArray(1);
-        mStorage = new HashMap<>();
+        mMockContentResolver.addProvider(Settings.Secure.CONTENT_URI.getAuthority(),
+                mMockContentProvider);
+        mConfigsCacheGenerationStore = new MemoryIntArray(2);
+        mConfigsCacheGenerationStore.set(0, 123);
+        mConfigsCacheGenerationStore.set(1, 456);
+        mSettingsCacheGenerationStore = new MemoryIntArray(3);
+        mSettingsCacheGenerationStore.set(0, 234);
+        mSettingsCacheGenerationStore.set(1, 567);
+        mConfigsStorage = new HashMap<>();
+        mSettingsStorage = new HashMap<>();
 
         // Stores keyValues for a given prefix and increments the generation. (Note that this
         // increments the generation no matter what, it doesn't pay attention to if anything
         // actually changed).
         when(mMockIContentProvider.call(any(), eq(Settings.Config.CONTENT_URI.getAuthority()),
-                eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
-                any(), any(Bundle.class))).thenAnswer(invocationOnMock -> {
+                eq(Settings.CALL_METHOD_SET_ALL_CONFIG), any(), any(Bundle.class))).thenAnswer(
+                invocationOnMock -> {
                     Bundle incomingBundle = invocationOnMock.getArgument(4);
                     HashMap<String, String> keyValues =
                             (HashMap<String, String>) incomingBundle.getSerializable(
-                                    Settings.CALL_METHOD_FLAGS_KEY);
+                                    Settings.CALL_METHOD_FLAGS_KEY, HashMap.class);
                     String prefix = incomingBundle.getString(Settings.CALL_METHOD_PREFIX_KEY);
-                    mStorage.put(prefix, keyValues);
-                    mCacheGenerationStore.set(0, ++mCurrentGeneration);
-
+                    mConfigsStorage.put(prefix, keyValues);
+                    int currentGeneration;
+                    // Different prefixes have different generation codes
+                    if (prefix.equals(NAMESPACE + "/")) {
+                        currentGeneration = mConfigsCacheGenerationStore.get(0);
+                        mConfigsCacheGenerationStore.set(0, ++currentGeneration);
+                    } else if (prefix.equals(NAMESPACE2 + "/")) {
+                        currentGeneration = mConfigsCacheGenerationStore.get(1);
+                        mConfigsCacheGenerationStore.set(1, ++currentGeneration);
+                    }
                     Bundle result = new Bundle();
                     result.putInt(Settings.KEY_CONFIG_SET_ALL_RETURN,
                             Settings.SET_ALL_RESULT_SUCCESS);
@@ -102,32 +126,111 @@
                 });
 
         // Returns the keyValues corresponding to a namespace, or an empty map if the namespace
-        // doesn't have anything stored for it. Returns the generation key if the caller asked
-        // for one.
+        // doesn't have anything stored for it. Returns the generation key if the map isn't empty
+        // and the caller asked for the generation key.
         when(mMockIContentProvider.call(any(), eq(Settings.Config.CONTENT_URI.getAuthority()),
-                eq(Settings.CALL_METHOD_LIST_CONFIG),
-                any(), any(Bundle.class))).thenAnswer(invocationOnMock -> {
+                eq(Settings.CALL_METHOD_LIST_CONFIG), any(), any(Bundle.class))).thenAnswer(
+                invocationOnMock -> {
                     Bundle incomingBundle = invocationOnMock.getArgument(4);
 
                     String prefix = incomingBundle.getString(Settings.CALL_METHOD_PREFIX_KEY);
 
-                    if (!mStorage.containsKey(prefix)) {
-                        mStorage.put(prefix, new HashMap<>());
+                    if (!mConfigsStorage.containsKey(prefix)) {
+                        mConfigsStorage.put(prefix, new HashMap<>());
                     }
-                    HashMap<String, String> keyValues = mStorage.get(prefix);
+                    HashMap<String, String> keyValues = mConfigsStorage.get(prefix);
 
                     Bundle bundle = new Bundle();
                     bundle.putSerializable(Settings.NameValueTable.VALUE, keyValues);
 
-                    if (incomingBundle.containsKey(Settings.CALL_METHOD_TRACK_GENERATION_KEY)) {
+                    if (!keyValues.isEmpty() && incomingBundle.containsKey(
+                            Settings.CALL_METHOD_TRACK_GENERATION_KEY)) {
+                        int index = prefix.equals(NAMESPACE + "/") ? 0 : 1;
                         bundle.putParcelable(Settings.CALL_METHOD_TRACK_GENERATION_KEY,
-                                mCacheGenerationStore);
-                        bundle.putInt(Settings.CALL_METHOD_GENERATION_INDEX_KEY, 0);
+                                mConfigsCacheGenerationStore);
+                        bundle.putInt(Settings.CALL_METHOD_GENERATION_INDEX_KEY, index);
                         bundle.putInt(Settings.CALL_METHOD_GENERATION_KEY,
-                                mCacheGenerationStore.get(0));
+                                mConfigsCacheGenerationStore.get(index));
                     }
                     return bundle;
                 });
+
+        // Stores value for a given setting's name and increments the generation. (Note that this
+        // increments the generation no matter what, it doesn't pay attention to if anything
+        // actually changed).
+        when(mMockIContentProvider.call(any(), eq(Settings.Secure.CONTENT_URI.getAuthority()),
+                eq(Settings.CALL_METHOD_PUT_SECURE), any(), any(Bundle.class))).thenAnswer(
+                invocationOnMock -> {
+                    Bundle incomingBundle = invocationOnMock.getArgument(4);
+                    String key = invocationOnMock.getArgument(3);
+                    String value = incomingBundle.getString(Settings.NameValueTable.VALUE);
+                    boolean newSetting = false;
+                    if (!mSettingsStorage.containsKey(key)) {
+                        newSetting = true;
+                    }
+                    mSettingsStorage.put(key, value);
+                    int currentGeneration;
+                    // Different settings have different generation codes
+                    if (key.equals(SETTING)) {
+                        currentGeneration = mSettingsCacheGenerationStore.get(0);
+                        mSettingsCacheGenerationStore.set(0, ++currentGeneration);
+                    } else if (key.equals(SETTING2)) {
+                        currentGeneration = mSettingsCacheGenerationStore.get(1);
+                        mSettingsCacheGenerationStore.set(1, ++currentGeneration);
+                    }
+                    if (newSetting) {
+                        // Tracking the generation of all unset settings.
+                        // Increment when a new setting is inserted
+                        currentGeneration = mSettingsCacheGenerationStore.get(2);
+                        mSettingsCacheGenerationStore.set(2, ++currentGeneration);
+                    }
+                    return null;
+                });
+
+        // Returns the value corresponding to a setting, or null if the setting
+        // doesn't have a value stored for it. Returns the generation key
+        // if the caller asked for the generation key.
+        when(mMockIContentProvider.call(any(), eq(Settings.Secure.CONTENT_URI.getAuthority()),
+                eq(Settings.CALL_METHOD_GET_SECURE), any(), any(Bundle.class))).thenAnswer(
+                invocationOnMock -> {
+                    Bundle incomingBundle = invocationOnMock.getArgument(4);
+                    String key = invocationOnMock.getArgument(3);
+                    String value = mSettingsStorage.get(key);
+
+                    Bundle bundle = new Bundle();
+                    bundle.putSerializable(Settings.NameValueTable.VALUE, value);
+
+                    if (incomingBundle.containsKey(
+                            Settings.CALL_METHOD_TRACK_GENERATION_KEY)) {
+                        int index;
+                        if (value != null) {
+                            index = key.equals(SETTING) ? 0 : 1;
+                        } else {
+                            // special index for unset settings
+                            index = 2;
+                        }
+                        // Manually make a copy of the memory int array to mimic sending it over IPC
+                        Parcel p = Parcel.obtain();
+                        mSettingsCacheGenerationStore.writeToParcel(p, 0);
+                        p.setDataPosition(0);
+                        MemoryIntArray parcelArray = MemoryIntArray.CREATOR.createFromParcel(p);
+                        bundle.putParcelable(Settings.CALL_METHOD_TRACK_GENERATION_KEY,
+                                parcelArray);
+                        bundle.putInt(Settings.CALL_METHOD_GENERATION_INDEX_KEY, index);
+                        bundle.putInt(Settings.CALL_METHOD_GENERATION_KEY,
+                                mSettingsCacheGenerationStore.get(index));
+                        p.recycle();
+                    }
+                    return bundle;
+                });
+    }
+
+    @After
+    public void cleanUp() throws IOException {
+        mConfigsStorage.clear();
+        mSettingsStorage.clear();
+        mSettingsCacheGenerationStore.close();
+        mConfigsCacheGenerationStore.close();
     }
 
     @Test
@@ -135,16 +238,13 @@
         HashMap<String, String> keyValues = new HashMap<>();
         keyValues.put("a", "b");
         Settings.Config.setStrings(mMockContentResolver, NAMESPACE, keyValues);
-        verify(mMockIContentProvider).call(any(), any(),
-                eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
-                any(), any(Bundle.class));
+        verify(mMockIContentProvider, times(1)).call(any(), any(),
+                eq(Settings.CALL_METHOD_SET_ALL_CONFIG), any(), any(Bundle.class));
 
         Map<String, String> returnedValues = Settings.Config.getStrings(mMockContentResolver,
-                NAMESPACE,
-                Collections.emptyList());
-        verify(mMockIContentProvider).call(any(), any(),
-                eq(Settings.CALL_METHOD_LIST_CONFIG),
-                any(), any(Bundle.class));
+                NAMESPACE, Collections.emptyList());
+        verify(mMockIContentProvider, times(1)).call(any(), any(),
+                eq(Settings.CALL_METHOD_LIST_CONFIG), any(), any(Bundle.class));
         assertThat(returnedValues).containsExactlyEntriesIn(keyValues);
 
         Map<String, String> cachedKeyValues = Settings.Config.getStrings(mMockContentResolver,
@@ -156,14 +256,12 @@
         keyValues.put("a", "c");
         Settings.Config.setStrings(mMockContentResolver, NAMESPACE, keyValues);
         verify(mMockIContentProvider, times(2)).call(any(), any(),
-                eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
-                any(), any(Bundle.class));
+                eq(Settings.CALL_METHOD_SET_ALL_CONFIG), any(), any(Bundle.class));
 
         Map<String, String> returnedValues2 = Settings.Config.getStrings(mMockContentResolver,
                 NAMESPACE, Collections.emptyList());
         verify(mMockIContentProvider, times(2)).call(any(), any(),
-                eq(Settings.CALL_METHOD_LIST_CONFIG),
-                any(), any(Bundle.class));
+                eq(Settings.CALL_METHOD_LIST_CONFIG), any(), any(Bundle.class));
         assertThat(returnedValues2).containsExactlyEntriesIn(keyValues);
 
         Map<String, String> cachedKeyValues2 = Settings.Config.getStrings(mMockContentResolver,
@@ -177,36 +275,31 @@
         HashMap<String, String> keyValues = new HashMap<>();
         keyValues.put("a", "b");
         Settings.Config.setStrings(mMockContentResolver, NAMESPACE, keyValues);
-        verify(mMockIContentProvider).call(any(), any(),
-                eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
+        verify(mMockIContentProvider).call(any(), any(), eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
                 any(), any(Bundle.class));
 
+        Map<String, String> returnedValues = Settings.Config.getStrings(mMockContentResolver,
+                NAMESPACE, Collections.emptyList());
+        verify(mMockIContentProvider).call(any(), any(), eq(Settings.CALL_METHOD_LIST_CONFIG),
+                any(), any(Bundle.class));
+        assertThat(returnedValues).containsExactlyEntriesIn(keyValues);
+
         HashMap<String, String> keyValues2 = new HashMap<>();
         keyValues2.put("c", "d");
         keyValues2.put("e", "f");
         Settings.Config.setStrings(mMockContentResolver, NAMESPACE2, keyValues2);
         verify(mMockIContentProvider, times(2)).call(any(), any(),
-                eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
-                any(), any(Bundle.class));
-
-        Map<String, String> returnedValues = Settings.Config.getStrings(mMockContentResolver,
-                NAMESPACE,
-                Collections.emptyList());
-        verify(mMockIContentProvider).call(any(), any(),
-                eq(Settings.CALL_METHOD_LIST_CONFIG),
-                any(), any(Bundle.class));
-        assertThat(returnedValues).containsExactlyEntriesIn(keyValues);
+                eq(Settings.CALL_METHOD_SET_ALL_CONFIG), any(), any(Bundle.class));
 
         Map<String, String> returnedValues2 = Settings.Config.getStrings(mMockContentResolver,
-                NAMESPACE2,
-                Collections.emptyList());
+                NAMESPACE2, Collections.emptyList());
         verify(mMockIContentProvider, times(2)).call(any(), any(),
-                eq(Settings.CALL_METHOD_LIST_CONFIG),
-                any(), any(Bundle.class));
+                eq(Settings.CALL_METHOD_LIST_CONFIG), any(), any(Bundle.class));
         assertThat(returnedValues2).containsExactlyEntriesIn(keyValues2);
 
         Map<String, String> cachedKeyValues = Settings.Config.getStrings(mMockContentResolver,
                 NAMESPACE, Collections.emptyList());
+        // Modifying the second namespace doesn't affect the cache of the first namespace
         verifyNoMoreInteractions(mMockIContentProvider);
         assertThat(cachedKeyValues).containsExactlyEntriesIn(keyValues);
 
@@ -219,17 +312,112 @@
     @Test
     public void testCaching_emptyNamespace() throws Exception {
         Map<String, String> returnedValues = Settings.Config.getStrings(mMockContentResolver,
-                NAMESPACE,
-                Collections.emptyList());
-        verify(mMockIContentProvider).call(any(), any(),
-                eq(Settings.CALL_METHOD_LIST_CONFIG),
-                any(), any(Bundle.class));
+                NAMESPACE, Collections.emptyList());
+        verify(mMockIContentProvider, times(1)).call(any(), any(),
+                eq(Settings.CALL_METHOD_LIST_CONFIG), any(), any(Bundle.class));
         assertThat(returnedValues).isEmpty();
 
         Map<String, String> cachedKeyValues = Settings.Config.getStrings(mMockContentResolver,
                 NAMESPACE, Collections.emptyList());
-        verifyNoMoreInteractions(mMockIContentProvider);
+        // Empty list won't be cached
+        verify(mMockIContentProvider, times(2)).call(any(), any(),
+                eq(Settings.CALL_METHOD_LIST_CONFIG), any(), any(Bundle.class));
         assertThat(cachedKeyValues).isEmpty();
     }
 
+    @Test
+    public void testCaching_singleSetting() throws Exception {
+        Settings.Secure.putString(mMockContentResolver, SETTING, "a");
+        verify(mMockIContentProvider, times(1)).call(any(), any(),
+                eq(Settings.CALL_METHOD_PUT_SECURE), any(), any(Bundle.class));
+
+        String returnedValue = Settings.Secure.getString(mMockContentResolver, SETTING);
+        verify(mMockIContentProvider, times(1)).call(any(), any(),
+                eq(Settings.CALL_METHOD_GET_SECURE), any(), any(Bundle.class));
+        assertThat(returnedValue).isEqualTo("a");
+
+        String cachedValue = Settings.Secure.getString(mMockContentResolver, SETTING);
+        verifyNoMoreInteractions(mMockIContentProvider);
+        assertThat(cachedValue).isEqualTo("a");
+
+        // Modify the value to invalidate the cache.
+        Settings.Secure.putString(mMockContentResolver, SETTING, "b");
+        verify(mMockIContentProvider, times(2)).call(any(), any(),
+                eq(Settings.CALL_METHOD_PUT_SECURE), any(), any(Bundle.class));
+
+        String returnedValue2 = Settings.Secure.getString(mMockContentResolver, SETTING);
+        verify(mMockIContentProvider, times(2)).call(any(), any(),
+                eq(Settings.CALL_METHOD_GET_SECURE), any(), any(Bundle.class));
+        assertThat(returnedValue2).isEqualTo("b");
+
+        String cachedValue2 = Settings.Secure.getString(mMockContentResolver, SETTING);
+        verifyNoMoreInteractions(mMockIContentProvider);
+        assertThat(cachedValue2).isEqualTo("b");
+    }
+
+    @Test
+    public void testCaching_multipleSettings() throws Exception {
+        Settings.Secure.putString(mMockContentResolver, SETTING, "a");
+        verify(mMockIContentProvider, times(1)).call(any(), any(),
+                eq(Settings.CALL_METHOD_PUT_SECURE), any(), any(Bundle.class));
+
+        String returnedValue = Settings.Secure.getString(mMockContentResolver, SETTING);
+        verify(mMockIContentProvider, times(1)).call(any(), any(),
+                eq(Settings.CALL_METHOD_GET_SECURE), any(), any(Bundle.class));
+        assertThat(returnedValue).isEqualTo("a");
+
+        Settings.Secure.putString(mMockContentResolver, SETTING2, "b");
+        verify(mMockIContentProvider, times(2)).call(any(), any(),
+                eq(Settings.CALL_METHOD_PUT_SECURE), any(), any(Bundle.class));
+
+        String returnedValue2 = Settings.Secure.getString(mMockContentResolver, SETTING2);
+        verify(mMockIContentProvider, times(2)).call(any(), any(),
+                eq(Settings.CALL_METHOD_GET_SECURE), any(), any(Bundle.class));
+        assertThat(returnedValue2).isEqualTo("b");
+
+        String cachedValue = Settings.Secure.getString(mMockContentResolver, SETTING);
+        // Modifying the second setting doesn't affect the cache of the first setting
+        verifyNoMoreInteractions(mMockIContentProvider);
+        assertThat(cachedValue).isEqualTo("a");
+
+        String cachedValue2 = Settings.Secure.getString(mMockContentResolver, SETTING2);
+        verifyNoMoreInteractions(mMockIContentProvider);
+        assertThat(cachedValue2).isEqualTo("b");
+    }
+
+    @Test
+    public void testCaching_unsetSetting() throws Exception {
+        String returnedValue = Settings.Secure.getString(mMockContentResolver, SETTING);
+        verify(mMockIContentProvider, times(1)).call(any(), any(),
+                eq(Settings.CALL_METHOD_GET_SECURE), any(), any(Bundle.class));
+        assertThat(returnedValue).isNull();
+
+        String cachedValue = Settings.Secure.getString(mMockContentResolver, SETTING);
+        // The first unset setting's generation number is cached
+        verifyNoMoreInteractions(mMockIContentProvider);
+        assertThat(cachedValue).isNull();
+
+        String returnedValue2 = Settings.Secure.getString(mMockContentResolver, SETTING2);
+        verify(mMockIContentProvider, times(2)).call(any(), any(),
+                eq(Settings.CALL_METHOD_GET_SECURE), any(), any(Bundle.class));
+        assertThat(returnedValue2).isNull();
+
+        String cachedValue2 = Settings.Secure.getString(mMockContentResolver, SETTING);
+        // The second unset setting's generation number is cached
+        verifyNoMoreInteractions(mMockIContentProvider);
+        assertThat(cachedValue2).isNull();
+
+        Settings.Secure.putString(mMockContentResolver, SETTING, "a");
+        // The generation for unset settings should have changed
+        returnedValue2 = Settings.Secure.getString(mMockContentResolver, SETTING2);
+        verify(mMockIContentProvider, times(3)).call(any(), any(),
+                eq(Settings.CALL_METHOD_GET_SECURE), any(), any(Bundle.class));
+        assertThat(returnedValue2).isNull();
+
+        // The generation tracker for the first setting should have change because it's set now
+        returnedValue = Settings.Secure.getString(mMockContentResolver, SETTING);
+        verify(mMockIContentProvider, times(4)).call(any(), any(),
+                eq(Settings.CALL_METHOD_GET_SECURE), any(), any(Bundle.class));
+        assertThat(returnedValue).isEqualTo("a");
+    }
 }
diff --git a/core/tests/coretests/src/android/view/AccessibilityInteractionControllerTest.java b/core/tests/coretests/src/android/view/AccessibilityInteractionControllerTest.java
index 7855ef9..d91541f 100644
--- a/core/tests/coretests/src/android/view/AccessibilityInteractionControllerTest.java
+++ b/core/tests/coretests/src/android/view/AccessibilityInteractionControllerTest.java
@@ -16,8 +16,8 @@
 
 package android.view;
 
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
 
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.app.Activity;
@@ -98,24 +98,42 @@
     @Test
     public void clearAccessibilityFocus_shouldClearFocus() throws Exception {
         performAccessibilityFocus("com.android.frameworks.coretests:id/appNameBtn");
-        assertTrue("Button should have a11y focus",
-                mButton.isAccessibilityFocused());
+        assertWithMessage("Button should have a11y focus").that(
+                mButton.isAccessibilityFocused()).isTrue();
         mAccessibilityInteractionController.clearAccessibilityFocusClientThread();
         sInstrumentation.waitForIdleSync();
-        assertFalse("Button should not have a11y focus",
-                mButton.isAccessibilityFocused());
+        assertWithMessage("Button should not have a11y focus").that(
+                mButton.isAccessibilityFocused()).isFalse();
     }
 
     @Test
     public void clearAccessibilityFocus_uiThread_shouldClearFocus() throws Exception {
         performAccessibilityFocus("com.android.frameworks.coretests:id/appNameBtn");
-        assertTrue("Button should have a11y focus",
-                mButton.isAccessibilityFocused());
-        sInstrumentation.runOnMainSync(() -> {
-            mAccessibilityInteractionController.clearAccessibilityFocusClientThread();
-        });
-        assertFalse("Button should not have a11y focus",
-                mButton.isAccessibilityFocused());
+        assertWithMessage("Button should have a11y focus").that(
+                mButton.isAccessibilityFocused()).isTrue();
+        sInstrumentation.runOnMainSync(() ->
+                mAccessibilityInteractionController.clearAccessibilityFocusClientThread());
+        assertWithMessage("Button should not have a11y focus").that(
+                mButton.isAccessibilityFocused()).isFalse();
+    }
+
+    @Test
+    public void clearAccessibilityFocus_sensitiveRootView_shouldClearFocus()
+            throws Exception {
+        final View rootView = mButton.getRootView();
+        assertThat(rootView).isNotNull();
+        try {
+            rootView.setAccessibilityDataSensitive(View.ACCESSIBILITY_DATA_SENSITIVE_YES);
+            performAccessibilityFocus("com.android.frameworks.coretests:id/appNameBtn");
+            assertWithMessage("Button should have a11y focus").that(
+                    mButton.isAccessibilityFocused()).isTrue();
+            sInstrumentation.runOnMainSync(() ->
+                    mAccessibilityInteractionController.clearAccessibilityFocusClientThread());
+            assertWithMessage("Button should not have a11y focus").that(
+                    mButton.isAccessibilityFocused()).isFalse();
+        } finally {
+            rootView.setAccessibilityDataSensitive(View.ACCESSIBILITY_DATA_SENSITIVE_AUTO);
+        }
     }
 
     private void launchActivity() {
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index ca1367a..0692052 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -248,17 +248,22 @@
 
     @Test
     public void testSystemDrivenInsetsAnimationLoggingListener_onReady() {
+        var loggingListener = mock(WindowInsetsAnimationControlListener.class);
+
         prepareControls();
         // only the original thread that created view hierarchy can touch its views
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
-            WindowInsetsAnimationControlListener loggingListener =
-                    mock(WindowInsetsAnimationControlListener.class);
             mController.setSystemDrivenInsetsAnimationLoggingListener(loggingListener);
             mController.getSourceConsumer(mImeSource).onWindowFocusGained(true);
             // since there is no focused view, forcefully make IME visible.
             mController.show(WindowInsets.Type.ime(), true /* fromIme */, null /* statsToken */);
-            verify(loggingListener).onReady(notNull(), anyInt());
+            // When using the animation thread, this must not invoke onReady()
+            mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
         });
+        // Wait for onReady() being dispatched on the animation thread.
+        InsetsAnimationThread.get().getThreadHandler().runWithScissors(() -> {}, 500);
+
+        verify(loggingListener).onReady(notNull(), anyInt());
     }
 
     @Test
diff --git a/core/tests/coretests/src/android/view/InsetsSourceTest.java b/core/tests/coretests/src/android/view/InsetsSourceTest.java
index 1db6587..6fa8f11 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceTest.java
@@ -19,6 +19,7 @@
 import static android.view.WindowInsets.Type.FIRST;
 import static android.view.WindowInsets.Type.LAST;
 import static android.view.WindowInsets.Type.SIZE;
+import static android.view.WindowInsets.Type.captionBar;
 import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowInsets.Type.navigationBars;
 
@@ -51,11 +52,13 @@
 
     private final InsetsSource mSource = new InsetsSource(0 /* id */, navigationBars());
     private final InsetsSource mImeSource = new InsetsSource(1 /* id */, ime());
+    private final InsetsSource mCaptionSource = new InsetsSource(2 /* id */, captionBar());
 
     @Before
     public void setUp() {
         mSource.setVisible(true);
         mImeSource.setVisible(true);
+        mCaptionSource.setVisible(true);
     }
 
     @Test
@@ -107,6 +110,17 @@
     }
 
     @Test
+    public void testCalculateInsets_caption_resizing() {
+        mCaptionSource.setFrame(new Rect(0, 0, 100, 100));
+        Insets insets = mCaptionSource.calculateInsets(new Rect(0, 0, 200, 200), false);
+        assertEquals(Insets.of(0, 100, 0, 0), insets);
+        insets = mCaptionSource.calculateInsets(new Rect(0, 0, 50, 200), false);
+        assertEquals(Insets.of(0, 100, 0, 0), insets);
+        insets = mCaptionSource.calculateInsets(new Rect(100, 100, 200, 500), false);
+        assertEquals(Insets.of(0, 100, 0, 0), insets);
+    }
+
+    @Test
     public void testCalculateInsets_invisible() {
         mSource.setFrame(new Rect(0, 0, 500, 100));
         mSource.setVisible(false);
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index b035c23..fde1a6d 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -248,6 +248,18 @@
     }
 
     @Test
+    public void testCalculateInsets_captionBarOffset() {
+        mState.getOrCreateSource(ID_CAPTION_BAR, captionBar())
+                .setFrame(new Rect(0, 0, 100, 300))
+                .setVisible(true);
+
+        Insets visibleInsets = mState.calculateVisibleInsets(
+                new Rect(0, 0, 150, 400), TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+                SOFT_INPUT_ADJUST_NOTHING, 0 /* windowFlags */);
+        assertEquals(Insets.of(0, 300, 0, 0), visibleInsets);
+    }
+
+    @Test
     public void testCalculateInsets_extraNavRightStatusTop() {
         mState.getOrCreateSource(ID_STATUS_BAR, statusBars())
                 .setFrame(new Rect(0, 0, 100, 100))
diff --git a/core/tests/coretests/src/android/view/OWNERS b/core/tests/coretests/src/android/view/OWNERS
index a142e27..2ca9994 100644
--- a/core/tests/coretests/src/android/view/OWNERS
+++ b/core/tests/coretests/src/android/view/OWNERS
@@ -1,4 +1,5 @@
 # Accessibility
+per-file AccessibilityInteractionControllerTest.java = file:/services/accessibility/OWNERS
 per-file WindowInfoTest.java = file:/services/accessibility/OWNERS
 
 # Input
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
index 6d635af..3d4918b 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
@@ -58,7 +58,7 @@
 
     // The number of flags held in boolean properties. Their values should also be double-checked
     // in the methods above.
-    private static final int NUM_BOOLEAN_PROPERTIES = 26;
+    private static final int NUM_BOOLEAN_PROPERTIES = 27;
 
     @Test
     public void testStandardActions_serializationFlagIsValid() {
diff --git a/core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java b/core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java
index 76f5277..1ec2613 100644
--- a/core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java
+++ b/core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java
@@ -64,10 +64,19 @@
     private static final int HW_BOUNDS_OFFSETS_BOTTOM_PX = 40;
     private int mHandwritingSlop = 4;
 
-    private static final Rect sHwArea = new Rect(100, 200, 500, 500);
+    private static final Rect sHwArea1;
+    private static final Rect sHwArea2;
+
+    static {
+        sHwArea1 = new Rect(100, 200, 500, 500);
+        // The extended handwriting area bounds of the two views are overlapping.
+        int hwArea2Top = sHwArea1.bottom + HW_BOUNDS_OFFSETS_TOP_PX / 2;
+        sHwArea2 = new Rect(sHwArea1.left, hwArea2Top, sHwArea1.right, hwArea2Top + 300);
+    }
 
     private HandwritingInitiator mHandwritingInitiator;
-    private View mTestView;
+    private View mTestView1;
+    private View mTestView2;
     private Context mContext;
 
     @Before
@@ -82,20 +91,27 @@
         mHandwritingInitiator =
                 spy(new HandwritingInitiator(viewConfiguration, inputMethodManager));
 
-        mTestView = createView(sHwArea, true /* autoHandwritingEnabled */,
-                true /* isStylusHandwritingAvailable */,
+        mTestView1 = createView(sHwArea1, /* autoHandwritingEnabled= */ true,
+                /* isStylusHandwritingAvailable= */ true,
                 HW_BOUNDS_OFFSETS_LEFT_PX,
                 HW_BOUNDS_OFFSETS_TOP_PX,
                 HW_BOUNDS_OFFSETS_RIGHT_PX,
                 HW_BOUNDS_OFFSETS_BOTTOM_PX);
-        mHandwritingInitiator.updateHandwritingAreasForView(mTestView);
+        mTestView2 = createView(sHwArea2, /* autoHandwritingEnabled= */ true,
+                /* isStylusHandwritingAvailable= */ true,
+                HW_BOUNDS_OFFSETS_LEFT_PX,
+                HW_BOUNDS_OFFSETS_TOP_PX,
+                HW_BOUNDS_OFFSETS_RIGHT_PX,
+                HW_BOUNDS_OFFSETS_BOTTOM_PX);
+        mHandwritingInitiator.updateHandwritingAreasForView(mTestView1);
+        mHandwritingInitiator.updateHandwritingAreasForView(mTestView2);
     }
 
     @Test
     public void onTouchEvent_startHandwriting_when_stylusMoveOnce_withinHWArea() {
-        mHandwritingInitiator.onInputConnectionCreated(mTestView);
-        final int x1 = (sHwArea.left + sHwArea.right) / 2;
-        final int y1 = (sHwArea.top + sHwArea.bottom) / 2;
+        mHandwritingInitiator.onInputConnectionCreated(mTestView1);
+        final int x1 = (sHwArea1.left + sHwArea1.right) / 2;
+        final int y1 = (sHwArea1.top + sHwArea1.bottom) / 2;
         MotionEvent stylusEvent1 = createStylusEvent(ACTION_DOWN, x1, y1, 0);
         boolean onTouchEventResult1 = mHandwritingInitiator.onTouchEvent(stylusEvent1);
 
@@ -106,7 +122,7 @@
         boolean onTouchEventResult2 = mHandwritingInitiator.onTouchEvent(stylusEvent2);
 
         // Stylus movement within HandwritingArea should trigger IMM.startHandwriting once.
-        verify(mHandwritingInitiator, times(1)).startHandwriting(mTestView);
+        verify(mHandwritingInitiator, times(1)).startHandwriting(mTestView1);
         assertThat(onTouchEventResult1).isFalse();
         // After IMM.startHandwriting is triggered, onTouchEvent should return true for ACTION_MOVE
         // events so that the events are not dispatched to the view tree.
@@ -115,9 +131,9 @@
 
     @Test
     public void onTouchEvent_startHandwritingOnce_when_stylusMoveMultiTimes_withinHWArea() {
-        mHandwritingInitiator.onInputConnectionCreated(mTestView);
-        final int x1 = (sHwArea.left + sHwArea.right) / 2;
-        final int y1 = (sHwArea.top + sHwArea.bottom) / 2;
+        mHandwritingInitiator.onInputConnectionCreated(mTestView1);
+        final int x1 = (sHwArea1.left + sHwArea1.right) / 2;
+        final int y1 = (sHwArea1.top + sHwArea1.bottom) / 2;
         MotionEvent stylusEvent1 = createStylusEvent(ACTION_DOWN, x1, y1, 0);
         boolean onTouchEventResult1 = mHandwritingInitiator.onTouchEvent(stylusEvent1);
 
@@ -140,7 +156,7 @@
         boolean onTouchEventResult5 = mHandwritingInitiator.onTouchEvent(stylusEvent5);
 
         // It only calls startHandwriting once for each ACTION_DOWN.
-        verify(mHandwritingInitiator, times(1)).startHandwriting(mTestView);
+        verify(mHandwritingInitiator, times(1)).startHandwriting(mTestView1);
         assertThat(onTouchEventResult1).isFalse();
         // stylusEvent2 does not trigger IMM.startHandwriting since the touch slop distance has not
         // been exceeded. onTouchEvent should return false so that the event is dispatched to the
@@ -155,9 +171,9 @@
 
     @Test
     public void onTouchEvent_startHandwriting_when_stylusMove_withinExtendedHWArea() {
-        mHandwritingInitiator.onInputConnectionCreated(mTestView);
-        final int x1 = sHwArea.left - HW_BOUNDS_OFFSETS_LEFT_PX / 2;
-        final int y1 = sHwArea.top - HW_BOUNDS_OFFSETS_TOP_PX / 2;
+        mHandwritingInitiator.onInputConnectionCreated(mTestView1);
+        final int x1 = sHwArea1.left - HW_BOUNDS_OFFSETS_LEFT_PX / 2;
+        final int y1 = sHwArea1.top - HW_BOUNDS_OFFSETS_TOP_PX / 2;
         MotionEvent stylusEvent1 = createStylusEvent(ACTION_DOWN, x1, y1, 0);
         mHandwritingInitiator.onTouchEvent(stylusEvent1);
 
@@ -168,13 +184,13 @@
         mHandwritingInitiator.onTouchEvent(stylusEvent2);
 
         // Stylus movement within extended HandwritingArea should trigger IMM.startHandwriting once.
-        verify(mHandwritingInitiator, times(1)).startHandwriting(mTestView);
+        verify(mHandwritingInitiator, times(1)).startHandwriting(mTestView1);
     }
 
     @Test
     public void onTouchEvent_startHandwriting_inputConnectionBuiltAfterStylusMove() {
-        final int x1 = (sHwArea.left + sHwArea.right) / 2;
-        final int y1 = (sHwArea.top + sHwArea.bottom) / 2;
+        final int x1 = (sHwArea1.left + sHwArea1.right) / 2;
+        final int y1 = (sHwArea1.top + sHwArea1.bottom) / 2;
         MotionEvent stylusEvent1 = createStylusEvent(ACTION_DOWN, x1, y1, 0);
         mHandwritingInitiator.onTouchEvent(stylusEvent1);
 
@@ -184,15 +200,15 @@
         mHandwritingInitiator.onTouchEvent(stylusEvent2);
 
         // InputConnection is created after stylus movement.
-        mHandwritingInitiator.onInputConnectionCreated(mTestView);
+        mHandwritingInitiator.onInputConnectionCreated(mTestView1);
 
-        verify(mHandwritingInitiator, times(1)).startHandwriting(mTestView);
+        verify(mHandwritingInitiator, times(1)).startHandwriting(mTestView1);
     }
 
     @Test
     public void onTouchEvent_startHandwriting_inputConnectionBuilt_stylusMoveInExtendedHWArea() {
-        final int x1 = sHwArea.right + HW_BOUNDS_OFFSETS_RIGHT_PX / 2;
-        final int y1 = sHwArea.bottom + HW_BOUNDS_OFFSETS_BOTTOM_PX / 2;
+        final int x1 = sHwArea1.right + HW_BOUNDS_OFFSETS_RIGHT_PX / 2;
+        final int y1 = sHwArea1.bottom + HW_BOUNDS_OFFSETS_BOTTOM_PX / 2;
         MotionEvent stylusEvent1 = createStylusEvent(ACTION_DOWN, x1, y1, 0);
         mHandwritingInitiator.onTouchEvent(stylusEvent1);
 
@@ -202,9 +218,9 @@
         mHandwritingInitiator.onTouchEvent(stylusEvent2);
 
         // InputConnection is created after stylus movement.
-        mHandwritingInitiator.onInputConnectionCreated(mTestView);
+        mHandwritingInitiator.onInputConnectionCreated(mTestView1);
 
-        verify(mHandwritingInitiator, times(1)).startHandwriting(mTestView);
+        verify(mHandwritingInitiator, times(1)).startHandwriting(mTestView1);
     }
 
     @Test
@@ -212,11 +228,11 @@
         View delegateView = new View(mContext);
         delegateView.setIsHandwritingDelegate(true);
 
-        mTestView.setHandwritingDelegatorCallback(
+        mTestView1.setHandwritingDelegatorCallback(
                 () -> mHandwritingInitiator.onInputConnectionCreated(delegateView));
 
-        final int x1 = (sHwArea.left + sHwArea.right) / 2;
-        final int y1 = (sHwArea.top + sHwArea.bottom) / 2;
+        final int x1 = (sHwArea1.left + sHwArea1.right) / 2;
+        final int y1 = (sHwArea1.top + sHwArea1.bottom) / 2;
         MotionEvent stylusEvent1 = createStylusEvent(ACTION_DOWN, x1, y1, 0);
         mHandwritingInitiator.onTouchEvent(stylusEvent1);
 
@@ -249,12 +265,12 @@
 
         // Stylus movement within HandwritingArea should not trigger IMM.startHandwriting since
         // the current IME doesn't support handwriting.
-        verify(mHandwritingInitiator, never()).startHandwriting(mTestView);
+        verify(mHandwritingInitiator, never()).startHandwriting(mTestView1);
     }
 
     @Test
     public void onTouchEvent_notStartHandwriting_when_stylusTap_withinHWArea() {
-        mHandwritingInitiator.onInputConnectionCreated(mTestView);
+        mHandwritingInitiator.onInputConnectionCreated(mTestView1);
         final int x1 = 200;
         final int y1 = 200;
         MotionEvent stylusEvent1 = createStylusEvent(ACTION_DOWN, x1, y1, 0);
@@ -265,12 +281,12 @@
         MotionEvent stylusEvent2 = createStylusEvent(ACTION_UP, x2, y2, 0);
         mHandwritingInitiator.onTouchEvent(stylusEvent2);
 
-        verify(mHandwritingInitiator, never()).startHandwriting(mTestView);
+        verify(mHandwritingInitiator, never()).startHandwriting(mTestView1);
     }
 
     @Test
     public void onTouchEvent_notStartHandwriting_when_stylusMove_outOfHWArea() {
-        mHandwritingInitiator.onInputConnectionCreated(mTestView);
+        mHandwritingInitiator.onInputConnectionCreated(mTestView1);
         final int x1 = 10;
         final int y1 = 10;
         MotionEvent stylusEvent1 = createStylusEvent(ACTION_DOWN, x1, y1, 0);
@@ -281,12 +297,12 @@
         MotionEvent stylusEvent2 = createStylusEvent(ACTION_MOVE, x2, y2, 0);
         mHandwritingInitiator.onTouchEvent(stylusEvent2);
 
-        verify(mHandwritingInitiator, never()).startHandwriting(mTestView);
+        verify(mHandwritingInitiator, never()).startHandwriting(mTestView1);
     }
 
     @Test
     public void onTouchEvent_notStartHandwriting_when_stylusMove_afterTimeOut() {
-        mHandwritingInitiator.onInputConnectionCreated(mTestView);
+        mHandwritingInitiator.onInputConnectionCreated(mTestView1);
         final int x1 = 10;
         final int y1 = 10;
         final long time1 = 10L;
@@ -300,13 +316,13 @@
         mHandwritingInitiator.onTouchEvent(stylusEvent2);
 
         // stylus movement is after TAP_TIMEOUT it shouldn't call startHandwriting.
-        verify(mHandwritingInitiator, never()).startHandwriting(mTestView);
+        verify(mHandwritingInitiator, never()).startHandwriting(mTestView1);
     }
 
     @Test
     public void onTouchEvent_focusView_stylusMoveOnce_withinHWArea() {
-        final int x1 = (sHwArea.left + sHwArea.right) / 2;
-        final int y1 = (sHwArea.top + sHwArea.bottom) / 2;
+        final int x1 = (sHwArea1.left + sHwArea1.right) / 2;
+        final int y1 = (sHwArea1.top + sHwArea1.bottom) / 2;
         MotionEvent stylusEvent1 = createStylusEvent(ACTION_DOWN, x1, y1, 0);
         mHandwritingInitiator.onTouchEvent(stylusEvent1);
 
@@ -317,13 +333,34 @@
         mHandwritingInitiator.onTouchEvent(stylusEvent2);
 
         // HandwritingInitiator will request focus for the registered view.
-        verify(mTestView, times(1)).requestFocus();
+        verify(mTestView1, times(1)).requestFocus();
+    }
+
+    @Test
+    public void onTouchEvent_focusView_inputConnectionAlreadyBuilt_stylusMoveOnce_withinHWArea() {
+        mHandwritingInitiator.onInputConnectionCreated(mTestView1);
+
+        final int x1 = (sHwArea1.left + sHwArea1.right) / 2;
+        final int y1 = (sHwArea1.top + sHwArea1.bottom) / 2;
+        MotionEvent stylusEvent1 = createStylusEvent(ACTION_DOWN, x1, y1, 0);
+        mHandwritingInitiator.onTouchEvent(stylusEvent1);
+
+        final int x2 = x1 + mHandwritingSlop * 2;
+        final int y2 = y1;
+
+        MotionEvent stylusEvent2 = createStylusEvent(ACTION_MOVE, x2, y2, 0);
+        mHandwritingInitiator.onTouchEvent(stylusEvent2);
+
+        // View has input connection but not focus, so HandwritingInitiator will request focus
+        // before starting handwriting.
+        verify(mTestView1).requestFocus();
+        verify(mHandwritingInitiator).startHandwriting(mTestView1);
     }
 
     @Test
     public void onTouchEvent_focusView_stylusMoveOnce_withinExtendedHWArea() {
-        final int x1 = sHwArea.left - HW_BOUNDS_OFFSETS_LEFT_PX / 2;
-        final int y1 = sHwArea.top - HW_BOUNDS_OFFSETS_TOP_PX / 2;
+        final int x1 = sHwArea1.left - HW_BOUNDS_OFFSETS_LEFT_PX / 2;
+        final int y1 = sHwArea1.top - HW_BOUNDS_OFFSETS_TOP_PX / 2;
         MotionEvent stylusEvent1 = createStylusEvent(ACTION_DOWN, x1, y1, 0);
         mHandwritingInitiator.onTouchEvent(stylusEvent1);
 
@@ -334,16 +371,16 @@
         mHandwritingInitiator.onTouchEvent(stylusEvent2);
 
         // HandwritingInitiator will request focus for the registered view.
-        verify(mTestView, times(1)).requestFocus();
+        verify(mTestView1, times(1)).requestFocus();
     }
 
     @Test
-    public void autoHandwriting_whenDisabled_wontStartHW() {
-        View mockView = createView(sHwArea, false /* autoHandwritingEnabled */,
-                true /* isStylusHandwritingAvailable */);
-        mHandwritingInitiator.onInputConnectionCreated(mockView);
-        final int x1 = (sHwArea.left + sHwArea.right) / 2;
-        final int y1 = (sHwArea.top + sHwArea.bottom) / 2;
+    public void onTouchEvent_handwritingAreaOverlapped_initiateForCloserView() {
+        // The ACTION_DOWN location is within the handwriting bounds of both mTestView1 and
+        // mTestView2. Because it's closer to mTestView2's handwriting bounds, handwriting is
+        // initiated for mTestView2.
+        final int x1 = (sHwArea1.left + sHwArea1.right) / 2;
+        final int y1 = sHwArea1.bottom + HW_BOUNDS_OFFSETS_BOTTOM_PX - 1;
         MotionEvent stylusEvent1 = createStylusEvent(ACTION_DOWN, x1, y1, 0);
         mHandwritingInitiator.onTouchEvent(stylusEvent1);
 
@@ -353,14 +390,57 @@
         MotionEvent stylusEvent2 = createStylusEvent(ACTION_MOVE, x2, y2, 0);
         mHandwritingInitiator.onTouchEvent(stylusEvent2);
 
-        verify(mHandwritingInitiator, never()).startHandwriting(mTestView);
+        verify(mTestView2, times(1)).requestFocus();
+
+        mHandwritingInitiator.onInputConnectionCreated(mTestView2);
+        verify(mHandwritingInitiator, times(1)).startHandwriting(mTestView2);
+    }
+
+    @Test
+    public void onTouchEvent_handwritingAreaOverlapped_focusedViewHasPriority() {
+        // Simulate the case where mTestView1 is focused.
+        mHandwritingInitiator.onInputConnectionCreated(mTestView1);
+        // The ACTION_DOWN location is within the handwriting bounds of both mTestView1 and
+        // mTestView2. Although it's closer to mTestView2's handwriting bounds, handwriting is
+        // initiated for mTestView1 because it's focused.
+        final int x1 = (sHwArea1.left + sHwArea1.right) / 2;
+        final int y1 = sHwArea1.bottom + HW_BOUNDS_OFFSETS_BOTTOM_PX - 1;
+        MotionEvent stylusEvent1 = createStylusEvent(ACTION_DOWN, x1, y1, 0);
+        mHandwritingInitiator.onTouchEvent(stylusEvent1);
+
+        final int x2 = x1 + mHandwritingSlop * 2;
+        final int y2 = y1;
+
+        MotionEvent stylusEvent2 = createStylusEvent(ACTION_MOVE, x2, y2, 0);
+        mHandwritingInitiator.onTouchEvent(stylusEvent2);
+
+        verify(mHandwritingInitiator, times(1)).startHandwriting(mTestView1);
+    }
+
+    @Test
+    public void autoHandwriting_whenDisabled_wontStartHW() {
+        View mockView = createView(sHwArea1, false /* autoHandwritingEnabled */,
+                true /* isStylusHandwritingAvailable */);
+        mHandwritingInitiator.onInputConnectionCreated(mockView);
+        final int x1 = (sHwArea1.left + sHwArea1.right) / 2;
+        final int y1 = (sHwArea1.top + sHwArea1.bottom) / 2;
+        MotionEvent stylusEvent1 = createStylusEvent(ACTION_DOWN, x1, y1, 0);
+        mHandwritingInitiator.onTouchEvent(stylusEvent1);
+
+        final int x2 = x1 + mHandwritingSlop * 2;
+        final int y2 = y1;
+
+        MotionEvent stylusEvent2 = createStylusEvent(ACTION_MOVE, x2, y2, 0);
+        mHandwritingInitiator.onTouchEvent(stylusEvent2);
+
+        verify(mHandwritingInitiator, never()).startHandwriting(mTestView1);
     }
 
     @Test
     public void onInputConnectionCreated() {
-        mHandwritingInitiator.onInputConnectionCreated(mTestView);
+        mHandwritingInitiator.onInputConnectionCreated(mTestView1);
         assertThat(mHandwritingInitiator.mConnectedView).isNotNull();
-        assertThat(mHandwritingInitiator.mConnectedView.get()).isEqualTo(mTestView);
+        assertThat(mHandwritingInitiator.mConnectedView.get()).isEqualTo(mTestView1);
     }
 
     @Test
@@ -375,8 +455,8 @@
 
     @Test
     public void onInputConnectionClosed() {
-        mHandwritingInitiator.onInputConnectionCreated(mTestView);
-        mHandwritingInitiator.onInputConnectionClosed(mTestView);
+        mHandwritingInitiator.onInputConnectionCreated(mTestView1);
+        mHandwritingInitiator.onInputConnectionClosed(mTestView1);
 
         assertThat(mHandwritingInitiator.mConnectedView).isNull();
     }
@@ -396,12 +476,12 @@
         // When IMM restarts input connection, View#onInputConnectionCreatedInternal might be
         // called before View#onInputConnectionClosedInternal. As a result, we need to handle the
         // case where "one view "2 InputConnections".
-        mHandwritingInitiator.onInputConnectionCreated(mTestView);
-        mHandwritingInitiator.onInputConnectionCreated(mTestView);
-        mHandwritingInitiator.onInputConnectionClosed(mTestView);
+        mHandwritingInitiator.onInputConnectionCreated(mTestView1);
+        mHandwritingInitiator.onInputConnectionCreated(mTestView1);
+        mHandwritingInitiator.onInputConnectionClosed(mTestView1);
 
         assertThat(mHandwritingInitiator.mConnectedView).isNotNull();
-        assertThat(mHandwritingInitiator.mConnectedView.get()).isEqualTo(mTestView);
+        assertThat(mHandwritingInitiator.mConnectedView.get()).isEqualTo(mTestView1);
     }
 
     private MotionEvent createStylusEvent(int action, int x, int y, long eventTime) {
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 973b904..03d366e6 100644
--- a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutChooserActivityTest.java
@@ -33,6 +33,9 @@
 import static org.hamcrest.Matchers.endsWith;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.accessibilityservice.AccessibilityServiceInfo;
@@ -54,6 +57,7 @@
 import com.android.internal.R;
 import com.android.internal.accessibility.dialog.AccessibilityShortcutChooserActivity;
 
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -71,6 +75,7 @@
     private static final String ONE_HANDED_MODE = "One-Handed mode";
     private static final String TEST_LABEL = "TEST_LABEL";
     private static final ComponentName TEST_COMPONENT_NAME = new ComponentName("package", "class");
+    private TestAccessibilityShortcutChooserActivity mActivity;
 
     @Rule
     public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@@ -85,10 +90,22 @@
     @Mock
     private IAccessibilityManager mAccessibilityManagerService;
 
+    @Before
+    public void setUp() throws Exception {
+        when(mAccessibilityServiceInfo.getResolveInfo()).thenReturn(mResolveInfo);
+        mResolveInfo.serviceInfo = mServiceInfo;
+        mServiceInfo.applicationInfo = mApplicationInfo;
+        when(mResolveInfo.loadLabel(any(PackageManager.class))).thenReturn(TEST_LABEL);
+        when(mAccessibilityServiceInfo.getComponentName()).thenReturn(TEST_COMPONENT_NAME);
+        when(mAccessibilityManagerService.getInstalledAccessibilityServiceList(
+                anyInt())).thenReturn(Collections.singletonList(mAccessibilityServiceInfo));
+        when(mAccessibilityManagerService.isAccessibilityTargetAllowed(
+                anyString(), anyInt(), anyInt())).thenReturn(true);
+        TestAccessibilityShortcutChooserActivity.setupForTesting(mAccessibilityManagerService);
+    }
+
     @Test
-    public void doubleClickTestServiceAndClickDenyButton_permissionDialogDoesNotExist()
-            throws Exception {
-        configureTestService();
+    public void doubleClickTestServiceAndClickDenyButton_permissionDialogDoesNotExist() {
         final ActivityScenario<TestAccessibilityShortcutChooserActivity> scenario =
                 ActivityScenario.launch(TestAccessibilityShortcutChooserActivity.class);
         scenario.moveToState(Lifecycle.State.CREATED);
@@ -101,6 +118,7 @@
         onView(withText(TEST_LABEL)).perform(scrollTo(), doubleClick());
         onView(withId(R.id.accessibility_permission_enable_deny_button)).perform(scrollTo(),
                 click());
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
 
         onView(withId(R.id.accessibility_permissionDialog_title)).inRoot(isDialog()).check(
                 doesNotExist());
@@ -108,6 +126,29 @@
     }
 
     @Test
+    public void clickServiceTarget_notPermittedByAdmin_sendRestrictedDialogIntent()
+            throws Exception {
+        when(mAccessibilityManagerService.isAccessibilityTargetAllowed(
+                eq(TEST_COMPONENT_NAME.getPackageName()), anyInt(), anyInt())).thenReturn(false);
+        final ActivityScenario<TestAccessibilityShortcutChooserActivity> scenario =
+                ActivityScenario.launch(TestAccessibilityShortcutChooserActivity.class);
+        scenario.onActivity(activity -> mActivity = activity);
+        scenario.moveToState(Lifecycle.State.CREATED);
+        scenario.moveToState(Lifecycle.State.STARTED);
+        scenario.moveToState(Lifecycle.State.RESUMED);
+
+        onView(withText(R.string.accessibility_select_shortcut_menu_title)).inRoot(
+                isDialog()).check(matches(isDisplayed()));
+        onView(withText(R.string.edit_accessibility_shortcut_menu_button)).perform(click());
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+        onView(withText(TEST_LABEL)).perform(scrollTo(), click());
+        verify(mAccessibilityManagerService).sendRestrictedDialogIntent(
+                eq(TEST_COMPONENT_NAME.getPackageName()), anyInt(), anyInt());
+        scenario.moveToState(Lifecycle.State.DESTROYED);
+    }
+
+    @Test
     public void popEditShortcutMenuList_oneHandedModeEnabled_shouldBeInListView() {
         TestUtils.setOneHandedModeEnabled(this, /* enabled= */ true);
         final ActivityScenario<TestAccessibilityShortcutChooserActivity> scenario =
@@ -145,18 +186,6 @@
         scenario.moveToState(Lifecycle.State.DESTROYED);
     }
 
-    private void configureTestService() throws Exception {
-        when(mAccessibilityServiceInfo.getResolveInfo()).thenReturn(mResolveInfo);
-        mResolveInfo.serviceInfo = mServiceInfo;
-        mServiceInfo.applicationInfo = mApplicationInfo;
-        when(mResolveInfo.loadLabel(any(PackageManager.class))).thenReturn(TEST_LABEL);
-        when(mAccessibilityServiceInfo.getComponentName()).thenReturn(TEST_COMPONENT_NAME);
-        when(mAccessibilityManagerService.getInstalledAccessibilityServiceList(
-                anyInt())).thenReturn(Collections.singletonList(mAccessibilityServiceInfo));
-
-        TestAccessibilityShortcutChooserActivity.setupForTesting(mAccessibilityManagerService);
-    }
-
     /**
      * Used for testing.
      */
diff --git a/core/tests/coretests/src/com/android/internal/app/procstats/ProcessStatsTest.java b/core/tests/coretests/src/com/android/internal/app/procstats/ProcessStatsTest.java
index 9b9a84b..35b3267 100644
--- a/core/tests/coretests/src/com/android/internal/app/procstats/ProcessStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/procstats/ProcessStatsTest.java
@@ -156,4 +156,19 @@
                         eq(0),
                         eq(APP_1_PROCESS_NAME));
     }
+
+    @SmallTest
+    public void testSafelyResetClearsProcessInUidState() throws Exception {
+        ProcessStats processStats = new ProcessStats();
+        ProcessState processState =
+                processStats.getProcessStateLocked(
+                        APP_1_PACKAGE_NAME, APP_1_UID, APP_1_VERSION, APP_1_PROCESS_NAME);
+        processState.makeActive();
+        UidState uidState = processStats.mUidStates.get(APP_1_UID);
+        assertTrue(uidState.isInUse());
+        processState.makeInactive();
+        uidState.resetSafely(NOW_MS);
+        processState.makeActive();
+        assertFalse(uidState.isInUse());
+    }
 }
diff --git a/core/tests/coretests/src/com/android/internal/os/SafeZipPathValidatorCallbackTest.java b/core/tests/coretests/src/com/android/internal/os/SafeZipPathValidatorCallbackTest.java
deleted file mode 100644
index c540a15..0000000
--- a/core/tests/coretests/src/com/android/internal/os/SafeZipPathValidatorCallbackTest.java
+++ /dev/null
@@ -1,244 +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.internal.os;
-
-import static org.junit.Assert.assertThrows;
-
-import android.compat.testing.PlatformCompatChangeRule;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
-import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TestRule;
-import org.junit.runner.RunWith;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipException;
-import java.util.zip.ZipFile;
-import java.util.zip.ZipInputStream;
-import java.util.zip.ZipOutputStream;
-
-/**
- * Test SafeZipPathCallback.
- */
-@RunWith(AndroidJUnit4.class)
-public class SafeZipPathValidatorCallbackTest {
-    @Rule
-    public TestRule mCompatChangeRule = new PlatformCompatChangeRule();
-
-    @Before
-    public void setUp() {
-        RuntimeInit.initZipPathValidatorCallback();
-    }
-
-    @Test
-    @EnableCompatChanges({SafeZipPathValidatorCallback.VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL})
-    public void testNewZipFile_whenZipFileHasDangerousEntriesAndChangeEnabled_throws()
-            throws Exception {
-        final String[] dangerousEntryNames = {
-            "../foo.bar",
-            "foo/../bar.baz",
-            "foo/../../bar.baz",
-            "foo.bar/..",
-            "foo.bar/../",
-            "..",
-            "../",
-            "/foo",
-        };
-        for (String entryName : dangerousEntryNames) {
-            final File tempFile = File.createTempFile("smdc", "zip");
-            try {
-                writeZipFileOutputStreamWithEmptyEntry(tempFile, entryName);
-
-                assertThrows(
-                        "ZipException expected for entry: " + entryName,
-                        ZipException.class,
-                        () -> {
-                            new ZipFile(tempFile);
-                        });
-            } finally {
-                tempFile.delete();
-            }
-        }
-    }
-
-    @Test
-    @EnableCompatChanges({SafeZipPathValidatorCallback.VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL})
-    public void
-            testZipInputStreamGetNextEntry_whenZipFileHasDangerousEntriesAndChangeEnabled_throws()
-                    throws Exception {
-        final String[] dangerousEntryNames = {
-            "../foo.bar",
-            "foo/../bar.baz",
-            "foo/../../bar.baz",
-            "foo.bar/..",
-            "foo.bar/../",
-            "..",
-            "../",
-            "/foo",
-        };
-        for (String entryName : dangerousEntryNames) {
-            byte[] badZipBytes = getZipBytesFromZipOutputStreamWithEmptyEntry(entryName);
-            try (ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(badZipBytes))) {
-                assertThrows(
-                        "ZipException expected for entry: " + entryName,
-                        ZipException.class,
-                        () -> {
-                            zis.getNextEntry();
-                        });
-            }
-        }
-    }
-
-    @Test
-    @EnableCompatChanges({SafeZipPathValidatorCallback.VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL})
-    public void testNewZipFile_whenZipFileHasNormalEntriesAndChangeEnabled_doesNotThrow()
-            throws Exception {
-        final String[] normalEntryNames = {
-            "foo", "foo.bar", "foo..bar",
-        };
-        for (String entryName : normalEntryNames) {
-            final File tempFile = File.createTempFile("smdc", "zip");
-            try {
-                writeZipFileOutputStreamWithEmptyEntry(tempFile, entryName);
-                try {
-                    new ZipFile((tempFile));
-                } catch (ZipException e) {
-                    throw new AssertionError("ZipException not expected for entry: " + entryName);
-                }
-            } finally {
-                tempFile.delete();
-            }
-        }
-    }
-
-    @Test
-    @DisableCompatChanges({SafeZipPathValidatorCallback.VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL})
-    public void
-            testZipInputStreamGetNextEntry_whenZipFileHasNormalEntriesAndChangeEnabled_doesNotThrow()
-                    throws Exception {
-        final String[] normalEntryNames = {
-            "foo", "foo.bar", "foo..bar",
-        };
-        for (String entryName : normalEntryNames) {
-            byte[] zipBytes = getZipBytesFromZipOutputStreamWithEmptyEntry(entryName);
-            try {
-                ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(zipBytes));
-                zis.getNextEntry();
-            } catch (ZipException e) {
-                throw new AssertionError("ZipException not expected for entry: " + entryName);
-            }
-        }
-    }
-
-    @Test
-    @DisableCompatChanges({SafeZipPathValidatorCallback.VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL})
-    public void
-            testNewZipFile_whenZipFileHasNormalAndDangerousEntriesAndChangeDisabled_doesNotThrow()
-                    throws Exception {
-        final String[] entryNames = {
-            "../foo.bar",
-            "foo/../bar.baz",
-            "foo/../../bar.baz",
-            "foo.bar/..",
-            "foo.bar/../",
-            "..",
-            "../",
-            "/foo",
-            "foo",
-            "foo.bar",
-            "foo..bar",
-        };
-        for (String entryName : entryNames) {
-            final File tempFile = File.createTempFile("smdc", "zip");
-            try {
-                writeZipFileOutputStreamWithEmptyEntry(tempFile, entryName);
-                try {
-                    new ZipFile((tempFile));
-                } catch (ZipException e) {
-                    throw new AssertionError("ZipException not expected for entry: " + entryName);
-                }
-            } finally {
-                tempFile.delete();
-            }
-        }
-    }
-
-    @Test
-    @DisableCompatChanges({SafeZipPathValidatorCallback.VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL})
-    public void
-            testZipInputStreamGetNextEntry_whenZipFileHasNormalAndDangerousEntriesAndChangeDisabled_doesNotThrow()
-                    throws Exception {
-        final String[] entryNames = {
-            "../foo.bar",
-            "foo/../bar.baz",
-            "foo/../../bar.baz",
-            "foo.bar/..",
-            "foo.bar/../",
-            "..",
-            "../",
-            "/foo",
-            "foo",
-            "foo.bar",
-            "foo..bar",
-        };
-        for (String entryName : entryNames) {
-            byte[] zipBytes = getZipBytesFromZipOutputStreamWithEmptyEntry(entryName);
-            try {
-                ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(zipBytes));
-                zis.getNextEntry();
-            } catch (ZipException e) {
-                throw new AssertionError("ZipException not expected for entry: " + entryName);
-            }
-        }
-    }
-
-    private void writeZipFileOutputStreamWithEmptyEntry(File tempFile, String entryName)
-            throws IOException {
-        FileOutputStream tempFileStream = new FileOutputStream(tempFile);
-        writeZipOutputStreamWithEmptyEntry(tempFileStream, entryName);
-        tempFileStream.close();
-    }
-
-    private byte[] getZipBytesFromZipOutputStreamWithEmptyEntry(String entryName)
-            throws IOException {
-        ByteArrayOutputStream bos = new ByteArrayOutputStream();
-        writeZipOutputStreamWithEmptyEntry(bos, entryName);
-        return bos.toByteArray();
-    }
-
-    private void writeZipOutputStreamWithEmptyEntry(OutputStream os, String entryName)
-            throws IOException {
-        ZipOutputStream zos = new ZipOutputStream(os);
-        ZipEntry entry = new ZipEntry(entryName);
-        zos.putNextEntry(entry);
-        zos.write(new byte[2]);
-        zos.closeEntry();
-        zos.close();
-    }
-}
diff --git a/core/tests/fuzzers/ParcelFuzzer/ReadUtils.java b/core/tests/fuzzers/ParcelFuzzer/ReadUtils.java
index 0eff5f2..b5e5b25 100644
--- a/core/tests/fuzzers/ParcelFuzzer/ReadUtils.java
+++ b/core/tests/fuzzers/ParcelFuzzer/ReadUtils.java
@@ -97,7 +97,7 @@
     public static ReadOperation[] READ_OPERATIONS =
             new ReadOperation[] {
                     (parcel, provider) -> {
-                        parcel.setDataPosition(provider.consumeInt());
+                        parcel.setDataPosition(provider.consumeInt(0, Integer.MAX_VALUE));
                     },
                     (parcel, provider) -> {
                         parcel.setDataCapacity(provider.consumeInt());
@@ -155,6 +155,7 @@
                         byte[] array;
                         if (provider.consumeBoolean()) {
                             int pos = parcel.dataPosition();
+                            if (pos < 0) return;
                             array = new byte[Math.min(MAX_LEN, parcel.readInt())];
                             parcel.setDataPosition(pos);
                         } else {
@@ -166,6 +167,7 @@
                         char[] array;
                         if (provider.consumeBoolean()) {
                             int pos = parcel.dataPosition();
+                            if (pos < 0) return;
                             array = new char[Math.min(MAX_LEN, parcel.readInt())];
                             parcel.setDataPosition(pos);
                         } else {
@@ -177,6 +179,7 @@
                         int[] array;
                         if (provider.consumeBoolean()) {
                             int pos = parcel.dataPosition();
+                            if (pos < 0) return;
                             array = new int[Math.min(MAX_LEN, parcel.readInt())];
                             parcel.setDataPosition(pos);
                         } else {
@@ -188,6 +191,7 @@
                         double[] array;
                         if (provider.consumeBoolean()) {
                             int pos = parcel.dataPosition();
+                            if (pos < 0) return;
                             array = new double[Math.min(MAX_LEN, parcel.readInt())];
                             parcel.setDataPosition(pos);
                         } else {
@@ -199,6 +203,7 @@
                         float[] array;
                         if (provider.consumeBoolean()) {
                             int pos = parcel.dataPosition();
+                            if (pos < 0) return;
                             array = new float[Math.min(MAX_LEN, parcel.readInt())];
                             parcel.setDataPosition(pos);
                         } else {
@@ -210,6 +215,7 @@
                         boolean[] array;
                         if (provider.consumeBoolean()) {
                             int pos = parcel.dataPosition();
+                            if (pos < 0) return;
                             array = new boolean[Math.min(MAX_LEN, parcel.readInt())];
                             parcel.setDataPosition(pos);
                         } else {
@@ -221,6 +227,7 @@
                         long[] array;
                         if (provider.consumeBoolean()) {
                             int pos = parcel.dataPosition();
+                            if (pos < 0) return;
                             array = new long[Math.min(MAX_LEN, parcel.readInt())];
                             parcel.setDataPosition(pos);
                         } else {
@@ -232,6 +239,7 @@
                         IBinder[] array;
                         if (provider.consumeBoolean()) {
                             int pos = parcel.dataPosition();
+                            if (pos < 0) return;
                             array = new IBinder[Math.min(MAX_LEN, parcel.readInt())];
                             parcel.setDataPosition(pos);
                         } else {
@@ -274,6 +282,7 @@
                         SingleDataParcelable[] array;
                         if (provider.consumeBoolean()) {
                             int pos = parcel.dataPosition();
+                            if (pos < 0) return;
                             array = new SingleDataParcelable[Math.min(MAX_LEN, parcel.readInt())];
                             parcel.setDataPosition(pos);
                         } else {
@@ -293,6 +302,7 @@
                         EmptyParcelable[] array;
                         if (provider.consumeBoolean()) {
                             int pos = parcel.dataPosition();
+                            if (pos < 0) return;
                             array = new EmptyParcelable[Math.min(MAX_LEN, parcel.readInt())];
                             parcel.setDataPosition(pos);
                         } else {
@@ -312,6 +322,7 @@
                         GenericDataParcelable[] array;
                         if (provider.consumeBoolean()) {
                             int pos = parcel.dataPosition();
+                            if (pos < 0) return;
                             array = new GenericDataParcelable[Math.min(MAX_LEN, parcel.readInt())];
                             parcel.setDataPosition(pos);
                         } else {
@@ -334,6 +345,7 @@
                         SomeParcelable[] array;
                         if (provider.consumeBoolean()) {
                             int pos = parcel.dataPosition();
+                            if (pos < 0) return;
                             array = new SomeParcelable[Math.min(MAX_LEN, parcel.readInt())];
                             parcel.setDataPosition(pos);
                         } else {
@@ -390,6 +402,7 @@
                         TestInterface[] array;
                         if (provider.consumeBoolean()) {
                             int pos = parcel.dataPosition();
+                            if (pos < 0) return;
                             array = new TestInterface[Math.min(MAX_LEN, parcel.readInt())];
                             parcel.setDataPosition(pos);
                         } else {
diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
index 539eb62..be2c27d 100644
--- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
+++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
@@ -51,6 +51,7 @@
 import android.app.LoadedApk;
 import android.app.servertransaction.PendingTransactionActions;
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
@@ -293,7 +294,7 @@
 
         private Activity launchActivity(ActivityClientRecord r) {
             return mThread.handleLaunchActivity(r, null /* pendingActions */,
-                    null /* customIntent */);
+                    Context.DEVICE_ID_DEFAULT, null /* customIntent */);
         }
 
         private void startActivity(ActivityClientRecord r) {
@@ -347,7 +348,7 @@
             doNothing().when(packageInfo).updateApplicationInfo(any(), any());
 
             return new ActivityClientRecord(mock(IBinder.class), Intent.makeMainActivity(component),
-                    0 /* ident */, info, new Configuration(), 0 /*deviceId */, null /* referrer */,
+                    0 /* ident */, info, new Configuration(), null /* referrer */,
                     null /* voiceInteractor */, null /* state */, null /* persistentState */,
                     null /* pendingResults */, null /* pendingNewIntents */,
                     null /* activityOptions */, true /* isForward */, null /* profilerInfo */,
diff --git a/core/tests/overlaytests/device/Android.bp b/core/tests/overlaytests/device/Android.bp
index 0d3b15a..2b22344 100644
--- a/core/tests/overlaytests/device/Android.bp
+++ b/core/tests/overlaytests/device/Android.bp
@@ -29,6 +29,7 @@
     static_libs: [
         "androidx.test.rules",
         "testng",
+        "compatibility-device-util-axt",
     ],
     test_suites: ["device-tests"],
     data: [
diff --git a/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java b/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java
index 8e4b9ef..fcf71ed 100644
--- a/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java
+++ b/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java
@@ -37,10 +37,12 @@
 
 import androidx.test.InstrumentationRegistry;
 
+import com.android.compatibility.common.util.AmUtils;
 import com.android.internal.util.ArrayUtils;
 import com.android.overlaytest.view.TestTextView;
 
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Ignore;
 import org.junit.Test;
 
@@ -70,6 +72,13 @@
         mMode = mode;
     }
 
+    @BeforeClass
+    public static void setUpClass() {
+        // Wait for package_added broadcasts to be handled so that OverlayManagerService
+        // can update it's internal state with the new packages.
+        AmUtils.waitForBroadcastBarrier();
+    }
+
     @Before
     public void setUp() {
         mContext = InstrumentationRegistry.getContext();
diff --git a/data/etc/com.android.systemui.xml b/data/etc/com.android.systemui.xml
index 116aa489..fe639ff 100644
--- a/data/etc/com.android.systemui.xml
+++ b/data/etc/com.android.systemui.xml
@@ -24,7 +24,7 @@
         <permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/>
         <permission name="android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST"/>
         <permission name="android.permission.CHANGE_OVERLAY_PACKAGES"/>
-        <permission name="android.permission.COMPONENT_OPTION_INTERACTIVE"/>
+        <permission name="android.permission.BROADCAST_OPTION_INTERACTIVE"/>
         <permission name="android.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS"/>
         <permission name="android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS"/>
         <permission name="android.permission.CONTROL_VPN"/>
diff --git a/data/etc/preinstalled-packages-platform-overlays.xml b/data/etc/preinstalled-packages-platform-overlays.xml
index 6f6390b..9959433 100644
--- a/data/etc/preinstalled-packages-platform-overlays.xml
+++ b/data/etc/preinstalled-packages-platform-overlays.xml
@@ -53,6 +53,9 @@
     <install-in-user-type package="com.android.internal.systemui.onehanded.gestural">
         <install-in user-type="FULL" />
     </install-in-user-type>
+    <install-in-user-type package="com.android.internal.systemui.navbar.transparent">
+        <install-in user-type="FULL" />
+    </install-in-user-type>
     <install-in-user-type package="com.android.theme.color.amethyst">
         <install-in user-type="FULL" />
         <install-in user-type="PROFILE" />
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 5cb5ffa0..5d303cf 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -275,6 +275,7 @@
         <!-- Permission required to test onPermissionsChangedListener -->
         <permission name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS"/>
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+        <permission name="android.permission.QUERY_USERS"/>
         <permission name="android.permission.LOCAL_MAC_ADDRESS"/>
         <permission name="android.permission.MANAGE_ACCESSIBILITY"/>
         <permission name="android.permission.MANAGE_DEVICE_ADMINS"/>
@@ -511,6 +512,8 @@
         <permission name="android.permission.WRITE_APN_SETTINGS"/>
         <!-- Permission required for GTS test - GtsStatsdHostTestCases -->
         <permission name="android.permission.READ_RESTRICTED_STATS"/>
+        <!-- Permission required for CTS test -->
+        <permission name="android.permission.LOG_FOREGROUND_RESOURCE_USE"/>
     </privapp-permissions>
 
     <privapp-permissions package="com.android.statementservice">
@@ -539,6 +542,12 @@
         <permission name="android.permission.BIND_WALLPAPER"/>
     </privapp-permissions>
 
+    <privapp-permissions package="com.android.wallpaper">
+        <permission name="android.permission.SET_WALLPAPER_COMPONENT"/>
+        <permission name="android.permission.BIND_WALLPAPER"/>
+        <permission name="android.permission.CUSTOMIZE_SYSTEM_UI"/>
+    </privapp-permissions>
+
     <privapp-permissions package="com.android.dynsystem">
         <permission name="android.permission.REBOOT"/>
         <permission name="android.permission.MANAGE_DYNAMIC_SYSTEM"/>
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 3d81d37..ffc5ff2 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -271,6 +271,12 @@
       "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
       "at": "com\/android\/server\/wm\/AppTransition.java"
     },
+    "-1868518158": {
+      "message": "Pending back animation due to another animation is running",
+      "level": "WARN",
+      "group": "WM_DEBUG_BACK_PREVIEW",
+      "at": "com\/android\/server\/wm\/BackNavigationController.java"
+    },
     "-1868124841": {
       "message": "screenOnEarly=%b, awake=%b, currentAppOrientation=%d, orientationSensorEnabled=%b, keyguardDrawComplete=%b, windowManagerDrawComplete=%b",
       "level": "VERBOSE",
@@ -1093,6 +1099,12 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/WindowContainer.java"
     },
+    "-1104347731": {
+      "message": "Setting requested orientation %s for %s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_ORIENTATION",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "-1103716954": {
       "message": "Not removing %s due to exit animation",
       "level": "VERBOSE",
@@ -1291,6 +1303,12 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "-894942237": {
+      "message": "Force Playing Transition: %d",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_WINDOW_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/Transition.java"
+    },
     "-883738232": {
       "message": "Adding more than one toast window for UID at a time.",
       "level": "WARN",
@@ -1549,6 +1567,12 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/DragState.java"
     },
+    "-692907078": {
+      "message": "Handling the deferred animation after transition finished",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_BACK_PREVIEW",
+      "at": "com\/android\/server\/wm\/BackNavigationController.java"
+    },
     "-677449371": {
       "message": "moveTaskToRootTask: moving task=%d to rootTaskId=%d toTop=%b",
       "level": "DEBUG",
@@ -4231,12 +4255,6 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/DisplayContent.java"
     },
-    "1878927091": {
-      "message": "prepareSurface: No changes in animation for %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ANIM",
-      "at": "com\/android\/server\/wm\/WindowStateAnimator.java"
-    },
     "1891501279": {
       "message": "cancelAnimation(): reason=%s",
       "level": "DEBUG",
diff --git a/data/keyboards/Vendor_004c_Product_0265.idc b/data/keyboards/Vendor_004c_Product_0265.idc
new file mode 120000
index 0000000..707dfcf
--- /dev/null
+++ b/data/keyboards/Vendor_004c_Product_0265.idc
@@ -0,0 +1 @@
+Vendor_05ac_Product_0265.idc
\ No newline at end of file
diff --git a/data/keyboards/Vendor_03f6_Product_a001.idc b/data/keyboards/Vendor_03f6_Product_a001.idc
new file mode 100644
index 0000000..bcb4ee3
--- /dev/null
+++ b/data/keyboards/Vendor_03f6_Product_a001.idc
@@ -0,0 +1,22 @@
+# 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.
+
+#
+# Brydge Touchpad
+#
+
+# Reports from this touchpad sometimes get bunched together due to Bluetooth
+# batching, leading to bad timestamps that mess up finger velocity calculations.
+# To fix this, set a fake delta using the touchpad's known report rate.
+gestureProp.Fake_Timestamp_Delta = 0.010
diff --git a/data/keyboards/Vendor_046d_Product_4011.idc b/data/keyboards/Vendor_046d_Product_4011.idc
new file mode 100644
index 0000000..3a23830
--- /dev/null
+++ b/data/keyboards/Vendor_046d_Product_4011.idc
@@ -0,0 +1,32 @@
+# 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.
+
+#
+# Logitech Wireless Touchpad
+#
+
+gestureProp.Touchpad_Stack_Version = 1
+gestureProp.IIR_b0 = 1
+gestureProp.IIR_b1 = 0
+gestureProp.IIR_b2 = 0
+gestureProp.IIR_b3 = 0
+gestureProp.IIR_a1 = 0
+gestureProp.IIR_a2 = 0
+gestureProp.Pressure_Calibration_Offset = -313.240741792594
+gestureProp.Pressure_Calibration_Slope = 4.39678062436752
+gestureProp.Max_Allowed_Pressure_Change_Per_Sec = 100000.0
+gestureProp.Max_Hysteresis_Pressure_Per_Sec = 100000.0
+gestureProp.Palm_Pressure = 100000.0
+gestureProp.Two_Finger_Vertical_Close_Distance_Thresh = 35.0
+gestureProp.Fling_Buffer_Suppress_Zero_Length_Scrolls = 0
diff --git a/data/keyboards/Vendor_046d_Product_4101.idc b/data/keyboards/Vendor_046d_Product_4101.idc
new file mode 100644
index 0000000..47e2530
--- /dev/null
+++ b/data/keyboards/Vendor_046d_Product_4101.idc
@@ -0,0 +1,31 @@
+# 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.
+
+#
+# Logitech T650
+#
+
+gestureProp.Touchpad_Stack_Version = 1
+gestureProp.IIR_b0 = 1
+gestureProp.IIR_b1 = 0
+gestureProp.IIR_b2 = 0
+gestureProp.IIR_b3 = 0
+gestureProp.IIR_a1 = 0
+gestureProp.IIR_a2 = 0
+gestureProp.Pressure_Calibration_Offset = -0.439288351750068
+gestureProp.Pressure_Calibration_Slope = 3.05998553523335
+gestureProp.Max_Allowed_Pressure_Change_Per_Sec = 100000.0
+gestureProp.Max_Hysteresis_Pressure_Per_Sec = 100000.0
+gestureProp.Two_Finger_Vertical_Close_Distance_Thresh = 35.0
+gestureProp.Fling_Buffer_Suppress_Zero_Length_Scrolls = 0
diff --git a/data/keyboards/Vendor_046d_Product_4102.idc b/data/keyboards/Vendor_046d_Product_4102.idc
new file mode 100644
index 0000000..e33a28a
--- /dev/null
+++ b/data/keyboards/Vendor_046d_Product_4102.idc
@@ -0,0 +1,24 @@
+# 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.
+
+#
+# Logitech TK820
+#
+
+gestureProp.Touchpad_Stack_Version = 2
+# Pressure jumps around a lot on this touchpad, so allow that:
+gestureProp.Max_Allowed_Pressure_Change_Per_Sec = 100000.0
+gestureProp.Max_Hysteresis_Pressure_Per_Sec = 100000.0
+gestureProp.Pressure_Calibration_Offset = -18.8078435
+gestureProp.Pressure_Calibration_Slope = 2.466208137
diff --git a/data/keyboards/Vendor_046d_Product_b00c.idc b/data/keyboards/Vendor_046d_Product_b00c.idc
new file mode 100644
index 0000000..a49970c
--- /dev/null
+++ b/data/keyboards/Vendor_046d_Product_b00c.idc
@@ -0,0 +1,31 @@
+# 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.
+
+#
+# Logitech T651
+#
+
+gestureProp.Touchpad_Stack_Version = 1
+gestureProp.IIR_b0 = 1
+gestureProp.IIR_b1 = 0
+gestureProp.IIR_b2 = 0
+gestureProp.IIR_b3 = 0
+gestureProp.IIR_a1 = 0
+gestureProp.IIR_a2 = 0
+gestureProp.Pressure_Calibration_Offset = -4.46520447177073
+gestureProp.Pressure_Calibration_Slope = 3.21071719332644
+gestureProp.Max_Allowed_Pressure_Change_Per_Sec = 100000.0
+gestureProp.Max_Hysteresis_Pressure_Per_Sec = 100000.0
+gestureProp.Two_Finger_Vertical_Close_Distance_Thresh = 35.0
+gestureProp.Fling_Buffer_Suppress_Zero_Length_Scrolls = 0
diff --git a/data/keyboards/Vendor_05ac_Product_0265.idc b/data/keyboards/Vendor_05ac_Product_0265.idc
new file mode 100644
index 0000000..d72de64
--- /dev/null
+++ b/data/keyboards/Vendor_05ac_Product_0265.idc
@@ -0,0 +1,34 @@
+# 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.
+
+#
+# Apple Magic Trackpad 2 configuration file
+#   Bluetooth vendor ID 004c
+#   USB vendor ID 05ac
+#
+
+gestureProp.Pressure_Calibration_Offset = 30
+gestureProp.Palm_Pressure = 250.0
+gestureProp.Palm_Width = 20.0
+gestureProp.Multiple_Palm_Width = 20.0
+
+# Enable Stationary Wiggle Filter
+gestureProp.Stationary_Wiggle_Filter_Enabled = 1
+gestureProp.Finger_Moving_Energy = 0.0008
+gestureProp.Finger_Moving_Hysteresis = 0.0004
+
+# Avoid accidental scroll/move on finger lift
+gestureProp.Max_Stationary_Move_Speed = 47
+gestureProp.Max_Stationary_Move_Speed_Hysteresis = 1
+gestureProp.Max_Stationary_Move_Suppress_Distance = 0.2
diff --git a/data/keyboards/Vendor_05ac_Product_030e.idc b/data/keyboards/Vendor_05ac_Product_030e.idc
new file mode 100644
index 0000000..23a2e18
--- /dev/null
+++ b/data/keyboards/Vendor_05ac_Product_030e.idc
@@ -0,0 +1,38 @@
+# 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.
+
+#
+# Apple Magic Trackpad
+#
+
+gestureProp.Touchpad_Stack_Version = 1
+# We are using raw touch major value as pressure value, so set the Palm
+# pressure threshold high.
+gestureProp.Palm_Pressure = 1000
+gestureProp.Compute_Surface_Area_from_Pressure = 0
+gestureProp.IIR_b0 = 1
+gestureProp.IIR_b1 = 0
+gestureProp.IIR_b2 = 0
+gestureProp.IIR_b3 = 0
+gestureProp.IIR_a1 = 0
+gestureProp.IIR_a2 = 0
+# NOTE: bias on X-axis is uncalibrated
+gestureProp.Touchpad_Device_Output_Bias_on_X-Axis = -283.3226025266607
+gestureProp.Touchpad_Device_Output_Bias_on_Y-Axis = -283.3226025266607
+gestureProp.Max_Allowed_Pressure_Change_Per_Sec = 100000.0
+gestureProp.Max_Hysteresis_Pressure_Per_Sec = 100000.0
+# Drumroll suppression causes janky movement on this touchpad.
+gestureProp.Drumroll_Suppression_Enable = 0
+gestureProp.Two_Finger_Vertical_Close_Distance_Thresh = 35.0
+gestureProp.Fling_Buffer_Suppress_Zero_Length_Scrolls = 0
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index a39dd08..8dd23b7 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -2001,7 +2001,7 @@
         checkPixelAccess(x, y);
 
         final ColorSpace cs = getColorSpace();
-        if (cs.equals(ColorSpace.get(ColorSpace.Named.SRGB))) {
+        if (cs == null || cs.equals(ColorSpace.get(ColorSpace.Named.SRGB))) {
             return Color.valueOf(nativeGetPixel(mNativePtr, x, y));
         }
         // The returned value is in kRGBA_F16_SkColorType, which is packed as
diff --git a/graphics/java/android/graphics/Color.java b/graphics/java/android/graphics/Color.java
index 87a8053..0f2f879 100644
--- a/graphics/java/android/graphics/Color.java
+++ b/graphics/java/android/graphics/Color.java
@@ -767,7 +767,7 @@
      * Returns the alpha component encoded in the specified color long.
      * The returned value is always in the range \([0..1]\).
      *
-     * @param color The color long whose blue channel to extract
+     * @param color The color long whose alpha channel to extract
      * @return A float value in the range \([0..1]\)
      *
      * @see #colorSpace(long)
diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java
index 4c669b8..24fea01 100644
--- a/graphics/java/android/graphics/ColorSpace.java
+++ b/graphics/java/android/graphics/ColorSpace.java
@@ -170,7 +170,7 @@
     /**
      * Standard CIE 1931 2° illuminant D65, encoded in xyY.
      * This illuminant has a color temperature of 6504K. This illuminant
-     * is commonly used in RGB color spaces such as sRGB, BT.209, etc.
+     * is commonly used in RGB color spaces such as sRGB, BT.709, etc.
      */
     public static final float[] ILLUMINANT_D65 = { 0.31271f, 0.32902f };
     /**
@@ -862,8 +862,8 @@
     public enum Model {
         /**
          * The RGB model is a color model with 3 components that
-         * refer to the three additive primiaries: red, green
-         * andd blue.
+         * refer to the three additive primaries: red, green
+         * and blue.
          */
         RGB(3),
         /**
@@ -2537,7 +2537,7 @@
          * does not need to be specified and is assumed to be 1.0. Only the xy components
          * are required.</p>
          *
-         * <p class="note">The ID, areturned by {@link #getId()}, of an object created by
+         * <p class="note">The ID, as returned by {@link #getId()}, of an object created by
          * this constructor is always {@link #MIN_ID}.</p>
          *
          * @param name Name of the color space, cannot be null, its length must be >= 1
@@ -3961,7 +3961,7 @@
              *
              * <p>We can only connect color spaces if they use the same profile
              * connection space. We assume the connection space is always
-             * CIE XYZ but we maye need to perform a chromatic adaptation to
+             * CIE XYZ but we maybe need to perform a chromatic adaptation to
              * match the white points. If an adaptation is needed, we use the
              * CIE standard illuminant D50. The unmatched color space is adapted
              * using the von Kries transform and the {@link Adaptation#BRADFORD}
diff --git a/graphics/java/android/graphics/Gainmap.java b/graphics/java/android/graphics/Gainmap.java
index a7c508c..9ac84a6 100644
--- a/graphics/java/android/graphics/Gainmap.java
+++ b/graphics/java/android/graphics/Gainmap.java
@@ -25,13 +25,11 @@
 
 /**
  * Gainmap represents a mechanism for augmenting an SDR image to produce an HDR one with variable
- * display adjustment capability.
- *
- * It is a combination of a set of metadata describing how to apply the gainmap, as well as either
- * a 1 (such as {@link android.graphics.Bitmap.Config#ALPHA_8} or 3
+ * display adjustment capability. It is a combination of a set of metadata describing how to apply
+ * the gainmap, as well as either a 1 (such as {@link android.graphics.Bitmap.Config#ALPHA_8} or 3
  * (such as {@link android.graphics.Bitmap.Config#ARGB_8888} with the alpha channel ignored)
  * channel Bitmap that represents the gainmap data itself.
- *
+ * <p>
  * When rendering to an {@link android.content.pm.ActivityInfo#COLOR_MODE_HDR} activity, the
  * hardware accelerated {@link Canvas} will automatically apply the gainmap when sufficient
  * HDR headroom is available.
@@ -45,7 +43,7 @@
  * image, often at a lower resolution (such as 1/4th), along with some metadata to describe
  * how to apply the gainmap. The gainmap image itself is then a greyscale image representing
  * the transformation to apply onto the base image to reconstruct an HDR rendition of it.
- *
+ * <p>
  * As such these "gainmap images" consist of 3 parts - a base {@link Bitmap} with a
  * {@link Bitmap#getGainmap()} that returns an instance of this class which in turn contains
  * the enhancement layer represented as another Bitmap, accessible via {@link #getGainmapContents()}
@@ -55,28 +53,30 @@
  * When doing custom rendering such as to an OpenGL ES or Vulkan context, the gainmap is not
  * automatically applied. In such situations, the following steps are appropriate to render the
  * gainmap in combination with the base image.
- *
+ * <p>
  * Suppose our display has HDR to SDR ratio of H, and we wish to display an image with gainmap on
  * this display. Let B be the pixel value from the base image in a color space that has the
  * primaries of the base image and a linear transfer function. Let G be the pixel value from the
  * gainmap. Let D be the output pixel in the same color space as B. The value of D is computed
  * as follows:
- *
+ * <p>
  * First, let W be a weight parameter determining how much the gainmap will be applied.
- *   W = clamp((log(H)               - log(displayRatioHdr)) /
- *             (log(displayRatioHdr) - log(displayRatioSdr), 0, 1)
+ * <pre class="prettyprint">
+ *   W = clamp((log(H)                      - log(minDisplayRatioForHdrTransition)) /
+ *             (log(displayRatioForFullHdr) - log(minDisplayRatioForHdrTransition), 0, 1)</pre>
  *
  * Next, let L be the gainmap value in log space. We compute this from the value G that was
  * sampled from the texture as follows:
- *   L = mix(log(gainmapRatioMin), log(gainmapRatioMax), pow(G, gainmapGamma))
- *
+ * <pre class="prettyprint">
+ *   L = mix(log(ratioMin), log(ratioMax), pow(G, gamma))</pre>
  * Finally, apply the gainmap to compute D, the displayed pixel. If the base image is SDR then
  * compute:
- *   D = (B + epsilonSdr) * exp(L * W) - epsilonHdr
- * If the base image is HDR then compute:
- *   D = (B + epsilonHdr) * exp(L * (W - 1)) - epsilonSdr
- *
- * In the above math, log() is a natural logarithm and exp() is natural exponentiation.
+ * <pre class="prettyprint">
+ *   D = (B + epsilonSdr) * exp(L * W) - epsilonHdr</pre>
+ * <p>
+ * In the above math, log() is a natural logarithm and exp() is natural exponentiation. The base
+ * for these functions cancels out and does not affect the result, so other bases may be used
+ * if preferred.
  */
 public final class Gainmap implements Parcelable {
 
@@ -150,7 +150,6 @@
     /**
      * Sets the gainmap ratio min. For single-plane gainmaps, r, g, and b should be the same.
      */
-    @NonNull
     public void setRatioMin(float r, float g, float b) {
         nSetRatioMin(mNativePtr, r, g, b);
     }
@@ -169,7 +168,6 @@
     /**
      * Sets the gainmap ratio max. For single-plane gainmaps, r, g, and b should be the same.
      */
-    @NonNull
     public void setRatioMax(float r, float g, float b) {
         nSetRatioMax(mNativePtr, r, g, b);
     }
@@ -188,7 +186,6 @@
     /**
      * Sets the gainmap gamma. For single-plane gainmaps, r, g, and b should be the same.
      */
-    @NonNull
     public void setGamma(float r, float g, float b) {
         nSetGamma(mNativePtr, r, g, b);
     }
@@ -208,7 +205,6 @@
      * Sets the sdr epsilon which is used to avoid numerical instability.
      * For single-plane gainmaps, r, g, and b should be the same.
      */
-    @NonNull
     public void setEpsilonSdr(float r, float g, float b) {
         nSetEpsilonSdr(mNativePtr, r, g, b);
     }
@@ -228,7 +224,6 @@
      * Sets the hdr epsilon which is used to avoid numerical instability.
      * For single-plane gainmaps, r, g, and b should be the same.
      */
-    @NonNull
     public void setEpsilonHdr(float r, float g, float b) {
         nSetEpsilonHdr(mNativePtr, r, g, b);
     }
@@ -248,8 +243,7 @@
      * Sets the hdr/sdr ratio at which point the gainmap is fully applied.
      * @param max The hdr/sdr ratio at which the gainmap is fully applied. Must be >= 1.0f
      */
-    @NonNull
-    public void setDisplayRatioForFullHdr(float max) {
+    public void setDisplayRatioForFullHdr(@FloatRange(from = 1.0f) float max) {
         if (!Float.isFinite(max) || max < 1f) {
             throw new IllegalArgumentException(
                     "setDisplayRatioForFullHdr must be >= 1.0f, got = " + max);
@@ -269,7 +263,6 @@
      * Sets the hdr/sdr ratio below which only the SDR image is displayed.
      * @param min The minimum hdr/sdr ratio at which to begin applying the gainmap. Must be >= 1.0f
      */
-    @NonNull
     public void setMinDisplayRatioForHdrTransition(@FloatRange(from = 1.0f) float min) {
         if (!Float.isFinite(min) || min < 1f) {
             throw new IllegalArgumentException(
diff --git a/graphics/java/android/graphics/Mesh.java b/graphics/java/android/graphics/Mesh.java
index 6a1313e..66fabec 100644
--- a/graphics/java/android/graphics/Mesh.java
+++ b/graphics/java/android/graphics/Mesh.java
@@ -341,7 +341,6 @@
      * @hide so only calls from module can utilize it
      */
     long getNativeWrapperInstance() {
-        nativeUpdateMesh(mNativeMeshWrapper, mIsIndexed);
         return mNativeMeshWrapper;
     }
 
@@ -383,5 +382,4 @@
 
     private static native void nativeUpdateUniforms(long builder, String uniformName, int[] values);
 
-    private static native void nativeUpdateMesh(long nativeMeshWrapper, boolean mIsIndexed);
 }
diff --git a/graphics/java/android/graphics/text/GraphemeBreak.java b/graphics/java/android/graphics/text/GraphemeBreak.java
new file mode 100644
index 0000000..f82b2fd
--- /dev/null
+++ b/graphics/java/android/graphics/text/GraphemeBreak.java
@@ -0,0 +1,59 @@
+/*
+ * 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.text;
+
+/** @hide */
+public class GraphemeBreak {
+    private GraphemeBreak() { }
+
+    /**
+     * Util method that checks if the offsets in given range are grapheme break.
+     *
+     * @param advances the advances of characters in the given text. It contains the font
+     *                information used by the algorithm to determine the grapheme break. It's useful
+     *                 when some character is missing in the font. For example, if the smile emoji
+     *                 "0xD83D 0xDE0A" is not found in the font and is displayed as 2 characters.
+     *                 We can't treat it as a single grapheme cluster.
+     * @param text the text to be processed.
+     * @param start the start offset of the queried range, inclusive.
+     * @param end the end offset of the queried range, exclusive.
+     * @param isGraphemeBreak the array to receive the result. The i-th element of the
+     *                       array will be set to true if the offset (start + i) is a grapheme
+     *                       break; otherwise, it will be set to false.
+     */
+    public static void isGraphemeBreak(float[] advances, char[] text, int start, int end,
+            boolean[] isGraphemeBreak) {
+        if (start > end) {
+            throw new IllegalArgumentException("start is greater than end: start = " + start
+                    + " end = " + end);
+        }
+        if (advances.length < end) {
+            throw new IllegalArgumentException("the length of advances is less than end"
+                    + "advances.length = " + advances.length
+                    + " end = " + end);
+        }
+        if (isGraphemeBreak.length < end - start) {
+            throw new IndexOutOfBoundsException("isGraphemeBreak doesn't have enough space to "
+                    + "receive the result, isGraphemeBreak.length: " + isGraphemeBreak.length
+                    + " needed space: " + (end - start));
+        }
+        nIsGraphemeBreak(advances, text, start, end, isGraphemeBreak);
+    }
+
+    private static native void nIsGraphemeBreak(float[] advances, char[] text, int start, int end,
+            boolean[] isGraphemeBreak);
+}
diff --git a/graphics/java/android/graphics/text/LineBreaker.java b/graphics/java/android/graphics/text/LineBreaker.java
index 67eb117..babcfc3 100644
--- a/graphics/java/android/graphics/text/LineBreaker.java
+++ b/graphics/java/android/graphics/text/LineBreaker.java
@@ -22,7 +22,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Px;
-import android.os.Trace;
 
 import dalvik.annotation.optimization.CriticalNative;
 import dalvik.annotation.optimization.FastNative;
@@ -476,26 +475,19 @@
             @NonNull MeasuredText measuredPara,
             @NonNull ParagraphConstraints constraints,
             @IntRange(from = 0) int lineNumber) {
-        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "compute line break");
-        long result = 0;
-        try {
-            result = nComputeLineBreaks(
-                    mNativePtr,
+        return new Result(nComputeLineBreaks(
+                mNativePtr,
 
-                    // Inputs
-                    measuredPara.getChars(),
-                    measuredPara.getNativePtr(),
-                    measuredPara.getChars().length,
-                    constraints.mFirstWidth,
-                    constraints.mFirstWidthLineCount,
-                    constraints.mWidth,
-                    constraints.mVariableTabStops,
-                    constraints.mDefaultTabStop,
-                    lineNumber);
-        } finally {
-            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
-        }
-        return new Result(result);
+                // Inputs
+                measuredPara.getChars(),
+                measuredPara.getNativePtr(),
+                measuredPara.getChars().length,
+                constraints.mFirstWidth,
+                constraints.mFirstWidthLineCount,
+                constraints.mWidth,
+                constraints.mVariableTabStops,
+                constraints.mDefaultTabStop,
+                lineNumber));
     }
 
     @FastNative
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
index c1f6c29..c3b0f9b 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -808,9 +808,12 @@
                         KeymasterDefs.KM_TAG_ATTESTATION_ID_BRAND,
                         platformReportedBrand.getBytes(StandardCharsets.UTF_8)
                 ));
+                final String platformReportedDevice =
+                        isPropertyEmptyOrUnknown(Build.DEVICE_FOR_ATTESTATION)
+                                ? Build.DEVICE : Build.DEVICE_FOR_ATTESTATION;
                 params.add(KeyStore2ParameterUtils.makeBytes(
                         KeymasterDefs.KM_TAG_ATTESTATION_ID_DEVICE,
-                        Build.DEVICE.getBytes(StandardCharsets.UTF_8)
+                        platformReportedDevice.getBytes(StandardCharsets.UTF_8)
                 ));
                 final String platformReportedProduct =
                         isPropertyEmptyOrUnknown(Build.PRODUCT_FOR_ATTESTATION)
@@ -819,9 +822,12 @@
                         KeymasterDefs.KM_TAG_ATTESTATION_ID_PRODUCT,
                         platformReportedProduct.getBytes(StandardCharsets.UTF_8)
                 ));
+                final String platformReportedManufacturer =
+                        isPropertyEmptyOrUnknown(Build.MANUFACTURER_FOR_ATTESTATION)
+                                ? Build.MANUFACTURER : Build.MANUFACTURER_FOR_ATTESTATION;
                 params.add(KeyStore2ParameterUtils.makeBytes(
                         KeymasterDefs.KM_TAG_ATTESTATION_ID_MANUFACTURER,
-                        Build.MANUFACTURER.getBytes(StandardCharsets.UTF_8)
+                        platformReportedManufacturer.getBytes(StandardCharsets.UTF_8)
                 ));
                 final String platformReportedModel =
                         isPropertyEmptyOrUnknown(Build.MODEL_FOR_ATTESTATION)
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/CommonFoldingFeature.java b/libs/WindowManager/Jetpack/src/androidx/window/common/CommonFoldingFeature.java
index 68ff806..65955b1 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/common/CommonFoldingFeature.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/common/CommonFoldingFeature.java
@@ -21,6 +21,7 @@
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.graphics.Rect;
+import android.hardware.devicestate.DeviceStateManager;
 import android.util.Log;
 
 import androidx.annotation.NonNull;
@@ -33,7 +34,8 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-/** A representation of a folding feature for both Extension and Sidecar.
+/**
+ * A representation of a folding feature for both Extension and Sidecar.
  * For Sidecar this is the same as combining {@link androidx.window.sidecar.SidecarDeviceState} and
  * {@link androidx.window.sidecar.SidecarDisplayFeature}. For Extensions this is the mirror of
  * {@link androidx.window.extensions.layout.FoldingFeature}.
@@ -67,10 +69,11 @@
     public static final int COMMON_STATE_UNKNOWN = -1;
 
     /**
-     * A common state to represent a FLAT hinge. This is needed because the definitions in Sidecar
-     * and Extensions do not match exactly.
+     * A common state that contains no folding features. For example, an in-folding device in the
+     * "closed" device state.
      */
-    public static final int COMMON_STATE_FLAT = 3;
+    public static final int COMMON_STATE_NO_FOLDING_FEATURES = 1;
+
     /**
      * A common state to represent a HALF_OPENED hinge. This is needed because the definitions in
      * Sidecar and Extensions do not match exactly.
@@ -78,9 +81,27 @@
     public static final int COMMON_STATE_HALF_OPENED = 2;
 
     /**
-     * The possible states for a folding hinge.
+     * A common state to represent a FLAT hinge. This is needed because the definitions in Sidecar
+     * and Extensions do not match exactly.
      */
-    @IntDef({COMMON_STATE_UNKNOWN, COMMON_STATE_FLAT, COMMON_STATE_HALF_OPENED})
+    public static final int COMMON_STATE_FLAT = 3;
+
+    /**
+     * A common state where the hinge state should be derived using the base state from
+     * {@link DeviceStateManager.DeviceStateCallback#onBaseStateChanged(int)} instead of the
+     * emulated state. This is an internal state and must not be passed to clients.
+     */
+    public static final int COMMON_STATE_USE_BASE_STATE = 1000;
+
+    /**
+     * The possible states for a folding hinge. Common in this context means normalized between
+     * extensions and sidecar.
+     */
+    @IntDef({COMMON_STATE_UNKNOWN,
+            COMMON_STATE_NO_FOLDING_FEATURES,
+            COMMON_STATE_HALF_OPENED,
+            COMMON_STATE_FLAT,
+            COMMON_STATE_USE_BASE_STATE})
     @Retention(RetentionPolicy.SOURCE)
     public @interface State {
     }
@@ -167,7 +188,7 @@
             }
             String stateString = featureMatcher.group(6);
             stateString = stateString == null ? "" : stateString;
-            final int state;
+            @State final int state;
             switch (stateString) {
                 case PATTERN_STATE_FLAT:
                     state = COMMON_STATE_FLAT;
@@ -191,8 +212,8 @@
     @NonNull
     private final Rect mRect;
 
-    CommonFoldingFeature(int type, int state, @NonNull Rect rect) {
-        assertValidState(state);
+    CommonFoldingFeature(int type, @State int state, @NonNull Rect rect) {
+        assertReportableState(state);
         this.mType = type;
         this.mState = state;
         if (rect.width() == 0 && rect.height() == 0) {
@@ -231,13 +252,22 @@
     }
 
     @Override
+    public String toString() {
+        return "CommonFoldingFeature=[Type: " + mType + ", state: " + mState + "]";
+    }
+
+    @Override
     public int hashCode() {
         return Objects.hash(mType, mState, mRect);
     }
 
-    private static void assertValidState(@Nullable Integer state) {
-        if (state != null && state != COMMON_STATE_FLAT
-                && state != COMMON_STATE_HALF_OPENED && state != COMMON_STATE_UNKNOWN) {
+    /**
+     * Checks if the provided folding feature state should be reported to clients. See
+     * {@link androidx.window.extensions.layout.FoldingFeature}
+     */
+    private static void assertReportableState(@State int state) {
+        if (state != COMMON_STATE_FLAT && state != COMMON_STATE_HALF_OPENED
+                && state != COMMON_STATE_UNKNOWN) {
             throw new IllegalArgumentException("Invalid state: " + state
                     + "must be either COMMON_STATE_FLAT or COMMON_STATE_HALF_OPENED");
         }
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java
index 0bdf98c..66f27f5 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java
@@ -19,6 +19,7 @@
 import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
 
 import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_UNKNOWN;
+import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_USE_BASE_STATE;
 import static androidx.window.common.CommonFoldingFeature.parseListFromString;
 
 import android.annotation.NonNull;
@@ -52,13 +53,54 @@
             DeviceStateManagerFoldingFeatureProducer.class.getSimpleName();
     private static final boolean DEBUG = false;
 
+    /**
+     * Emulated device state {@link DeviceStateManager.DeviceStateCallback#onStateChanged(int)} to
+     * {@link CommonFoldingFeature.State} map.
+     */
     private final SparseIntArray mDeviceStateToPostureMap = new SparseIntArray();
 
+    /**
+     * Emulated device state received via
+     * {@link DeviceStateManager.DeviceStateCallback#onStateChanged(int)}.
+     * "Emulated" states differ from "base" state in the sense that they may not correspond 1:1 with
+     * physical device states. They represent the state of the device when various software
+     * features and APIs are applied. The emulated states generally consist of all "base" states,
+     * but may have additional states such as "concurrent" or "rear display". Concurrent mode for
+     * example is activated via public API and can be active in both the "open" and "half folded"
+     * device states.
+     */
     private int mCurrentDeviceState = INVALID_DEVICE_STATE;
 
+    /**
+     * Base device state received via
+     * {@link DeviceStateManager.DeviceStateCallback#onBaseStateChanged(int)}.
+     * "Base" in this context means the "physical" state of the device.
+     */
+    private int mCurrentBaseDeviceState = INVALID_DEVICE_STATE;
+
     @NonNull
     private final BaseDataProducer<String> mRawFoldSupplier;
 
+    private final DeviceStateCallback mDeviceStateCallback = new DeviceStateCallback() {
+        @Override
+        public void onStateChanged(int state) {
+            mCurrentDeviceState = state;
+            mRawFoldSupplier.getData(DeviceStateManagerFoldingFeatureProducer
+                    .this::notifyFoldingFeatureChange);
+        }
+
+        @Override
+        public void onBaseStateChanged(int state) {
+            mCurrentBaseDeviceState = state;
+
+            if (mDeviceStateToPostureMap.get(mCurrentDeviceState)
+                    == COMMON_STATE_USE_BASE_STATE) {
+                mRawFoldSupplier.getData(DeviceStateManagerFoldingFeatureProducer
+                        .this::notifyFoldingFeatureChange);
+            }
+        }
+    };
+
     public DeviceStateManagerFoldingFeatureProducer(@NonNull Context context,
             @NonNull BaseDataProducer<String> rawFoldSupplier) {
         mRawFoldSupplier = rawFoldSupplier;
@@ -92,12 +134,8 @@
         }
 
         if (mDeviceStateToPostureMap.size() > 0) {
-            DeviceStateCallback deviceStateCallback = (state) -> {
-                mCurrentDeviceState = state;
-                mRawFoldSupplier.getData(this::notifyFoldingFeatureChange);
-            };
             Objects.requireNonNull(context.getSystemService(DeviceStateManager.class))
-                    .registerCallback(context.getMainExecutor(), deviceStateCallback);
+                    .registerCallback(context.getMainExecutor(), mDeviceStateCallback);
         }
     }
 
@@ -178,11 +216,18 @@
     }
 
     private List<CommonFoldingFeature> calculateFoldingFeature(String displayFeaturesString) {
-        final int globalHingeState = globalHingeState();
-        return parseListFromString(displayFeaturesString, globalHingeState);
+        return parseListFromString(displayFeaturesString, currentHingeState());
     }
 
-    private int globalHingeState() {
-        return mDeviceStateToPostureMap.get(mCurrentDeviceState, COMMON_STATE_UNKNOWN);
+    @CommonFoldingFeature.State
+    private int currentHingeState() {
+        @CommonFoldingFeature.State
+        int posture = mDeviceStateToPostureMap.get(mCurrentDeviceState, COMMON_STATE_UNKNOWN);
+
+        if (posture == CommonFoldingFeature.COMMON_STATE_USE_BASE_STATE) {
+            posture = mDeviceStateToPostureMap.get(mCurrentBaseDeviceState, COMMON_STATE_UNKNOWN);
+        }
+
+        return posture;
     }
 }
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 274dcae..575b0ce 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
@@ -263,8 +263,10 @@
                 return;
             }
             @WindowAreaStatus int currentStatus = getCurrentRearDisplayPresentationModeStatus();
+            DisplayMetrics metrics =
+                    currentStatus == STATUS_UNSUPPORTED ? null : getRearDisplayMetrics();
             consumer.accept(
-                    new RearDisplayPresentationStatus(currentStatus, getRearDisplayMetrics()));
+                    new RearDisplayPresentationStatus(currentStatus, metrics));
         }
     }
 
@@ -408,6 +410,10 @@
 
     @GuardedBy("mLock")
     private int getCurrentRearDisplayModeStatus() {
+        if (mRearDisplayState == INVALID_DEVICE_STATE) {
+            return WindowAreaComponent.STATUS_UNSUPPORTED;
+        }
+
         if (mRearDisplaySessionStatus == WindowAreaComponent.SESSION_STATE_ACTIVE
                 || !ArrayUtils.contains(mCurrentSupportedDeviceStates, mRearDisplayState)
                 || isRearDisplayActive()) {
@@ -441,6 +447,10 @@
 
     @GuardedBy("mLock")
     private int getCurrentRearDisplayPresentationModeStatus() {
+        if (mConcurrentDisplayState == INVALID_DEVICE_STATE) {
+            return WindowAreaComponent.STATUS_UNSUPPORTED;
+        }
+
         if (mCurrentDeviceState == mConcurrentDisplayState
                 || !ArrayUtils.contains(mCurrentSupportedDeviceStates, mConcurrentDisplayState)
                 || isDeviceFolded()) {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 9f3c19b..404429a 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -752,8 +752,6 @@
     @GuardedBy("mLock")
     void onActivityCreated(@NonNull WindowContainerTransaction wct,
             @NonNull Activity launchedActivity) {
-        // TODO(b/229680885): we don't support launching into primary yet because we want to always
-        // launch the new activity on top.
         resolveActivityToContainer(wct, launchedActivity, false /* isOnReparent */);
         updateCallbackIfNecessary();
     }
@@ -789,6 +787,13 @@
             return true;
         }
 
+        final TaskFragmentContainer container = getContainerWithActivity(activity);
+        if (!isOnReparent && container != null
+                && container.getTaskContainer().getTopTaskFragmentContainer() != container) {
+            // Do not resolve if the launched activity is not the top-most container in the Task.
+            return true;
+        }
+
         /*
          * We will check the following to see if there is any embedding rule matched:
          * 1. Whether the new launched activity should always expand.
@@ -811,6 +816,13 @@
             return true;
         }
 
+        // Skip resolving the following split-rules if the launched activity has been requested
+        // to be launched into its current container.
+        if (container != null && container.isActivityInRequestedTaskFragment(
+                activity.getActivityToken())) {
+            return true;
+        }
+
         // 3. Whether the new launched activity has already been in a split with a rule matched.
         if (isNewActivityInSplitWithRuleMatched(activity)) {
             return true;
@@ -988,7 +1000,10 @@
     Activity findActivityBelow(@NonNull Activity activity) {
         Activity activityBelow = null;
         final TaskFragmentContainer container = getContainerWithActivity(activity);
-        if (container != null) {
+        // Looking for the activity below from the information we already have if the container
+        // only embeds activities of the same process because activities of other processes are not
+        // available in this embedding host process for security concern.
+        if (container != null && !container.hasCrossProcessActivities()) {
             final List<Activity> containerActivities = container.collectNonFinishingActivities();
             final int index = containerActivities.indexOf(activity);
             if (index > 0) {
@@ -2066,6 +2081,12 @@
                         if (!container.hasActivity(activityToken)
                                 && container.getTaskFragmentToken()
                                 .equals(initialTaskFragmentToken)) {
+                            if (ActivityClient.getInstance().isRequestedToLaunchInTaskFragment(
+                                    activityToken, initialTaskFragmentToken)) {
+                                container.addPendingAppearedInRequestedTaskFragmentActivity(
+                                        activity);
+                            }
+
                             // The onTaskFragmentInfoChanged callback containing this activity has
                             // not reached the client yet, so add the activity to the pending
                             // appeared activities.
@@ -2157,6 +2178,14 @@
             // TODO(b/232042367): Consolidate the activity create handling so that we can handle
             // cross-process the same as normal.
 
+            // Early return if the launching taskfragment is already been set.
+            if (options.getBinder(ActivityOptions.KEY_LAUNCH_TASK_FRAGMENT_TOKEN) != null) {
+                synchronized (mLock) {
+                    mCurrentIntent = intent;
+                }
+                return super.onStartActivity(who, intent, options);
+            }
+
             final Activity launchingActivity;
             if (who instanceof Activity) {
                 // We will check if the new activity should be split with the activity that launched
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
index b38f824..60be9d1 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
@@ -86,6 +86,12 @@
     @Nullable
     private Intent mPendingAppearedIntent;
 
+    /**
+     * The activities that were explicitly requested to be launched in its current TaskFragment,
+     * but haven't been added to {@link #mInfo} yet.
+     */
+    final ArrayList<IBinder> mPendingAppearedInRequestedTaskFragmentActivities = new ArrayList<>();
+
     /** Containers that are dependent on this one and should be completely destroyed on exit. */
     private final List<TaskFragmentContainer> mContainersToFinishOnExit =
             new ArrayList<>();
@@ -147,6 +153,11 @@
     Runnable mAppearEmptyTimeout;
 
     /**
+     * Whether this TaskFragment contains activities of another process/package.
+     */
+    private boolean mHasCrossProcessActivities;
+
+    /**
      * Creates a container with an existing activity that will be re-parented to it in a window
      * container transaction.
      * @param pairedPrimaryContainer    when it is set, the new container will be add right above it
@@ -296,6 +307,8 @@
 
     void removePendingAppearedActivity(@NonNull IBinder activityToken) {
         mPendingAppearedActivities.remove(activityToken);
+        // Also remove the activity from the mPendingInRequestedTaskFragmentActivities.
+        mPendingAppearedInRequestedTaskFragmentActivities.remove(activityToken);
     }
 
     @GuardedBy("mController.mLock")
@@ -410,10 +423,18 @@
             mAppearEmptyTimeout = null;
         }
 
+        mHasCrossProcessActivities = false;
         mInfo = info;
         if (mInfo == null || mInfo.isEmpty()) {
             return;
         }
+
+        // Contains activities of another process if the activities size is not matched to the
+        // running activity count
+        if (mInfo.getRunningActivityCount() != mInfo.getActivities().size()) {
+            mHasCrossProcessActivities = true;
+        }
+
         // Only track the pending Intent when the container is empty.
         mPendingAppearedIntent = null;
         if (mPendingAppearedActivities.isEmpty()) {
@@ -424,7 +445,7 @@
         for (int i = mPendingAppearedActivities.size() - 1; i >= 0; --i) {
             final IBinder activityToken = mPendingAppearedActivities.get(i);
             if (infoActivities.contains(activityToken)) {
-                mPendingAppearedActivities.remove(i);
+                removePendingAppearedActivity(activityToken);
             }
         }
     }
@@ -720,6 +741,34 @@
         mLastCompanionTaskFragment = fragmentToken;
     }
 
+    /**
+     * Adds the pending appeared activity that has requested to be launched in this task fragment.
+     * @see android.app.ActivityClient#isRequestedToLaunchInTaskFragment
+     */
+    void addPendingAppearedInRequestedTaskFragmentActivity(Activity activity) {
+        final IBinder activityToken = activity.getActivityToken();
+        if (hasActivity(activityToken)) {
+            return;
+        }
+        mPendingAppearedInRequestedTaskFragmentActivities.add(activity.getActivityToken());
+    }
+
+    /**
+     * Checks if the given activity has requested to be launched in this task fragment.
+     * @see #addPendingAppearedInRequestedTaskFragmentActivity
+     */
+    boolean isActivityInRequestedTaskFragment(IBinder activityToken) {
+        if (mInfo != null && mInfo.getActivitiesRequestedInTaskFragment().contains(activityToken)) {
+            return true;
+        }
+        return mPendingAppearedInRequestedTaskFragmentActivities.contains(activityToken);
+    }
+
+    /** Whether contains activities of another process */
+    boolean hasCrossProcessActivities() {
+        return mHasCrossProcessActivities;
+    }
+
     /** Gets the parent leaf Task id. */
     int getTaskId() {
         return mTaskContainer.getTaskId();
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
index 459ec9f..a069ac7 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
@@ -177,6 +177,7 @@
                 1,
                 isVisible,
                 Collections.singletonList(activity.getActivityToken()),
+                new ArrayList<>(),
                 new Point(),
                 false /* isTaskClearedForReuse */,
                 false /* isTaskFragmentClearedForPip */,
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
index bbb454d..dd087e8 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
@@ -124,7 +124,7 @@
     private TaskFragmentInfo createMockInfo(TaskFragmentContainer container) {
         return new TaskFragmentInfo(container.getTaskFragmentToken(),
                 mock(WindowContainerToken.class), new Configuration(), 0 /* runningActivityCount */,
-                false /* isVisible */, new ArrayList<>(), new Point(),
+                false /* isVisible */, new ArrayList<>(), new ArrayList<>(), new Point(),
                 false /* isTaskClearedForReuse */, false /* isTaskFragmentClearedForPip */,
                 false /* isClearedForReorderActivityToFront */, new Point());
     }
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
index 61cd748..cbdc262 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
@@ -700,7 +700,7 @@
         final boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
                 false /* isOnReparent */);
 
-        assertFalse(result);
+        assertTrue(result);
         verify(mSplitPresenter, never()).startActivityToSide(any(), any(), any(), any(), any(),
                 any(), anyBoolean());
     }
@@ -734,7 +734,7 @@
         final boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
                 false /* isOnReparent */);
 
-        assertFalse(result);
+        assertTrue(result);
         verify(mSplitPresenter, never()).startActivityToSide(any(), any(), any(), any(), any(),
                 any(), anyBoolean());
     }
@@ -808,7 +808,7 @@
         final Activity launchedActivity = createMockActivity();
         primaryContainer.addPendingAppearedActivity(launchedActivity);
 
-        assertFalse(mSplitController.resolveActivityToContainer(mTransaction, launchedActivity,
+        assertTrue(mSplitController.resolveActivityToContainer(mTransaction, launchedActivity,
                 false /* isOnReparent */));
     }
 
@@ -944,7 +944,7 @@
         boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
                 false /* isOnReparent */);
 
-        assertFalse(result);
+        assertTrue(result);
         assertEquals(primaryContainer, mSplitController.getContainerWithActivity(mActivity));
 
 
@@ -1014,6 +1014,25 @@
     }
 
     @Test
+    public void testFindActivityBelow() {
+        // Create a container with two activities
+        final TaskFragmentContainer container = createMockTaskFragmentContainer(mActivity);
+        final Activity pendingAppearedActivity = createMockActivity();
+        container.addPendingAppearedActivity(pendingAppearedActivity);
+
+        // Ensure the activity below matches
+        assertEquals(mActivity,
+                mSplitController.findActivityBelow(pendingAppearedActivity));
+
+        // Ensure that the activity look up won't search for the in-process activities and should
+        // IPC to WM core to get the activity below. It should be `null` for this mock test.
+        spyOn(container);
+        doReturn(true).when(container).hasCrossProcessActivities();
+        assertNotEquals(mActivity,
+                mSplitController.findActivityBelow(pendingAppearedActivity));
+    }
+
+    @Test
     public void testResolveActivityToContainer_inUnknownTaskFragment() {
         doReturn(new Binder()).when(mSplitController)
                 .getTaskFragmentTokenFromActivityClientRecord(mActivity);
diff --git a/libs/WindowManager/Shell/OWNERS b/libs/WindowManager/Shell/OWNERS
index 4b12590..852edef 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 = hwwang@google.com, lbill@google.com, madym@google.com
+per-file res*/*/*.xml = hwwang@google.com, jorgegil@google.com, lbill@google.com, madym@google.com
diff --git a/libs/WindowManager/Shell/res/color/split_divider_background.xml b/libs/WindowManager/Shell/res/color-night/taskbar_background.xml
similarity index 83%
rename from libs/WindowManager/Shell/res/color/split_divider_background.xml
rename to libs/WindowManager/Shell/res/color-night/taskbar_background.xml
index 0499808..9473cdd6 100644
--- a/libs/WindowManager/Shell/res/color/split_divider_background.xml
+++ b/libs/WindowManager/Shell/res/color-night/taskbar_background.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  ~ Copyright (C) 2021 The Android Open Source Project
+  ~ Copyright (C) 2023 The Android Open Source Project
   ~
   ~ Licensed under the Apache License, Version 2.0 (the "License");
   ~ you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
+<!-- Should be the same as in packages/apps/Launcher3/res/color-night-v31/taskbar_background.xml -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:color="@android:color/system_neutral1_500" android:lStar="15" />
 </selector>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/color/taskbar_background.xml b/libs/WindowManager/Shell/res/color/taskbar_background.xml
index b3d26029..0e165fc 100644
--- a/libs/WindowManager/Shell/res/color/taskbar_background.xml
+++ b/libs/WindowManager/Shell/res/color/taskbar_background.xml
@@ -16,5 +16,5 @@
   -->
 <!-- Should be the same as in packages/apps/Launcher3/res/color-v31/taskbar_background.xml -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@android:color/system_neutral1_500" android:lStar="15" />
+    <item android:color="@android:color/system_neutral1_500" android:lStar="95" />
 </selector>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/desktop_mode_decor_menu_background.xml b/libs/WindowManager/Shell/res/drawable/desktop_mode_decor_menu_background.xml
index 9167382..c6e634c 100644
--- a/libs/WindowManager/Shell/res/drawable/desktop_mode_decor_menu_background.xml
+++ b/libs/WindowManager/Shell/res/drawable/desktop_mode_decor_menu_background.xml
@@ -17,6 +17,6 @@
 <shape android:shape="rectangle"
        xmlns:android="http://schemas.android.com/apk/res/android">
     <solid android:color="@android:color/white" />
-    <corners android:radius="20dp" />
+    <corners android:radius="@dimen/caption_menu_corner_radius" />
     <stroke android:width="1dp" android:color="#b3b3b3"/>
 </shape>
diff --git a/libs/WindowManager/Shell/res/drawable/tv_window_button_bg.xml b/libs/WindowManager/Shell/res/drawable/tv_window_button_bg.xml
index 2dba37d..4c28e51 100644
--- a/libs/WindowManager/Shell/res/drawable/tv_window_button_bg.xml
+++ b/libs/WindowManager/Shell/res/drawable/tv_window_button_bg.xml
@@ -17,5 +17,5 @@
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
     <corners android:radius="@dimen/tv_window_menu_button_radius" />
-    <solid android:color="@color/tv_window_menu_icon_bg" />
+    <solid android:color="@android:color/white" />
 </shape>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_decor_handle_menu.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_decor_handle_menu.xml
index f6e3f2e..f9aeb6a 100644
--- a/libs/WindowManager/Shell/res/layout/desktop_mode_decor_handle_menu.xml
+++ b/libs/WindowManager/Shell/res/layout/desktop_mode_decor_handle_menu.xml
@@ -21,7 +21,6 @@
     android:layout_height="match_parent"
     android:orientation="vertical"
     android:background="@drawable/desktop_mode_decor_menu_background"
-    android:elevation="@dimen/caption_menu_elevation"
     android:divider="?android:attr/dividerHorizontal"
     android:showDividers="middle"
     android:dividerPadding="18dip">
@@ -63,38 +62,46 @@
             android:layout_width="0dp"
             android:layout_height="1dp"
             android:layout_weight="0.5" />
-        <Button
+        <ImageButton
             style="@style/CaptionWindowingButtonStyle"
             android:id="@+id/fullscreen_button"
             android:contentDescription="@string/fullscreen_text"
-            android:background="@drawable/caption_fullscreen_button"/>
+            android:src="@drawable/caption_fullscreen_button"
+            android:scaleType="fitCenter"
+            android:background="?android:selectableItemBackgroundBorderless"/>
         <Space
             android:layout_width="0dp"
             android:layout_height="1dp"
             android:layout_weight="1" />
-        <Button
+        <ImageButton
             style="@style/CaptionWindowingButtonStyle"
             android:id="@+id/split_screen_button"
             android:contentDescription="@string/split_screen_text"
-            android:background="@drawable/caption_split_screen_button"/>
+            android:src="@drawable/caption_split_screen_button"
+            android:scaleType="fitCenter"
+            android:background="?android:selectableItemBackgroundBorderless"/>
         <Space
             android:layout_width="0dp"
             android:layout_height="1dp"
             android:layout_weight="1" />
-        <Button
+        <ImageButton
             style="@style/CaptionWindowingButtonStyle"
             android:id="@+id/floating_button"
             android:contentDescription="@string/float_button_text"
-            android:background="@drawable/caption_floating_button"/>
+            android:src="@drawable/caption_floating_button"
+            android:scaleType="fitCenter"
+            android:background="?android:selectableItemBackgroundBorderless"/>
         <Space
             android:layout_width="0dp"
             android:layout_height="1dp"
             android:layout_weight="1" />
-        <Button
+        <ImageButton
             style="@style/CaptionWindowingButtonStyle"
             android:id="@+id/desktop_button"
             android:contentDescription="@string/desktop_text"
-            android:background="@drawable/caption_desktop_button"/>
+            android:src="@drawable/caption_desktop_button"
+            android:scaleType="fitCenter"
+            android:background="?android:selectableItemBackgroundBorderless"/>
         <Space
             android:layout_width="0dp"
             android:layout_height="1dp"
diff --git a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
index e8edad1..413cfd7 100644
--- a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
@@ -16,9 +16,7 @@
 <com.android.wm.shell.compatui.letterboxedu.LetterboxEduDialogLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:background="@android:color/system_neutral1_900">
+    style="@style/LetterboxDialog">
 
     <!-- The background of the top-level layout acts as the background dim. -->
 
diff --git a/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml
index ba9852c..5aff415 100644
--- a/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml
@@ -16,14 +16,10 @@
 <com.android.wm.shell.compatui.RestartDialogLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:background="@android:color/system_neutral1_900">
+    style="@style/LetterboxDialog">
 
     <!-- The background of the top-level layout acts as the background dim. -->
 
-    <!--TODO (b/266288912): Resolve overdraw warning -->
-
     <!-- Vertical margin will be set dynamically since it depends on task bounds.
          Setting the alpha of the dialog container to 0, since it shouldn't be visible until the
          enter animation starts. -->
diff --git a/libs/WindowManager/Shell/res/values-night/colors.xml b/libs/WindowManager/Shell/res/values-night/colors.xml
index 83c4d93..5c6bb57 100644
--- a/libs/WindowManager/Shell/res/values-night/colors.xml
+++ b/libs/WindowManager/Shell/res/values-night/colors.xml
@@ -15,6 +15,7 @@
   -->
 
 <resources>
+    <color name="docked_divider_handle">#ffffff</color>
     <!-- Bubbles -->
     <color name="bubbles_icon_tint">@color/GM2_grey_200</color>
     <!-- Splash screen-->
diff --git a/libs/WindowManager/Shell/res/values/colors.xml b/libs/WindowManager/Shell/res/values/colors.xml
index 6e750a3..6fb70006 100644
--- a/libs/WindowManager/Shell/res/values/colors.xml
+++ b/libs/WindowManager/Shell/res/values/colors.xml
@@ -17,7 +17,8 @@
  */
 -->
 <resources>
-    <color name="docked_divider_handle">#ffffff</color>
+    <color name="docked_divider_handle">#000000</color>
+    <color name="split_divider_background">@color/taskbar_background</color>
     <drawable name="forced_resizable_background">#59000000</drawable>
     <color name="minimize_dock_shadow_start">#60000000</color>
     <color name="minimize_dock_shadow_end">#00000000</color>
@@ -41,6 +42,9 @@
     <color name="letterbox_education_accent_primary">@android:color/system_accent1_100</color>
     <color name="letterbox_education_text_secondary">@android:color/system_neutral2_200</color>
 
+    <!-- Letterbox Dialog -->
+    <color name="letterbox_dialog_background">@android:color/system_neutral1_900</color>
+
     <!-- GM2 colors -->
     <color name="GM2_grey_200">#E8EAED</color>
     <color name="GM2_grey_700">#5F6368</color>
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 336c156..680ad51 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -370,6 +370,10 @@
 
     <dimen name="freeform_resize_corner">44dp</dimen>
 
-    <dimen name="caption_menu_elevation">4dp</dimen>
+    <!-- The radius of the caption menu shadow. -->
+    <dimen name="caption_menu_shadow_radius">4dp</dimen>
+
+    <!-- The radius of the caption menu corners. -->
+    <dimen name="caption_menu_corner_radius">20dp</dimen>
 
 </resources>
diff --git a/libs/WindowManager/Shell/res/values/styles.xml b/libs/WindowManager/Shell/res/values/styles.xml
index 0a0c49f..bc2e71d 100644
--- a/libs/WindowManager/Shell/res/values/styles.xml
+++ b/libs/WindowManager/Shell/res/values/styles.xml
@@ -38,11 +38,9 @@
     </style>
 
     <style name="CaptionWindowingButtonStyle">
-        <item name="android:layout_width">32dp</item>
-        <item name="android:layout_height">32dp</item>
+        <item name="android:layout_width">40dp</item>
+        <item name="android:layout_height">40dp</item>
         <item name="android:padding">4dp</item>
-        <item name="android:layout_marginTop">5dp</item>
-        <item name="android:layout_marginBottom">5dp</item>
     </style>
 
     <style name="CaptionMenuButtonStyle" parent="@style/Widget.AppCompat.Button.Borderless">
@@ -80,6 +78,12 @@
         <item name="android:textColor">@color/tv_pip_edu_text</item>
     </style>
 
+    <style name="LetterboxDialog" parent="@android:style/Theme.Holo">
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:background">@color/letterbox_dialog_background</item>
+    </style>
+
     <style name="RestartDialogTitleText">
         <item name="android:textSize">24sp</item>
         <item name="android:textColor">?android:attr/textColorPrimary</item>
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 b3fff1d..349ff36 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
@@ -120,6 +120,9 @@
     @Nullable
     private IOnBackInvokedCallback mActiveCallback;
 
+    private CrossActivityAnimation mDefaultActivityAnimation;
+    private CustomizeActivityAnimation mCustomizeActivityAnimation;
+
     @VisibleForTesting
     final RemoteCallback mNavigationObserver = new RemoteCallback(
             new RemoteCallback.OnResultListener() {
@@ -194,10 +197,12 @@
                 new CrossTaskBackAnimation(mContext, mAnimationBackground);
         mAnimationDefinition.set(BackNavigationInfo.TYPE_CROSS_TASK,
                 crossTaskAnimation.mBackAnimationRunner);
-        final CrossActivityAnimation crossActivityAnimation =
+        mDefaultActivityAnimation =
                 new CrossActivityAnimation(mContext, mAnimationBackground);
         mAnimationDefinition.set(BackNavigationInfo.TYPE_CROSS_ACTIVITY,
-                crossActivityAnimation.mBackAnimationRunner);
+                mDefaultActivityAnimation.mBackAnimationRunner);
+        mCustomizeActivityAnimation =
+                new CustomizeActivityAnimation(mContext, mAnimationBackground);
         // TODO (236760237): register dialog close animation when it's completed.
     }
 
@@ -368,7 +373,6 @@
         final boolean shouldDispatchToAnimator = shouldDispatchToAnimator();
         if (shouldDispatchToAnimator) {
             if (mAnimationDefinition.contains(backType)) {
-                mActiveCallback = mAnimationDefinition.get(backType).getCallback();
                 mAnimationDefinition.get(backType).startGesture();
             } else {
                 mActiveCallback = null;
@@ -542,16 +546,18 @@
         }
 
         final int backType = mBackNavigationInfo.getType();
+        final BackAnimationRunner runner = mAnimationDefinition.get(backType);
         // Simply trigger and finish back navigation when no animator defined.
-        if (!shouldDispatchToAnimator() || mActiveCallback == null) {
+        if (!shouldDispatchToAnimator() || runner == null) {
             invokeOrCancelBack();
             return;
         }
-
-        final BackAnimationRunner runner = mAnimationDefinition.get(backType);
         if (runner.isWaitingAnimation()) {
             ProtoLog.w(WM_SHELL_BACK_PREVIEW, "Gesture released, but animation didn't ready.");
             return;
+        } else if (runner.isAnimationCancelled()) {
+            invokeOrCancelBack();
+            return;
         }
         startPostCommitAnimation();
     }
@@ -604,6 +610,12 @@
         mShouldStartOnNextMoveEvent = false;
         mTouchTracker.reset();
         mActiveCallback = null;
+        // reset to default
+        if (mDefaultActivityAnimation != null
+                && mAnimationDefinition.contains(BackNavigationInfo.TYPE_CROSS_ACTIVITY)) {
+            mAnimationDefinition.set(BackNavigationInfo.TYPE_CROSS_ACTIVITY,
+                    mDefaultActivityAnimation.mBackAnimationRunner);
+        }
         if (mBackNavigationInfo != null) {
             mBackNavigationInfo.onBackNavigationFinished(mTriggerBack);
             mBackNavigationInfo = null;
@@ -611,14 +623,35 @@
         mTriggerBack = false;
     }
 
+    private BackAnimationRunner getAnimationRunnerAndInit() {
+        int type = mBackNavigationInfo.getType();
+        // Initiate customized cross-activity animation, or fall back to cross activity animation
+        if (type == BackNavigationInfo.TYPE_CROSS_ACTIVITY && mAnimationDefinition.contains(type)) {
+            final BackNavigationInfo.CustomAnimationInfo animationInfo =
+                    mBackNavigationInfo.getCustomAnimationInfo();
+            if (animationInfo != null && mCustomizeActivityAnimation != null
+                    && mCustomizeActivityAnimation.prepareNextAnimation(animationInfo)) {
+                mAnimationDefinition.get(type).resetWaitingAnimation();
+                mAnimationDefinition.set(BackNavigationInfo.TYPE_CROSS_ACTIVITY,
+                        mCustomizeActivityAnimation.mBackAnimationRunner);
+            }
+        }
+        return mAnimationDefinition.get(type);
+    }
+
     private void createAdapter() {
         IBackAnimationRunner runner = new IBackAnimationRunner.Stub() {
             @Override
-            public void onAnimationStart(int type, RemoteAnimationTarget[] apps,
+            public void onAnimationStart(RemoteAnimationTarget[] apps,
                     RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
                     IBackAnimationFinishedCallback finishedCallback) {
                 mShellExecutor.execute(() -> {
-                    final BackAnimationRunner runner = mAnimationDefinition.get(type);
+                    if (mBackNavigationInfo == null) {
+                        Log.e(TAG, "Lack of navigation info to start animation.");
+                        return;
+                    }
+                    final int type = mBackNavigationInfo.getType();
+                    final BackAnimationRunner runner = getAnimationRunnerAndInit();
                     if (runner == null) {
                         Log.e(TAG, "Animation didn't be defined for type "
                                 + BackNavigationInfo.typeToString(type));
@@ -631,6 +664,7 @@
                         }
                         return;
                     }
+                    mActiveCallback = runner.getCallback();
                     mBackAnimationFinishedCallback = finishedCallback;
 
                     ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: startAnimation()");
@@ -642,18 +676,32 @@
                                 mActiveCallback, mTouchTracker.createStartEvent(apps[0]));
                     }
 
+                    // Dispatch the first progress after animation start for smoothing the initial
+                    // animation, instead of waiting for next onMove.
+                    final BackMotionEvent backFinish = mTouchTracker.createProgressEvent();
+                    dispatchOnBackProgressed(mActiveCallback, backFinish);
                     if (!mBackGestureStarted) {
                         // if the down -> up gesture happened before animation start, we have to
                         // trigger the uninterruptible transition to finish the back animation.
-                        final BackMotionEvent backFinish = mTouchTracker.createProgressEvent();
-                        dispatchOnBackProgressed(mActiveCallback, backFinish);
                         startPostCommitAnimation();
                     }
                 });
             }
 
             @Override
-            public void onAnimationCancelled() { }
+            public void onAnimationCancelled() {
+                mShellExecutor.execute(() -> {
+                    final BackAnimationRunner runner = mAnimationDefinition.get(
+                            mBackNavigationInfo.getType());
+                    if (runner == null) {
+                        return;
+                    }
+                    runner.cancelAnimation();
+                    if (!mBackGestureStarted) {
+                        invokeOrCancelBack();
+                    }
+                });
+            }
         };
         mBackAnimationAdapter = new BackAnimationAdapter(runner);
     }
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 d70b8f5..22b841a 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
@@ -41,6 +41,9 @@
     // Whether we are waiting to receive onAnimationStart
     private boolean mWaitingAnimation;
 
+    /** True when the back animation is cancelled */
+    private boolean mAnimationCancelled;
+
     BackAnimationRunner(@NonNull IOnBackInvokedCallback callback,
             @NonNull IRemoteAnimationRunner runner) {
         mCallback = callback;
@@ -81,9 +84,23 @@
 
     void startGesture() {
         mWaitingAnimation = true;
+        mAnimationCancelled = false;
     }
 
     boolean isWaitingAnimation() {
         return mWaitingAnimation;
     }
+
+    void cancelAnimation() {
+        mWaitingAnimation = false;
+        mAnimationCancelled = true;
+    }
+
+    boolean isAnimationCancelled() {
+        return mAnimationCancelled;
+    }
+
+    void resetWaitingAnimation() {
+        mWaitingAnimation = false;
+    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java
new file mode 100644
index 0000000..ae33b94
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.back;
+
+import static android.view.RemoteAnimationTarget.MODE_CLOSING;
+import static android.view.RemoteAnimationTarget.MODE_OPENING;
+
+import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BACK_PREVIEW;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.annotation.NonNull;
+import android.content.Context;
+import android.graphics.Rect;
+import android.os.RemoteException;
+import android.util.FloatProperty;
+import android.view.Choreographer;
+import android.view.IRemoteAnimationFinishedCallback;
+import android.view.IRemoteAnimationRunner;
+import android.view.RemoteAnimationTarget;
+import android.view.SurfaceControl;
+import android.view.animation.Animation;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Transformation;
+import android.window.BackEvent;
+import android.window.BackMotionEvent;
+import android.window.BackNavigationInfo;
+import android.window.BackProgressAnimator;
+import android.window.IOnBackInvokedCallback;
+
+import com.android.internal.dynamicanimation.animation.SpringAnimation;
+import com.android.internal.dynamicanimation.animation.SpringForce;
+import com.android.internal.policy.ScreenDecorationsUtils;
+import com.android.internal.policy.TransitionAnimation;
+import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.common.annotations.ShellMainThread;
+
+/**
+ * Class that handle customized close activity transition animation.
+ */
+@ShellMainThread
+class CustomizeActivityAnimation {
+    private final BackProgressAnimator mProgressAnimator = new BackProgressAnimator();
+    final BackAnimationRunner mBackAnimationRunner;
+    private final float mCornerRadius;
+    private final SurfaceControl.Transaction mTransaction;
+    private final BackAnimationBackground mBackground;
+    private RemoteAnimationTarget mEnteringTarget;
+    private RemoteAnimationTarget mClosingTarget;
+    private IRemoteAnimationFinishedCallback mFinishCallback;
+    /** Duration of post animation after gesture committed. */
+    private static final int POST_ANIMATION_DURATION = 250;
+
+    private static final int SCALE_FACTOR = 1000;
+    private final SpringAnimation mProgressSpring;
+    private float mLatestProgress = 0.0f;
+
+    private static final float TARGET_COMMIT_PROGRESS = 0.5f;
+
+    private final float[] mTmpFloat9 = new float[9];
+    private final DecelerateInterpolator mDecelerateInterpolator = new DecelerateInterpolator();
+
+    final CustomAnimationLoader mCustomAnimationLoader;
+    private Animation mEnterAnimation;
+    private Animation mCloseAnimation;
+    final Transformation mTransformation = new Transformation();
+
+    private final Choreographer mChoreographer;
+
+    CustomizeActivityAnimation(Context context, BackAnimationBackground background) {
+        this(context, background, new SurfaceControl.Transaction(), null);
+    }
+
+    CustomizeActivityAnimation(Context context, BackAnimationBackground background,
+            SurfaceControl.Transaction transaction, Choreographer choreographer) {
+        mCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context);
+        mBackground = background;
+        mBackAnimationRunner = new BackAnimationRunner(new Callback(), new Runner());
+        mCustomAnimationLoader = new CustomAnimationLoader(context);
+
+        mProgressSpring = new SpringAnimation(this, ENTER_PROGRESS_PROP);
+        mProgressSpring.setSpring(new SpringForce()
+                .setStiffness(SpringForce.STIFFNESS_MEDIUM)
+                .setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY));
+        mTransaction = transaction == null ? new SurfaceControl.Transaction() : transaction;
+        mChoreographer = choreographer != null ? choreographer : Choreographer.getInstance();
+    }
+
+    private float getLatestProgress() {
+        return mLatestProgress * SCALE_FACTOR;
+    }
+    private void setLatestProgress(float value) {
+        mLatestProgress = value / SCALE_FACTOR;
+        applyTransformTransaction(mLatestProgress);
+    }
+
+    private static final FloatProperty<CustomizeActivityAnimation> ENTER_PROGRESS_PROP =
+            new FloatProperty<>("enter") {
+                @Override
+                public void setValue(CustomizeActivityAnimation anim, float value) {
+                    anim.setLatestProgress(value);
+                }
+
+                @Override
+                public Float get(CustomizeActivityAnimation object) {
+                    return object.getLatestProgress();
+                }
+            };
+
+    // The target will lose focus when alpha == 0, so keep a minimum value for it.
+    private static float keepMinimumAlpha(float transAlpha) {
+        return Math.max(transAlpha, 0.005f);
+    }
+
+    private static void initializeAnimation(Animation animation, Rect bounds) {
+        final int width = bounds.width();
+        final int height = bounds.height();
+        animation.initialize(width, height, width, height);
+    }
+
+    private void startBackAnimation() {
+        if (mEnteringTarget == null || mClosingTarget == null
+                || mCloseAnimation == null || mEnterAnimation == null) {
+            ProtoLog.d(WM_SHELL_BACK_PREVIEW, "Entering target or closing target is null.");
+            return;
+        }
+        initializeAnimation(mCloseAnimation, mClosingTarget.localBounds);
+        initializeAnimation(mEnterAnimation, mEnteringTarget.localBounds);
+
+        // Draw background with task background color.
+        if (mEnteringTarget.taskInfo != null && mEnteringTarget.taskInfo.taskDescription != null) {
+            mBackground.ensureBackground(
+                    mEnteringTarget.taskInfo.taskDescription.getBackgroundColor(), mTransaction);
+        }
+    }
+
+    private void applyTransformTransaction(float progress) {
+        if (mClosingTarget == null || mEnteringTarget == null) {
+            return;
+        }
+        applyTransform(mClosingTarget.leash, progress, mCloseAnimation);
+        applyTransform(mEnteringTarget.leash, progress, mEnterAnimation);
+        mTransaction.setFrameTimelineVsync(mChoreographer.getVsyncId());
+        mTransaction.apply();
+    }
+
+    private void applyTransform(SurfaceControl leash, float progress, Animation animation) {
+        mTransformation.clear();
+        animation.getTransformationAt(progress, mTransformation);
+        mTransaction.setMatrix(leash, mTransformation.getMatrix(), mTmpFloat9);
+        mTransaction.setAlpha(leash, keepMinimumAlpha(mTransformation.getAlpha()));
+        mTransaction.setCornerRadius(leash, mCornerRadius);
+    }
+
+    void finishAnimation() {
+        if (mCloseAnimation != null) {
+            mCloseAnimation.reset();
+            mCloseAnimation = null;
+        }
+        if (mEnterAnimation != null) {
+            mEnterAnimation.reset();
+            mEnterAnimation = null;
+        }
+        if (mEnteringTarget != null) {
+            mEnteringTarget.leash.release();
+            mEnteringTarget = null;
+        }
+        if (mClosingTarget != null) {
+            mClosingTarget.leash.release();
+            mClosingTarget = null;
+        }
+        if (mBackground != null) {
+            mBackground.removeBackground(mTransaction);
+        }
+        mTransaction.setFrameTimelineVsync(mChoreographer.getVsyncId());
+        mTransaction.apply();
+        mTransformation.clear();
+        mLatestProgress = 0;
+        if (mFinishCallback != null) {
+            try {
+                mFinishCallback.onAnimationFinished();
+            } catch (RemoteException e) {
+                e.printStackTrace();
+            }
+            mFinishCallback = null;
+        }
+        mProgressSpring.animateToFinalPosition(0);
+        mProgressSpring.skipToEnd();
+    }
+
+    void onGestureProgress(@NonNull BackEvent backEvent) {
+        if (mEnteringTarget == null || mClosingTarget == null
+                || mCloseAnimation == null || mEnterAnimation == null) {
+            return;
+        }
+
+        final float progress = backEvent.getProgress();
+
+        float springProgress = (progress > 0.1f
+                ? mapLinear(progress, 0.1f, 1f, TARGET_COMMIT_PROGRESS, 1f)
+                : mapLinear(progress, 0, 1f, 0f, TARGET_COMMIT_PROGRESS)) * SCALE_FACTOR;
+
+        mProgressSpring.animateToFinalPosition(springProgress);
+    }
+
+    static float mapLinear(float x, float a1, float a2, float b1, float b2) {
+        return b1 + (x - a1) * (b2 - b1) / (a2 - a1);
+    }
+
+    void onGestureCommitted() {
+        if (mEnteringTarget == null || mClosingTarget == null
+                || mCloseAnimation == null || mEnterAnimation == null) {
+            finishAnimation();
+            return;
+        }
+        mProgressSpring.cancel();
+
+        // Enter phase 2 of the animation
+        final ValueAnimator valueAnimator = ValueAnimator.ofFloat(mLatestProgress, 1f)
+                .setDuration(POST_ANIMATION_DURATION);
+        valueAnimator.setInterpolator(mDecelerateInterpolator);
+        valueAnimator.addUpdateListener(animation -> {
+            float progress = (float) animation.getAnimatedValue();
+            applyTransformTransaction(progress);
+        });
+
+        valueAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                finishAnimation();
+            }
+        });
+        valueAnimator.start();
+    }
+
+    /**
+     * Load customize animation before animation start.
+     */
+    boolean prepareNextAnimation(BackNavigationInfo.CustomAnimationInfo animationInfo) {
+        mCloseAnimation = mCustomAnimationLoader.load(
+                animationInfo, false /* enterAnimation */);
+        if (mCloseAnimation != null) {
+            mEnterAnimation = mCustomAnimationLoader.load(
+                    animationInfo, true /* enterAnimation */);
+            return true;
+        }
+        return false;
+    }
+
+    private final class Callback extends IOnBackInvokedCallback.Default {
+        @Override
+        public void onBackStarted(BackMotionEvent backEvent) {
+            mProgressAnimator.onBackStarted(backEvent,
+                    CustomizeActivityAnimation.this::onGestureProgress);
+        }
+
+        @Override
+        public void onBackProgressed(@NonNull BackMotionEvent backEvent) {
+            mProgressAnimator.onBackProgressed(backEvent);
+        }
+
+        @Override
+        public void onBackCancelled() {
+            mProgressAnimator.onBackCancelled(CustomizeActivityAnimation.this::finishAnimation);
+        }
+
+        @Override
+        public void onBackInvoked() {
+            mProgressAnimator.reset();
+            onGestureCommitted();
+        }
+    }
+
+    private final class Runner extends IRemoteAnimationRunner.Default {
+        @Override
+        public void onAnimationStart(
+                int transit,
+                RemoteAnimationTarget[] apps,
+                RemoteAnimationTarget[] wallpapers,
+                RemoteAnimationTarget[] nonApps,
+                IRemoteAnimationFinishedCallback finishedCallback) {
+            ProtoLog.d(WM_SHELL_BACK_PREVIEW, "Start back to customize animation.");
+            for (RemoteAnimationTarget a : apps) {
+                if (a.mode == MODE_CLOSING) {
+                    mClosingTarget = a;
+                }
+                if (a.mode == MODE_OPENING) {
+                    mEnteringTarget = a;
+                }
+            }
+            if (mCloseAnimation == null || mEnterAnimation == null) {
+                ProtoLog.d(WM_SHELL_BACK_PREVIEW,
+                        "No animation loaded, should choose cross-activity animation?");
+            }
+
+            startBackAnimation();
+            mFinishCallback = finishedCallback;
+        }
+
+        @Override
+        public void onAnimationCancelled(boolean isKeyguardOccluded) {
+            finishAnimation();
+        }
+    }
+
+    /**
+     * Helper class to load custom animation.
+     */
+    static class CustomAnimationLoader {
+        private final TransitionAnimation mTransitionAnimation;
+
+        CustomAnimationLoader(Context context) {
+            mTransitionAnimation = new TransitionAnimation(
+                    context, false /* debug */, "CustomizeBackAnimation");
+        }
+
+        Animation load(BackNavigationInfo.CustomAnimationInfo animationInfo,
+                boolean enterAnimation) {
+            final String packageName = animationInfo.getPackageName();
+            if (packageName.isEmpty()) {
+                return null;
+            }
+            final int windowAnimations = animationInfo.getWindowAnimations();
+            if (windowAnimations == 0) {
+                return null;
+            }
+            final int attrs = enterAnimation
+                    ? com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation
+                    : com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
+            Animation a = mTransitionAnimation.loadAnimationAttr(packageName, windowAnimations,
+                    attrs, false /* translucent */);
+            // Only allow to load default animation for opening target.
+            if (a == null && enterAnimation) {
+                a = mTransitionAnimation.loadDefaultAnimationAttr(attrs, false /* translucent */);
+            }
+            if (a != null) {
+                ProtoLog.d(WM_SHELL_BACK_PREVIEW, "custom animation loaded %s", a);
+            } else {
+                ProtoLog.e(WM_SHELL_BACK_PREVIEW, "No custom animation loaded");
+            }
+            return a;
+        }
+    }
+}
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 36c0cb6..ef53839 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
@@ -61,6 +61,7 @@
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.service.notification.NotificationListenerService;
@@ -129,6 +130,39 @@
     private static final String SYSTEM_DIALOG_REASON_KEY = "reason";
     private static final String SYSTEM_DIALOG_REASON_GESTURE_NAV = "gestureNav";
 
+    // TODO(b/256873975) Should use proper flag when available to shell/launcher
+    /**
+     * Whether bubbles are showing in the bubble bar from launcher. This is only available
+     * on large screens and {@link BubbleController#isShowingAsBubbleBar()} should be used
+     * to check all conditions that indicate if the bubble bar is in use.
+     */
+    private static final boolean BUBBLE_BAR_ENABLED =
+            SystemProperties.getBoolean("persist.wm.debug.bubble_bar", false);
+
+
+    /**
+     * Common interface to send updates to bubble views.
+     */
+    public interface BubbleViewCallback {
+        /** Called when the provided bubble should be removed. */
+        void removeBubble(Bubble removedBubble);
+        /** Called when the provided bubble should be added. */
+        void addBubble(Bubble addedBubble);
+        /** Called when the provided bubble should be updated. */
+        void updateBubble(Bubble updatedBubble);
+        /** Called when the provided bubble should be selected. */
+        void selectionChanged(BubbleViewProvider selectedBubble);
+        /** Called when the provided bubble's suppression state has changed. */
+        void suppressionChanged(Bubble bubble, boolean isSuppressed);
+        /** Called when the expansion state of bubbles has changed. */
+        void expansionChanged(boolean isExpanded);
+        /**
+         * Called when the order of the bubble list has changed. Depending on the expanded state
+         * the pointer might need to be updated.
+         */
+        void bubbleOrderChanged(List<Bubble> bubbleOrder, boolean updatePointer);
+    }
+
     private final Context mContext;
     private final BubblesImpl mImpl = new BubblesImpl();
     private Bubbles.BubbleExpandListener mExpandListener;
@@ -152,12 +186,8 @@
     // Used to post to main UI thread
     private final ShellExecutor mMainExecutor;
     private final Handler mMainHandler;
-
     private final ShellExecutor mBackgroundExecutor;
 
-    // Whether or not we should show bubbles pinned at the bottom of the screen.
-    private boolean mIsBubbleBarEnabled;
-
     private BubbleLogger mLogger;
     private BubbleData mBubbleData;
     @Nullable private BubbleStackView mStackView;
@@ -540,10 +570,10 @@
         mDataRepository.removeBubblesForUser(removedUserId, parentUserId);
     }
 
-    // TODO(b/256873975): Should pass this into the constructor once flags are available to shell.
-    /** Sets whether the bubble bar is enabled (i.e. bubbles pinned to bottom on large screens). */
-    public void setBubbleBarEnabled(boolean enabled) {
-        mIsBubbleBarEnabled = enabled;
+    /** Whether bubbles are showing in the bubble bar. */
+    public boolean isShowingAsBubbleBar() {
+        // TODO(b/269670598): should also check that we're in gesture nav
+        return BUBBLE_BAR_ENABLED && mBubblePositioner.isLargeScreen();
     }
 
     /** Whether this userId belongs to the current user. */
@@ -612,12 +642,6 @@
             mStackView.setUnbubbleConversationCallback(mSysuiProxy::onUnbubbleConversation);
         }
 
-        if (mIsBubbleBarEnabled && mBubblePositioner.isLargeScreen()) {
-            mBubblePositioner.setUsePinnedLocation(true);
-        } else {
-            mBubblePositioner.setUsePinnedLocation(false);
-        }
-
         addToWindowManagerMaybe();
     }
 
@@ -1319,6 +1343,58 @@
         });
     }
 
+    private final BubbleViewCallback mBubbleViewCallback = new BubbleViewCallback() {
+        @Override
+        public void removeBubble(Bubble removedBubble) {
+            if (mStackView != null) {
+                mStackView.removeBubble(removedBubble);
+            }
+        }
+
+        @Override
+        public void addBubble(Bubble addedBubble) {
+            if (mStackView != null) {
+                mStackView.addBubble(addedBubble);
+            }
+        }
+
+        @Override
+        public void updateBubble(Bubble updatedBubble) {
+            if (mStackView != null) {
+                mStackView.updateBubble(updatedBubble);
+            }
+        }
+
+        @Override
+        public void bubbleOrderChanged(List<Bubble> bubbleOrder, boolean updatePointer) {
+            if (mStackView != null) {
+                mStackView.updateBubbleOrder(bubbleOrder, updatePointer);
+            }
+        }
+
+        @Override
+        public void suppressionChanged(Bubble bubble, boolean isSuppressed) {
+            if (mStackView != null) {
+                mStackView.setBubbleSuppressed(bubble, isSuppressed);
+            }
+        }
+
+        @Override
+        public void expansionChanged(boolean isExpanded) {
+            if (mStackView != null) {
+                mStackView.setExpanded(isExpanded);
+            }
+        }
+
+        @Override
+        public void selectionChanged(BubbleViewProvider selectedBubble) {
+            if (mStackView != null) {
+                mStackView.setSelectedBubble(selectedBubble);
+            }
+
+        }
+    };
+
     @SuppressWarnings("FieldCanBeLocal")
     private final BubbleData.Listener mBubbleDataListener = new BubbleData.Listener() {
 
@@ -1341,7 +1417,8 @@
             // Lazy load overflow bubbles from disk
             loadOverflowBubblesFromDisk();
 
-            mStackView.updateOverflowButtonDot();
+            // If bubbles in the overflow have a dot, make sure the overflow shows a dot
+            updateOverflowButtonDot();
 
             // Update bubbles in overflow.
             if (mOverflowListener != null) {
@@ -1356,9 +1433,7 @@
                 final Bubble bubble = removed.first;
                 @Bubbles.DismissReason final int reason = removed.second;
 
-                if (mStackView != null) {
-                    mStackView.removeBubble(bubble);
-                }
+                mBubbleViewCallback.removeBubble(bubble);
 
                 // Leave the notification in place if we're dismissing due to user switching, or
                 // because DND is suppressing the bubble. In both of those cases, we need to be able
@@ -1388,49 +1463,47 @@
             }
             mDataRepository.removeBubbles(mCurrentUserId, bubblesToBeRemovedFromRepository);
 
-            if (update.addedBubble != null && mStackView != null) {
+            if (update.addedBubble != null) {
                 mDataRepository.addBubble(mCurrentUserId, update.addedBubble);
-                mStackView.addBubble(update.addedBubble);
+                mBubbleViewCallback.addBubble(update.addedBubble);
             }
 
-            if (update.updatedBubble != null && mStackView != null) {
-                mStackView.updateBubble(update.updatedBubble);
+            if (update.updatedBubble != null) {
+                mBubbleViewCallback.updateBubble(update.updatedBubble);
             }
 
-            if (update.suppressedBubble != null && mStackView != null) {
-                mStackView.setBubbleSuppressed(update.suppressedBubble, true);
+            if (update.suppressedBubble != null) {
+                mBubbleViewCallback.suppressionChanged(update.suppressedBubble, true);
             }
 
-            if (update.unsuppressedBubble != null && mStackView != null) {
-                mStackView.setBubbleSuppressed(update.unsuppressedBubble, false);
+            if (update.unsuppressedBubble != null) {
+                mBubbleViewCallback.suppressionChanged(update.unsuppressedBubble, false);
             }
 
             boolean collapseStack = update.expandedChanged && !update.expanded;
 
             // At this point, the correct bubbles are inflated in the stack.
             // Make sure the order in bubble data is reflected in bubble row.
-            if (update.orderChanged && mStackView != null) {
+            if (update.orderChanged) {
                 mDataRepository.addBubbles(mCurrentUserId, update.bubbles);
                 // if the stack is going to be collapsed, do not update pointer position
                 // after reordering
-                mStackView.updateBubbleOrder(update.bubbles, !collapseStack);
+                mBubbleViewCallback.bubbleOrderChanged(update.bubbles, !collapseStack);
             }
 
             if (collapseStack) {
-                mStackView.setExpanded(false);
+                mBubbleViewCallback.expansionChanged(/* expanded= */ false);
                 mSysuiProxy.requestNotificationShadeTopUi(false, TAG);
             }
 
-            if (update.selectionChanged && mStackView != null) {
-                mStackView.setSelectedBubble(update.selectedBubble);
+            if (update.selectionChanged) {
+                mBubbleViewCallback.selectionChanged(update.selectedBubble);
             }
 
             // Expanding? Apply this last.
             if (update.expandedChanged && update.expanded) {
-                if (mStackView != null) {
-                    mStackView.setExpanded(true);
-                    mSysuiProxy.requestNotificationShadeTopUi(true, TAG);
-                }
+                mBubbleViewCallback.expansionChanged(/* expanded= */ true);
+                mSysuiProxy.requestNotificationShadeTopUi(true, TAG);
             }
 
             mSysuiProxy.notifyInvalidateNotifications("BubbleData.Listener.applyUpdate");
@@ -1441,6 +1514,19 @@
         }
     };
 
+    private void updateOverflowButtonDot() {
+        BubbleOverflow overflow = mBubbleData.getOverflow();
+        if (overflow == null) return;
+
+        for (Bubble b : mBubbleData.getOverflowBubbles()) {
+            if (b.showDot()) {
+                overflow.setShowDot(true);
+                return;
+            }
+        }
+        overflow.setShowDot(false);
+    }
+
     private boolean handleDismissalInterception(BubbleEntry entry,
             @Nullable List<BubbleEntry> children, IntConsumer removeCallback) {
         if (isSummaryOfBubbles(entry)) {
@@ -1918,13 +2004,6 @@
         }
 
         @Override
-        public void setBubbleBarEnabled(boolean enabled) {
-            mMainExecutor.execute(() -> {
-                BubbleController.this.setBubbleBarEnabled(enabled);
-            });
-        }
-
-        @Override
         public void onNotificationPanelExpandedChanged(boolean expanded) {
             mMainExecutor.execute(
                     () -> BubbleController.this.onNotificationPanelExpandedChanged(expanded));
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 6230d22..3fd0967 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
@@ -283,7 +283,7 @@
     }
 
     boolean isShowingOverflow() {
-        return mShowingOverflow && (isExpanded() || mPositioner.showingInTaskbar());
+        return mShowingOverflow && isExpanded();
     }
 
     /**
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 57c7731..ecddbda 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
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.bubbles;
 
+import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED;
 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
@@ -226,6 +227,8 @@
                 try {
                     options.setTaskAlwaysOnTop(true);
                     options.setLaunchedFromBubble(true);
+                    options.setPendingIntentBackgroundActivityStartMode(
+                            MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
 
                     Intent fillInIntent = new Intent();
                     // Apply flags to make behaviour match documentLaunchMode=always.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
index 07c5852..5ea2450 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
@@ -18,9 +18,6 @@
 
 import static android.view.View.LAYOUT_DIRECTION_RTL;
 
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
-import android.annotation.IntDef;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -39,8 +36,6 @@
 import com.android.launcher3.icons.IconNormalizer;
 import com.android.wm.shell.R;
 
-import java.lang.annotation.Retention;
-
 /**
  * Keeps track of display size, configuration, and specific bubble sizes. One place for all
  * placement and positioning calculations to refer to.
@@ -50,15 +45,6 @@
             ? "BubblePositioner"
             : BubbleDebugConfig.TAG_BUBBLES;
 
-    @Retention(SOURCE)
-    @IntDef({TASKBAR_POSITION_NONE, TASKBAR_POSITION_RIGHT, TASKBAR_POSITION_LEFT,
-            TASKBAR_POSITION_BOTTOM})
-    @interface TaskbarPosition {}
-    public static final int TASKBAR_POSITION_NONE = -1;
-    public static final int TASKBAR_POSITION_RIGHT = 0;
-    public static final int TASKBAR_POSITION_LEFT = 1;
-    public static final int TASKBAR_POSITION_BOTTOM = 2;
-
     /** When the bubbles are collapsed in a stack only some of them are shown, this is how many. **/
     public static final int NUM_VISIBLE_WHEN_RESTING = 2;
     /** Indicates a bubble's height should be the maximum available space. **/
@@ -108,15 +94,9 @@
     private int mOverflowHeight;
     private int mMinimumFlyoutWidthLargeScreen;
 
-    private PointF mPinLocation;
     private PointF mRestingStackPosition;
     private int[] mPaddings = new int[4];
 
-    private boolean mShowingInTaskbar;
-    private @TaskbarPosition int mTaskbarPosition = TASKBAR_POSITION_NONE;
-    private int mTaskbarIconSize;
-    private int mTaskbarSize;
-
     public BubblePositioner(Context context, WindowManager windowManager) {
         mContext = context;
         mWindowManager = windowManager;
@@ -153,27 +133,11 @@
                     + " insets: " + insets
                     + " isLargeScreen: " + mIsLargeScreen
                     + " isSmallTablet: " + mIsSmallTablet
-                    + " bounds: " + bounds
-                    + " showingInTaskbar: " + mShowingInTaskbar);
+                    + " bounds: " + bounds);
         }
         updateInternal(mRotation, insets, bounds);
     }
 
-    /**
-     * Updates position information to account for taskbar state.
-     *
-     * @param taskbarPosition which position the taskbar is displayed in.
-     * @param showingInTaskbar whether the taskbar is being shown.
-     */
-    public void updateForTaskbar(int iconSize,
-            @TaskbarPosition int taskbarPosition, boolean showingInTaskbar, int taskbarSize) {
-        mShowingInTaskbar = showingInTaskbar;
-        mTaskbarIconSize =  iconSize;
-        mTaskbarPosition = taskbarPosition;
-        mTaskbarSize = taskbarSize;
-        update();
-    }
-
     @VisibleForTesting
     public void updateInternal(int rotation, Insets insets, Rect bounds) {
         mRotation = rotation;
@@ -232,10 +196,6 @@
                 R.dimen.bubbles_flyout_min_width_large_screen);
 
         mMaxBubbles = calculateMaxBubbles();
-
-        if (mShowingInTaskbar) {
-            adjustForTaskbar();
-        }
     }
 
     /**
@@ -260,30 +220,6 @@
         return mDefaultMaxBubbles;
     }
 
-    /**
-     * Taskbar insets appear as navigationBar insets, however, unlike navigationBar this should
-     * not inset bubbles UI as bubbles floats above the taskbar. This adjust the available space
-     * and insets to account for the taskbar.
-     */
-    // TODO(b/171559950): When the insets are reported correctly we can remove this logic
-    private void adjustForTaskbar() {
-        // When bar is showing on edges... subtract that inset because we appear on top
-        if (mShowingInTaskbar && mTaskbarPosition != TASKBAR_POSITION_BOTTOM) {
-            WindowInsets metricInsets = mWindowManager.getCurrentWindowMetrics().getWindowInsets();
-            Insets navBarInsets = metricInsets.getInsetsIgnoringVisibility(
-                    WindowInsets.Type.navigationBars());
-            int newInsetLeft = mInsets.left;
-            int newInsetRight = mInsets.right;
-            if (mTaskbarPosition == TASKBAR_POSITION_LEFT) {
-                mPositionRect.left -= navBarInsets.left;
-                newInsetLeft -= navBarInsets.left;
-            } else if (mTaskbarPosition == TASKBAR_POSITION_RIGHT) {
-                mPositionRect.right += navBarInsets.right;
-                newInsetRight -= navBarInsets.right;
-            }
-            mInsets = Insets.of(newInsetLeft, mInsets.top, newInsetRight, mInsets.bottom);
-        }
-    }
 
     /**
      * @return a rect of available screen space accounting for orientation, system bars and cutouts.
@@ -327,14 +263,12 @@
      * to the left or right side.
      */
     public boolean showBubblesVertically() {
-        return isLandscape() || mShowingInTaskbar || mIsLargeScreen;
+        return isLandscape() || mIsLargeScreen;
     }
 
     /** Size of the bubble. */
     public int getBubbleSize() {
-        return (mShowingInTaskbar && mTaskbarIconSize > 0)
-                ? mTaskbarIconSize
-                : mBubbleSize;
+        return mBubbleSize;
     }
 
     /** The amount of padding at the top of the screen that the bubbles avoid when being placed. */
@@ -699,9 +633,6 @@
 
     /** The position the bubble stack should rest at when collapsed. */
     public PointF getRestingPosition() {
-        if (mPinLocation != null) {
-            return mPinLocation;
-        }
         if (mRestingStackPosition == null) {
             return getDefaultStartPosition();
         }
@@ -713,9 +644,6 @@
      * is being shown.
      */
     public PointF getDefaultStartPosition() {
-        if (mPinLocation != null) {
-            return mPinLocation;
-        }
         // Start on the left if we're in LTR, right otherwise.
         final boolean startOnLeft =
                 mContext.getResources().getConfiguration().getLayoutDirection()
@@ -730,7 +658,6 @@
                         1 /* default starts with 1 bubble */));
     }
 
-
     /**
      * Returns the region that the stack position must stay within. This goes slightly off the left
      * and right sides of the screen, below the status bar/cutout and above the navigation bar.
@@ -751,39 +678,6 @@
     }
 
     /**
-     * @return whether the bubble stack is pinned to the taskbar.
-     */
-    public boolean showingInTaskbar() {
-        return mShowingInTaskbar;
-    }
-
-    /**
-     * @return the taskbar position if set.
-     */
-    public int getTaskbarPosition() {
-        return mTaskbarPosition;
-    }
-
-    public int getTaskbarSize() {
-        return mTaskbarSize;
-    }
-
-    /**
-     * In some situations bubbles will be pinned to a specific onscreen location. This sets whether
-     * bubbles should be pinned or not.
-     */
-    public void setUsePinnedLocation(boolean usePinnedLocation) {
-        if (usePinnedLocation) {
-            mShowingInTaskbar = true;
-            mPinLocation = new PointF(mPositionRect.right - mBubbleSize,
-                    mPositionRect.bottom - mBubbleSize);
-        } else {
-            mPinLocation = null;
-            mShowingInTaskbar = false;
-        }
-    }
-
-    /**
      * Navigation bar has an area where system gestures can be started from.
      *
      * @return {@link Rect} for system navigation bar gesture zone
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index abe42ee..0b947c8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -680,8 +680,6 @@
 
                     // Re-show the expanded view if we hid it.
                     showExpandedViewIfNeeded();
-                } else if (mPositioner.showingInTaskbar()) {
-                    mStackAnimationController.snapStackBack();
                 } else {
                     // Fling the stack to the edge, and save whether or not it's going to end up on
                     // the left side of the screen.
@@ -1361,16 +1359,6 @@
         updateOverflowVisibility();
     }
 
-    void updateOverflowButtonDot() {
-        for (Bubble b : mBubbleData.getOverflowBubbles()) {
-            if (b.showDot()) {
-                mBubbleOverflow.setShowDot(true);
-                return;
-            }
-        }
-        mBubbleOverflow.setShowDot(false);
-    }
-
     /**
      * Handle theme changes.
      */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
index 1753cda..4c0a93f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
@@ -273,11 +273,6 @@
      */
     void onUserRemoved(int removedUserId);
 
-    /**
-     * Sets whether bubble bar should be enabled or not.
-     */
-    void setBubbleBarEnabled(boolean enabled);
-
     /** Listener to find out about stack expansion / collapse events. */
     interface BubbleExpandListener {
         /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java
index 0ee0ea6..5533842 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java
@@ -417,23 +417,9 @@
     }
 
     /**
-     * Snaps the stack back to the previous resting position.
-     */
-    public void snapStackBack() {
-        if (mLayout == null) {
-            return;
-        }
-        PointF p = getStackPositionAlongNearestHorizontalEdge();
-        springStackAfterFling(p.x, p.y);
-    }
-
-    /**
      * Where the stack would be if it were snapped to the nearest horizontal edge (left or right).
      */
     public PointF getStackPositionAlongNearestHorizontalEdge() {
-        if (mPositioner.showingInTaskbar()) {
-            return mPositioner.getRestingPosition();
-        }
         final PointF stackPos = getStackPosition();
         final boolean onLeft = mLayout.isFirstChildXLeftOfCenter(stackPos.x);
         final RectF bounds = mPositioner.getAllowableStackPositionRegion(getBubbleCount());
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DevicePostureController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DevicePostureController.java
index 22587f4..8b4ac1a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DevicePostureController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DevicePostureController.java
@@ -39,6 +39,9 @@
  *
  * Note that most of the implementation here inherits from
  * {@link com.android.systemui.statusbar.policy.DevicePostureController}.
+ *
+ * Use the {@link TabletopModeController} if you are interested in tabletop mode change only,
+ * which is more common.
  */
 public class DevicePostureController {
     @IntDef(prefix = {"DEVICE_POSTURE_"}, value = {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TabletopModeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TabletopModeController.java
new file mode 100644
index 0000000..cb1a6e7
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TabletopModeController.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.common;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static com.android.wm.shell.common.DevicePostureController.DEVICE_POSTURE_HALF_OPENED;
+import static com.android.wm.shell.common.DevicePostureController.DEVICE_POSTURE_UNKNOWN;
+import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_FOLDABLE;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.app.WindowConfiguration;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.os.SystemProperties;
+import android.util.ArraySet;
+import android.view.Surface;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.common.annotations.ShellMainThread;
+import com.android.wm.shell.sysui.ShellInit;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Wrapper class to track the tabletop (aka. flex) mode change on Fold-ables.
+ * See also <a
+ * href="https://developer.android.com/guide/topics/large-screens/learn-about-foldables
+ * #foldable_postures">Foldable states and postures</a> for reference.
+ *
+ * Use the {@link DevicePostureController} for more detailed posture changes.
+ */
+public class TabletopModeController implements
+        DevicePostureController.OnDevicePostureChangedListener,
+        DisplayController.OnDisplaysChangedListener {
+    /**
+     * When {@code true}, floating windows like PiP would auto move to the position
+     * specified by {@link #PREFER_TOP_HALF_IN_TABLETOP} when in tabletop mode.
+     */
+    private static final boolean ENABLE_MOVE_FLOATING_WINDOW_IN_TABLETOP =
+            SystemProperties.getBoolean(
+                    "persist.wm.debug.enable_move_floating_window_in_tabletop", false);
+
+    /**
+     * Prefer the {@link #PREFERRED_TABLETOP_HALF_TOP} if this flag is enabled,
+     * {@link #PREFERRED_TABLETOP_HALF_BOTTOM} otherwise.
+     * See also {@link #getPreferredHalfInTabletopMode()}.
+     */
+    private static final boolean PREFER_TOP_HALF_IN_TABLETOP =
+            SystemProperties.getBoolean("persist.wm.debug.prefer_top_half_in_tabletop", true);
+
+    private static final long TABLETOP_MODE_DELAY_MILLIS = 1_000;
+
+    @IntDef(prefix = {"PREFERRED_TABLETOP_HALF_"}, value = {
+            PREFERRED_TABLETOP_HALF_TOP,
+            PREFERRED_TABLETOP_HALF_BOTTOM
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PreferredTabletopHalf {}
+
+    public static final int PREFERRED_TABLETOP_HALF_TOP = 0;
+    public static final int PREFERRED_TABLETOP_HALF_BOTTOM = 1;
+
+    private final Context mContext;
+
+    private final DevicePostureController mDevicePostureController;
+
+    private final DisplayController mDisplayController;
+
+    private final ShellExecutor mMainExecutor;
+
+    private final Set<Integer> mTabletopModeRotations = new ArraySet<>();
+
+    private final List<OnTabletopModeChangedListener> mListeners = new ArrayList<>();
+
+    @VisibleForTesting
+    final Runnable mOnEnterTabletopModeCallback = () -> {
+        if (isInTabletopMode()) {
+            // We are still in tabletop mode, go ahead.
+            mayBroadcastOnTabletopModeChange(true /* isInTabletopMode */);
+        }
+    };
+
+    @DevicePostureController.DevicePostureInt
+    private int mDevicePosture = DEVICE_POSTURE_UNKNOWN;
+
+    @Surface.Rotation
+    private int mDisplayRotation = WindowConfiguration.ROTATION_UNDEFINED;
+
+    /**
+     * Track the last callback value for {@link OnTabletopModeChangedListener}.
+     * This is to avoid duplicated {@code false} callback to {@link #mListeners}.
+     */
+    private Boolean mLastIsInTabletopModeForCallback;
+
+    public TabletopModeController(Context context,
+            ShellInit shellInit,
+            DevicePostureController postureController,
+            DisplayController displayController,
+            @ShellMainThread ShellExecutor mainExecutor) {
+        mContext = context;
+        mDevicePostureController = postureController;
+        mDisplayController = displayController;
+        mMainExecutor = mainExecutor;
+        shellInit.addInitCallback(this::onInit, this);
+    }
+
+    @VisibleForTesting
+    void onInit() {
+        mDevicePostureController.registerOnDevicePostureChangedListener(this);
+        mDisplayController.addDisplayWindowListener(this);
+        // Aligns with what's in {@link com.android.server.wm.DisplayRotation}.
+        final int[] deviceTabletopRotations = mContext.getResources().getIntArray(
+                com.android.internal.R.array.config_deviceTabletopRotations);
+        if (deviceTabletopRotations == null || deviceTabletopRotations.length == 0) {
+            ProtoLog.e(WM_SHELL_FOLDABLE,
+                    "No valid config_deviceTabletopRotations, can not tell"
+                            + " tabletop mode in WMShell");
+            return;
+        }
+        for (int angle : deviceTabletopRotations) {
+            switch (angle) {
+                case 0:
+                    mTabletopModeRotations.add(Surface.ROTATION_0);
+                    break;
+                case 90:
+                    mTabletopModeRotations.add(Surface.ROTATION_90);
+                    break;
+                case 180:
+                    mTabletopModeRotations.add(Surface.ROTATION_180);
+                    break;
+                case 270:
+                    mTabletopModeRotations.add(Surface.ROTATION_270);
+                    break;
+                default:
+                    ProtoLog.e(WM_SHELL_FOLDABLE,
+                            "Invalid surface rotation angle in "
+                                    + "config_deviceTabletopRotations: %d",
+                            angle);
+                    break;
+            }
+        }
+    }
+
+    /**
+     * @return {@code true} if floating windows like PiP would auto move to the position
+     * specified by {@link #getPreferredHalfInTabletopMode()} when in tabletop mode.
+     */
+    public boolean enableMoveFloatingWindowInTabletop() {
+        return ENABLE_MOVE_FLOATING_WINDOW_IN_TABLETOP;
+    }
+
+    /** @return Preferred half for floating windows like PiP when in tabletop mode. */
+    @PreferredTabletopHalf
+    public int getPreferredHalfInTabletopMode() {
+        return PREFER_TOP_HALF_IN_TABLETOP
+                ? PREFERRED_TABLETOP_HALF_TOP
+                : PREFERRED_TABLETOP_HALF_BOTTOM;
+    }
+
+    /** Register {@link OnTabletopModeChangedListener} to listen for tabletop mode change. */
+    public void registerOnTabletopModeChangedListener(
+            @NonNull OnTabletopModeChangedListener listener) {
+        if (listener == null || mListeners.contains(listener)) return;
+        mListeners.add(listener);
+        listener.onTabletopModeChanged(isInTabletopMode());
+    }
+
+    /** Unregister {@link OnTabletopModeChangedListener} for tabletop mode change. */
+    public void unregisterOnTabletopModeChangedListener(
+            @NonNull OnTabletopModeChangedListener listener) {
+        mListeners.remove(listener);
+    }
+
+    @Override
+    public void onDevicePostureChanged(@DevicePostureController.DevicePostureInt int posture) {
+        if (mDevicePosture != posture) {
+            onDevicePostureOrDisplayRotationChanged(posture, mDisplayRotation);
+        }
+    }
+
+    @Override
+    public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
+        final int newDisplayRotation = newConfig.windowConfiguration.getDisplayRotation();
+        if (displayId == DEFAULT_DISPLAY && newDisplayRotation != mDisplayRotation) {
+            onDevicePostureOrDisplayRotationChanged(mDevicePosture, newDisplayRotation);
+        }
+    }
+
+    private void onDevicePostureOrDisplayRotationChanged(
+            @DevicePostureController.DevicePostureInt int newPosture,
+            @Surface.Rotation int newDisplayRotation) {
+        final boolean wasInTabletopMode = isInTabletopMode();
+        mDevicePosture = newPosture;
+        mDisplayRotation = newDisplayRotation;
+        final boolean couldBeInTabletopMode = isInTabletopMode();
+        mMainExecutor.removeCallbacks(mOnEnterTabletopModeCallback);
+        if (!wasInTabletopMode && couldBeInTabletopMode) {
+            // May enter tabletop mode, but we need to wait for additional time since this
+            // could be an intermediate state.
+            mMainExecutor.executeDelayed(mOnEnterTabletopModeCallback, TABLETOP_MODE_DELAY_MILLIS);
+        } else {
+            // Cancel entering tabletop mode if any condition's changed.
+            mayBroadcastOnTabletopModeChange(false /* isInTabletopMode */);
+        }
+    }
+
+    private boolean isHalfOpened(@DevicePostureController.DevicePostureInt int posture) {
+        return posture == DEVICE_POSTURE_HALF_OPENED;
+    }
+
+    private boolean isInTabletopMode() {
+        return isHalfOpened(mDevicePosture) && mTabletopModeRotations.contains(mDisplayRotation);
+    }
+
+    private void mayBroadcastOnTabletopModeChange(boolean isInTabletopMode) {
+        if (mLastIsInTabletopModeForCallback == null
+                || mLastIsInTabletopModeForCallback != isInTabletopMode) {
+            mListeners.forEach(l -> l.onTabletopModeChanged(isInTabletopMode));
+            mLastIsInTabletopModeForCallback = isInTabletopMode;
+        }
+    }
+
+    /**
+     * Listener interface for tabletop mode change.
+     */
+    public interface OnTabletopModeChangedListener {
+        /**
+         * Callback when tabletop mode changes. Expect duplicated callbacks with {@code false}.
+         * @param isInTabletopMode {@code true} if enters tabletop mode, {@code false} otherwise.
+         */
+        void onTabletopModeChanged(boolean isInTabletopMode);
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TvWindowMenuActionButton.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TvWindowMenuActionButton.java
index 8ba785a..931cf0c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TvWindowMenuActionButton.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TvWindowMenuActionButton.java
@@ -70,6 +70,8 @@
             setTextAndDescription(textResId);
         }
         typedArray.recycle();
+
+        setIsCustomCloseAction(false);
     }
 
     /**
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 713dd39..69f0bad 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
@@ -371,7 +371,14 @@
         mViewHost.relayout(lp);
     }
 
-    void setInteractive(boolean interactive, String from) {
+    /**
+     * Set divider should interactive to user or not.
+     *
+     * @param interactive divider interactive.
+     * @param hideHandle divider handle hidden or not, only work when interactive is false.
+     * @param from caller from where.
+     */
+    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",
@@ -387,7 +394,7 @@
             mMoving = false;
         }
         releaseTouching();
-        mHandle.setVisibility(mInteractive ? View.VISIBLE : View.INVISIBLE);
+        mHandle.setVisibility(!mInteractive && hideHandle ? View.INVISIBLE : View.VISIBLE);
     }
 
     private boolean isLandscape() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
index e44257e..4970fa0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
@@ -248,11 +248,11 @@
 
     /** Stops showing resizing hint. */
     public void onResized(SurfaceControl.Transaction t, Runnable animFinishedCallback) {
-        if (mScreenshot != null) {
-            if (mScreenshotAnimator != null && mScreenshotAnimator.isRunning()) {
-                mScreenshotAnimator.cancel();
-            }
+        if (mScreenshotAnimator != null && mScreenshotAnimator.isRunning()) {
+            mScreenshotAnimator.cancel();
+        }
 
+        if (mScreenshot != null) {
             t.setPosition(mScreenshot, mOffsetX, mOffsetY);
 
             final SurfaceControl.Transaction animT = new SurfaceControl.Transaction();
@@ -322,6 +322,10 @@
     /** Screenshot host leash and attach on it if meet some conditions */
     public void screenshotIfNeeded(SurfaceControl.Transaction t) {
         if (!mShown && mIsResizing && !mOldBounds.equals(mResizingBounds)) {
+            if (mScreenshotAnimator != null && mScreenshotAnimator.isRunning()) {
+                mScreenshotAnimator.cancel();
+            }
+
             mTempRect.set(mOldBounds);
             mTempRect.offsetTo(0, 0);
             mScreenshot = ScreenshotUtils.takeScreenshot(t, mHostLeash, mTempRect,
@@ -334,6 +338,10 @@
         if (screenshot == null || !screenshot.isValid()) return;
 
         if (!mShown && mIsResizing && !mOldBounds.equals(mResizingBounds)) {
+            if (mScreenshotAnimator != null && mScreenshotAnimator.isRunning()) {
+                mScreenshotAnimator.cancel();
+            }
+
             mScreenshot = screenshot;
             t.reparent(screenshot, mHostLeash);
             t.setLayer(screenshot, Integer.MAX_VALUE - 1);
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 8a18271..b447a54 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
@@ -120,6 +120,7 @@
     private int mOrientation;
     private int mRotation;
     private int mDensity;
+    private int mUiMode;
 
     private final boolean mDimNonImeSide;
     private ValueAnimator mDividerFlingAnimator;
@@ -295,10 +296,12 @@
         final Rect rootBounds = configuration.windowConfiguration.getBounds();
         final int orientation = configuration.orientation;
         final int density = configuration.densityDpi;
+        final int uiMode = configuration.uiMode;
 
         if (mOrientation == orientation
                 && mRotation == rotation
                 && mDensity == density
+                && mUiMode == uiMode
                 && mRootBounds.equals(rootBounds)) {
             return false;
         }
@@ -310,6 +313,7 @@
         mRootBounds.set(rootBounds);
         mRotation = rotation;
         mDensity = density;
+        mUiMode = uiMode;
         mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds, null);
         updateDividerConfig(mContext);
         initDividerPosition(mTempRect);
@@ -486,6 +490,17 @@
     }
 
     /**
+     * Set divider should interactive to user or not.
+     *
+     * @param interactive divider interactive.
+     * @param hideHandle divider handle hidden or not, only work when interactive is false.
+     * @param from caller from where.
+     */
+    public void setDividerInteractive(boolean interactive, boolean hideHandle, String from) {
+        mSplitWindowManager.setInteractive(interactive, hideHandle, from);
+    }
+
+    /**
      * Sets new divide position and updates bounds correspondingly. Notifies listener if the new
      * target indicates dismissing split.
      */
@@ -735,21 +750,28 @@
         }
     }
 
-    /** Apply recorded task layout to the {@link WindowContainerTransaction}. */
-    public void applyTaskChanges(WindowContainerTransaction wct,
+    /** Apply recorded task layout to the {@link WindowContainerTransaction}.
+     *
+     * @return true if stage bounds actually update.
+     */
+    public boolean applyTaskChanges(WindowContainerTransaction wct,
             ActivityManager.RunningTaskInfo task1, ActivityManager.RunningTaskInfo task2) {
+        boolean boundsChanged = false;
         if (!mBounds1.equals(mWinBounds1) || !task1.token.equals(mWinToken1)) {
             wct.setBounds(task1.token, mBounds1);
             wct.setSmallestScreenWidthDp(task1.token, getSmallestWidthDp(mBounds1));
             mWinBounds1.set(mBounds1);
             mWinToken1 = task1.token;
+            boundsChanged = true;
         }
         if (!mBounds2.equals(mWinBounds2) || !task2.token.equals(mWinToken2)) {
             wct.setBounds(task2.token, mBounds2);
             wct.setSmallestScreenWidthDp(task2.token, getSmallestWidthDp(mBounds2));
             mWinBounds2.set(mBounds2);
             mWinToken2 = task2.token;
+            boundsChanged = true;
         }
+        return boundsChanged;
     }
 
     private int getSmallestWidthDp(Rect bounds) {
@@ -1091,7 +1113,7 @@
             // ImePositionProcessor#onImeVisibilityChanged directly in DividerView is not enough
             // because DividerView won't receive onImeVisibilityChanged callback after it being
             // re-inflated.
-            mSplitWindowManager.setInteractive(!mImeShown || !mHasImeFocus || isFloating,
+            setDividerInteractive(!mImeShown || !mHasImeFocus || isFloating, true,
                     "onImeStartPositioning");
 
             return needOffset ? IME_ANIMATION_NO_ALPHA : 0;
@@ -1118,7 +1140,7 @@
             // Restore the split layout when wm-shell is not controlling IME insets anymore.
             if (!controlling && mImeShown) {
                 reset();
-                mSplitWindowManager.setInteractive(true, "onImeControlTargetChanged");
+                setDividerInteractive(true, true, "onImeControlTargetChanged");
                 mSplitLayoutHandler.setLayoutOffsetTarget(0, 0, SplitLayout.this);
                 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 eb3c1df..00361d9 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
@@ -168,9 +168,16 @@
         }
     }
 
-    void setInteractive(boolean interactive, String from) {
+    /**
+     * Set divider should interactive to user or not.
+     *
+     * @param interactive divider interactive.
+     * @param hideHandle divider handle hidden or not, only work when interactive is false.
+     * @param from caller from where.
+     */
+    void setInteractive(boolean interactive, boolean hideHandle, String from) {
         if (mDividerView == null) return;
-        mDividerView.setInteractive(interactive, from);
+        mDividerView.setInteractive(interactive, hideHandle, from);
     }
 
     View getDividerView() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
index 3b2db51..76d9152 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
@@ -126,14 +126,12 @@
     private final Lazy<Transitions> mTransitionsLazy;
     private final DockStateReader mDockStateReader;
     private final CompatUIConfiguration mCompatUIConfiguration;
-
-    private CompatUICallback mCallback;
-
     // Only show each hint once automatically in the process life.
     private final CompatUIHintsState mCompatUIHintsState;
-
     private final CompatUIShellCommandHandler mCompatUIShellCommandHandler;
 
+    private CompatUICallback mCallback;
+
     // Indicates if the keyguard is currently showing, in which case compat UIs shouldn't
     // be shown.
     private boolean mKeyguardShowing;
@@ -372,19 +370,20 @@
         RestartDialogWindowManager layout =
                 mTaskIdToRestartDialogWindowManagerMap.get(taskInfo.taskId);
         if (layout != null) {
-            // TODO(b/266262111) Handle theme change when taskListener changes
-            if (layout.getTaskListener() != taskListener) {
-                mSetOfTaskIdsShowingRestartDialog.remove(taskInfo.taskId);
-            }
-            layout.setRequestRestartDialog(
-                    mSetOfTaskIdsShowingRestartDialog.contains(taskInfo.taskId));
-            // UI already exists, update the UI layout.
-            if (!layout.updateCompatInfo(taskInfo, taskListener,
-                    showOnDisplay(layout.getDisplayId()))) {
-                // The layout is no longer eligible to be shown, remove from active layouts.
+            if (layout.needsToBeRecreated(taskInfo, taskListener)) {
                 mTaskIdToRestartDialogWindowManagerMap.remove(taskInfo.taskId);
+                layout.release();
+            } else {
+                layout.setRequestRestartDialog(
+                        mSetOfTaskIdsShowingRestartDialog.contains(taskInfo.taskId));
+                // UI already exists, update the UI layout.
+                if (!layout.updateCompatInfo(taskInfo, taskListener,
+                        showOnDisplay(layout.getDisplayId()))) {
+                    // The layout is no longer eligible to be shown, remove from active layouts.
+                    mTaskIdToRestartDialogWindowManagerMap.remove(taskInfo.taskId);
+                }
+                return;
             }
-            return;
         }
         // Create a new UI layout.
         final Context context = getOrCreateDisplayContext(taskInfo.displayId);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
index efd4594..b22c9c7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
@@ -151,7 +151,6 @@
     @Override
     public void setConfiguration(Configuration configuration) {
         super.setConfiguration(configuration);
-        // TODO(b/266262111): Investigate loss of theme configuration when switching TaskListener
         mContext = mContext.createConfigurationContext(configuration);
     }
 
@@ -210,7 +209,8 @@
         }
 
         View layout = getLayout();
-        if (layout == null || prevTaskListener != taskListener) {
+        if (layout == null || prevTaskListener != taskListener
+                || mTaskConfig.uiMode != prevTaskConfig.uiMode) {
             // Layout wasn't created yet or TaskListener changed, recreate the layout for new
             // surface parent.
             release();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java
index 10f25d0..2440838 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java
@@ -155,6 +155,11 @@
         return super.updateCompatInfo(taskInfo, taskListener, canShow);
     }
 
+    boolean needsToBeRecreated(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) {
+        return taskInfo.configuration.uiMode != mTaskInfo.configuration.uiMode
+                || !getTaskListener().equals(taskListener);
+    }
+
     private void updateDialogMargins() {
         if (mLayout == null) {
             return;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvPipModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvPipModule.java
index ab96856..3d1ed87 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvPipModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvPipModule.java
@@ -31,6 +31,7 @@
 import com.android.wm.shell.pip.Pip;
 import com.android.wm.shell.pip.PipAnimationController;
 import com.android.wm.shell.pip.PipAppOpsListener;
+import com.android.wm.shell.pip.PipDisplayLayoutState;
 import com.android.wm.shell.pip.PipMediaController;
 import com.android.wm.shell.pip.PipParamsChangedForwarder;
 import com.android.wm.shell.pip.PipSnapAlgorithm;
@@ -70,7 +71,7 @@
             ShellInit shellInit,
             ShellController shellController,
             TvPipBoundsState tvPipBoundsState,
-            PipSizeSpecHandler pipSizeSpecHandler,
+            PipDisplayLayoutState pipDisplayLayoutState,
             TvPipBoundsAlgorithm tvPipBoundsAlgorithm,
             TvPipBoundsController tvPipBoundsController,
             PipAppOpsListener pipAppOpsListener,
@@ -91,7 +92,7 @@
                         shellInit,
                         shellController,
                         tvPipBoundsState,
-                        pipSizeSpecHandler,
+                        pipDisplayLayoutState,
                         tvPipBoundsAlgorithm,
                         tvPipBoundsController,
                         pipAppOpsListener,
@@ -141,14 +142,15 @@
     @WMSingleton
     @Provides
     static TvPipBoundsState provideTvPipBoundsState(Context context,
-            PipSizeSpecHandler pipSizeSpecHandler) {
-        return new TvPipBoundsState(context, pipSizeSpecHandler);
+            PipSizeSpecHandler pipSizeSpecHandler, PipDisplayLayoutState pipDisplayLayoutState) {
+        return new TvPipBoundsState(context, pipSizeSpecHandler, pipDisplayLayoutState);
     }
 
     @WMSingleton
     @Provides
-    static PipSizeSpecHandler providePipSizeSpecHelper(Context context) {
-        return new PipSizeSpecHandler(context);
+    static PipSizeSpecHandler providePipSizeSpecHelper(Context context,
+            PipDisplayLayoutState pipDisplayLayoutState) {
+        return new PipSizeSpecHandler(context, pipDisplayLayoutState);
     }
 
     // Handler needed for loadDrawableAsync() in PipControlsViewController
@@ -203,7 +205,7 @@
             TvPipMenuController tvPipMenuController,
             SyncTransactionQueue syncTransactionQueue,
             TvPipBoundsState tvPipBoundsState,
-            PipSizeSpecHandler pipSizeSpecHandler,
+            PipDisplayLayoutState pipDisplayLayoutState,
             PipTransitionState pipTransitionState,
             TvPipBoundsAlgorithm tvPipBoundsAlgorithm,
             PipAnimationController pipAnimationController,
@@ -215,7 +217,7 @@
             PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer,
             @ShellMainThread ShellExecutor mainExecutor) {
         return new TvPipTaskOrganizer(context,
-                syncTransactionQueue, pipTransitionState, tvPipBoundsState, pipSizeSpecHandler,
+                syncTransactionQueue, pipTransitionState, tvPipBoundsState, pipDisplayLayoutState,
                 tvPipBoundsAlgorithm, tvPipMenuController, pipAnimationController,
                 pipSurfaceTransactionHelper, pipTransitionController, pipParamsChangedForwarder,
                 splitScreenControllerOptional, displayController, pipUiEventLogger,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index 8380225..3d5230d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -52,6 +52,7 @@
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.common.SystemWindows;
+import com.android.wm.shell.common.TabletopModeController;
 import com.android.wm.shell.common.TaskStackListenerImpl;
 import com.android.wm.shell.common.TransactionPool;
 import com.android.wm.shell.common.annotations.ShellAnimationThread;
@@ -172,6 +173,18 @@
 
     @WMSingleton
     @Provides
+    static TabletopModeController provideTabletopModeController(
+            Context context,
+            ShellInit shellInit,
+            DevicePostureController postureController,
+            DisplayController displayController,
+            @ShellMainThread ShellExecutor mainExecutor) {
+        return new TabletopModeController(
+                context, shellInit, postureController, displayController, mainExecutor);
+    }
+
+    @WMSingleton
+    @Provides
     static DragAndDropController provideDragAndDropController(Context context,
             ShellInit shellInit,
             ShellController shellController,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index d1f4398..7a83d10 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -45,6 +45,7 @@
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.common.SystemWindows;
+import com.android.wm.shell.common.TabletopModeController;
 import com.android.wm.shell.common.TaskStackListenerImpl;
 import com.android.wm.shell.common.TransactionPool;
 import com.android.wm.shell.common.annotations.ShellBackgroundThread;
@@ -65,6 +66,7 @@
 import com.android.wm.shell.pip.PipAppOpsListener;
 import com.android.wm.shell.pip.PipBoundsAlgorithm;
 import com.android.wm.shell.pip.PipBoundsState;
+import com.android.wm.shell.pip.PipDisplayLayoutState;
 import com.android.wm.shell.pip.PipMediaController;
 import com.android.wm.shell.pip.PipParamsChangedForwarder;
 import com.android.wm.shell.pip.PipSnapAlgorithm;
@@ -196,7 +198,8 @@
             DisplayController displayController,
             SyncTransactionQueue syncQueue,
             Optional<DesktopModeController> desktopModeController,
-            Optional<DesktopTasksController> desktopTasksController) {
+            Optional<DesktopTasksController> desktopTasksController,
+            Optional<SplitScreenController> splitScreenController) {
         if (DesktopModeStatus.isAnyEnabled()) {
             return new DesktopModeWindowDecorViewModel(
                     context,
@@ -206,7 +209,8 @@
                     displayController,
                     syncQueue,
                     desktopModeController,
-                    desktopTasksController);
+                    desktopTasksController,
+                    splitScreenController);
         }
         return new CaptionWindowDecorViewModel(
                     context,
@@ -342,6 +346,7 @@
             PhonePipKeepClearAlgorithm pipKeepClearAlgorithm,
             PipBoundsState pipBoundsState,
             PipSizeSpecHandler pipSizeSpecHandler,
+            PipDisplayLayoutState pipDisplayLayoutState,
             PipMotionHelper pipMotionHelper,
             PipMediaController pipMediaController,
             PhonePipMenuController phonePipMenuController,
@@ -353,23 +358,24 @@
             TaskStackListenerImpl taskStackListener,
             PipParamsChangedForwarder pipParamsChangedForwarder,
             DisplayInsetsController displayInsetsController,
+            TabletopModeController pipTabletopController,
             Optional<OneHandedController> oneHandedController,
             @ShellMainThread ShellExecutor mainExecutor) {
         return Optional.ofNullable(PipController.create(
                 context, shellInit, shellCommandHandler, shellController,
                 displayController, pipAnimationController, pipAppOpsListener, pipBoundsAlgorithm,
-                pipKeepClearAlgorithm, pipBoundsState, pipSizeSpecHandler, pipMotionHelper,
-                pipMediaController, phonePipMenuController, pipTaskOrganizer, pipTransitionState,
-                pipTouchHandler, pipTransitionController, windowManagerShellWrapper,
-                taskStackListener, pipParamsChangedForwarder, displayInsetsController,
-                oneHandedController, mainExecutor));
+                pipKeepClearAlgorithm, pipBoundsState, pipSizeSpecHandler, pipDisplayLayoutState,
+                pipMotionHelper, pipMediaController, phonePipMenuController, pipTaskOrganizer,
+                pipTransitionState, pipTouchHandler, pipTransitionController,
+                windowManagerShellWrapper, taskStackListener, pipParamsChangedForwarder,
+                displayInsetsController, pipTabletopController, oneHandedController, mainExecutor));
     }
 
     @WMSingleton
     @Provides
     static PipBoundsState providePipBoundsState(Context context,
-            PipSizeSpecHandler pipSizeSpecHandler) {
-        return new PipBoundsState(context, pipSizeSpecHandler);
+            PipSizeSpecHandler pipSizeSpecHandler, PipDisplayLayoutState pipDisplayLayoutState) {
+        return new PipBoundsState(context, pipSizeSpecHandler, pipDisplayLayoutState);
     }
 
     @WMSingleton
@@ -386,8 +392,9 @@
 
     @WMSingleton
     @Provides
-    static PipSizeSpecHandler providePipSizeSpecHelper(Context context) {
-        return new PipSizeSpecHandler(context);
+    static PipSizeSpecHandler providePipSizeSpecHelper(Context context,
+            PipDisplayLayoutState pipDisplayLayoutState) {
+        return new PipSizeSpecHandler(context, pipDisplayLayoutState);
     }
 
     @WMSingleton
@@ -444,7 +451,7 @@
             SyncTransactionQueue syncTransactionQueue,
             PipTransitionState pipTransitionState,
             PipBoundsState pipBoundsState,
-            PipSizeSpecHandler pipSizeSpecHandler,
+            PipDisplayLayoutState pipDisplayLayoutState,
             PipBoundsAlgorithm pipBoundsAlgorithm,
             PhonePipMenuController menuPhoneController,
             PipAnimationController pipAnimationController,
@@ -456,7 +463,7 @@
             PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer,
             @ShellMainThread ShellExecutor mainExecutor) {
         return new PipTaskOrganizer(context,
-                syncTransactionQueue, pipTransitionState, pipBoundsState, pipSizeSpecHandler,
+                syncTransactionQueue, pipTransitionState, pipBoundsState, pipDisplayLayoutState,
                 pipBoundsAlgorithm, menuPhoneController, pipAnimationController,
                 pipSurfaceTransactionHelper, pipTransitionController, pipParamsChangedForwarder,
                 splitScreenControllerOptional, displayController, pipUiEventLogger,
@@ -475,12 +482,12 @@
     static PipTransitionController providePipTransitionController(Context context,
             ShellInit shellInit, ShellTaskOrganizer shellTaskOrganizer, Transitions transitions,
             PipAnimationController pipAnimationController, PipBoundsAlgorithm pipBoundsAlgorithm,
-            PipBoundsState pipBoundsState, PipSizeSpecHandler pipSizeSpecHandler,
+            PipBoundsState pipBoundsState, PipDisplayLayoutState pipDisplayLayoutState,
             PipTransitionState pipTransitionState, PhonePipMenuController pipMenuController,
             PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
             Optional<SplitScreenController> splitScreenOptional) {
         return new PipTransition(context, shellInit, shellTaskOrganizer, transitions,
-                pipBoundsState, pipSizeSpecHandler, pipTransitionState, pipMenuController,
+                pipBoundsState, pipDisplayLayoutState, pipTransitionState, pipMenuController,
                 pipBoundsAlgorithm, pipAnimationController, pipSurfaceTransactionHelper,
                 splitScreenOptional);
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
index b59fe18..4cfaae6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
@@ -36,6 +36,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
 
 import android.content.ClipDescription;
+import android.content.ComponentCallbacks2;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.PixelFormat;
@@ -58,9 +59,9 @@
 import com.android.wm.shell.R;
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.annotations.ExternalMainThread;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
 import com.android.wm.shell.splitscreen.SplitScreenController;
-import com.android.wm.shell.sysui.ConfigurationChangeListener;
 import com.android.wm.shell.sysui.ShellController;
 import com.android.wm.shell.sysui.ShellInit;
 
@@ -70,7 +71,7 @@
  * Handles the global drag and drop handling for the Shell.
  */
 public class DragAndDropController implements DisplayController.OnDisplaysChangedListener,
-        View.OnDragListener, ConfigurationChangeListener {
+        View.OnDragListener, ComponentCallbacks2 {
 
     private static final String TAG = DragAndDropController.class.getSimpleName();
 
@@ -119,7 +120,6 @@
         mMainExecutor.executeDelayed(() -> {
             mDisplayController.addDisplayWindowListener(this);
         }, 0);
-        mShellController.addConfigurationChangeListener(this);
     }
 
     /**
@@ -180,6 +180,7 @@
         try {
             wm.addView(rootView, layoutParams);
             addDisplayDropTarget(displayId, context, wm, rootView, dragLayout);
+            context.registerComponentCallbacks(this);
         } catch (WindowManager.InvalidDisplayException e) {
             Slog.w(TAG, "Unable to add view for display id: " + displayId);
         }
@@ -209,6 +210,7 @@
         if (pd == null) {
             return;
         }
+        pd.context.unregisterComponentCallbacks(this);
         pd.wm.removeViewImmediate(pd.rootView);
         mDisplayDropTargets.remove(displayId);
     }
@@ -328,18 +330,29 @@
         return mimeTypes;
     }
 
-    @Override
-    public void onThemeChanged() {
-        for (int i = 0; i < mDisplayDropTargets.size(); i++) {
-            mDisplayDropTargets.get(i).dragLayout.onThemeChange();
-        }
-    }
-
+    // Note: Component callbacks are always called on the main thread of the process
+    @ExternalMainThread
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
-        for (int i = 0; i < mDisplayDropTargets.size(); i++) {
-            mDisplayDropTargets.get(i).dragLayout.onConfigChanged(newConfig);
-        }
+        mMainExecutor.execute(() -> {
+            for (int i = 0; i < mDisplayDropTargets.size(); i++) {
+                mDisplayDropTargets.get(i).dragLayout.onConfigChanged(newConfig);
+            }
+        });
+    }
+
+    // Note: Component callbacks are always called on the main thread of the process
+    @ExternalMainThread
+    @Override
+    public void onTrimMemory(int level) {
+        // Do nothing
+    }
+
+    // Note: Component callbacks are always called on the main thread of the process
+    @ExternalMainThread
+    @Override
+    public void onLowMemory() {
+        // Do nothing
     }
 
     private static class PerDisplay {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
index 44fd8ee..fe42822a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
@@ -18,6 +18,8 @@
 
 import static android.app.StatusBarManager.DISABLE_NONE;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.content.pm.ActivityInfo.CONFIG_ASSETS_PATHS;
+import static android.content.pm.ActivityInfo.CONFIG_UI_MODE;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 
 import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
@@ -72,6 +74,7 @@
     private final SplitScreenController mSplitScreenController;
     private final IconProvider mIconProvider;
     private final StatusBarManager mStatusBarManager;
+    private final Configuration mLastConfiguration = new Configuration();
 
     private DragAndDropPolicy.Target mCurrentTarget = null;
     private DropZoneView mDropZoneView1;
@@ -92,6 +95,7 @@
         mIconProvider = iconProvider;
         mPolicy = new DragAndDropPolicy(context, splitScreenController);
         mStatusBarManager = context.getSystemService(StatusBarManager.class);
+        mLastConfiguration.setTo(context.getResources().getConfiguration());
 
         mDisplayMargin = context.getResources().getDimensionPixelSize(
                 R.dimen.drop_layout_display_margin);
@@ -132,11 +136,6 @@
         return super.onApplyWindowInsets(insets);
     }
 
-    public void onThemeChange() {
-        mDropZoneView1.onThemeChange();
-        mDropZoneView2.onThemeChange();
-    }
-
     public void onConfigChanged(Configuration newConfig) {
         if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE
                 && getOrientation() != HORIZONTAL) {
@@ -147,6 +146,15 @@
             setOrientation(LinearLayout.VERTICAL);
             updateContainerMargins(newConfig.orientation);
         }
+
+        final int diff = newConfig.diff(mLastConfiguration);
+        final boolean themeChanged = (diff & CONFIG_ASSETS_PATHS) != 0
+                || (diff & CONFIG_UI_MODE) != 0;
+        if (themeChanged) {
+            mDropZoneView1.onThemeChange();
+            mDropZoneView2.onThemeChange();
+        }
+        mLastConfiguration.setTo(newConfig);
     }
 
     private void updateContainerMarginsForSingleTask() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java
index d094c22..998728d6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java
@@ -129,6 +129,7 @@
     public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
         final State state = mTasks.get(taskInfo.taskId);
         final Point oldPositionInParent = state.mTaskInfo.positionInParent;
+        boolean oldVisible = state.mTaskInfo.isVisible;
 
         if (mWindowDecorViewModelOptional.isPresent()) {
             mWindowDecorViewModelOptional.get().onTaskInfoChanged(taskInfo);
@@ -138,12 +139,18 @@
         updateRecentsForVisibleFullscreenTask(taskInfo);
 
         final Point positionInParent = state.mTaskInfo.positionInParent;
-        if (!oldPositionInParent.equals(state.mTaskInfo.positionInParent)) {
+        boolean positionInParentChanged = !oldPositionInParent.equals(positionInParent);
+        boolean becameVisible = !oldVisible && state.mTaskInfo.isVisible;
+
+        if (becameVisible || positionInParentChanged) {
             mSyncQueue.runInSync(t -> {
                 if (!state.mLeash.isValid()) {
                     // Task vanished before sync completion
                     return;
                 }
+                if (becameVisible) {
+                    t.show(state.mLeash);
+                }
                 t.setPosition(state.mLeash, positionInParent.x, positionInParent.y);
             });
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java
index 9796e4c..2d84d21 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java
@@ -267,6 +267,11 @@
             mLaunchRootTask = taskInfo;
         }
 
+        if (mHomeTask != null && mHomeTask.taskId == taskInfo.taskId
+                && !taskInfo.equals(mHomeTask)) {
+            mHomeTask = taskInfo;
+        }
+
         super.onTaskInfoChanged(taskInfo);
     }
 
@@ -376,6 +381,7 @@
         final WindowContainerTransaction wct = getWindowContainerTransaction();
         final Rect taskBounds = calculateBounds();
         wct.setBounds(mLaunchRootTask.token, taskBounds);
+        wct.setBounds(mHomeTask.token, new Rect(0, 0, mDisplayWidth, mDisplayHeight));
         mSyncQueue.queue(wct);
         final SurfaceControl finalLeash = mLaunchRootLeash;
         mSyncQueue.runInSync(t -> {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl
index 2624ee5..d961d86 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl
@@ -70,4 +70,9 @@
      * Sets the next pip animation type to be the alpha animation.
      */
     oneway void setPipAnimationTypeToAlpha() = 5;
+
+    /**
+     * Sets the height and visibility of the Launcher keep clear area.
+     */
+    oneway void setLauncherKeepClearAreaHeight(boolean visible, int height) = 6;
 }
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 23f73f6..fe8ede6 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
@@ -36,6 +36,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
+import com.android.launcher3.icons.IconProvider;
 import com.android.wm.shell.animation.Interpolators;
 import com.android.wm.shell.transition.Transitions;
 
@@ -372,7 +373,8 @@
 
         void setAppIconContentOverlay(Context context, Rect bounds, ActivityInfo activityInfo) {
             reattachContentOverlay(
-                    new PipContentOverlay.PipAppIconOverlay(context, bounds, activityInfo));
+                    new PipContentOverlay.PipAppIconOverlay(context, bounds,
+                            () -> new IconProvider(context).getIcon(activityInfo)));
         }
 
         private void reattachContentOverlay(PipContentOverlay overlay) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
index 5be18d8..f08742d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
@@ -30,7 +30,6 @@
 import android.os.RemoteException;
 import android.util.ArraySet;
 import android.util.Size;
-import android.view.Display;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.protolog.common.ProtoLog;
@@ -44,7 +43,9 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 import java.util.function.Consumer;
@@ -77,6 +78,7 @@
     private final @NonNull Rect mExpandedBounds = new Rect();
     private final @NonNull Rect mNormalMovementBounds = new Rect();
     private final @NonNull Rect mExpandedMovementBounds = new Rect();
+    private final @NonNull PipDisplayLayoutState mPipDisplayLayoutState;
     private final Point mMaxSize = new Point();
     private final Point mMinSize = new Point();
     private final @NonNull Context mContext;
@@ -86,8 +88,6 @@
     private @Nullable PipReentryState mPipReentryState;
     private final @Nullable PipSizeSpecHandler mPipSizeSpecHandler;
     private @Nullable ComponentName mLastPipComponentName;
-    private int mDisplayId = Display.DEFAULT_DISPLAY;
-    private final @NonNull DisplayLayout mDisplayLayout = new DisplayLayout();
     private final @NonNull MotionBoundsState mMotionBoundsState = new MotionBoundsState();
     private boolean mIsImeShowing;
     private int mImeHeight;
@@ -115,15 +115,23 @@
      * @see android.view.View#setPreferKeepClearRects
      */
     private final Set<Rect> mUnrestrictedKeepClearAreas = new ArraySet<>();
+    /**
+     * Additional to {@link #mUnrestrictedKeepClearAreas}, allow the caller to append named bounds
+     * as unrestricted keep clear area. Values in this map would be appended to
+     * {@link #getUnrestrictedKeepClearAreas()} and this is meant for internal usage only.
+     */
+    private final Map<String, Rect> mNamedUnrestrictedKeepClearAreas = new HashMap<>();
 
     private @Nullable Runnable mOnMinimalSizeChangeCallback;
     private @Nullable TriConsumer<Boolean, Integer, Boolean> mOnShelfVisibilityChangeCallback;
     private List<Consumer<Rect>> mOnPipExclusionBoundsChangeCallbacks = new ArrayList<>();
 
-    public PipBoundsState(@NonNull Context context, PipSizeSpecHandler pipSizeSpecHandler) {
+    public PipBoundsState(@NonNull Context context, PipSizeSpecHandler pipSizeSpecHandler,
+            PipDisplayLayoutState pipDisplayLayoutState) {
         mContext = context;
         reloadResources();
         mPipSizeSpecHandler = pipSizeSpecHandler;
+        mPipDisplayLayoutState = pipDisplayLayoutState;
     }
 
     /** Reloads the resources. */
@@ -290,31 +298,16 @@
         return mLastPipComponentName;
     }
 
-    /** Get the current display id. */
-    public int getDisplayId() {
-        return mDisplayId;
-    }
-
-    /** Set the current display id for the associated display layout. */
-    public void setDisplayId(int displayId) {
-        mDisplayId = displayId;
-    }
-
     /** Returns the display's bounds. */
     @NonNull
     public Rect getDisplayBounds() {
-        return new Rect(0, 0, mDisplayLayout.width(), mDisplayLayout.height());
-    }
-
-    /** Update the display layout. */
-    public void setDisplayLayout(@NonNull DisplayLayout displayLayout) {
-        mDisplayLayout.set(displayLayout);
+        return mPipDisplayLayoutState.getDisplayBounds();
     }
 
     /** Get a copy of the display layout. */
     @NonNull
     public DisplayLayout getDisplayLayout() {
-        return new DisplayLayout(mDisplayLayout);
+        return mPipDisplayLayoutState.getDisplayLayout();
     }
 
     @VisibleForTesting
@@ -393,6 +386,16 @@
         mUnrestrictedKeepClearAreas.addAll(unrestrictedAreas);
     }
 
+    /** Add a named unrestricted keep clear area. */
+    public void addNamedUnrestrictedKeepClearArea(@NonNull String name, Rect unrestrictedArea) {
+        mNamedUnrestrictedKeepClearAreas.put(name, unrestrictedArea);
+    }
+
+    /** Remove a named unrestricted keep clear area. */
+    public void removeNamedUnrestrictedKeepClearArea(@NonNull String name) {
+        mNamedUnrestrictedKeepClearAreas.remove(name);
+    }
+
     @NonNull
     public Set<Rect> getRestrictedKeepClearAreas() {
         return mRestrictedKeepClearAreas;
@@ -400,7 +403,10 @@
 
     @NonNull
     public Set<Rect> getUnrestrictedKeepClearAreas() {
-        return mUnrestrictedKeepClearAreas;
+        if (mNamedUnrestrictedKeepClearAreas.isEmpty()) return mUnrestrictedKeepClearAreas;
+        final Set<Rect> unrestrictedAreas = new ArraySet<>(mUnrestrictedKeepClearAreas);
+        unrestrictedAreas.addAll(mNamedUnrestrictedKeepClearAreas.values());
+        return unrestrictedAreas;
     }
 
     /**
@@ -568,7 +574,6 @@
         pw.println(innerPrefix + "mExpandedMovementBounds=" + mExpandedMovementBounds);
         pw.println(innerPrefix + "mLastPipComponentName=" + mLastPipComponentName);
         pw.println(innerPrefix + "mAspectRatio=" + mAspectRatio);
-        pw.println(innerPrefix + "mDisplayId=" + mDisplayId);
         pw.println(innerPrefix + "mStashedState=" + mStashedState);
         pw.println(innerPrefix + "mStashOffset=" + mStashOffset);
         pw.println(innerPrefix + "mIsImeShowing=" + mIsImeShowing);
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 480bf93..d228dfb 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
@@ -20,9 +20,6 @@
 
 import android.annotation.Nullable;
 import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -35,10 +32,15 @@
 import android.view.SurfaceSession;
 import android.window.TaskSnapshot;
 
+import java.util.function.Supplier;
+
 /**
  * Represents the content overlay used during the entering PiP animation.
  */
 public abstract class PipContentOverlay {
+    // Fixed string used in WMShellFlickerTests
+    protected static final String LAYER_NAME = "PipContentOverlay";
+
     protected SurfaceControl mLeash;
 
     /** Attaches the internal {@link #mLeash} to the given parent leash. */
@@ -86,7 +88,7 @@
             mContext = context;
             mLeash = new SurfaceControl.Builder(new SurfaceSession())
                     .setCallsite(TAG)
-                    .setName(TAG)
+                    .setName(LAYER_NAME)
                     .setColorLayer()
                     .build();
         }
@@ -139,7 +141,7 @@
             mSourceRectHint = new Rect(sourceRectHint);
             mLeash = new SurfaceControl.Builder(new SurfaceSession())
                     .setCallsite(TAG)
-                    .setName(TAG)
+                    .setName(LAYER_NAME)
                     .build();
         }
 
@@ -174,7 +176,9 @@
     /** A {@link PipContentOverlay} shows app icon on solid color background. */
     public static final class PipAppIconOverlay extends PipContentOverlay {
         private static final String TAG = PipAppIconOverlay.class.getSimpleName();
-        private static final int APP_ICON_SIZE_DP = 48;
+        // Align with the practical / reasonable launcher:iconImageSize as in
+        // vendor/unbundled_google/packages/NexusLauncher/res/xml/device_profiles.xml
+        private static final int APP_ICON_SIZE_DP = 66;
 
         private final Context mContext;
         private final int mAppIconSizePx;
@@ -184,17 +188,17 @@
 
         private Bitmap mBitmap;
 
-        public PipAppIconOverlay(Context context, Rect appBounds, ActivityInfo activityInfo) {
+        public PipAppIconOverlay(Context context, Rect appBounds, Supplier<Drawable> iconSupplier) {
             mContext = context;
             mAppIconSizePx = (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, APP_ICON_SIZE_DP,
                     context.getResources().getDisplayMetrics());
             mAppBounds = new Rect(appBounds);
             mBitmap = Bitmap.createBitmap(appBounds.width(), appBounds.height(),
                     Bitmap.Config.ARGB_8888);
-            prepareAppIconOverlay(activityInfo);
+            prepareAppIconOverlay(iconSupplier);
             mLeash = new SurfaceControl.Builder(new SurfaceSession())
                     .setCallsite(TAG)
-                    .setName(TAG)
+                    .setName(LAYER_NAME)
                     .build();
         }
 
@@ -234,7 +238,7 @@
             }
         }
 
-        private void prepareAppIconOverlay(ActivityInfo activityInfo) {
+        private void prepareAppIconOverlay(Supplier<Drawable> iconSupplier) {
             final Canvas canvas = new Canvas();
             canvas.setBitmap(mBitmap);
             final TypedArray ta = mContext.obtainStyledAttributes(new int[] {
@@ -248,8 +252,7 @@
             } finally {
                 ta.recycle();
             }
-            final Drawable appIcon = loadActivityInfoIcon(activityInfo,
-                    mContext.getResources().getConfiguration().densityDpi);
+            final Drawable appIcon = iconSupplier.get();
             final Rect appIconBounds = new Rect(
                     mAppBounds.centerX() - mAppIconSizePx / 2,
                     mAppBounds.centerY() - mAppIconSizePx / 2,
@@ -259,24 +262,5 @@
             appIcon.draw(canvas);
             mBitmap = mBitmap.copy(Bitmap.Config.HARDWARE, false /* mutable */);
         }
-
-        // Copied from com.android.launcher3.icons.IconProvider#loadActivityInfoIcon
-        private Drawable loadActivityInfoIcon(ActivityInfo ai, int density) {
-            final int iconRes = ai.getIconResource();
-            Drawable icon = null;
-            // Get the preferred density icon from the app's resources
-            if (density != 0 && iconRes != 0) {
-                try {
-                    final Resources resources = mContext.getPackageManager()
-                            .getResourcesForApplication(ai.applicationInfo);
-                    icon = resources.getDrawableForDensity(iconRes, density);
-                } catch (PackageManager.NameNotFoundException | Resources.NotFoundException exc) { }
-            }
-            // Get the default density icon
-            if (icon == null) {
-                icon = ai.loadIcon(mContext.getPackageManager());
-            }
-            return icon;
-        }
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipDisplayLayoutState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipDisplayLayoutState.java
new file mode 100644
index 0000000..0f76af4
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipDisplayLayoutState.java
@@ -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.wm.shell.pip;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.view.Surface;
+
+import androidx.annotation.NonNull;
+
+import com.android.wm.shell.common.DisplayLayout;
+import com.android.wm.shell.dagger.WMSingleton;
+
+import java.io.PrintWriter;
+
+import javax.inject.Inject;
+
+/**
+ * Acts as a source of truth for display related information for PIP.
+ */
+@WMSingleton
+public class PipDisplayLayoutState {
+    private static final String TAG = PipDisplayLayoutState.class.getSimpleName();
+
+    private Context mContext;
+    private int mDisplayId;
+    @NonNull private DisplayLayout mDisplayLayout;
+
+    @Inject
+    public PipDisplayLayoutState(Context context) {
+        mContext = context;
+        mDisplayLayout = new DisplayLayout();
+    }
+
+    /** Update the display layout. */
+    public void setDisplayLayout(@NonNull DisplayLayout displayLayout) {
+        mDisplayLayout.set(displayLayout);
+    }
+
+    /** Get a copy of the display layout. */
+    @NonNull
+    public DisplayLayout getDisplayLayout() {
+        return new DisplayLayout(mDisplayLayout);
+    }
+
+    /** Get the display bounds */
+    @NonNull
+    public Rect getDisplayBounds() {
+        return new Rect(0, 0, mDisplayLayout.width(), mDisplayLayout.height());
+    }
+
+    /**
+     * Apply a rotation to this layout and its parameters.
+     * @param targetRotation
+     */
+    public void rotateTo(@Surface.Rotation int targetRotation) {
+        mDisplayLayout.rotateTo(mContext.getResources(), targetRotation);
+    }
+
+    /** Get the current display id */
+    public int getDisplayId() {
+        return mDisplayId;
+    }
+
+    /** Set the current display id for the associated display layout. */
+    public void setDisplayId(int displayId) {
+        mDisplayId = displayId;
+    }
+
+    /** Dumps internal state. */
+    public void dump(PrintWriter pw, String prefix) {
+        final String innerPrefix = prefix + "  ";
+        pw.println(prefix + TAG);
+        pw.println(innerPrefix + "mDisplayId=" + mDisplayId);
+        pw.println(innerPrefix + "getDisplayBounds=" + getDisplayBounds());
+    }
+}
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 f11836e..d5b9c5e 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
@@ -79,13 +79,11 @@
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.animation.Interpolators;
 import com.android.wm.shell.common.DisplayController;
-import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.common.ScreenshotUtils;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.common.annotations.ShellMainThread;
 import com.android.wm.shell.pip.phone.PipMotionHelper;
-import com.android.wm.shell.pip.phone.PipSizeSpecHandler;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
 import com.android.wm.shell.splitscreen.SplitScreenController;
 import com.android.wm.shell.transition.Transitions;
@@ -128,7 +126,7 @@
     private final Context mContext;
     private final SyncTransactionQueue mSyncTransactionQueue;
     private final PipBoundsState mPipBoundsState;
-    private final PipSizeSpecHandler mPipSizeSpecHandler;
+    private final PipDisplayLayoutState mPipDisplayLayoutState;
     private final PipBoundsAlgorithm mPipBoundsAlgorithm;
     private final @NonNull PipMenuController mPipMenuController;
     private final PipAnimationController mPipAnimationController;
@@ -316,7 +314,7 @@
             @NonNull SyncTransactionQueue syncTransactionQueue,
             @NonNull PipTransitionState pipTransitionState,
             @NonNull PipBoundsState pipBoundsState,
-            @NonNull PipSizeSpecHandler pipSizeSpecHandler,
+            @NonNull PipDisplayLayoutState pipDisplayLayoutState,
             @NonNull PipBoundsAlgorithm boundsHandler,
             @NonNull PipMenuController pipMenuController,
             @NonNull PipAnimationController pipAnimationController,
@@ -332,7 +330,7 @@
         mSyncTransactionQueue = syncTransactionQueue;
         mPipTransitionState = pipTransitionState;
         mPipBoundsState = pipBoundsState;
-        mPipSizeSpecHandler = pipSizeSpecHandler;
+        mPipDisplayLayoutState = pipDisplayLayoutState;
         mPipBoundsAlgorithm = boundsHandler;
         mPipMenuController = pipMenuController;
         mPipTransitionController = pipTransitionController;
@@ -653,7 +651,7 @@
 
         // If the displayId of the task is different than what PipBoundsHandler has, then update
         // it. This is possible if we entered PiP on an external display.
-        if (info.displayId != mPipBoundsState.getDisplayId()
+        if (info.displayId != mPipDisplayLayoutState.getDisplayId()
                 && mOnDisplayIdChangeCallback != null) {
             mOnDisplayIdChangeCallback.accept(info.displayId);
         }
@@ -1179,6 +1177,20 @@
     }
 
     /**
+     * Directly update the animator bounds.
+     */
+    public void updateAnimatorBounds(Rect bounds) {
+        final PipAnimationController.PipTransitionAnimator animator =
+                mPipAnimationController.getCurrentAnimator();
+        if (animator != null && animator.isRunning()) {
+            if (animator.getAnimationType() == ANIM_TYPE_BOUNDS) {
+                animator.updateEndValue(bounds);
+            }
+            animator.setDestinationBounds(bounds);
+        }
+    }
+
+    /**
      * Handles all changes to the PictureInPictureParams.
      */
     protected void applyNewPictureInPictureParams(@NonNull PictureInPictureParams params) {
@@ -1594,7 +1606,7 @@
             // source rect hint to enter PiP use bounds animation.
             if (sourceHintRect == null) {
                 if (SystemProperties.getBoolean(
-                        "persist.wm.debug.enable_pip_app_icon_overlay", false)) {
+                        "persist.wm.debug.enable_pip_app_icon_overlay", true)) {
                     animator.setAppIconContentOverlay(
                             mContext, currentBounds, mTaskInfo.topActivityInfo);
                 } else {
@@ -1621,15 +1633,15 @@
         return animator;
     }
 
-    /** Computes destination bounds in old rotation and returns source hint rect if available. */
+    /** Computes destination bounds in old rotation and returns source hint rect if available.
+     *
+     * Note: updates the internal state of {@link PipDisplayLayoutState} by applying a rotation
+     * transformation onto the display layout.
+     */
     private @Nullable Rect computeRotatedBounds(int rotationDelta, int direction,
             Rect outDestinationBounds, Rect sourceHintRect) {
         if (direction == TRANSITION_DIRECTION_TO_PIP) {
-            DisplayLayout layoutCopy = mPipBoundsState.getDisplayLayout();
-
-            layoutCopy.rotateTo(mContext.getResources(), mNextRotation);
-            mPipBoundsState.setDisplayLayout(layoutCopy);
-            mPipSizeSpecHandler.setDisplayLayout(layoutCopy);
+            mPipDisplayLayoutState.rotateTo(mNextRotation);
 
             final Rect displayBounds = mPipBoundsState.getDisplayBounds();
             outDestinationBounds.set(mPipBoundsAlgorithm.getEntryDestinationBounds());
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 6b0337d..45bb73b 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
@@ -64,8 +64,6 @@
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.R;
 import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.common.DisplayLayout;
-import com.android.wm.shell.pip.phone.PipSizeSpecHandler;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
 import com.android.wm.shell.splitscreen.SplitScreenController;
 import com.android.wm.shell.sysui.ShellInit;
@@ -85,7 +83,7 @@
 
     private final Context mContext;
     private final PipTransitionState mPipTransitionState;
-    private final PipSizeSpecHandler mPipSizeSpecHandler;
+    private final PipDisplayLayoutState mPipDisplayLayoutState;
     private final int mEnterExitAnimationDuration;
     private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
     private final Optional<SplitScreenController> mSplitScreenOptional;
@@ -116,7 +114,7 @@
             @NonNull ShellTaskOrganizer shellTaskOrganizer,
             @NonNull Transitions transitions,
             PipBoundsState pipBoundsState,
-            PipSizeSpecHandler pipSizeSpecHandler,
+            PipDisplayLayoutState pipDisplayLayoutState,
             PipTransitionState pipTransitionState,
             PipMenuController pipMenuController,
             PipBoundsAlgorithm pipBoundsAlgorithm,
@@ -127,7 +125,7 @@
                 pipBoundsAlgorithm, pipAnimationController);
         mContext = context;
         mPipTransitionState = pipTransitionState;
-        mPipSizeSpecHandler = pipSizeSpecHandler;
+        mPipDisplayLayoutState = pipDisplayLayoutState;
         mEnterExitAnimationDuration = context.getResources()
                 .getInteger(R.integer.config_pipResizeAnimationDuration);
         mSurfaceTransactionHelper = pipSurfaceTransactionHelper;
@@ -313,11 +311,7 @@
             // initial state under the new rotation.
             int rotationDelta = deltaRotation(startRotation, endRotation);
             if (rotationDelta != Surface.ROTATION_0) {
-                DisplayLayout layoutCopy = mPipBoundsState.getDisplayLayout();
-
-                layoutCopy.rotateTo(mContext.getResources(), endRotation);
-                mPipBoundsState.setDisplayLayout(layoutCopy);
-                mPipSizeSpecHandler.setDisplayLayout(layoutCopy);
+                mPipDisplayLayoutState.rotateTo(endRotation);
 
                 final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds();
                 wct.setBounds(mRequestedEnterTask, destinationBounds);
@@ -398,7 +392,7 @@
                 // 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
                 // finishTransaction is using the updated bounds in the display rotation.
-                final Rect displayBounds = mPipBoundsState.getDisplayBounds();
+                final Rect displayBounds = mPipDisplayLayoutState.getDisplayBounds();
                 final Rect finishBounds = new Rect(destinationBounds);
                 rotateBounds(finishBounds, displayBounds, mEndFixedRotation, displayRotation);
                 mSurfaceTransactionHelper.crop(mFinishTransaction, leash, finishBounds);
@@ -495,10 +489,11 @@
         // Reparent the pip leash to the root with max layer so that we can animate it outside of
         // parent crop, and make sure it is not covered by other windows.
         final SurfaceControl pipLeash = pipChange.getLeash();
-        startTransaction.reparent(pipLeash, info.getRootLeash());
+        final int rootIdx = TransitionUtil.rootIndexFor(pipChange, info);
+        startTransaction.reparent(pipLeash, info.getRoot(rootIdx).getLeash());
         startTransaction.setLayer(pipLeash, Integer.MAX_VALUE);
         // Note: because of this, the bounds to animate should be translated to the root coordinate.
-        final Point offset = info.getRootOffset();
+        final Point offset = info.getRoot(rootIdx).getOffset();
         final Rect currentBounds = mPipBoundsState.getBounds();
         currentBounds.offset(-offset.x, -offset.y);
         startTransaction.setPosition(pipLeash, currentBounds.left, currentBounds.top);
@@ -640,7 +635,7 @@
             @NonNull TaskInfo taskInfo) {
         startTransaction.apply();
         finishTransaction.setWindowCrop(info.getChanges().get(0).getLeash(),
-                mPipBoundsState.getDisplayBounds());
+                mPipDisplayLayoutState.getDisplayBounds());
         mPipOrganizer.onExitPipFinished(taskInfo);
         finishCallback.onTransitionFinished(null, null);
     }
@@ -803,8 +798,15 @@
             if (sourceHintRect == null) {
                 // We use content overlay when there is no source rect hint to enter PiP use bounds
                 // animation.
+                // TODO(b/272819817): cleanup the null-check and extra logging.
+                final boolean hasTopActivityInfo = taskInfo.topActivityInfo != null;
+                if (!hasTopActivityInfo) {
+                    ProtoLog.w(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+                            "%s: TaskInfo.topActivityInfo is null", TAG);
+                }
                 if (SystemProperties.getBoolean(
-                        "persist.wm.debug.enable_pip_app_icon_overlay", false)) {
+                        "persist.wm.debug.enable_pip_app_icon_overlay", true)
+                        && hasTopActivityInfo) {
                     animator.setAppIconContentOverlay(
                             mContext, currentBounds, taskInfo.topActivityInfo);
                 } else {
@@ -834,13 +836,9 @@
     /** Computes destination bounds in old rotation and updates source hint rect if available. */
     private void computeEnterPipRotatedBounds(int rotationDelta, int startRotation, int endRotation,
             TaskInfo taskInfo, Rect outDestinationBounds, @Nullable Rect outSourceHintRect) {
-        DisplayLayout layoutCopy = mPipBoundsState.getDisplayLayout();
+        mPipDisplayLayoutState.rotateTo(endRotation);
 
-        layoutCopy.rotateTo(mContext.getResources(), endRotation);
-        mPipBoundsState.setDisplayLayout(layoutCopy);
-        mPipSizeSpecHandler.setDisplayLayout(layoutCopy);
-
-        final Rect displayBounds = mPipBoundsState.getDisplayBounds();
+        final Rect displayBounds = mPipDisplayLayoutState.getDisplayBounds();
         outDestinationBounds.set(mPipBoundsAlgorithm.getEntryDestinationBounds());
         // Transform the destination bounds to current display coordinates.
         rotateBounds(outDestinationBounds, displayBounds, endRotation, startRotation);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java
index c6b5ce9..db6138a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java
@@ -93,6 +93,11 @@
         return hasEnteredPip(mState);
     }
 
+    /** Returns true if activity is currently entering PiP mode. */
+    public boolean isEnteringPip() {
+        return isEnteringPip(mState);
+    }
+
     public void setInSwipePipToHomeTransition(boolean inSwipePipToHomeTransition) {
         mInSwipePipToHomeTransition = inSwipePipToHomeTransition;
     }
@@ -130,6 +135,11 @@
         return state == ENTERED_PIP;
     }
 
+    /** Returns true if activity is currently entering PiP mode. */
+    public static boolean isEnteringPip(@TransitionState int state) {
+        return state == ENTERING_PIP;
+    }
+
     public interface OnPipTransitionStateChangedListener {
         void onPipTransitionStateChanged(@TransitionState int oldState,
                 @TransitionState int newState);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index a1483a8..be9b529 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -43,6 +43,7 @@
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.RemoteException;
 import android.os.SystemProperties;
@@ -71,6 +72,7 @@
 import com.android.wm.shell.common.RemoteCallable;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SingleInstanceRemoteListener;
+import com.android.wm.shell.common.TabletopModeController;
 import com.android.wm.shell.common.TaskStackListenerCallback;
 import com.android.wm.shell.common.TaskStackListenerImpl;
 import com.android.wm.shell.onehanded.OneHandedController;
@@ -83,6 +85,7 @@
 import com.android.wm.shell.pip.PipAppOpsListener;
 import com.android.wm.shell.pip.PipBoundsAlgorithm;
 import com.android.wm.shell.pip.PipBoundsState;
+import com.android.wm.shell.pip.PipDisplayLayoutState;
 import com.android.wm.shell.pip.PipKeepClearAlgorithmInterface;
 import com.android.wm.shell.pip.PipMediaController;
 import com.android.wm.shell.pip.PipParamsChangedForwarder;
@@ -101,6 +104,7 @@
 import com.android.wm.shell.transition.Transitions;
 
 import java.io.PrintWriter;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
@@ -138,12 +142,14 @@
     private PipKeepClearAlgorithmInterface mPipKeepClearAlgorithm;
     private PipBoundsState mPipBoundsState;
     private PipSizeSpecHandler mPipSizeSpecHandler;
+    private PipDisplayLayoutState mPipDisplayLayoutState;
     private PipMotionHelper mPipMotionHelper;
     private PipTouchHandler mTouchHandler;
     private PipTransitionController mPipTransitionController;
     private TaskStackListenerImpl mTaskStackListener;
     private PipParamsChangedForwarder mPipParamsChangedForwarder;
     private DisplayInsetsController mDisplayInsetsController;
+    private TabletopModeController mTabletopModeController;
     private Optional<OneHandedController> mOneHandedController;
     private final ShellCommandHandler mShellCommandHandler;
     private final ShellController mShellController;
@@ -181,14 +187,20 @@
             // early bail out if the keep clear areas feature is disabled
             return;
         }
-        // only move if already in pip, other transitions account for keep clear areas
-        if (mPipTransitionState.hasEnteredPip()) {
+        // only move if we're in PiP or transitioning into PiP
+        if (!mPipTransitionState.shouldBlockResizeRequest()) {
             Rect destBounds = mPipKeepClearAlgorithm.adjust(mPipBoundsState,
                     mPipBoundsAlgorithm);
             // only move if the bounds are actually different
             if (destBounds != mPipBoundsState.getBounds()) {
-                mPipTaskOrganizer.scheduleAnimateResizePip(destBounds,
-                        mEnterAnimationDuration, null);
+                if (mPipTransitionState.hasEnteredPip()) {
+                    // if already in PiP, schedule separate animation
+                    mPipTaskOrganizer.scheduleAnimateResizePip(destBounds,
+                            mEnterAnimationDuration, null);
+                } else if (mPipTransitionState.isEnteringPip()) {
+                    // while entering PiP we just need to update animator bounds
+                    mPipTaskOrganizer.updateAnimatorBounds(destBounds);
+                }
             }
         }
     }
@@ -303,7 +315,7 @@
 
                 @Override
                 public void onDisplayAdded(int displayId) {
-                    if (displayId != mPipBoundsState.getDisplayId()) {
+                    if (displayId != mPipDisplayLayoutState.getDisplayId()) {
                         return;
                     }
                     onDisplayChanged(mDisplayController.getDisplayLayout(displayId),
@@ -312,7 +324,7 @@
 
                 @Override
                 public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
-                    if (displayId != mPipBoundsState.getDisplayId()) {
+                    if (displayId != mPipDisplayLayoutState.getDisplayId()) {
                         return;
                     }
                     onDisplayChanged(mDisplayController.getDisplayLayout(displayId),
@@ -322,7 +334,7 @@
                 @Override
                 public void onKeepClearAreasChanged(int displayId, Set<Rect> restricted,
                         Set<Rect> unrestricted) {
-                    if (mPipBoundsState.getDisplayId() == displayId) {
+                    if (mPipDisplayLayoutState.getDisplayId() == displayId) {
                         if (mEnablePipKeepClearAlgorithm) {
                             mPipBoundsState.setKeepClearAreas(restricted, unrestricted);
 
@@ -382,6 +394,7 @@
             PipKeepClearAlgorithmInterface pipKeepClearAlgorithm,
             PipBoundsState pipBoundsState,
             PipSizeSpecHandler pipSizeSpecHandler,
+            PipDisplayLayoutState pipDisplayLayoutState,
             PipMotionHelper pipMotionHelper,
             PipMediaController pipMediaController,
             PhonePipMenuController phonePipMenuController,
@@ -393,6 +406,7 @@
             TaskStackListenerImpl taskStackListener,
             PipParamsChangedForwarder pipParamsChangedForwarder,
             DisplayInsetsController displayInsetsController,
+            TabletopModeController pipTabletopController,
             Optional<OneHandedController> oneHandedController,
             ShellExecutor mainExecutor) {
         if (!context.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
@@ -404,10 +418,10 @@
         return new PipController(context, shellInit, shellCommandHandler, shellController,
                 displayController, pipAnimationController, pipAppOpsListener,
                 pipBoundsAlgorithm, pipKeepClearAlgorithm, pipBoundsState, pipSizeSpecHandler,
-                pipMotionHelper, pipMediaController, phonePipMenuController, pipTaskOrganizer,
-                pipTransitionState, pipTouchHandler, pipTransitionController,
+                pipDisplayLayoutState, pipMotionHelper, pipMediaController, phonePipMenuController,
+                pipTaskOrganizer, pipTransitionState, pipTouchHandler, pipTransitionController,
                 windowManagerShellWrapper, taskStackListener, pipParamsChangedForwarder,
-                displayInsetsController, oneHandedController, mainExecutor)
+                displayInsetsController, pipTabletopController, oneHandedController, mainExecutor)
                 .mImpl;
     }
 
@@ -422,6 +436,7 @@
             PipKeepClearAlgorithmInterface pipKeepClearAlgorithm,
             @NonNull PipBoundsState pipBoundsState,
             PipSizeSpecHandler pipSizeSpecHandler,
+            @NonNull PipDisplayLayoutState pipDisplayLayoutState,
             PipMotionHelper pipMotionHelper,
             PipMediaController pipMediaController,
             PhonePipMenuController phonePipMenuController,
@@ -433,6 +448,7 @@
             TaskStackListenerImpl taskStackListener,
             PipParamsChangedForwarder pipParamsChangedForwarder,
             DisplayInsetsController displayInsetsController,
+            TabletopModeController tabletopModeController,
             Optional<OneHandedController> oneHandedController,
             ShellExecutor mainExecutor
     ) {
@@ -448,6 +464,7 @@
         mPipKeepClearAlgorithm = pipKeepClearAlgorithm;
         mPipBoundsState = pipBoundsState;
         mPipSizeSpecHandler = pipSizeSpecHandler;
+        mPipDisplayLayoutState = pipDisplayLayoutState;
         mPipMotionHelper = pipMotionHelper;
         mPipTaskOrganizer = pipTaskOrganizer;
         mPipTransitionState = pipTransitionState;
@@ -465,6 +482,7 @@
                 .getInteger(R.integer.config_pipEnterAnimationDuration);
         mPipParamsChangedForwarder = pipParamsChangedForwarder;
         mDisplayInsetsController = displayInsetsController;
+        mTabletopModeController = tabletopModeController;
 
         shellInit.addInitCallback(this::onInit, this);
     }
@@ -475,7 +493,7 @@
                 INPUT_CONSUMER_PIP, mMainExecutor);
         mPipTransitionController.registerPipTransitionCallback(this);
         mPipTaskOrganizer.registerOnDisplayIdChangeCallback((int displayId) -> {
-            mPipBoundsState.setDisplayId(displayId);
+            mPipDisplayLayoutState.setDisplayId(displayId);
             onDisplayChanged(mDisplayController.getDisplayLayout(displayId),
                     false /* saveRestoreSnapFraction */);
         });
@@ -515,11 +533,10 @@
 
         // Ensure that we have the display info in case we get calls to update the bounds before the
         // listener calls back
-        mPipBoundsState.setDisplayId(mContext.getDisplayId());
+        mPipDisplayLayoutState.setDisplayId(mContext.getDisplayId());
 
         DisplayLayout layout = new DisplayLayout(mContext, mContext.getDisplay());
-        mPipSizeSpecHandler.setDisplayLayout(layout);
-        mPipBoundsState.setDisplayLayout(layout);
+        mPipDisplayLayoutState.setDisplayLayout(layout);
 
         try {
             mWindowManagerShellWrapper.addPinnedStackListener(mPinnedTaskListener);
@@ -614,12 +631,12 @@
                     }
                 });
 
-        mDisplayInsetsController.addInsetsChangedListener(mPipBoundsState.getDisplayId(),
+        mDisplayInsetsController.addInsetsChangedListener(mPipDisplayLayoutState.getDisplayId(),
                 new DisplayInsetsController.OnInsetsChangedListener() {
                     @Override
                     public void insetsChanged(InsetsState insetsState) {
-                        DisplayLayout pendingLayout =
-                                mDisplayController.getDisplayLayout(mPipBoundsState.getDisplayId());
+                        DisplayLayout pendingLayout = mDisplayController
+                                .getDisplayLayout(mPipDisplayLayoutState.getDisplayId());
                         if (mIsInFixedRotation
                                 || pendingLayout.rotation()
                                 != mPipBoundsState.getDisplayLayout().rotation()) {
@@ -627,8 +644,8 @@
                             return;
                         }
                         int oldMaxMovementBound = mPipBoundsState.getMovementBounds().bottom;
-                        onDisplayChangedUncheck(
-                                mDisplayController.getDisplayLayout(mPipBoundsState.getDisplayId()),
+                        onDisplayChangedUncheck(mDisplayController
+                                        .getDisplayLayout(mPipDisplayLayoutState.getDisplayId()),
                                 false /* saveRestoreSnapFraction */);
                         int newMaxMovementBound = mPipBoundsState.getMovementBounds().bottom;
                         if (!mEnablePipKeepClearAlgorithm) {
@@ -648,6 +665,42 @@
                     }
                 });
 
+        mTabletopModeController.registerOnTabletopModeChangedListener((isInTabletopMode) -> {
+            if (!mTabletopModeController.enableMoveFloatingWindowInTabletop()) return;
+            final String tag = "tabletop-mode";
+            if (!isInTabletopMode) {
+                mPipBoundsState.removeNamedUnrestrictedKeepClearArea(tag);
+                return;
+            }
+
+            // To prepare for the entry bounds.
+            final Rect displayBounds = mPipBoundsState.getDisplayBounds();
+            if (mTabletopModeController.getPreferredHalfInTabletopMode()
+                    == TabletopModeController.PREFERRED_TABLETOP_HALF_TOP) {
+                // Prefer top, avoid the bottom half of the display.
+                mPipBoundsState.addNamedUnrestrictedKeepClearArea(tag, new Rect(
+                        displayBounds.left, displayBounds.centerY(),
+                        displayBounds.right, displayBounds.bottom));
+            } else {
+                // Prefer bottom, avoid the top half of the display.
+                mPipBoundsState.addNamedUnrestrictedKeepClearArea(tag, new Rect(
+                        displayBounds.left, displayBounds.top,
+                        displayBounds.right, displayBounds.centerY()));
+            }
+
+            // Try to move the PiP window if we have entered PiP mode.
+            if (mPipTransitionState.hasEnteredPip()) {
+                final Rect pipBounds = mPipBoundsState.getBounds();
+                final Point edgeInsets = mPipSizeSpecHandler.getScreenEdgeInsets();
+                if ((pipBounds.height() + 2 * edgeInsets.y) > (displayBounds.height() / 2)) {
+                    // PiP bounds is too big to fit either half, bail early.
+                    return;
+                }
+                mMainExecutor.removeCallbacks(mMovePipInResponseToKeepClearAreasChangeCallback);
+                mMainExecutor.execute(mMovePipInResponseToKeepClearAreasChangeCallback);
+            }
+        });
+
         mOneHandedController.ifPresent(controller -> {
             controller.registerTransitionCallback(
                     new OneHandedTransitionCallback() {
@@ -714,7 +767,7 @@
     }
 
     private void onDisplayChanged(DisplayLayout layout, boolean saveRestoreSnapFraction) {
-        if (!mPipBoundsState.getDisplayLayout().isSameGeometry(layout)) {
+        if (!mPipDisplayLayoutState.getDisplayLayout().isSameGeometry(layout)) {
             PipAnimationController.PipTransitionAnimator animator =
                     mPipAnimationController.getCurrentAnimator();
             if (animator != null && animator.isRunning()) {
@@ -728,11 +781,10 @@
     private void onDisplayChangedUncheck(DisplayLayout layout, boolean saveRestoreSnapFraction) {
         Runnable updateDisplayLayout = () -> {
             final boolean fromRotation = Transitions.ENABLE_SHELL_TRANSITIONS
-                    && mPipBoundsState.getDisplayLayout().rotation() != layout.rotation();
+                    && mPipDisplayLayoutState.getDisplayLayout().rotation() != layout.rotation();
 
             // update the internal state of objects subscribed to display changes
-            mPipSizeSpecHandler.setDisplayLayout(layout);
-            mPipBoundsState.setDisplayLayout(layout);
+            mPipDisplayLayoutState.setDisplayLayout(layout);
 
             final WindowContainerTransaction wct =
                     fromRotation ? new WindowContainerTransaction() : null;
@@ -756,11 +808,13 @@
                     mPipBoundsState.getStashedState());
 
             // Scale PiP on density dpi change, so it appears to be the same size physically.
-            final boolean densityDpiChanged = mPipBoundsState.getDisplayLayout().densityDpi() != 0
-                    && (mPipBoundsState.getDisplayLayout().densityDpi() != layout.densityDpi());
+            final boolean densityDpiChanged =
+                    mPipDisplayLayoutState.getDisplayLayout().densityDpi() != 0
+                    && (mPipDisplayLayoutState.getDisplayLayout().densityDpi()
+                            != layout.densityDpi());
             if (densityDpiChanged) {
                 final float scale = (float) layout.densityDpi()
-                        / mPipBoundsState.getDisplayLayout().densityDpi();
+                        / mPipDisplayLayoutState.getDisplayLayout().densityDpi();
                 postChangeBounds.set(0, 0,
                         (int) (postChangeBounds.width() * scale),
                         (int) (postChangeBounds.height() * scale));
@@ -775,8 +829,8 @@
             pipSnapAlgorithm.applySnapFraction(postChangeBounds, postChangeMovementBounds,
                     snapFraction, mPipBoundsState.getStashedState(),
                     mPipBoundsState.getStashOffset(),
-                    mPipBoundsState.getDisplayBounds(),
-                    mPipBoundsState.getDisplayLayout().stableInsets());
+                    mPipDisplayLayoutState.getDisplayBounds(),
+                    mPipDisplayLayoutState.getDisplayLayout().stableInsets());
 
             if (densityDpiChanged) {
                 // Using PipMotionHelper#movePip directly here may cause race condition since
@@ -874,6 +928,21 @@
         }
     }
 
+    private void setLauncherKeepClearAreaHeight(boolean visible, int height) {
+        if (visible) {
+            Rect rect = new Rect(
+                    0, mPipBoundsState.getDisplayBounds().bottom - height,
+                    mPipBoundsState.getDisplayBounds().right,
+                    mPipBoundsState.getDisplayBounds().bottom);
+            Set<Rect> restrictedKeepClearAreas = new HashSet<>(
+                    mPipBoundsState.getRestrictedKeepClearAreas());
+            restrictedKeepClearAreas.add(rect);
+            mPipBoundsState.setKeepClearAreas(restrictedKeepClearAreas,
+                    mPipBoundsState.getUnrestrictedKeepClearAreas());
+            updatePipPositionForKeepClearAreas();
+        }
+    }
+
     private void setOnIsInPipStateChangedListener(Consumer<Boolean> callback) {
         mOnIsInPipStateChangedListener = callback;
         if (mOnIsInPipStateChangedListener != null) {
@@ -1018,7 +1087,7 @@
         // Populate inset / normal bounds and DisplayInfo from mPipBoundsHandler before
         // passing to mTouchHandler/mPipTaskOrganizer
         final Rect outBounds = new Rect(toBounds);
-        final int rotation = mPipBoundsState.getDisplayLayout().rotation();
+        final int rotation = mPipDisplayLayoutState.getDisplayLayout().rotation();
 
         mPipBoundsAlgorithm.getInsetBounds(mTmpInsetBounds);
         mPipBoundsState.setNormalBounds(mPipBoundsAlgorithm.getNormalBounds());
@@ -1042,11 +1111,7 @@
     private void onDisplayRotationChangedNotInPip(Context context, int toRotation) {
         // Update the display layout, note that we have to do this on every rotation even if we
         // aren't in PIP since we need to update the display layout to get the right resources
-        DisplayLayout layoutCopy = mPipBoundsState.getDisplayLayout();
-
-        layoutCopy.rotateTo(context.getResources(), toRotation);
-        mPipBoundsState.setDisplayLayout(layoutCopy);
-        mPipSizeSpecHandler.setDisplayLayout(layoutCopy);
+        mPipDisplayLayoutState.rotateTo(toRotation);
     }
 
     /**
@@ -1059,7 +1124,7 @@
             Rect outInsetBounds,
             int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) {
         // Bail early if the event is not sent to current display
-        if ((displayId != mPipBoundsState.getDisplayId()) || (fromRotation == toRotation)) {
+        if ((displayId != mPipDisplayLayoutState.getDisplayId()) || (fromRotation == toRotation)) {
             return false;
         }
 
@@ -1083,11 +1148,7 @@
                         mPipBoundsState.getStashedState());
 
         // Update the display layout
-        DisplayLayout layoutCopy = mPipBoundsState.getDisplayLayout();
-
-        layoutCopy.rotateTo(context.getResources(), toRotation);
-        mPipBoundsState.setDisplayLayout(layoutCopy);
-        mPipSizeSpecHandler.setDisplayLayout(layoutCopy);
+        mPipDisplayLayoutState.rotateTo(toRotation);
 
         // Calculate the stack bounds in the new orientation based on same fraction along the
         // rotated movement bounds.
@@ -1095,8 +1156,8 @@
                 postChangeStackBounds, false /* adjustForIme */);
         pipSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
                 snapFraction, mPipBoundsState.getStashedState(), mPipBoundsState.getStashOffset(),
-                mPipBoundsState.getDisplayBounds(),
-                mPipBoundsState.getDisplayLayout().stableInsets());
+                mPipDisplayLayoutState.getDisplayBounds(),
+                mPipDisplayLayoutState.getDisplayLayout().stableInsets());
 
         mPipBoundsAlgorithm.getInsetBounds(outInsetBounds);
         outBounds.set(postChangeStackBounds);
@@ -1114,6 +1175,7 @@
         mPipBoundsState.dump(pw, innerPrefix);
         mPipInputConsumer.dump(pw, innerPrefix);
         mPipSizeSpecHandler.dump(pw, innerPrefix);
+        mPipDisplayLayoutState.dump(pw, innerPrefix);
     }
 
     /**
@@ -1240,6 +1302,14 @@
         }
 
         @Override
+        public void setLauncherKeepClearAreaHeight(boolean visible, int height) {
+            executeRemoteCallWithTaskPermission(mController, "setLauncherKeepClearAreaHeight",
+                    (controller) -> {
+                        controller.setLauncherKeepClearAreaHeight(visible, height);
+                    });
+        }
+
+        @Override
         public void setPipAnimationListener(IPipAnimationListener listener) {
             executeRemoteCallWithTaskPermission(mController, "setPipAnimationListener",
                     (controller) -> {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipSizeSpecHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipSizeSpecHandler.java
index d03d075..23988a6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipSizeSpecHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipSizeSpecHandler.java
@@ -31,6 +31,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.wm.shell.R;
 import com.android.wm.shell.common.DisplayLayout;
+import com.android.wm.shell.pip.PipDisplayLayoutState;
 
 import java.io.PrintWriter;
 
@@ -40,10 +41,9 @@
 public class PipSizeSpecHandler {
     private static final String TAG = PipSizeSpecHandler.class.getSimpleName();
 
-    @NonNull private final DisplayLayout mDisplayLayout = new DisplayLayout();
+    @NonNull private final PipDisplayLayoutState mPipDisplayLayoutState;
 
-    @VisibleForTesting
-    final SizeSpecSource mSizeSpecSourceImpl;
+    private final SizeSpecSource mSizeSpecSourceImpl;
 
     /** The preferred minimum (and default minimum) size specified by apps. */
     @Nullable private Size mOverrideMinSize;
@@ -361,8 +361,9 @@
         }
     }
 
-    public PipSizeSpecHandler(Context context) {
+    public PipSizeSpecHandler(Context context, PipDisplayLayoutState pipDisplayLayoutState) {
         mContext = context;
+        mPipDisplayLayoutState = pipDisplayLayoutState;
 
         boolean enablePipSizeLargeScreen = SystemProperties
                 .getBoolean("persist.wm.debug.enable_pip_size_large_screen", false);
@@ -403,15 +404,9 @@
         mSizeSpecSourceImpl.reloadResources();
     }
 
-    /** Returns the display's bounds. */
     @NonNull
-    public Rect getDisplayBounds() {
-        return new Rect(0, 0, mDisplayLayout.width(), mDisplayLayout.height());
-    }
-
-    /** Update the display layout. */
-    public void setDisplayLayout(@NonNull DisplayLayout displayLayout) {
-        mDisplayLayout.set(displayLayout);
+    private Rect getDisplayBounds() {
+        return mPipDisplayLayoutState.getDisplayBounds();
     }
 
     public Point getScreenEdgeInsets() {
@@ -423,11 +418,12 @@
      */
     public Rect getInsetBounds() {
         Rect insetBounds = new Rect();
-        Rect insets = mDisplayLayout.stableInsets();
+        DisplayLayout displayLayout = mPipDisplayLayoutState.getDisplayLayout();
+        Rect insets = displayLayout.stableInsets();
         insetBounds.set(insets.left + mScreenEdgeInsets.x,
                 insets.top + mScreenEdgeInsets.y,
-                mDisplayLayout.width() - insets.right - mScreenEdgeInsets.x,
-                mDisplayLayout.height() - insets.bottom - mScreenEdgeInsets.y);
+                displayLayout.width() - insets.right - mScreenEdgeInsets.x,
+                displayLayout.height() - insets.bottom - mScreenEdgeInsets.y);
         return insetBounds;
     }
 
@@ -522,8 +518,8 @@
     public void dump(PrintWriter pw, String prefix) {
         final String innerPrefix = prefix + "  ";
         pw.println(prefix + TAG);
-        pw.println(innerPrefix + "mSizeSpecSourceImpl=" + mSizeSpecSourceImpl.toString());
-        pw.println(innerPrefix + "mDisplayLayout=" + mDisplayLayout);
+        pw.println(innerPrefix + "mSizeSpecSourceImpl=" + mSizeSpecSourceImpl);
         pw.println(innerPrefix + "mOverrideMinSize=" + mOverrideMinSize);
+        pw.println(innerPrefix + "mScreenEdgeInsets=" + mScreenEdgeInsets);
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsState.java
index 22b3f49..e1737ec 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsState.java
@@ -31,6 +31,7 @@
 
 import com.android.wm.shell.pip.PipBoundsAlgorithm;
 import com.android.wm.shell.pip.PipBoundsState;
+import com.android.wm.shell.pip.PipDisplayLayoutState;
 import com.android.wm.shell.pip.phone.PipSizeSpecHandler;
 
 import java.lang.annotation.Retention;
@@ -75,8 +76,9 @@
     private Insets mPipMenuTemporaryDecorInsets = Insets.NONE;
 
     public TvPipBoundsState(@NonNull Context context,
-            @NonNull PipSizeSpecHandler pipSizeSpecHandler) {
-        super(context, pipSizeSpecHandler);
+            @NonNull PipSizeSpecHandler pipSizeSpecHandler,
+            @NonNull PipDisplayLayoutState pipDisplayLayoutState) {
+        super(context, pipSizeSpecHandler, pipDisplayLayoutState);
         mContext = context;
         updateDefaultGravity();
         mPreviousCollapsedGravity = mDefaultGravity;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
index a437a3b..d73723c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
@@ -51,11 +51,11 @@
 import com.android.wm.shell.pip.Pip;
 import com.android.wm.shell.pip.PipAnimationController;
 import com.android.wm.shell.pip.PipAppOpsListener;
+import com.android.wm.shell.pip.PipDisplayLayoutState;
 import com.android.wm.shell.pip.PipMediaController;
 import com.android.wm.shell.pip.PipParamsChangedForwarder;
 import com.android.wm.shell.pip.PipTaskOrganizer;
 import com.android.wm.shell.pip.PipTransitionController;
-import com.android.wm.shell.pip.phone.PipSizeSpecHandler;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
 import com.android.wm.shell.sysui.ConfigurationChangeListener;
 import com.android.wm.shell.sysui.ShellController;
@@ -119,7 +119,7 @@
 
     private final ShellController mShellController;
     private final TvPipBoundsState mTvPipBoundsState;
-    private final PipSizeSpecHandler mPipSizeSpecHandler;
+    private final PipDisplayLayoutState mPipDisplayLayoutState;
     private final TvPipBoundsAlgorithm mTvPipBoundsAlgorithm;
     private final TvPipBoundsController mTvPipBoundsController;
     private final PipAppOpsListener mAppOpsListener;
@@ -154,7 +154,7 @@
             ShellInit shellInit,
             ShellController shellController,
             TvPipBoundsState tvPipBoundsState,
-            PipSizeSpecHandler pipSizeSpecHandler,
+            PipDisplayLayoutState pipDisplayLayoutState,
             TvPipBoundsAlgorithm tvPipBoundsAlgorithm,
             TvPipBoundsController tvPipBoundsController,
             PipAppOpsListener pipAppOpsListener,
@@ -174,7 +174,7 @@
                 shellInit,
                 shellController,
                 tvPipBoundsState,
-                pipSizeSpecHandler,
+                pipDisplayLayoutState,
                 tvPipBoundsAlgorithm,
                 tvPipBoundsController,
                 pipAppOpsListener,
@@ -196,7 +196,7 @@
             ShellInit shellInit,
             ShellController shellController,
             TvPipBoundsState tvPipBoundsState,
-            PipSizeSpecHandler pipSizeSpecHandler,
+            PipDisplayLayoutState pipDisplayLayoutState,
             TvPipBoundsAlgorithm tvPipBoundsAlgorithm,
             TvPipBoundsController tvPipBoundsController,
             PipAppOpsListener pipAppOpsListener,
@@ -220,10 +220,11 @@
         DisplayLayout layout = new DisplayLayout(context, context.getDisplay());
 
         mTvPipBoundsState = tvPipBoundsState;
-        mTvPipBoundsState.setDisplayLayout(layout);
-        mTvPipBoundsState.setDisplayId(context.getDisplayId());
-        mPipSizeSpecHandler = pipSizeSpecHandler;
-        mPipSizeSpecHandler.setDisplayLayout(layout);
+
+        mPipDisplayLayoutState = pipDisplayLayoutState;
+        mPipDisplayLayoutState.setDisplayLayout(layout);
+        mPipDisplayLayoutState.setDisplayId(context.getDisplayId());
+
         mTvPipBoundsAlgorithm = tvPipBoundsAlgorithm;
         mTvPipBoundsController = tvPipBoundsController;
         mTvPipBoundsController.setListener(this);
@@ -392,7 +393,7 @@
     @Override
     public void onKeepClearAreasChanged(int displayId, Set<Rect> restricted,
             Set<Rect> unrestricted) {
-        if (mTvPipBoundsState.getDisplayId() == displayId) {
+        if (mPipDisplayLayoutState.getDisplayId() == displayId) {
             boolean unrestrictedAreasChanged = !Objects.equals(unrestricted,
                     mTvPipBoundsState.getUnrestrictedKeepClearAreas());
             mTvPipBoundsState.setKeepClearAreas(restricted, unrestricted);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipCustomAction.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipCustomAction.java
index 449a2bf..49d40d3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipCustomAction.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipCustomAction.java
@@ -60,6 +60,7 @@
         }
         button.setImageIconAsync(mRemoteAction.getIcon(), mainHandler);
         button.setEnabled(isCloseAction() || mRemoteAction.isEnabled());
+        button.setIsCustomCloseAction(isCloseAction());
     }
 
     PendingIntent getPendingIntent() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java
index 8895fca..73123b1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java
@@ -25,16 +25,14 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.graphics.Insets;
-import android.graphics.Matrix;
 import android.graphics.Rect;
-import android.graphics.RectF;
 import android.os.Handler;
 import android.view.LayoutInflater;
 import android.view.SurfaceControl;
-import android.view.SyncRtSurfaceTransactionApplier;
 import android.view.View;
 import android.view.ViewRootImpl;
 import android.view.WindowManagerGlobal;
+import android.window.SurfaceSyncGroup;
 
 import androidx.annotation.Nullable;
 
@@ -71,12 +69,6 @@
     // exiting the move menu instead of showing the regular button menu.
     private boolean mCloseAfterExitMoveMenu;
 
-    private SyncRtSurfaceTransactionApplier mApplier;
-    private SyncRtSurfaceTransactionApplier mBackgroundApplier;
-    RectF mTmpSourceRectF = new RectF();
-    RectF mTmpDestinationRectF = new RectF();
-    Matrix mMoveTransform = new Matrix();
-
     public TvPipMenuController(Context context, TvPipBoundsState tvPipBoundsState,
             SystemWindows systemWindows, Handler mainHandler) {
         mContext = context;
@@ -324,44 +316,36 @@
      */
     @Override
     public void resizePipMenu(@Nullable SurfaceControl pipLeash,
-            @Nullable SurfaceControl.Transaction t,
-            Rect destinationBounds) {
+            @Nullable SurfaceControl.Transaction pipTx,
+            Rect pipBounds) {
         ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
-                "%s: resizePipMenu: %s", TAG, destinationBounds.toShortString());
-        if (destinationBounds.isEmpty()) {
+                "%s: resizePipMenu: %s", TAG, pipBounds.toShortString());
+        if (pipBounds.isEmpty()) {
             return;
         }
 
-        if (!maybeCreateSyncApplier()) {
+        if (!isMenuReadyToMove()) {
             return;
         }
 
-        final Rect menuBounds = calculateMenuSurfaceBounds(destinationBounds);
 
         final SurfaceControl frontSurface = getSurfaceControl(mPipMenuView);
-        final SyncRtSurfaceTransactionApplier.SurfaceParams frontParams =
-                new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(frontSurface)
-                        .withWindowCrop(menuBounds)
-                        .build();
-
         final SurfaceControl backSurface = getSurfaceControl(mPipBackgroundView);
-        final SyncRtSurfaceTransactionApplier.SurfaceParams backParams =
-                new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(backSurface)
-                        .withWindowCrop(menuBounds)
-                        .build();
-
-        // TODO(b/226580399): switch to using SurfaceSyncer (see b/200284684) to synchronize the
-        // animations of the pip surface with the content of the front and back menu surfaces
-        mBackgroundApplier.scheduleApply(backParams);
-        if (pipLeash != null && t != null) {
-            final SyncRtSurfaceTransactionApplier.SurfaceParams
-                    pipParams = new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(pipLeash)
-                    .withMergeTransaction(t)
-                    .build();
-            mApplier.scheduleApply(frontParams, pipParams);
-        } else {
-            mApplier.scheduleApply(frontParams);
+        final Rect menuBounds = calculateMenuSurfaceBounds(pipBounds);
+        if (pipTx == null) {
+            pipTx = new SurfaceControl.Transaction();
         }
+        pipTx.setWindowCrop(frontSurface, menuBounds.width(), menuBounds.height());
+        pipTx.setWindowCrop(backSurface, menuBounds.width(), menuBounds.height());
+
+        // Synchronize drawing the content in the front and back surfaces together with the pip
+        // transaction and the window crop for the front and back surfaces
+        final SurfaceSyncGroup syncGroup = new SurfaceSyncGroup("TvPip");
+        syncGroup.add(mPipMenuView.getRootSurfaceControl(), null);
+        syncGroup.add(mPipBackgroundView.getRootSurfaceControl(), null);
+        updateMenuBounds(pipBounds);
+        syncGroup.addTransaction(pipTx);
+        syncGroup.markSyncReady();
     }
 
     private SurfaceControl getSurfaceControl(View v) {
@@ -369,102 +353,66 @@
     }
 
     @Override
-    public void movePipMenu(SurfaceControl pipLeash, SurfaceControl.Transaction transaction,
-            Rect pipDestBounds) {
+    public void movePipMenu(SurfaceControl pipLeash, SurfaceControl.Transaction pipTx,
+            Rect pipBounds) {
         ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
-                "%s: movePipMenu: %s", TAG, pipDestBounds.toShortString());
+                "%s: movePipMenu: %s", TAG, pipBounds.toShortString());
 
-        if (pipDestBounds.isEmpty()) {
-            if (transaction == null) {
+        if (pipBounds.isEmpty()) {
+            if (pipTx == null) {
                 ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                         "%s: no transaction given", TAG);
             }
             return;
         }
-        if (!maybeCreateSyncApplier()) {
+        if (!isMenuReadyToMove()) {
             return;
         }
 
-        final Rect menuDestBounds = calculateMenuSurfaceBounds(pipDestBounds);
-        final Rect tmpSourceBounds = new Rect();
-        // If there is no pip leash supplied, that means the PiP leash is already finalized
-        // resizing and the PiP menu is also resized. We then want to do a scale from the current
-        // new menu bounds.
-        if (pipLeash != null && transaction != null) {
-            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
-                    "%s: tmpSourceBounds based on mPipMenuView.getBoundsOnScreen()", TAG);
-            mPipMenuView.getBoundsOnScreen(tmpSourceBounds);
-        } else {
-            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
-                    "%s: tmpSourceBounds based on menu width and height", TAG);
-            tmpSourceBounds.set(0, 0, menuDestBounds.width(), menuDestBounds.height());
-        }
-
-        mTmpSourceRectF.set(tmpSourceBounds);
-        mTmpDestinationRectF.set(menuDestBounds);
-        mMoveTransform.setTranslate(mTmpDestinationRectF.left, mTmpDestinationRectF.top);
-
         final SurfaceControl frontSurface = getSurfaceControl(mPipMenuView);
-        final SyncRtSurfaceTransactionApplier.SurfaceParams frontParams =
-                new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(frontSurface)
-                        .withMatrix(mMoveTransform)
-                        .build();
-
         final SurfaceControl backSurface = getSurfaceControl(mPipBackgroundView);
-        final SyncRtSurfaceTransactionApplier.SurfaceParams backParams =
-                new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(backSurface)
-                        .withMatrix(mMoveTransform)
-                        .build();
-
-        // TODO(b/226580399): switch to using SurfaceSyncer (see b/200284684) to synchronize the
-        // animations of the pip surface with the content of the front and back menu surfaces
-        mBackgroundApplier.scheduleApply(backParams);
-        if (pipLeash != null && transaction != null) {
-            final SyncRtSurfaceTransactionApplier.SurfaceParams pipParams =
-                    new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(pipLeash)
-                            .withMergeTransaction(transaction)
-                            .build();
-            mApplier.scheduleApply(frontParams, pipParams);
-        } else {
-            mApplier.scheduleApply(frontParams);
+        final Rect menuDestBounds = calculateMenuSurfaceBounds(pipBounds);
+        if (pipTx == null) {
+            pipTx = new SurfaceControl.Transaction();
         }
+        pipTx.setPosition(frontSurface, menuDestBounds.left, menuDestBounds.top);
+        pipTx.setPosition(backSurface, menuDestBounds.left, menuDestBounds.top);
 
-        updateMenuBounds(pipDestBounds);
+        // Synchronize drawing the content in the front and back surfaces together with the pip
+        // transaction and the position change for the front and back surfaces
+        final SurfaceSyncGroup syncGroup = new SurfaceSyncGroup("TvPip");
+        syncGroup.add(mPipMenuView.getRootSurfaceControl(), null);
+        syncGroup.add(mPipBackgroundView.getRootSurfaceControl(), null);
+        updateMenuBounds(pipBounds);
+        syncGroup.addTransaction(pipTx);
+        syncGroup.markSyncReady();
     }
 
-    private boolean maybeCreateSyncApplier() {
-        if (mPipMenuView == null || mPipMenuView.getViewRootImpl() == null) {
+    private boolean isMenuReadyToMove() {
+        final boolean ready = mPipMenuView != null && mPipMenuView.getViewRootImpl() != null
+                && mPipBackgroundView != null && mPipBackgroundView.getViewRootImpl() != null;
+        if (!ready) {
             ProtoLog.v(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                     "%s: Not going to move PiP, either menu or its parent is not created.", TAG);
-            return false;
         }
-
-        if (mApplier == null) {
-            mApplier = new SyncRtSurfaceTransactionApplier(mPipMenuView);
-        }
-        if (mBackgroundApplier == null) {
-            mBackgroundApplier = new SyncRtSurfaceTransactionApplier(mPipBackgroundView);
-        }
-        return true;
+        return ready;
     }
 
     private void detachPipMenu() {
         if (mPipMenuView != null) {
-            mApplier = null;
             mSystemWindows.removeView(mPipMenuView);
             mPipMenuView = null;
         }
 
         if (mPipBackgroundView != null) {
-            mBackgroundApplier = null;
             mSystemWindows.removeView(mPipBackgroundView);
             mPipBackgroundView = null;
         }
     }
 
     @Override
-    public void updateMenuBounds(Rect destinationBounds) {
-        final Rect menuBounds = calculateMenuSurfaceBounds(destinationBounds);
+    public void updateMenuBounds(Rect pipBounds) {
+        final Rect menuBounds = calculateMenuSurfaceBounds(pipBounds);
         ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                 "%s: updateMenuBounds: %s", TAG, menuBounds.toShortString());
         mSystemWindows.updateViewLayout(mPipBackgroundView,
@@ -473,9 +421,8 @@
         mSystemWindows.updateViewLayout(mPipMenuView,
                 getPipMenuLayoutParams(mContext, MENU_WINDOW_TITLE, menuBounds.width(),
                         menuBounds.height()));
-
         if (mPipMenuView != null) {
-            mPipMenuView.updateBounds(destinationBounds);
+            mPipMenuView.updateBounds(pipBounds);
         }
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipSystemAction.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipSystemAction.java
index 93b6a90..4b82e4b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipSystemAction.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipSystemAction.java
@@ -61,6 +61,7 @@
         button.setTextAndDescription(mTitleResource);
         button.setImageResource(mIconResource);
         button.setEnabled(true);
+        button.setIsCustomCloseAction(false);
     }
 
     PendingIntent getPendingIntent() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTaskOrganizer.java
index be9b936..f6856f1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTaskOrganizer.java
@@ -28,6 +28,7 @@
 import com.android.wm.shell.pip.PipAnimationController;
 import com.android.wm.shell.pip.PipBoundsAlgorithm;
 import com.android.wm.shell.pip.PipBoundsState;
+import com.android.wm.shell.pip.PipDisplayLayoutState;
 import com.android.wm.shell.pip.PipMenuController;
 import com.android.wm.shell.pip.PipParamsChangedForwarder;
 import com.android.wm.shell.pip.PipSurfaceTransactionHelper;
@@ -36,7 +37,6 @@
 import com.android.wm.shell.pip.PipTransitionState;
 import com.android.wm.shell.pip.PipUiEventLogger;
 import com.android.wm.shell.pip.PipUtils;
-import com.android.wm.shell.pip.phone.PipSizeSpecHandler;
 import com.android.wm.shell.splitscreen.SplitScreenController;
 
 import java.util.Objects;
@@ -51,7 +51,7 @@
             @NonNull SyncTransactionQueue syncTransactionQueue,
             @NonNull PipTransitionState pipTransitionState,
             @NonNull PipBoundsState pipBoundsState,
-            @NonNull PipSizeSpecHandler pipSizeSpecHandler,
+            @NonNull PipDisplayLayoutState pipDisplayLayoutState,
             @NonNull PipBoundsAlgorithm boundsHandler,
             @NonNull PipMenuController pipMenuController,
             @NonNull PipAnimationController pipAnimationController,
@@ -63,8 +63,8 @@
             @NonNull PipUiEventLogger pipUiEventLogger,
             @NonNull ShellTaskOrganizer shellTaskOrganizer,
             ShellExecutor mainExecutor) {
-        super(context, syncTransactionQueue, pipTransitionState, pipBoundsState, pipSizeSpecHandler,
-                boundsHandler, pipMenuController, pipAnimationController,
+        super(context, syncTransactionQueue, pipTransitionState, pipBoundsState,
+                pipDisplayLayoutState, boundsHandler, pipMenuController, pipAnimationController,
                 surfaceTransactionHelper, pipTransitionController, pipParamsChangedForwarder,
                 splitScreenOptional, displayController, pipUiEventLogger, shellTaskOrganizer,
                 mainExecutor);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java
index 75f9a4c..c9b3a1a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java
@@ -50,6 +50,8 @@
             Consts.TAG_WM_SHELL),
     WM_SHELL_FLOATING_APPS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
             Consts.TAG_WM_SHELL),
+    WM_SHELL_FOLDABLE(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
+            Consts.TAG_WM_SHELL),
     TEST_GROUP(true, true, false, "WindowManagerShellProtoLogTest");
 
     private final boolean mEnabled;
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 c7ad4fd..94b9e90 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
@@ -422,6 +422,11 @@
         mStageCoordinator.goToFullscreenFromSplit();
     }
 
+    /** Move the specified task to fullscreen, regardless of focus state. */
+    public void moveTaskToFullscreen(int taskId) {
+        mStageCoordinator.moveTaskToFullscreen(taskId);
+    }
+
     public boolean isLaunchToSplit(TaskInfo taskInfo) {
         return mStageCoordinator.isLaunchToSplit(taskInfo);
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
index c96323a..4b5ad1d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
@@ -37,6 +37,7 @@
 import android.animation.ValueAnimator;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.IBinder;
 import android.view.SurfaceControl;
@@ -67,7 +68,6 @@
 
     DismissTransition mPendingDismiss = null;
     TransitSession mPendingEnter = null;
-    TransitSession mPendingRecent = null;
     TransitSession mPendingResize = null;
 
     private IBinder mAnimatingTransition = null;
@@ -128,6 +128,7 @@
             final int mode = info.getChanges().get(i).getMode();
 
             if (mode == TRANSIT_CHANGE) {
+                final int rootIdx = TransitionUtil.rootIndexFor(change, info);
                 if (change.getParent() != null) {
                     // This is probably reparented, so we want the parent to be immediately visible
                     final TransitionInfo.Change parentChange = info.getChange(change.getParent());
@@ -135,7 +136,7 @@
                     t.setAlpha(parentChange.getLeash(), 1.f);
                     // and then animate this layer outside the parent (since, for example, this is
                     // the home task animating from fullscreen to part-screen).
-                    t.reparent(leash, info.getRootLeash());
+                    t.reparent(leash, info.getRoot(rootIdx).getLeash());
                     t.setLayer(leash, info.getChanges().size() - i);
                     // build the finish reparent/reposition
                     mFinishTransaction.reparent(leash, parentChange.getLeash());
@@ -145,8 +146,9 @@
                 // TODO(shell-transitions): screenshot here
                 final Rect startBounds = new Rect(change.getStartAbsBounds());
                 final Rect endBounds = new Rect(change.getEndAbsBounds());
-                startBounds.offset(-info.getRootOffset().x, -info.getRootOffset().y);
-                endBounds.offset(-info.getRootOffset().x, -info.getRootOffset().y);
+                final Point rootOffset = info.getRoot(rootIdx).getOffset();
+                startBounds.offset(-rootOffset.x, -rootOffset.y);
+                endBounds.offset(-rootOffset.x, -rootOffset.y);
                 startExampleResizeAnimation(leash, startBounds, endBounds);
             }
             boolean isRootOrSplitSideRoot = change.getParent() == null
@@ -257,10 +259,6 @@
         return mPendingEnter != null && mPendingEnter.mTransition == transition;
     }
 
-    boolean isPendingRecent(IBinder transition) {
-        return mPendingRecent != null && mPendingRecent.mTransition == transition;
-    }
-
     boolean isPendingDismiss(IBinder transition) {
         return mPendingDismiss != null && mPendingDismiss.mTransition == transition;
     }
@@ -273,8 +271,6 @@
     private TransitSession getPendingTransition(IBinder transition) {
         if (isPendingEnter(transition)) {
             return mPendingEnter;
-        } else if (isPendingRecent(transition)) {
-            return mPendingRecent;
         } else if (isPendingDismiss(transition)) {
             return mPendingDismiss;
         } else if (isPendingResize(transition)) {
@@ -340,6 +336,12 @@
     IBinder startResizeTransition(WindowContainerTransaction wct,
             Transitions.TransitionHandler handler,
             @Nullable TransitionFinishedCallback finishCallback) {
+        if (mPendingResize != null) {
+            mPendingResize.cancel(null);
+            mAnimations.clear();
+            onFinish(null /* wct */, null /* wctCB */);
+        }
+
         IBinder transition = mTransitions.startTransition(TRANSIT_CHANGE, wct, handler);
         setResizeTransition(transition, finishCallback);
         return transition;
@@ -352,32 +354,10 @@
                 + " deduced Resize split screen");
     }
 
-    void setRecentTransition(@NonNull IBinder transition,
-            @Nullable RemoteTransition remoteTransition,
-            @Nullable TransitionFinishedCallback finishCallback) {
-        mPendingRecent = new TransitSession(transition, null /* consumedCb */, finishCallback);
-
-        if (remoteTransition != null) {
-            // Wrapping it for ease-of-use (OneShot handles all the binder linking/death stuff)
-            mPendingRemoteHandler = new OneShotRemoteHandler(
-                    mTransitions.getMainExecutor(), remoteTransition);
-            mPendingRemoteHandler.setTransition(transition);
-        }
-
-        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "  splitTransition "
-                + " deduced Enter recent panel");
-    }
-
     void mergeAnimation(IBinder transition, TransitionInfo info, SurfaceControl.Transaction t,
             IBinder mergeTarget, Transitions.TransitionFinishCallback finishCallback) {
         if (mergeTarget != mAnimatingTransition) return;
 
-        if (isPendingEnter(transition) && isPendingRecent(mergeTarget)) {
-            // Since there's an entering transition merged, recent transition no longer
-            // need to handle entering split screen after the transition finished.
-            mPendingRecent.setFinishedCallback(null);
-        }
-
         if (mActiveRemoteHandler != null) {
             mActiveRemoteHandler.mergeAnimation(transition, info, t, mergeTarget, finishCallback);
         } else {
@@ -414,10 +394,6 @@
         } else if (isPendingDismiss(transition)) {
             mPendingDismiss.onConsumed(aborted);
             mPendingDismiss = null;
-        } else if (isPendingRecent(transition)) {
-            mPendingRecent.onConsumed(aborted);
-            mPendingRecent = null;
-            mPendingRemoteHandler = null;
         } else if (isPendingResize(transition)) {
             mPendingResize.onConsumed(aborted);
             mPendingResize = null;
@@ -431,9 +407,6 @@
         if (isPendingEnter(mAnimatingTransition)) {
             mPendingEnter.onFinished(wct, mFinishTransaction);
             mPendingEnter = null;
-        } else if (isPendingRecent(mAnimatingTransition)) {
-            mPendingRecent.onFinished(wct, mFinishTransaction);
-            mPendingRecent = null;
         } else if (isPendingDismiss(mAnimatingTransition)) {
             mPendingDismiss.onFinished(wct, mFinishTransaction);
             mPendingDismiss = null;
@@ -543,7 +516,7 @@
     }
 
     /** Calls when the transition finished. */
-    interface TransitionFinishedCallback {
+    public interface TransitionFinishedCallback {
         void onFinished(WindowContainerTransaction wct, SurfaceControl.Transaction t);
     }
 
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 8b24d86..9d1a7ea 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
@@ -20,7 +20,6 @@
 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static android.app.ComponentOptions.KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED;
 import static android.app.ComponentOptions.KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED_BY_PERMISSION;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
@@ -205,9 +204,10 @@
     // and exit, since exit itself can trigger a number of changes that update the stages.
     private boolean mShouldUpdateRecents;
     private boolean mExitSplitScreenOnHide;
-    private boolean mIsSplitEntering;
+    private boolean mIsDividerRemoteAnimating;
     private boolean mIsDropEntering;
     private boolean mIsExiting;
+    private boolean mIsRootTranslucent;
 
     private DefaultMixedHandler mMixedHandler;
     private final Toast mSplitUnsupportedToast;
@@ -259,37 +259,6 @@
                 }
             };
 
-    private final SplitScreenTransitions.TransitionFinishedCallback
-            mRecentTransitionFinishedCallback =
-            new SplitScreenTransitions.TransitionFinishedCallback() {
-                @Override
-                public void onFinished(WindowContainerTransaction finishWct,
-                        SurfaceControl.Transaction finishT) {
-                    // Check if the recent transition is finished by returning to the current
-                    // split, so we
-                    // can restore the divider bar.
-                    for (int i = 0; i < finishWct.getHierarchyOps().size(); ++i) {
-                        final WindowContainerTransaction.HierarchyOp op =
-                                finishWct.getHierarchyOps().get(i);
-                        final IBinder container = op.getContainer();
-                        if (op.getType() == HIERARCHY_OP_TYPE_REORDER && op.getToTop()
-                                && (mMainStage.containsContainer(container)
-                                || mSideStage.containsContainer(container))) {
-                            updateSurfaceBounds(mSplitLayout, finishT,
-                                    false /* applyResizingOffset */);
-                            setDividerVisibility(true, finishT);
-                            return;
-                        }
-                    }
-
-                    // Dismiss the split screen if it's not returning to split.
-                    prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, finishWct);
-                    setSplitsVisible(false);
-                    setDividerVisibility(false, finishT);
-                    logExit(EXIT_REASON_UNKNOWN);
-                }
-            };
-
     protected StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
             ShellTaskOrganizer taskOrganizer, DisplayController displayController,
             DisplayImeController displayImeController,
@@ -388,6 +357,11 @@
         return mMainStage.isActive();
     }
 
+    /** Checks if `transition` is a pending enter-split transition. */
+    public boolean isPendingEnter(IBinder transition) {
+        return mSplitTransitions.isPendingEnter(transition);
+    }
+
     @StageType
     int getStageOfTask(int taskId) {
         if (mMainStage.containsTask(taskId)) {
@@ -423,6 +397,11 @@
             }
         }
 
+        if (!isSplitActive()) {
+            // prevent the fling divider to center transitioni if split screen didn't active.
+            mIsDropEntering = true;
+        }
+
         setSideStagePosition(sideStagePosition, wct);
         final WindowContainerTransaction evictWct = new WindowContainerTransaction();
         targetStage.evictAllChildren(evictWct);
@@ -437,28 +416,13 @@
         // reparent the task to an invisible split root will make the activity invisible.  Reorder
         // the root task to front to make the entering transition from pip to split smooth.
         wct.reorder(mRootTaskInfo.token, true);
-        wct.setForceTranslucent(mRootTaskInfo.token, true);
         wct.reorder(targetStage.mRootTaskInfo.token, true);
-        wct.setForceTranslucent(targetStage.mRootTaskInfo.token, true);
-        // prevent the fling divider to center transition
-        mIsDropEntering = true;
-
         targetStage.addTask(task, wct);
 
-        if (ENABLE_SHELL_TRANSITIONS) {
-            prepareEnterSplitScreen(wct);
-            mSplitTransitions.startEnterTransition(TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE, wct,
-                    null, this, null /* consumedCallback */, (finishWct, finishT) -> {
-                        if (!evictWct.isEmpty()) {
-                            finishWct.merge(evictWct, true);
-                        }
-                    } /* finishedCallback */);
-        } else {
-            if (!evictWct.isEmpty()) {
-                wct.merge(evictWct, true /* transfer */);
-            }
-            mTaskOrganizer.applyTransaction(wct);
+        if (!evictWct.isEmpty()) {
+            wct.merge(evictWct, true /* transfer */);
         }
+        mTaskOrganizer.applyTransaction(wct);
         return true;
     }
 
@@ -661,6 +625,7 @@
             @Nullable Bundle options2, @SplitPosition int splitPosition, float splitRatio,
             @Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
         final WindowContainerTransaction wct = new WindowContainerTransaction();
+        prepareEvictChildTasksIfSplitActive(wct);
         setSideStagePosition(splitPosition, wct);
         options1 = options1 != null ? options1 : new Bundle();
         addActivityOptions(options1, mSideStage);
@@ -675,6 +640,7 @@
             @SplitPosition int splitPosition, float splitRatio,
             @Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
         final WindowContainerTransaction wct = new WindowContainerTransaction();
+        prepareEvictChildTasksIfSplitActive(wct);
         setSideStagePosition(splitPosition, wct);
         options1 = options1 != null ? options1 : new Bundle();
         addActivityOptions(options1, mSideStage);
@@ -688,6 +654,7 @@
             int taskId, @Nullable Bundle options2, @SplitPosition int splitPosition,
             float splitRatio, @Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
         final WindowContainerTransaction wct = new WindowContainerTransaction();
+        prepareEvictChildTasksIfSplitActive(wct);
         setSideStagePosition(splitPosition, wct);
         options1 = options1 != null ? options1 : new Bundle();
         addActivityOptions(options1, mSideStage);
@@ -706,10 +673,7 @@
     private void startWithTask(WindowContainerTransaction wct, int mainTaskId,
             @Nullable Bundle mainOptions, float splitRatio,
             @Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
-        if (mMainStage.isActive()) {
-            mMainStage.evictAllChildren(wct);
-            mSideStage.evictAllChildren(wct);
-        } else {
+        if (!mMainStage.isActive()) {
             // Build a request WCT that will launch both apps such that task 0 is on the main stage
             // while task 1 is on the side stage.
             mMainStage.activate(wct, false /* reparent */);
@@ -717,7 +681,7 @@
         mSplitLayout.setDivideRatio(splitRatio);
         updateWindowBounds(mSplitLayout, wct);
         wct.reorder(mRootTaskInfo.token, true);
-        wct.setForceTranslucent(mRootTaskInfo.token, false);
+        setRootForceTranslucent(false, wct);
 
         // Make sure the launch options will put tasks in the corresponding split roots
         mainOptions = mainOptions != null ? mainOptions : new Bundle();
@@ -765,17 +729,9 @@
         final WindowContainerTransaction wct = new WindowContainerTransaction();
         if (options1 == null) options1 = new Bundle();
         if (pendingIntent2 == null) {
-            // Launching a solo task.
-            ActivityOptions activityOptions = ActivityOptions.fromBundle(options1);
-            activityOptions.update(ActivityOptions.makeRemoteAnimation(adapter));
-            options1 = activityOptions.toBundle();
-            addActivityOptions(options1, null /* launchTarget */);
-            if (shortcutInfo1 != null) {
-                wct.startShortcut(mContext.getPackageName(), shortcutInfo1, options1);
-            } else {
-                wct.sendPendingIntent(pendingIntent1, fillInIntent1, options1);
-            }
-            mSyncQueue.queue(wct);
+            // Launching a solo intent or shortcut as fullscreen.
+            launchAsFullscreenWithRemoteAnimation(pendingIntent1, fillInIntent1, shortcutInfo1,
+                    options1, adapter, wct);
             return;
         }
 
@@ -798,13 +754,9 @@
         final WindowContainerTransaction wct = new WindowContainerTransaction();
         if (options1 == null) options1 = new Bundle();
         if (taskId == INVALID_TASK_ID) {
-            // Launching a solo task.
-            ActivityOptions activityOptions = ActivityOptions.fromBundle(options1);
-            activityOptions.update(ActivityOptions.makeRemoteAnimation(adapter));
-            options1 = activityOptions.toBundle();
-            addActivityOptions(options1, null /* launchTarget */);
-            wct.sendPendingIntent(pendingIntent, fillInIntent, options1);
-            mSyncQueue.queue(wct);
+            // Launching a solo intent as fullscreen.
+            launchAsFullscreenWithRemoteAnimation(pendingIntent, fillInIntent, null, options1,
+                    adapter, wct);
             return;
         }
 
@@ -823,13 +775,8 @@
         final WindowContainerTransaction wct = new WindowContainerTransaction();
         if (options1 == null) options1 = new Bundle();
         if (taskId == INVALID_TASK_ID) {
-            // Launching a solo task.
-            ActivityOptions activityOptions = ActivityOptions.fromBundle(options1);
-            activityOptions.update(ActivityOptions.makeRemoteAnimation(adapter));
-            options1 = activityOptions.toBundle();
-            addActivityOptions(options1, null /* launchTarget */);
-            wct.startShortcut(mContext.getPackageName(), shortcutInfo, options1);
-            mSyncQueue.queue(wct);
+            // Launching a solo shortcut as fullscreen.
+            launchAsFullscreenWithRemoteAnimation(null, null, shortcutInfo, options1, adapter, wct);
             return;
         }
 
@@ -839,6 +786,49 @@
                 instanceId);
     }
 
+    private void launchAsFullscreenWithRemoteAnimation(@Nullable PendingIntent pendingIntent,
+            @Nullable Intent fillInIntent, @Nullable ShortcutInfo shortcutInfo,
+            @Nullable Bundle options, RemoteAnimationAdapter adapter,
+            WindowContainerTransaction wct) {
+        LegacyTransitions.ILegacyTransition transition =
+                (transit, apps, wallpapers, nonApps, finishedCallback, t) -> {
+                    if (apps == null || apps.length == 0) {
+                        onRemoteAnimationFinished(apps);
+                        t.apply();
+                        try {
+                            adapter.getRunner().onAnimationCancelled(mKeyguardShowing);
+                        } catch (RemoteException e) {
+                            Slog.e(TAG, "Error starting remote animation", e);
+                        }
+                        return;
+                    }
+
+                    for (int i = 0; i < apps.length; ++i) {
+                        if (apps[i].mode == MODE_OPENING) {
+                            t.show(apps[i].leash);
+                        }
+                    }
+                    t.apply();
+
+                    try {
+                        adapter.getRunner().onAnimationStart(
+                                transit, apps, wallpapers, nonApps, finishedCallback);
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "Error starting remote animation", e);
+                    }
+                };
+
+        addActivityOptions(options, null /* launchTarget */);
+        if (shortcutInfo != null) {
+            wct.startShortcut(mContext.getPackageName(), shortcutInfo, options);
+        } else if (pendingIntent != null) {
+            wct.sendPendingIntent(pendingIntent, fillInIntent, options);
+        } else {
+            Slog.e(TAG, "Pending intent and shortcut are null is invalid case.");
+        }
+        mSyncQueue.queue(transition, WindowManager.TRANSIT_OPEN, wct);
+    }
+
     private void startWithLegacyTransition(WindowContainerTransaction wct,
             @Nullable PendingIntent mainPendingIntent, @Nullable Intent mainFillInIntent,
             @Nullable ShortcutInfo mainShortcutInfo, @Nullable Bundle mainOptions,
@@ -882,7 +872,7 @@
 
         // Set false to avoid record new bounds with old task still on top;
         mShouldUpdateRecents = false;
-        mIsSplitEntering = true;
+        mIsDividerRemoteAnimating = true;
         if (mSplitRequest == null) {
             mSplitRequest = new SplitRequest(mainTaskId,
                     mainPendingIntent != null ? mainPendingIntent.getIntent() : null,
@@ -895,23 +885,25 @@
 
         if (options == null) options = new Bundle();
         addActivityOptions(options, mMainStage);
-        options = wrapAsSplitRemoteAnimation(adapter, options);
 
         updateWindowBounds(mSplitLayout, wct);
+        wct.reorder(mRootTaskInfo.token, true);
+        setRootForceTranslucent(false, wct);
 
         // TODO(b/268008375): Merge APIs to start a split pair into one.
         if (mainTaskId != INVALID_TASK_ID) {
+            options = wrapAsSplitRemoteAnimation(adapter, options);
             wct.startTask(mainTaskId, options);
-        } else if (mainShortcutInfo != null) {
-            wct.startShortcut(mContext.getPackageName(), mainShortcutInfo, options);
+            mSyncQueue.queue(wct);
         } else {
-            wct.sendPendingIntent(mainPendingIntent, mainFillInIntent, options);
+            if (mainShortcutInfo != null) {
+                wct.startShortcut(mContext.getPackageName(), mainShortcutInfo, options);
+            } else {
+                wct.sendPendingIntent(mainPendingIntent, mainFillInIntent, options);
+            }
+            mSyncQueue.queue(wrapAsSplitRemoteAnimation(adapter), WindowManager.TRANSIT_OPEN, wct);
         }
 
-        wct.reorder(mRootTaskInfo.token, true);
-        wct.setForceTranslucent(mRootTaskInfo.token, false);
-
-        mSyncQueue.queue(wct);
         mSyncQueue.runInSync(t -> {
             setDividerVisibility(true, t);
         });
@@ -937,7 +929,7 @@
                         new IRemoteAnimationFinishedCallback.Stub() {
                             @Override
                             public void onAnimationFinished() throws RemoteException {
-                                onRemoteAnimationFinishedOrCancelled(false /* cancel */, evictWct);
+                                onRemoteAnimationFinishedOrCancelled(evictWct);
                                 finishedCallback.onAnimationFinished();
                             }
                         };
@@ -953,7 +945,7 @@
 
             @Override
             public void onAnimationCancelled(boolean isKeyguardOccluded) {
-                onRemoteAnimationFinishedOrCancelled(true /* cancel */, evictWct);
+                onRemoteAnimationFinishedOrCancelled(evictWct);
                 try {
                     adapter.getRunner().onAnimationCancelled(isKeyguardOccluded);
                 } catch (RemoteException e) {
@@ -968,21 +960,68 @@
         return activityOptions.toBundle();
     }
 
+    private LegacyTransitions.ILegacyTransition wrapAsSplitRemoteAnimation(
+            RemoteAnimationAdapter adapter) {
+        LegacyTransitions.ILegacyTransition transition =
+                (transit, apps, wallpapers, nonApps, finishedCallback, t) -> {
+                    if (apps == null || apps.length == 0) {
+                        onRemoteAnimationFinished(apps);
+                        t.apply();
+                        try {
+                            adapter.getRunner().onAnimationCancelled(mKeyguardShowing);
+                        } catch (RemoteException e) {
+                            Slog.e(TAG, "Error starting remote animation", e);
+                        }
+                        return;
+                    }
+
+                    // Wrap the divider bar into non-apps target to animate together.
+                    nonApps = ArrayUtils.appendElement(RemoteAnimationTarget.class, nonApps,
+                            getDividerBarLegacyTarget());
+
+                    for (int i = 0; i < apps.length; ++i) {
+                        if (apps[i].mode == MODE_OPENING) {
+                            t.show(apps[i].leash);
+                            // Reset the surface position of the opening app to prevent offset.
+                            t.setPosition(apps[i].leash, 0, 0);
+                        }
+                    }
+                    t.apply();
+
+                    IRemoteAnimationFinishedCallback wrapCallback =
+                            new IRemoteAnimationFinishedCallback.Stub() {
+                                @Override
+                                public void onAnimationFinished() throws RemoteException {
+                                    onRemoteAnimationFinished(apps);
+                                    finishedCallback.onAnimationFinished();
+                                }
+                            };
+                    Transitions.setRunningRemoteTransitionDelegate(adapter.getCallingApplication());
+                    try {
+                        adapter.getRunner().onAnimationStart(
+                                transit, apps, wallpapers, nonApps, wrapCallback);
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "Error starting remote animation", e);
+                    }
+                };
+
+        return transition;
+    }
+
     private void setEnterInstanceId(InstanceId instanceId) {
         if (instanceId != null) {
             mLogger.enterRequested(instanceId, ENTER_REASON_LAUNCHER);
         }
     }
 
-    private void onRemoteAnimationFinishedOrCancelled(boolean cancel,
-            WindowContainerTransaction evictWct) {
-        mIsSplitEntering = false;
+    private void onRemoteAnimationFinishedOrCancelled(WindowContainerTransaction evictWct) {
+        mIsDividerRemoteAnimating = false;
         mShouldUpdateRecents = true;
         mSplitRequest = null;
         // If any stage has no child after animation finished, it means that split will display
         // nothing, such status will happen if task and intent is same app but not support
         // multi-instance, we should exit split and expand that app as full screen.
-        if (!cancel && (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0)) {
+        if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0) {
             mMainExecutor.execute(() ->
                     exitSplitScreen(mMainStage.getChildCount() == 0
                             ? mSideStage : mMainStage, EXIT_REASON_UNKNOWN));
@@ -995,6 +1034,27 @@
         }
     }
 
+    private void onRemoteAnimationFinished(RemoteAnimationTarget[] apps) {
+        mIsDividerRemoteAnimating = false;
+        mShouldUpdateRecents = true;
+        mSplitRequest = null;
+        // If any stage has no child after finished animation, that side of the split will display
+        // nothing. This might happen if starting the same app on the both sides while not
+        // supporting multi-instance. Exit the split screen and expand that app to full screen.
+        if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0) {
+            mMainExecutor.execute(() -> exitSplitScreen(mMainStage.getChildCount() == 0
+                    ? mSideStage : mMainStage, EXIT_REASON_UNKNOWN));
+            mSplitUnsupportedToast.show();
+            return;
+        }
+
+        final WindowContainerTransaction evictWct = new WindowContainerTransaction();
+        prepareEvictNonOpeningChildTasks(SPLIT_POSITION_TOP_OR_LEFT, apps, evictWct);
+        prepareEvictNonOpeningChildTasks(SPLIT_POSITION_BOTTOM_OR_RIGHT, apps, evictWct);
+        mSyncQueue.queue(evictWct);
+    }
+
+
     /**
      * Collects all the current child tasks of a specific split and prepares transaction to evict
      * them to display.
@@ -1021,6 +1081,13 @@
         mSideStage.evictInvisibleChildren(wct);
     }
 
+    void prepareEvictChildTasksIfSplitActive(WindowContainerTransaction wct) {
+        if (mMainStage.isActive()) {
+            mMainStage.evictAllChildren(wct);
+            mSideStage.evictAllChildren(wct);
+        }
+    }
+
     Bundle resolveStartStage(@StageType int stage, @SplitPosition int position,
             @Nullable Bundle options, @Nullable WindowContainerTransaction wct) {
         switch (stage) {
@@ -1237,19 +1304,19 @@
             // Notify recents if we are exiting in a way that breaks the pair, and disable further
             // updates to splits in the recents until we enter split again
             if (shouldBreakPairedTaskInRecents(exitReason) && mShouldUpdateRecents) {
-                recentTasks.removeSplitPair(mMainStage.getLastVisibleTaskId());
-                recentTasks.removeSplitPair(mSideStage.getLastVisibleTaskId());
+                recentTasks.removeSplitPair(mMainStage.getTopVisibleChildTaskId());
+                recentTasks.removeSplitPair(mSideStage.getTopVisibleChildTaskId());
             }
         });
         mShouldUpdateRecents = false;
-        mIsSplitEntering = false;
+        mIsDividerRemoteAnimating = false;
 
         mSplitLayout.getInvisibleBounds(mTempRect1);
         if (childrenToTop == null || childrenToTop.getTopVisibleChildTaskId() == INVALID_TASK_ID) {
             mSideStage.removeAllTasks(wct, false /* toTop */);
             mMainStage.deactivate(wct, false /* toTop */);
             wct.reorder(mRootTaskInfo.token, false /* onTop */);
-            wct.setForceTranslucent(mRootTaskInfo.token, true);
+            setRootForceTranslucent(true, wct);
             wct.setBounds(mSideStage.mRootTaskInfo.token, mTempRect1);
             onTransitionAnimationComplete();
         } else {
@@ -1281,7 +1348,7 @@
                     mMainStage.deactivate(finishedWCT, childrenToTop == mMainStage /* toTop */);
                     mSideStage.removeAllTasks(finishedWCT, childrenToTop == mSideStage /* toTop */);
                     finishedWCT.reorder(mRootTaskInfo.token, false /* toTop */);
-                    finishedWCT.setForceTranslucent(mRootTaskInfo.token, true);
+                    setRootForceTranslucent(true, wct);
                     finishedWCT.setBounds(mSideStage.mRootTaskInfo.token, mTempRect1);
                     mSyncQueue.queue(finishedWCT);
                     mSyncQueue.runInSync(at -> {
@@ -1403,7 +1470,7 @@
         mMainStage.activate(wct, true /* includingTopTask */);
         updateWindowBounds(mSplitLayout, wct);
         wct.reorder(mRootTaskInfo.token, true);
-        wct.setForceTranslucent(mRootTaskInfo.token, false);
+        setRootForceTranslucent(false, wct);
     }
 
     void finishEnterSplitScreen(SurfaceControl.Transaction t) {
@@ -1585,7 +1652,7 @@
                 && !ENABLE_SHELL_TRANSITIONS) {
             // Clear the divider remote animating flag as the divider will be re-rendered to apply
             // the new rotation config.
-            mIsSplitEntering = false;
+            mIsDividerRemoteAnimating = false;
             mSplitLayout.update(null /* t */);
             onLayoutSizeChanged(mSplitLayout);
         }
@@ -1607,6 +1674,7 @@
 
         mRootTaskInfo = null;
         mRootTaskLeash = null;
+        mIsRootTranslucent = false;
     }
 
 
@@ -1625,7 +1693,7 @@
         // Make the stages adjacent to each other so they occlude what's behind them.
         wct.setAdjacentRoots(mMainStage.mRootTaskInfo.token, mSideStage.mRootTaskInfo.token);
         wct.setLaunchAdjacentFlagRoot(mSideStage.mRootTaskInfo.token);
-        wct.setForceTranslucent(mRootTaskInfo.token, true);
+        setRootForceTranslucent(true, wct);
         mSplitLayout.getInvisibleBounds(mTempRect1);
         wct.setBounds(mSideStage.mRootTaskInfo.token, mTempRect1);
         mSyncQueue.queue(wct);
@@ -1635,9 +1703,9 @@
     }
 
     void onChildTaskAppeared(StageListenerImpl stageListener, int taskId) {
+        // Handle entering split screen while there is a split pair running in the background.
         if (stageListener == mSideStageListener && !isSplitScreenVisible() && isSplitActive()
-                && !mIsSplitEntering) {
-            // Handle entring split case here if split already running background.
+                && mSplitRequest == null) {
             if (mIsDropEntering) {
                 mSplitLayout.resetDividerPosition();
             } else {
@@ -1649,7 +1717,7 @@
             mSideStage.evictOtherChildren(wct, taskId);
             updateWindowBounds(mSplitLayout, wct);
             wct.reorder(mRootTaskInfo.token, true);
-            wct.setForceTranslucent(mRootTaskInfo.token, false);
+            setRootForceTranslucent(false, wct);
 
             mSyncQueue.queue(wct);
             mSyncQueue.runInSync(t -> {
@@ -1673,6 +1741,13 @@
         mDisplayInsetsController.removeInsetsChangedListener(mDisplayId, mSplitLayout);
     }
 
+    private void setRootForceTranslucent(boolean translucent, WindowContainerTransaction wct) {
+        if (mIsRootTranslucent == translucent) return;
+
+        mIsRootTranslucent = translucent;
+        wct.setForceTranslucent(mRootTaskInfo.token, translucent);
+    }
+
     private void onStageVisibilityChanged(StageListenerImpl stageListener) {
         // If split didn't active, just ignore this callback because we should already did these
         // on #applyExitSplitScreen.
@@ -1699,10 +1774,11 @@
             // Split entering background.
             wct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token,
                     true /* setReparentLeafTaskIfRelaunch */);
-            wct.setForceTranslucent(mRootTaskInfo.token, true);
+            setRootForceTranslucent(true, wct);
         } else {
             wct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token,
                     false /* setReparentLeafTaskIfRelaunch */);
+            setRootForceTranslucent(false, wct);
         }
 
         mSyncQueue.queue(wct);
@@ -1729,7 +1805,7 @@
         mDividerVisible = visible;
         sendSplitVisibilityChanged();
 
-        if (mIsSplitEntering) {
+        if (mIsDividerRemoteAnimating) {
             ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
                     "   Skip animating divider bar due to it's remote animating.");
             return;
@@ -1749,7 +1825,7 @@
                     "   Skip animating divider bar due to divider leash not ready.");
             return;
         }
-        if (mIsSplitEntering) {
+        if (mIsDividerRemoteAnimating) {
             ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
                     "   Skip animating divider bar due to it's remote animating.");
             return;
@@ -1817,7 +1893,8 @@
                 mSplitLayout.flingDividerToDismiss(
                         mSideStagePosition != SPLIT_POSITION_BOTTOM_OR_RIGHT,
                         EXIT_REASON_APP_FINISHED);
-            } else if (!isSplitScreenVisible() && !mIsSplitEntering) {
+            } else if (!isSplitScreenVisible() && mSplitRequest == null) {
+                // Dismiss split screen in the background once any sides of the split become empty.
                 exitSplitScreen(null /* childrenToTop */, EXIT_REASON_APP_FINISHED);
             }
         } else if (isSideStage && hasChildren && !mMainStage.isActive()) {
@@ -1833,7 +1910,7 @@
                 mMainStage.activate(wct, true /* includingTopTask */);
                 updateWindowBounds(mSplitLayout, wct);
                 wct.reorder(mRootTaskInfo.token, true);
-                wct.setForceTranslucent(mRootTaskInfo.token, false);
+                setRootForceTranslucent(false, wct);
             }
 
             mSyncQueue.queue(wct);
@@ -1925,10 +2002,14 @@
         }
 
         final WindowContainerTransaction wct = new WindowContainerTransaction();
-        updateWindowBounds(layout, wct);
+        boolean sizeChanged = updateWindowBounds(layout, wct);
+        if (!sizeChanged) return;
+
         sendOnBoundsChanged();
         if (ENABLE_SHELL_TRANSITIONS) {
-            mSplitTransitions.startResizeTransition(wct, this, null /* callback */);
+            mSplitLayout.setDividerInteractive(false, false, "onSplitResizeStart");
+            mSplitTransitions.startResizeTransition(wct, this, (finishWct, t) ->
+                    mSplitLayout.setDividerInteractive(true, false, "onSplitResizeFinish"));
         } else {
             mSyncQueue.queue(wct);
             mSyncQueue.runInSync(t -> {
@@ -1947,13 +2028,16 @@
     /**
      * Populates `wct` with operations that match the split windows to the current layout.
      * To match relevant surfaces, make sure to call updateSurfaceBounds after `wct` is applied
+     *
+     * @return true if stage bounds actually .
      */
-    private void updateWindowBounds(SplitLayout layout, WindowContainerTransaction wct) {
+    private boolean updateWindowBounds(SplitLayout layout, WindowContainerTransaction wct) {
         final StageTaskListener topLeftStage =
                 mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mSideStage : mMainStage;
         final StageTaskListener bottomRightStage =
                 mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mMainStage : mSideStage;
-        layout.applyTaskChanges(wct, topLeftStage.mRootTaskInfo, bottomRightStage.mRootTaskInfo);
+        return layout.applyTaskChanges(wct, topLeftStage.mRootTaskInfo,
+                bottomRightStage.mRootTaskInfo);
     }
 
     void updateSurfaceBounds(@Nullable SplitLayout layout, @NonNull SurfaceControl.Transaction t,
@@ -2154,19 +2238,10 @@
                 }
             } else if (isOpening && inFullscreen) {
                 final int activityType = triggerTask.getActivityType();
-                if (activityType == ACTIVITY_TYPE_ASSISTANT) {
-                    // We don't want assistant panel to dismiss split screen, so do nothing.
-                } else if (activityType == ACTIVITY_TYPE_HOME
+                if (activityType == ACTIVITY_TYPE_HOME
                         || activityType == ACTIVITY_TYPE_RECENTS) {
-                    // Enter overview panel, so start recent transition.
-                    mSplitTransitions.setRecentTransition(transition, request.getRemoteTransition(),
-                            mRecentTransitionFinishedCallback);
-                } else if (mSplitTransitions.mPendingRecent == null) {
-                    // If split-task is not controlled by recents animation
-                    // and occluded by the other fullscreen task, dismiss both.
-                    prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, out);
-                    mSplitTransitions.setDismissTransition(
-                            transition, STAGE_TYPE_UNDEFINED, EXIT_REASON_UNKNOWN);
+                    // starting recents, so don't handle this.
+                    return null;
                 }
             }
         } else {
@@ -2295,8 +2370,6 @@
         if (mSplitTransitions.isPendingEnter(transition)) {
             shouldAnimate = startPendingEnterAnimation(
                     transition, info, startTransaction, finishTransaction);
-        } else if (mSplitTransitions.isPendingRecent(transition)) {
-            shouldAnimate = startPendingRecentAnimation(transition, info, startTransaction);
         } else if (mSplitTransitions.isPendingDismiss(transition)) {
             shouldAnimate = startPendingDismissAnimation(
                     mSplitTransitions.mPendingDismiss, info, startTransaction, finishTransaction);
@@ -2400,6 +2473,20 @@
         mSplitLayout.flingDividerToDismiss(!leftOrTop, EXIT_REASON_FULLSCREEN_SHORTCUT);
     }
 
+    /** Move the specified task to fullscreen, regardless of focus state. */
+    public void moveTaskToFullscreen(int taskId) {
+        boolean leftOrTop;
+        if (mMainStage.containsTask(taskId)) {
+            leftOrTop = (mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT);
+        } else if (mSideStage.containsTask(taskId)) {
+            leftOrTop = (mSideStagePosition == SPLIT_POSITION_BOTTOM_OR_RIGHT);
+        } else {
+            return;
+        }
+        mSplitLayout.flingDividerToDismiss(!leftOrTop, EXIT_REASON_FULLSCREEN_SHORTCUT);
+
+    }
+
     boolean isLaunchToSplit(TaskInfo taskInfo) {
         return getActivateSplitPosition(taskInfo) != SPLIT_POSITION_UNDEFINED;
     }
@@ -2537,10 +2624,35 @@
         return true;
     }
 
-    private boolean startPendingRecentAnimation(@NonNull IBinder transition,
-            @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t) {
+    /** Call this when starting the open-recents animation while split-screen is active. */
+    public void onRecentsInSplitAnimationStart(@NonNull SurfaceControl.Transaction t) {
         setDividerVisibility(false, t);
-        return true;
+    }
+
+    /** Call this when the recents animation during split-screen finishes. */
+    public void onRecentsInSplitAnimationFinish(WindowContainerTransaction finishWct,
+            SurfaceControl.Transaction finishT) {
+        // Check if the recent transition is finished by returning to the current
+        // split, so we can restore the divider bar.
+        for (int i = 0; i < finishWct.getHierarchyOps().size(); ++i) {
+            final WindowContainerTransaction.HierarchyOp op =
+                    finishWct.getHierarchyOps().get(i);
+            final IBinder container = op.getContainer();
+            if (op.getType() == HIERARCHY_OP_TYPE_REORDER && op.getToTop()
+                    && (mMainStage.containsContainer(container)
+                    || mSideStage.containsContainer(container))) {
+                updateSurfaceBounds(mSplitLayout, finishT,
+                        false /* applyResizingOffset */);
+                setDividerVisibility(true, finishT);
+                return;
+            }
+        }
+
+        // Dismiss the split screen if it's not returning to split.
+        prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, finishWct);
+        setSplitsVisible(false);
+        setDividerVisibility(false, finishT);
+        logExit(EXIT_REASON_UNKNOWN);
     }
 
     private void addDividerBarToTransition(@NonNull TransitionInfo info,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
index 0359761..a841b7f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -92,7 +92,6 @@
     protected SurfaceControl mDimLayer;
     protected SparseArray<ActivityManager.RunningTaskInfo> mChildrenTaskInfo = new SparseArray<>();
     private final SparseArray<SurfaceControl> mChildrenLeashes = new SparseArray<>();
-    private int mLastVisibleTaskId = INVALID_TASK_ID;
     // TODO(b/204308910): Extracts SplitDecorManager related code to common package.
     private SplitDecorManager mSplitDecorManager;
 
@@ -124,13 +123,6 @@
     }
 
     /**
-     * Returns the last visible task's id.
-     */
-    int getLastVisibleTaskId() {
-        return mLastVisibleTaskId;
-    }
-
-    /**
      * Returns the top visible child task's id.
      */
     int getTopVisibleChildTaskId() {
@@ -229,9 +221,6 @@
                 return;
             }
             mChildrenTaskInfo.put(taskInfo.taskId, taskInfo);
-            if (taskInfo.isVisible && taskInfo.taskId != mLastVisibleTaskId) {
-                mLastVisibleTaskId = taskInfo.taskId;
-            }
             mCallbacks.onChildTaskStatusChanged(taskInfo.taskId, true /* present */,
                     taskInfo.isVisible);
             if (!ENABLE_SHELL_TRANSITIONS) {
@@ -264,9 +253,6 @@
         } else if (mChildrenTaskInfo.contains(taskId)) {
             mChildrenTaskInfo.remove(taskId);
             mChildrenLeashes.remove(taskId);
-            if (taskId == mLastVisibleTaskId) {
-                mLastVisibleTaskId = INVALID_TASK_ID;
-            }
             mCallbacks.onChildTaskStatusChanged(taskId, false /* present */, taskInfo.isVisible);
             if (ENABLE_SHELL_TRANSITIONS) {
                 // Status is managed/synchronized by the transition lifecycle.
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 79cd891..dc91a11 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
@@ -384,10 +384,10 @@
 
     private static int estimateWindowBGColor(Drawable themeBGDrawable) {
         final DrawableColorTester themeBGTester = new DrawableColorTester(
-                themeBGDrawable, DrawableColorTester.TRANSPARENT_FILTER /* filterType */);
-        if (themeBGTester.passFilterRatio() == 0) {
-            // the window background is transparent, unable to draw
-            Slog.w(TAG, "Window background is transparent, fill background with black color");
+                themeBGDrawable, DrawableColorTester.TRANSLUCENT_FILTER /* filterType */);
+        if (themeBGTester.passFilterRatio() != 1) {
+            // the window background is translucent, unable to draw
+            Slog.w(TAG, "Window background is translucent, fill background with black color");
             return getSystemBGColor();
         } else {
             return themeBGTester.getDominateColor();
@@ -870,7 +870,7 @@
             @Override
             public float passFilterRatio() {
                 final int alpha = mColorDrawable.getAlpha();
-                return (float) (alpha / 255);
+                return alpha / 255.0f;
             }
 
             @Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java
index 4db81e2..8a4d4c2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java
@@ -434,12 +434,13 @@
             mCreateTime = SystemClock.uptimeMillis();
         }
 
-        void setSplashScreenView(SplashScreenView splashScreenView) {
+        void setSplashScreenView(@Nullable SplashScreenView splashScreenView) {
             if (mSetSplashScreen) {
                 return;
             }
             mSplashView = splashScreenView;
-            mBGColor = mSplashView.getInitBackgroundColor();
+            mBGColor = mSplashView != null ? mSplashView.getInitBackgroundColor()
+                    : Color.TRANSPARENT;
             mSetSplashScreen = true;
         }
 
@@ -477,28 +478,29 @@
 
         @Override
         public void removeIfPossible(StartingWindowRemovalInfo info, boolean immediately) {
-            if (mRootView != null) {
-                if (mSplashView != null) {
-                    clearSystemBarColor();
-                    if (immediately
-                            || mSuggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
-                        removeWindowInner(mRootView, false);
-                    } else {
-                        if (info.playRevealAnimation) {
-                            mSplashscreenContentDrawer.applyExitAnimation(mSplashView,
-                                    info.windowAnimationLeash, info.mainFrame,
-                                    () -> removeWindowInner(mRootView, true),
-                                    mCreateTime, info.roundedCornerRadius);
-                        } else {
-                            // the SplashScreenView has been copied to client, hide the view to skip
-                            // default exit animation
-                            removeWindowInner(mRootView, true);
-                        }
-                    }
+            if (mRootView == null) {
+                return;
+            }
+            if (mSplashView == null) {
+                // shouldn't happen, the app window may be drawn earlier than starting window?
+                Slog.e(TAG, "Found empty splash screen, remove!");
+                removeWindowInner(mRootView, false);
+                return;
+            }
+            clearSystemBarColor();
+            if (immediately
+                    || mSuggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
+                removeWindowInner(mRootView, false);
+            } else {
+                if (info.playRevealAnimation) {
+                    mSplashscreenContentDrawer.applyExitAnimation(mSplashView,
+                            info.windowAnimationLeash, info.mainFrame,
+                            () -> removeWindowInner(mRootView, true),
+                            mCreateTime, info.roundedCornerRadius);
                 } else {
-                    // shouldn't happen
-                    Slog.e(TAG, "Found empty splash screen, remove!");
-                    removeWindowInner(mRootView, false);
+                    // the SplashScreenView has been copied to client, hide the view to skip
+                    // default exit animation
+                    removeWindowInner(mRootView, true);
                 }
             }
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java
index ac52235..2e2f569 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java
@@ -21,6 +21,7 @@
 import android.os.Build;
 import android.os.SystemClock;
 import android.util.Pair;
+import android.view.SurfaceControl;
 
 import androidx.annotation.VisibleForTesting;
 
@@ -75,6 +76,7 @@
     @VisibleForTesting
     public void init() {
         ProtoLog.v(WM_SHELL_INIT, "Initializing Shell Components: %d", mInitCallbacks.size());
+        SurfaceControl.setDebugUsageAfterRelease(true);
         // Init in order of registration
         for (int i = 0; i < mInitCallbacks.size(); i++) {
             final Pair<String, Runnable> info = mInitCallbacks.get(i);
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 ef405c8..b9f6a01 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
@@ -18,6 +18,7 @@
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_TO_BACK;
 import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
@@ -25,6 +26,7 @@
 import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR;
 import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
 import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_CHILD_TASK_ENTER_PIP;
+import static com.android.wm.shell.util.TransitionUtil.isOpeningType;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -68,17 +70,22 @@
         /** Pip was entered while handling an intent with its own remoteTransition. */
         static final int TYPE_OPTIONS_REMOTE_AND_PIP_CHANGE = 3;
 
+        /** Recents transition while split-screen active. */
+        static final int TYPE_RECENTS_DURING_SPLIT = 4;
+
         /** The default animation for this mixed transition. */
         static final int ANIM_TYPE_DEFAULT = 0;
 
         /** For ENTER_PIP_FROM_SPLIT, indicates that this is a to-home animation. */
         static final int ANIM_TYPE_GOING_HOME = 1;
 
+        /** For RECENTS_DURING_SPLIT, is set when this turns into a pair->pair task switch. */
+        static final int ANIM_TYPE_PAIR_TO_PAIR = 1;
+
         final int mType;
-        int mAnimType = 0;
+        int mAnimType = ANIM_TYPE_DEFAULT;
         final IBinder mTransition;
 
-        Transitions.TransitionFinishCallback mFinishCallback = null;
         Transitions.TransitionHandler mLeftoversHandler = null;
         WindowContainerTransaction mFinishWCT = null;
 
@@ -168,6 +175,25 @@
             mixed.mLeftoversHandler = handler.first;
             mActiveTransitions.add(mixed);
             return handler.second;
+        } else if (mSplitHandler.isSplitActive()
+                && isOpeningType(request.getType())
+                && request.getTriggerTask() != null
+                && request.getTriggerTask().getWindowingMode() == WINDOWING_MODE_FULLSCREEN
+                && (request.getTriggerTask().getActivityType() == ACTIVITY_TYPE_HOME
+                        || request.getTriggerTask().getActivityType() == ACTIVITY_TYPE_RECENTS)) {
+            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a recents request while "
+                    + "Split-Screen is active, so treat it as Mixed.");
+            Pair<Transitions.TransitionHandler, WindowContainerTransaction> handler =
+                    mPlayer.dispatchRequest(transition, request, this);
+            if (handler == null) {
+                // fall through -- it will probably be picked-up by normal split handler.
+                return null;
+            }
+            final MixedTransition mixed = new MixedTransition(
+                    MixedTransition.TYPE_RECENTS_DURING_SPLIT, transition);
+            mixed.mLeftoversHandler = handler.first;
+            mActiveTransitions.add(mixed);
+            return handler.second;
         }
         return null;
     }
@@ -180,7 +206,9 @@
                 out.getChanges().add(info.getChanges().get(i));
             }
         }
-        out.setRootLeash(info.getRootLeash(), info.getRootOffset().x, info.getRootOffset().y);
+        for (int i = 0; i < info.getRootCount(); ++i) {
+            out.addRoot(info.getRoot(i));
+        }
         out.setAnimationOptions(info.getAnimationOptions());
         return out;
     }
@@ -215,6 +243,9 @@
         } else if (mixed.mType == MixedTransition.TYPE_OPTIONS_REMOTE_AND_PIP_CHANGE) {
             return animateOpenIntentWithRemoteAndPip(mixed, info, startTransaction,
                     finishTransaction, finishCallback);
+        } else if (mixed.mType == MixedTransition.TYPE_RECENTS_DURING_SPLIT) {
+            return animateRecentsDuringSplit(mixed, info, startTransaction, finishTransaction,
+                    finishCallback);
         } else {
             mActiveTransitions.remove(mixed);
             throw new IllegalStateException("Starting mixed animation without a known mixed type? "
@@ -241,20 +272,25 @@
         }
         if (pipChange == null) {
             if (mixed.mLeftoversHandler != null) {
-                return mixed.mLeftoversHandler.startAnimation(mixed.mTransition, info,
-                        startTransaction, finishTransaction, finishCallback);
+                if (mixed.mLeftoversHandler.startAnimation(mixed.mTransition,
+                        info, startTransaction, finishTransaction, (wct, wctCB) -> {
+                            mActiveTransitions.remove(mixed);
+                            finishCallback.onTransitionFinished(wct, wctCB);
+                        })) {
+                    return true;
+                }
             }
+            mActiveTransitions.remove(mixed);
             return false;
         }
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Splitting PIP into a separate"
                         + " animation because remote-animation likely doesn't support it");
-        mixed.mFinishCallback = finishCallback;
         Transitions.TransitionFinishCallback finishCB = (wct, wctCB) -> {
             --mixed.mInFlightSubAnimations;
             mixed.joinFinishArgs(wct, wctCB);
             if (mixed.mInFlightSubAnimations > 0) return;
             mActiveTransitions.remove(mixed);
-            mixed.mFinishCallback.onTransitionFinished(mixed.mFinishWCT, wctCB);
+            finishCallback.onTransitionFinished(mixed.mFinishWCT, wctCB);
         };
         // Split the transition into 2 parts: the pip part and the rest.
         mixed.mInFlightSubAnimations = 2;
@@ -304,10 +340,10 @@
         }
         if (pipChange == null) {
             // um, something probably went wrong.
+            mActiveTransitions.remove(mixed);
             return false;
         }
         final boolean isGoingHome = homeIsOpening;
-        mixed.mFinishCallback = finishCallback;
         Transitions.TransitionFinishCallback finishCB = (wct, wctCB) -> {
             --mixed.mInFlightSubAnimations;
             mixed.joinFinishArgs(wct, wctCB);
@@ -316,7 +352,7 @@
             if (isGoingHome) {
                 mSplitHandler.onTransitionAnimationComplete();
             }
-            mixed.mFinishCallback.onTransitionFinished(mixed.mFinishWCT, wctCB);
+            finishCallback.onTransitionFinished(mixed.mFinishWCT, wctCB);
         };
         if (isGoingHome) {
             ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Animation is actually mixed "
@@ -408,7 +444,6 @@
         unlinkMissingParents(everythingElse);
         final MixedTransition mixed = new MixedTransition(
                 MixedTransition.TYPE_DISPLAY_AND_SPLIT_CHANGE, transition);
-        mixed.mFinishCallback = finishCallback;
         mActiveTransitions.add(mixed);
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Animation is a mix of display change "
                 + "and split change.");
@@ -420,7 +455,7 @@
             mixed.joinFinishArgs(wct, wctCB);
             if (mixed.mInFlightSubAnimations > 0) return;
             mActiveTransitions.remove(mixed);
-            mixed.mFinishCallback.onTransitionFinished(mixed.mFinishWCT, null /* wctCB */);
+            finishCallback.onTransitionFinished(mixed.mFinishWCT, null /* wctCB */);
         };
 
         // Dispatch the display change. This will most-likely be taken by the default handler.
@@ -436,18 +471,48 @@
         return true;
     }
 
+    private boolean animateRecentsDuringSplit(@NonNull final MixedTransition mixed,
+            @NonNull TransitionInfo info,
+            @NonNull SurfaceControl.Transaction startTransaction,
+            @NonNull SurfaceControl.Transaction finishTransaction,
+            @NonNull Transitions.TransitionFinishCallback finishCallback) {
+        // Split-screen is only interested in the recents transition finishing (and merging), so
+        // just wrap finish and start recents animation directly.
+        Transitions.TransitionFinishCallback finishCB = (wct, wctCB) -> {
+            mixed.mInFlightSubAnimations = 0;
+            mActiveTransitions.remove(mixed);
+            // If pair-to-pair switching, the post-recents clean-up isn't needed.
+            if (mixed.mAnimType != MixedTransition.ANIM_TYPE_PAIR_TO_PAIR) {
+                wct = wct != null ? wct : new WindowContainerTransaction();
+                mSplitHandler.onRecentsInSplitAnimationFinish(wct, finishTransaction);
+            }
+            mSplitHandler.onTransitionAnimationComplete();
+            finishCallback.onTransitionFinished(wct, wctCB);
+        };
+        mixed.mInFlightSubAnimations = 1;
+        mSplitHandler.onRecentsInSplitAnimationStart(startTransaction);
+        final boolean handled = mixed.mLeftoversHandler.startAnimation(mixed.mTransition, info,
+                startTransaction, finishTransaction, finishCB);
+        if (!handled) {
+            mActiveTransitions.remove(mixed);
+        }
+        return handled;
+    }
+
     @Override
     public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
             @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget,
             @NonNull Transitions.TransitionFinishCallback finishCallback) {
         for (int i = 0; i < mActiveTransitions.size(); ++i) {
-            if (mActiveTransitions.get(i) != mergeTarget) continue;
+            if (mActiveTransitions.get(i).mTransition != mergeTarget) continue;
             MixedTransition mixed = mActiveTransitions.get(i);
             if (mixed.mInFlightSubAnimations <= 0) {
                 // Already done, so no need to end it.
                 return;
             }
-            if (mixed.mType == MixedTransition.TYPE_ENTER_PIP_FROM_SPLIT) {
+            if (mixed.mType == MixedTransition.TYPE_DISPLAY_AND_SPLIT_CHANGE) {
+                // queue since no actual animation.
+            } else if (mixed.mType == MixedTransition.TYPE_ENTER_PIP_FROM_SPLIT) {
                 if (mixed.mAnimType == MixedTransition.ANIM_TYPE_GOING_HOME) {
                     boolean ended = mSplitHandler.end();
                     // If split couldn't end (because it is remote), then don't end everything else
@@ -461,8 +526,20 @@
                 } else {
                     mPipHandler.end();
                 }
-            } else if (mixed.mType == MixedTransition.TYPE_DISPLAY_AND_SPLIT_CHANGE) {
-                // queue
+            } else if (mixed.mType == MixedTransition.TYPE_OPTIONS_REMOTE_AND_PIP_CHANGE) {
+                mPipHandler.end();
+                if (mixed.mLeftoversHandler != null) {
+                    mixed.mLeftoversHandler.mergeAnimation(transition, info, t, mergeTarget,
+                            finishCallback);
+                }
+            } else if (mixed.mType == MixedTransition.TYPE_RECENTS_DURING_SPLIT) {
+                if (mSplitHandler.isPendingEnter(transition)) {
+                    // Recents -> enter-split means that we are switching from one pair to
+                    // another pair.
+                    mixed.mAnimType = MixedTransition.ANIM_TYPE_PAIR_TO_PAIR;
+                }
+                mixed.mLeftoversHandler.mergeAnimation(transition, info, t, mergeTarget,
+                        finishCallback);
             } else {
                 throw new IllegalStateException("Playing a mixed transition with unknown type? "
                         + mixed.mType);
@@ -482,6 +559,8 @@
         if (mixed == null) return;
         if (mixed.mType == MixedTransition.TYPE_ENTER_PIP_FROM_SPLIT) {
             mPipHandler.onTransitionConsumed(transition, aborted, finishT);
+        } else if (mixed.mType == MixedTransition.TYPE_RECENTS_DURING_SPLIT) {
+            mixed.mLeftoversHandler.onTransitionConsumed(transition, aborted, finishT);
         }
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
index f66c26b..63c7969 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
@@ -383,9 +383,10 @@
                     continue;
                 }
                 // No default animation for this, so just update bounds/position.
+                final int rootIdx = TransitionUtil.rootIndexFor(change, info);
                 startTransaction.setPosition(change.getLeash(),
-                        change.getEndAbsBounds().left - info.getRootOffset().x,
-                        change.getEndAbsBounds().top - info.getRootOffset().y);
+                        change.getEndAbsBounds().left - info.getRoot(rootIdx).getOffset().x,
+                        change.getEndAbsBounds().top - info.getRoot(rootIdx).getOffset().y);
                 // Seamless display transition doesn't need to animate.
                 if (isSeamlessDisplayChange) continue;
                 if (isTask || (change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY)
@@ -474,8 +475,10 @@
         }
 
         if (backgroundColorForTransition != 0) {
-            addBackgroundToTransition(info.getRootLeash(), backgroundColorForTransition,
-                    startTransaction, finishTransaction);
+            for (int i = 0; i < info.getRootCount(); ++i) {
+                addBackgroundToTransition(info.getRoot(i).getLeash(), backgroundColorForTransition,
+                        startTransaction, finishTransaction);
+            }
         }
 
         if (postStartTransactionCallbacks.size() > 0) {
@@ -520,8 +523,10 @@
     private void startRotationAnimation(SurfaceControl.Transaction startTransaction,
             TransitionInfo.Change change, TransitionInfo info, int animHint,
             ArrayList<Animator> animations, Runnable onAnimFinish) {
+        final int rootIdx = TransitionUtil.rootIndexFor(change, info);
         final ScreenRotationAnimation anim = new ScreenRotationAnimation(mContext, mSurfaceSession,
-                mTransactionPool, startTransaction, change, info.getRootLeash(), animHint);
+                mTransactionPool, startTransaction, change, info.getRoot(rootIdx).getLeash(),
+                animHint);
         // The rotation animation may consist of 3 animations: fade-out screenshot, fade-in real
         // content, and background color. The item of "animGroup" will be removed if the sub
         // animation is finished. Then if the list becomes empty, the rotation animation is done.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/SleepHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/SleepHandler.java
new file mode 100644
index 0000000..0386ec3
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/SleepHandler.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.transition;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.IBinder;
+import android.util.Log;
+import android.view.SurfaceControl;
+import android.window.TransitionInfo;
+import android.window.TransitionRequestInfo;
+import android.window.WindowContainerTransaction;
+
+import java.util.ArrayList;
+
+/**
+ * A Simple handler that tracks SLEEP transitions. We track them specially since we (ab)use these
+ * as sentinels for fast-forwarding through animations when the screen is off.
+ *
+ * There should only be one SleepHandler and it is used explicitly by {@link Transitions} so we
+ * don't register it like a normal handler.
+ */
+class SleepHandler implements Transitions.TransitionHandler {
+    final ArrayList<IBinder> mSleepTransitions = new ArrayList<>();
+
+    @Override
+    public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
+            @NonNull SurfaceControl.Transaction startTransaction,
+            @NonNull SurfaceControl.Transaction finishTransaction,
+            @NonNull Transitions.TransitionFinishCallback finishCallback) {
+        startTransaction.apply();
+        finishCallback.onTransitionFinished(null, null);
+        mSleepTransitions.remove(transition);
+        return true;
+    }
+
+    @Override
+    @Nullable
+    public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
+            @NonNull TransitionRequestInfo request) {
+        mSleepTransitions.add(transition);
+        return new WindowContainerTransaction();
+    }
+
+    @Override
+    public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted,
+            @Nullable SurfaceControl.Transaction finishTransaction) {
+        Log.e(Transitions.TAG, "Sleep transition was consumed. This doesn't make sense");
+        mSleepTransitions.remove(transition);
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java
index 8d29901..bcc37ba 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java
@@ -143,8 +143,12 @@
         Animation a = null;
         if (animAttr != 0) {
             if (overrideType == ANIM_FROM_STYLE && !isTask) {
-                a = loadCustomActivityTransition(animAttr, options, enter, transitionAnimation);
-                if (a == null) {
+                final TransitionInfo.AnimationOptions.CustomActivityTransition customTransition =
+                        getCustomActivityTransition(animAttr, options);
+                if (customTransition != null) {
+                    a = loadCustomActivityTransition(
+                            customTransition, options, enter, transitionAnimation);
+                } else {
                     a = transitionAnimation
                             .loadAnimationAttr(options.getPackageName(), options.getAnimations(),
                                     animAttr, translucent);
@@ -161,10 +165,8 @@
         return a;
     }
 
-    static Animation loadCustomActivityTransition(int animAttr,
-            TransitionInfo.AnimationOptions options, boolean enter,
-            TransitionAnimation transitionAnimation) {
-        Animation a = null;
+    static TransitionInfo.AnimationOptions.CustomActivityTransition getCustomActivityTransition(
+            int animAttr, TransitionInfo.AnimationOptions options) {
         boolean isOpen = false;
         switch (animAttr) {
             case R.styleable.WindowAnimation_activityOpenEnterAnimation:
@@ -178,17 +180,19 @@
                 return null;
         }
 
-        final TransitionInfo.AnimationOptions.CustomActivityTransition transitionAnim =
-                options.getCustomActivityTransition(isOpen);
-        if (transitionAnim != null) {
-            a = transitionAnimation.loadAppTransitionAnimation(options.getPackageName(),
-                    enter ? transitionAnim.getCustomEnterResId()
-                            : transitionAnim.getCustomExitResId());
-            if (a != null && transitionAnim.getCustomBackgroundColor() != 0) {
-                a.setBackdropColor(transitionAnim.getCustomBackgroundColor());
-            }
-        }
+        return options.getCustomActivityTransition(isOpen);
+    }
 
+    static Animation loadCustomActivityTransition(
+            @NonNull TransitionInfo.AnimationOptions.CustomActivityTransition transitionAnim,
+            TransitionInfo.AnimationOptions options, boolean enter,
+            TransitionAnimation transitionAnimation) {
+        final Animation a = transitionAnimation.loadAppTransitionAnimation(options.getPackageName(),
+                enter ? transitionAnim.getCustomEnterResId()
+                        : transitionAnim.getCustomExitResId());
+        if (a != null && transitionAnim.getCustomBackgroundColor() != 0) {
+            a.setBackdropColor(transitionAnim.getCustomBackgroundColor());
+        }
         return a;
     }
 
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 3b154d1..039bde9 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
@@ -21,6 +21,7 @@
 import static android.view.WindowManager.TRANSIT_FIRST_CUSTOM;
 import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
 import static android.view.WindowManager.TRANSIT_OPEN;
+import static android.view.WindowManager.TRANSIT_SLEEP;
 import static android.view.WindowManager.TRANSIT_TO_BACK;
 import static android.view.WindowManager.TRANSIT_TO_FRONT;
 import static android.view.WindowManager.fixScale;
@@ -74,11 +75,29 @@
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
 import com.android.wm.shell.sysui.ShellController;
 import com.android.wm.shell.sysui.ShellInit;
+import com.android.wm.shell.util.TransitionUtil;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 
-/** Plays transition animations */
+/**
+ * Plays transition animations. Within this player, each transition has a lifecycle.
+ * 1. When a transition is directly started or requested, it is added to "pending" state.
+ * 2. Once WMCore applies the transition and notifies, the transition moves to "ready" state.
+ * 3. When a transition starts animating, it is moved to the "active" state.
+ *
+ * Basically: --start--> PENDING --onTransitionReady--> READY --play--> ACTIVE --finish--> |
+ *                                                            --merge--> MERGED --^
+ *
+ * At the moment, only one transition can be animating at a time. While a transition is animating,
+ * transitions will be queued in the "ready" state for their turn. At the same time, whenever a
+ * transition makes it to the head of the "ready" queue, it will attempt to merge to with the
+ * "active" transition. If the merge succeeds, it will be moved to the "active" transition's
+ * "merged" and then the next "ready" transition can attempt to merge.
+ *
+ * Once the "active" transition animation is finished, it will be removed from the "active" list
+ * and then the next "ready" transition can play.
+ */
 public class Transitions implements RemoteCallable<Transitions> {
     static final String TAG = "ShellTransitions";
 
@@ -124,6 +143,7 @@
     private final DisplayController mDisplayController;
     private final ShellController mShellController;
     private final ShellTransitionImpl mImpl = new ShellTransitionImpl();
+    private final SleepHandler mSleepHandler = new SleepHandler();
 
     private boolean mIsRegistered = false;
 
@@ -137,17 +157,33 @@
 
     private float mTransitionAnimationScaleSetting = 1.0f;
 
+    /**
+     * How much time we allow for an animation to finish itself on sleep. If it takes longer, we
+     * will force-finish it (on this end) which may leave it in a bad state but won't hang the
+     * device. This needs to be pretty small because it is an allowance for each queued animation,
+     * however it can't be too small since there is some potential IPC involved.
+     */
+    private static final int SLEEP_ALLOWANCE_MS = 120;
+
     private static final class ActiveTransition {
         IBinder mToken;
         TransitionHandler mHandler;
-        boolean mMerged;
         boolean mAborted;
         TransitionInfo mInfo;
         SurfaceControl.Transaction mStartT;
         SurfaceControl.Transaction mFinishT;
+
+        /** Ordered list of transitions which have been merged into this one. */
+        private ArrayList<ActiveTransition> mMerged;
     }
 
-    /** Keeps track of currently playing transitions in the order of receipt. */
+    /** Keeps track of transitions which have been started, but aren't ready yet. */
+    private final ArrayList<ActiveTransition> mPendingTransitions = new ArrayList<>();
+
+    /** Keeps track of transitions which are ready to play but still waiting for their turn. */
+    private final ArrayList<ActiveTransition> mReadyTransitions = new ArrayList<>();
+
+    /** Keeps track of currently playing transitions. For now, there can only be 1 max. */
     private final ArrayList<ActiveTransition> mActiveTransitions = new ArrayList<>();
 
     public Transitions(@NonNull Context context,
@@ -312,7 +348,8 @@
      * will be executed when the last active transition is finished.
      */
     public void runOnIdle(Runnable runnable) {
-        if (mActiveTransitions.isEmpty()) {
+        if (mActiveTransitions.isEmpty() && mPendingTransitions.isEmpty()
+                && mReadyTransitions.isEmpty()) {
             runnable.run();
         } else {
             mRunWhenIdleQueue.add(runnable);
@@ -379,8 +416,8 @@
     private static void setupAnimHierarchy(@NonNull TransitionInfo info,
             @NonNull SurfaceControl.Transaction t, @NonNull SurfaceControl.Transaction finishT) {
         boolean isOpening = isOpeningType(info.getType());
-        if (info.getRootLeash().isValid()) {
-            t.show(info.getRootLeash());
+        for (int i = 0; i < info.getRootCount(); ++i) {
+            t.show(info.getRoot(i).getLeash());
         }
         final int numChanges = info.getChanges().size();
         // Put animating stuff above this line and put static stuff below it.
@@ -398,10 +435,12 @@
 
             boolean hasParent = change.getParent() != null;
 
+            final int rootIdx = TransitionUtil.rootIndexFor(change, info);
             if (!hasParent) {
-                t.reparent(leash, info.getRootLeash());
-                t.setPosition(leash, change.getStartAbsBounds().left - info.getRootOffset().x,
-                        change.getStartAbsBounds().top - info.getRootOffset().y);
+                t.reparent(leash, info.getRoot(rootIdx).getLeash());
+                t.setPosition(leash,
+                        change.getStartAbsBounds().left - info.getRoot(rootIdx).getOffset().x,
+                        change.getStartAbsBounds().top - info.getRoot(rootIdx).getOffset().y);
             }
             final int layer;
             // Put all the OPEN/SHOW on top
@@ -431,9 +470,9 @@
         }
     }
 
-    private int findActiveTransition(IBinder token) {
-        for (int i = mActiveTransitions.size() - 1; i >= 0; --i) {
-            if (mActiveTransitions.get(i).mToken == token) return i;
+    private static int findByToken(ArrayList<ActiveTransition> list, IBinder token) {
+        for (int i = list.size() - 1; i >= 0; --i) {
+            if (list.get(i).mToken == token) return i;
         }
         return -1;
     }
@@ -471,28 +510,45 @@
             @NonNull SurfaceControl.Transaction t, @NonNull SurfaceControl.Transaction finishT) {
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "onTransitionReady %s: %s",
                 transitionToken, info);
-        final int activeIdx = findActiveTransition(transitionToken);
+        final int activeIdx = findByToken(mPendingTransitions, transitionToken);
         if (activeIdx < 0) {
-            throw new IllegalStateException("Got transitionReady for non-active transition "
+            throw new IllegalStateException("Got transitionReady for non-pending transition "
                     + transitionToken + ". expecting one of "
-                    + Arrays.toString(mActiveTransitions.stream().map(
+                    + Arrays.toString(mPendingTransitions.stream().map(
                             activeTransition -> activeTransition.mToken).toArray()));
         }
+        if (activeIdx > 0) {
+            Log.e(TAG, "Transition became ready out-of-order " + transitionToken + ". Expected"
+                    + " order: " + Arrays.toString(mPendingTransitions.stream().map(
+                            activeTransition -> activeTransition.mToken).toArray()));
+        }
+        // Move from pending to ready
+        final ActiveTransition active = mPendingTransitions.remove(activeIdx);
+        mReadyTransitions.add(active);
+        active.mInfo = info;
+        active.mStartT = t;
+        active.mFinishT = finishT;
 
         for (int i = 0; i < mObservers.size(); ++i) {
             mObservers.get(i).onTransitionReady(transitionToken, info, t, finishT);
         }
 
+        if (info.getType() == TRANSIT_SLEEP) {
+            if (activeIdx > 0) {
+                // Sleep starts a process of forcing all prior transitions to finish immediately
+                finishForSleep(null /* forceFinish */);
+                return;
+            }
+        }
+
         // Allow to notify keyguard un-occluding state to KeyguardService, which can happen while
         // screen-off, so there might no visibility change involved.
-        if (!info.getRootLeash().isValid() && info.getType() != TRANSIT_KEYGUARD_UNOCCLUDE) {
-            // Invalid root-leash implies that the transition is empty/no-op, so just do
+        if (info.getRootCount() == 0 && info.getType() != TRANSIT_KEYGUARD_UNOCCLUDE) {
+            // No root-leashes implies that the transition is empty/no-op, so just do
             // housekeeping and return.
-            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Invalid root leash (%s): %s",
+            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "No transition roots (%s): %s",
                     transitionToken, info);
-            t.apply();
-            finishT.apply();
-            onAbort(transitionToken);
+            onAbort(active);
             return;
         }
 
@@ -518,41 +574,90 @@
                 // changes are underneath another change.
                 || ((info.getType() == TRANSIT_TO_BACK || info.getType() == TRANSIT_TO_FRONT)
                 && allOccluded)) {
-            t.apply();
-            finishT.apply();
             // Treat this as an abort since we are bypassing any merge logic and effectively
             // finishing immediately.
-            onAbort(transitionToken);
-            releaseSurfaces(info);
+            onAbort(active);
             return;
         }
 
-        final ActiveTransition active = mActiveTransitions.get(activeIdx);
-        active.mInfo = info;
-        active.mStartT = t;
-        active.mFinishT = finishT;
         setupStartState(active.mInfo, active.mStartT, active.mFinishT);
 
-        if (activeIdx > 0) {
-            // This is now playing at the same time as an existing animation, so try merging it.
-            attemptMergeTransition(mActiveTransitions.get(0), active);
+        if (mReadyTransitions.size() > 1) {
+            // There are already transitions waiting in the queue, so just return.
             return;
         }
-        // The normal case, just play it.
-        playTransition(active);
+        processReadyQueue();
     }
 
-    /**
-     * Attempt to merge by delegating the transition start to the handler of the currently
-     * playing transition.
-     */
-    void attemptMergeTransition(@NonNull ActiveTransition playing,
-            @NonNull ActiveTransition merging) {
+    void processReadyQueue() {
+        if (mReadyTransitions.isEmpty()) {
+            // Check if idle.
+            if (mActiveTransitions.isEmpty() && mPendingTransitions.isEmpty()) {
+                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "All active transition "
+                        + "animations finished");
+                // Run all runnables from the run-when-idle queue.
+                for (int i = 0; i < mRunWhenIdleQueue.size(); i++) {
+                    mRunWhenIdleQueue.get(i).run();
+                }
+                mRunWhenIdleQueue.clear();
+            }
+            return;
+        }
+        final ActiveTransition ready = mReadyTransitions.get(0);
+        if (mActiveTransitions.isEmpty()) {
+            // The normal case, just play it (currently we only support 1 active transition).
+            mReadyTransitions.remove(0);
+            mActiveTransitions.add(ready);
+            if (ready.mAborted) {
+                // finish now since there's nothing to animate. Calls back into processReadyQueue
+                onFinish(ready, null, null);
+                return;
+            }
+            playTransition(ready);
+            // Attempt to merge any more queued-up transitions.
+            processReadyQueue();
+            return;
+        }
+        // An existing animation is playing, so see if we can merge.
+        final ActiveTransition playing = mActiveTransitions.get(0);
+        if (ready.mAborted) {
+            // record as merged since it is no-op. Calls back into processReadyQueue
+            onMerged(playing, ready);
+            return;
+        }
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition %s ready while"
                 + " another transition %s is still animating. Notify the animating transition"
-                + " in case they can be merged", merging.mToken, playing.mToken);
-        playing.mHandler.mergeAnimation(merging.mToken, merging.mInfo, merging.mStartT,
-                playing.mToken, (wct, cb) -> onFinish(merging.mToken, wct, cb));
+                + " in case they can be merged", ready.mToken, playing.mToken);
+        playing.mHandler.mergeAnimation(ready.mToken, ready.mInfo, ready.mStartT,
+                playing.mToken, (wct, cb) -> onMerged(playing, ready));
+    }
+
+    private void onMerged(@NonNull ActiveTransition playing, @NonNull ActiveTransition merged) {
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition was merged %s",
+                merged.mToken);
+        int readyIdx = 0;
+        if (mReadyTransitions.isEmpty() || mReadyTransitions.get(0) != merged) {
+            Log.e(TAG, "Merged transition out-of-order?");
+            readyIdx = mReadyTransitions.indexOf(merged);
+            if (readyIdx < 0) {
+                Log.e(TAG, "Merged a transition that is no-longer queued?");
+                return;
+            }
+        }
+        mReadyTransitions.remove(readyIdx);
+        if (playing.mMerged == null) {
+            playing.mMerged = new ArrayList<>();
+        }
+        playing.mMerged.add(merged);
+        // if it was aborted, then onConsumed has already been reported.
+        if (merged.mHandler != null && !merged.mAborted) {
+            merged.mHandler.onTransitionConsumed(merged.mToken, false /* abort */, merged.mFinishT);
+        }
+        for (int i = 0; i < mObservers.size(); ++i) {
+            mObservers.get(i).onTransitionMerged(merged.mToken, playing.mToken);
+        }
+        // See if we should merge another transition.
+        processReadyQueue();
     }
 
     private void playTransition(@NonNull ActiveTransition active) {
@@ -567,7 +672,7 @@
             ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " try firstHandler %s",
                     active.mHandler);
             boolean consumed = active.mHandler.startAnimation(active.mToken, active.mInfo,
-                    active.mStartT, active.mFinishT, (wct, cb) -> onFinish(active.mToken, wct, cb));
+                    active.mStartT, active.mFinishT, (wct, cb) -> onFinish(active, wct, cb));
             if (consumed) {
                 ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " animated by firstHandler");
                 return;
@@ -575,7 +680,7 @@
         }
         // Otherwise give every other handler a chance
         active.mHandler = dispatchTransition(active.mToken, active.mInfo, active.mStartT,
-                active.mFinishT, (wct, cb) -> onFinish(active.mToken, wct, cb), active.mHandler);
+                active.mFinishT, (wct, cb) -> onFinish(active, wct, cb), active.mHandler);
     }
 
     /**
@@ -618,15 +723,28 @@
         return null;
     }
 
-    /** Special version of finish just for dealing with no-op/invalid transitions. */
-    private void onAbort(IBinder transition) {
-        onFinish(transition, null /* wct */, null /* wctCB */, true /* abort */);
-    }
+    /** Aborts a transition. This will still queue it up to maintain order. */
+    private void onAbort(ActiveTransition transition) {
+        // apply immediately since they may be "parallel" operations: We currently we use abort for
+        // thing which are independent to other transitions (like starting-window transfer).
+        transition.mStartT.apply();
+        transition.mFinishT.apply();
+        transition.mAborted = true;
 
-    private void onFinish(IBinder transition,
-            @Nullable WindowContainerTransaction wct,
-            @Nullable WindowContainerTransactionCallback wctCB) {
-        onFinish(transition, wct, wctCB, false /* abort */);
+        if (transition.mHandler != null) {
+            // Notifies to clean-up the aborted transition.
+            transition.mHandler.onTransitionConsumed(
+                    transition.mToken, true /* aborted */, null /* finishTransaction */);
+        }
+
+        releaseSurfaces(transition.mInfo);
+
+        // This still went into the queue (to maintain the correct finish ordering).
+        if (mReadyTransitions.size() > 1) {
+            // There are already transitions waiting in the queue, so just return.
+            return;
+        }
+        processReadyQueue();
     }
 
     /**
@@ -638,195 +756,136 @@
         info.releaseAnimSurfaces();
     }
 
-    private void onFinish(IBinder transition,
+    private void onFinish(ActiveTransition active,
             @Nullable WindowContainerTransaction wct,
-            @Nullable WindowContainerTransactionCallback wctCB,
-            boolean abort) {
-        int activeIdx = findActiveTransition(transition);
+            @Nullable WindowContainerTransactionCallback wctCB) {
+        int activeIdx = mActiveTransitions.indexOf(active);
         if (activeIdx < 0) {
             Log.e(TAG, "Trying to finish a non-running transition. Either remote crashed or "
-                    + " a handler didn't properly deal with a merge.", new RuntimeException());
+                    + " a handler didn't properly deal with a merge. " + active.mToken,
+                    new RuntimeException());
             return;
-        } else if (activeIdx > 0) {
-            // This transition was merged.
-            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition was merged (abort=%b:"
-                    + " %s", abort, transition);
-            final ActiveTransition active = mActiveTransitions.get(activeIdx);
-            active.mMerged = true;
-            active.mAborted = abort;
-            if (active.mHandler != null) {
-                active.mHandler.onTransitionConsumed(
-                        active.mToken, abort, abort ? null : active.mFinishT);
-            }
-            for (int i = 0; i < mObservers.size(); ++i) {
-                mObservers.get(i).onTransitionMerged(
-                        active.mToken, mActiveTransitions.get(0).mToken);
-            }
-            return;
+        } else if (activeIdx != 0) {
+            // Relevant right now since we only allow 1 active transition at a time.
+            Log.e(TAG, "Finishing a transition out of order. " + active.mToken);
         }
-        final ActiveTransition active = mActiveTransitions.get(activeIdx);
-        active.mAborted = abort;
-        if (active.mAborted && active.mHandler != null) {
-            // Notifies to clean-up the aborted transition.
-            active.mHandler.onTransitionConsumed(
-                    transition, true /* aborted */, null /* finishTransaction */);
-        }
+        mActiveTransitions.remove(activeIdx);
+
         for (int i = 0; i < mObservers.size(); ++i) {
             mObservers.get(i).onTransitionFinished(active.mToken, active.mAborted);
         }
-        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
-                "Transition animation finished (abort=%b), notifying core %s", abort, transition);
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition animation finished "
+                + "(aborted=%b), notifying core %s", active.mAborted, active.mToken);
         if (active.mStartT != null) {
             // Applied by now, so clear immediately to remove any references. Do not set to null
             // yet, though, since nullness is used later to disambiguate malformed transitions.
             active.mStartT.clear();
         }
-        // Merge all relevant transactions together
+        // Merge all associated transactions together
         SurfaceControl.Transaction fullFinish = active.mFinishT;
-        for (int iA = activeIdx + 1; iA < mActiveTransitions.size(); ++iA) {
-            final ActiveTransition toMerge = mActiveTransitions.get(iA);
-            if (!toMerge.mMerged) break;
-            // Include start. It will be a no-op if it was already applied. Otherwise, we need it
-            // to maintain consistent state.
-            if (toMerge.mStartT != null) {
-                if (fullFinish == null) {
-                    fullFinish = toMerge.mStartT;
-                } else {
-                    fullFinish.merge(toMerge.mStartT);
+        if (active.mMerged != null) {
+            for (int iM = 0; iM < active.mMerged.size(); ++iM) {
+                final ActiveTransition toMerge = active.mMerged.get(iM);
+                // Include start. It will be a no-op if it was already applied. Otherwise, we need
+                // it to maintain consistent state.
+                if (toMerge.mStartT != null) {
+                    if (fullFinish == null) {
+                        fullFinish = toMerge.mStartT;
+                    } else {
+                        fullFinish.merge(toMerge.mStartT);
+                    }
                 }
-            }
-            if (toMerge.mFinishT != null) {
-                if (fullFinish == null) {
-                    fullFinish = toMerge.mFinishT;
-                } else {
-                    fullFinish.merge(toMerge.mFinishT);
+                if (toMerge.mFinishT != null) {
+                    if (fullFinish == null) {
+                        fullFinish = toMerge.mFinishT;
+                    } else {
+                        fullFinish.merge(toMerge.mFinishT);
+                    }
                 }
             }
         }
         if (fullFinish != null) {
             fullFinish.apply();
         }
-        // Now perform all the finishes.
+        // Now perform all the finish callbacks (starting with the playing one and then all the
+        // transitions merged into it).
         releaseSurfaces(active.mInfo);
-        mActiveTransitions.remove(activeIdx);
-        mOrganizer.finishTransition(transition, wct, wctCB);
-        while (activeIdx < mActiveTransitions.size()) {
-            if (!mActiveTransitions.get(activeIdx).mMerged) break;
-            ActiveTransition merged = mActiveTransitions.remove(activeIdx);
-            mOrganizer.finishTransition(merged.mToken, null /* wct */, null /* wctCB */);
-            releaseSurfaces(merged.mInfo);
-        }
-        // sift through aborted transitions
-        while (mActiveTransitions.size() > activeIdx
-                && mActiveTransitions.get(activeIdx).mAborted) {
-            ActiveTransition aborted = mActiveTransitions.remove(activeIdx);
-            // Notifies to clean-up the aborted transition.
-            if (aborted.mHandler != null) {
-                aborted.mHandler.onTransitionConsumed(
-                        transition, true /* aborted */, null /* finishTransaction */);
+        mOrganizer.finishTransition(active.mToken, wct, wctCB);
+        if (active.mMerged != null) {
+            for (int iM = 0; iM < active.mMerged.size(); ++iM) {
+                ActiveTransition merged = active.mMerged.get(iM);
+                mOrganizer.finishTransition(merged.mToken, null /* wct */, null /* wctCB */);
+                releaseSurfaces(merged.mInfo);
             }
-            mOrganizer.finishTransition(aborted.mToken, null /* wct */, null /* wctCB */);
-            for (int i = 0; i < mObservers.size(); ++i) {
-                mObservers.get(i).onTransitionFinished(aborted.mToken, true);
-            }
-            releaseSurfaces(aborted.mInfo);
-        }
-        if (mActiveTransitions.size() <= activeIdx) {
-            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "All active transition animations "
-                    + "finished");
-            // Run all runnables from the run-when-idle queue.
-            for (int i = 0; i < mRunWhenIdleQueue.size(); i++) {
-                mRunWhenIdleQueue.get(i).run();
-            }
-            mRunWhenIdleQueue.clear();
-            return;
-        }
-        // Start animating the next active transition
-        final ActiveTransition next = mActiveTransitions.get(activeIdx);
-        if (next.mInfo == null) {
-            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Pending transition after one"
-                    + " finished, but it isn't ready yet.");
-            return;
-        }
-        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Pending transitions after one"
-                + " finished, so start the next one.");
-        playTransition(next);
-        // Now try to merge the rest of the transitions (re-acquire activeIdx since next may have
-        // finished immediately)
-        activeIdx = findActiveTransition(next.mToken);
-        if (activeIdx < 0) {
-            // This means 'next' finished immediately and thus re-entered this function. Since
-            // that is the case, just return here since all relevant logic has already run in the
-            // re-entered call.
-            return;
+            active.mMerged.clear();
         }
 
-        // This logic is also convoluted because 'next' may finish immediately in response to any of
-        // the merge requests (eg. if it decided to "cancel" itself).
-        int mergeIdx = activeIdx + 1;
-        while (mergeIdx < mActiveTransitions.size()) {
-            ActiveTransition mergeCandidate = mActiveTransitions.get(mergeIdx);
-            if (mergeCandidate.mAborted) {
-                // transition was aborted, so we can skip for now (still leave it in the list
-                // so that it gets cleaned-up in the right order).
-                ++mergeIdx;
-                continue;
-            }
-            if (mergeCandidate.mMerged) {
-                throw new IllegalStateException("Can't merge a transition after not-merging"
-                        + " a preceding one.");
-            }
-            attemptMergeTransition(next, mergeCandidate);
-            mergeIdx = findActiveTransition(mergeCandidate.mToken);
-            if (mergeIdx < 0) {
-                // This means 'next' finished immediately and thus re-entered this function. Since
-                // that is the case, just return here since all relevant logic has already run in
-                // the re-entered call.
-                return;
-            }
-            ++mergeIdx;
+        // Now that this is done, check the ready queue for more work.
+        processReadyQueue();
+    }
+
+    private boolean isTransitionKnown(IBinder token) {
+        for (int i = 0; i < mPendingTransitions.size(); ++i) {
+            if (mPendingTransitions.get(i).mToken == token) return true;
         }
+        for (int i = 0; i < mReadyTransitions.size(); ++i) {
+            if (mReadyTransitions.get(i).mToken == token) return true;
+        }
+        for (int i = 0; i < mActiveTransitions.size(); ++i) {
+            final ActiveTransition active = mActiveTransitions.get(i);
+            if (active.mToken == token) return true;
+            if (active.mMerged == null) continue;
+            for (int m = 0; m < active.mMerged.size(); ++m) {
+                if (active.mMerged.get(m).mToken == token) return true;
+            }
+        }
+        return false;
     }
 
     void requestStartTransition(@NonNull IBinder transitionToken,
             @Nullable TransitionRequestInfo request) {
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition requested: %s %s",
                 transitionToken, request);
-        if (findActiveTransition(transitionToken) >= 0) {
+        if (isTransitionKnown(transitionToken)) {
             throw new RuntimeException("Transition already started " + transitionToken);
         }
         final ActiveTransition active = new ActiveTransition();
         WindowContainerTransaction wct = null;
-        for (int i = mHandlers.size() - 1; i >= 0; --i) {
-            wct = mHandlers.get(i).handleRequest(transitionToken, request);
-            if (wct != null) {
-                active.mHandler = mHandlers.get(i);
-                break;
-            }
-        }
-        if (request.getDisplayChange() != null) {
-            TransitionRequestInfo.DisplayChange change = request.getDisplayChange();
-            if (change.getEndRotation() != change.getStartRotation()) {
-                // Is a rotation, so dispatch to all displayChange listeners
-                if (wct == null) {
-                    wct = new WindowContainerTransaction();
+
+        // If we have sleep, we use a special handler and we try to finish everything ASAP.
+        if (request.getType() == TRANSIT_SLEEP) {
+            mSleepHandler.handleRequest(transitionToken, request);
+            active.mHandler = mSleepHandler;
+        } else {
+            for (int i = mHandlers.size() - 1; i >= 0; --i) {
+                wct = mHandlers.get(i).handleRequest(transitionToken, request);
+                if (wct != null) {
+                    active.mHandler = mHandlers.get(i);
+                    break;
                 }
-                mDisplayController.getChangeController().dispatchOnDisplayChange(wct,
-                        change.getDisplayId(), change.getStartRotation(), change.getEndRotation(),
-                        null /* newDisplayAreaInfo */);
+            }
+            if (request.getDisplayChange() != null) {
+                TransitionRequestInfo.DisplayChange change = request.getDisplayChange();
+                if (change.getEndRotation() != change.getStartRotation()) {
+                    // Is a rotation, so dispatch to all displayChange listeners
+                    if (wct == null) {
+                        wct = new WindowContainerTransaction();
+                    }
+                    mDisplayController.getChangeController().dispatchOnDisplayChange(wct,
+                            change.getDisplayId(), change.getStartRotation(),
+                            change.getEndRotation(), null /* newDisplayAreaInfo */);
+                }
             }
         }
         mOrganizer.startTransition(transitionToken, wct != null && wct.isEmpty() ? null : wct);
         active.mToken = transitionToken;
-        int insertIdx = 0;
-        for (; insertIdx < mActiveTransitions.size(); ++insertIdx) {
-            if (mActiveTransitions.get(insertIdx).mInfo == null) {
-                // A `startNewTransition` was sent to WMCore, but wasn't acknowledged before WMCore
-                // made this request, so insert this request beforehand to keep order in sync.
-                break;
-            }
-        }
-        mActiveTransitions.add(insertIdx, active);
+        // Currently, WMCore only does one transition at a time. If it makes a requestStart, it
+        // is already collecting that transition on core-side, so it will be the next one to
+        // become ready. There may already be pending transitions added as part of direct
+        // `startNewTransition` but if we have a request now, it means WM created the request
+        // transition before it acknowledged any of the pending `startNew` transitions. So, insert
+        // it at the front.
+        mPendingTransitions.add(0, active);
     }
 
     /** Start a new transition directly. */
@@ -835,11 +894,71 @@
         final ActiveTransition active = new ActiveTransition();
         active.mHandler = handler;
         active.mToken = mOrganizer.startNewTransition(type, wct);
-        mActiveTransitions.add(active);
+        mPendingTransitions.add(active);
         return active.mToken;
     }
 
     /**
+     * Finish running animations (almost) immediately when a SLEEP transition comes in. We use this
+     * as both a way to reduce unnecessary work (animations not visible while screen off) and as a
+     * failsafe to unblock "stuck" animations (in particular remote animations).
+     *
+     * This works by "merging" the sleep transition into the currently-playing transition (even if
+     * its out-of-order) -- turning SLEEP into a signal. If the playing transition doesn't finish
+     * within `SLEEP_ALLOWANCE_MS` from this merge attempt, this will then finish it directly (and
+     * send an abort/consumed message).
+     *
+     * This is then repeated until there are no more pending sleep transitions.
+     *
+     * @param forceFinish When non-null, this is the transition that we last sent the SLEEP merge
+     *                    signal to -- so it will be force-finished if it's still running.
+     */
+    private void finishForSleep(@Nullable ActiveTransition forceFinish) {
+        if ((mActiveTransitions.isEmpty() && mReadyTransitions.isEmpty())
+                || mSleepHandler.mSleepTransitions.isEmpty()) {
+            // Done finishing things.
+            // Prevent any weird leaks... shouldn't happen though.
+            mSleepHandler.mSleepTransitions.clear();
+            return;
+        }
+        if (forceFinish != null && mActiveTransitions.contains(forceFinish)) {
+            Log.e(TAG, "Forcing transition to finish due to sleep timeout: "
+                    + forceFinish.mToken);
+            forceFinish.mAborted = true;
+            // Last notify of it being consumed. Note: mHandler should never be null,
+            // but check just to be safe.
+            if (forceFinish.mHandler != null) {
+                forceFinish.mHandler.onTransitionConsumed(
+                        forceFinish.mToken, true /* aborted */, null /* finishTransaction */);
+            }
+            onFinish(forceFinish, null, null);
+        }
+        final SurfaceControl.Transaction dummyT = new SurfaceControl.Transaction();
+        while (!mActiveTransitions.isEmpty() && !mSleepHandler.mSleepTransitions.isEmpty()) {
+            final ActiveTransition playing = mActiveTransitions.get(0);
+            int sleepIdx = findByToken(mReadyTransitions, mSleepHandler.mSleepTransitions.get(0));
+            if (sleepIdx >= 0) {
+                // Try to signal that we are sleeping by attempting to merge the sleep transition
+                // into the playing one.
+                final ActiveTransition nextSleep = mReadyTransitions.get(sleepIdx);
+                playing.mHandler.mergeAnimation(nextSleep.mToken, nextSleep.mInfo, dummyT,
+                        playing.mToken, (wct, cb) -> {});
+            } else {
+                Log.e(TAG, "Couldn't find sleep transition in ready list: "
+                        + mSleepHandler.mSleepTransitions.get(0));
+            }
+            // it's possible to complete immediately. If that happens, just repeat the signal
+            // loop until we either finish everything or start playing an animation that isn't
+            // finishing immediately.
+            if (!mActiveTransitions.isEmpty() && mActiveTransitions.get(0) == playing) {
+                // Give it a (very) short amount of time to process it before forcing.
+                mMainExecutor.executeDelayed(() -> finishForSleep(playing), SLEEP_ALLOWANCE_MS);
+                break;
+            }
+        }
+    }
+
+    /**
      * Interface for a callback that must be called after a TransitionHandler finishes playing an
      * animation.
      */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java
index 145f759..7595c96 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java
@@ -16,18 +16,40 @@
 
 package com.android.wm.shell.util;
 
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static android.view.RemoteAnimationTarget.MODE_CHANGING;
+import static android.view.RemoteAnimationTarget.MODE_CLOSING;
+import static android.view.RemoteAnimationTarget.MODE_OPENING;
+import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
+import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
 import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
 import static android.view.WindowManager.TRANSIT_OPEN;
 import static android.view.WindowManager.TRANSIT_TO_BACK;
 import static android.view.WindowManager.TRANSIT_TO_FRONT;
+import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY;
 import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
+import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
+import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
+
+import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.app.ActivityManager;
+import android.app.WindowConfiguration;
+import android.graphics.Rect;
+import android.util.ArrayMap;
+import android.util.SparseBooleanArray;
+import android.view.RemoteAnimationTarget;
+import android.view.SurfaceControl;
 import android.view.WindowManager;
 import android.window.TransitionInfo;
 
+import java.util.function.Predicate;
+
 /** Various utility functions for transitions. */
 public class TransitionUtil {
 
@@ -54,4 +76,205 @@
         return false;
     }
 
+    /** Returns `true` if `change` is a wallpaper. */
+    public static boolean isWallpaper(TransitionInfo.Change change) {
+        return (change.getTaskInfo() == null)
+                && change.hasFlags(FLAG_IS_WALLPAPER)
+                && !change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY);
+    }
+
+    /** Returns `true` if `change` is not an app window or wallpaper. */
+    public static boolean isNonApp(TransitionInfo.Change change) {
+        return (change.getTaskInfo() == null)
+                && !change.hasFlags(FLAG_IS_WALLPAPER)
+                && !change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY);
+    }
+
+    /**
+     * Filter that selects leaf-tasks only. THIS IS ORDER-DEPENDENT! For it to work properly, you
+     * MUST call `test` in the same order that the changes appear in the TransitionInfo.
+     */
+    public static class LeafTaskFilter implements Predicate<TransitionInfo.Change> {
+        private final SparseBooleanArray mChildTaskTargets = new SparseBooleanArray();
+
+        @Override
+        public boolean test(TransitionInfo.Change change) {
+            final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
+            // Children always come before parent since changes are in top-to-bottom z-order.
+            if ((taskInfo == null) || mChildTaskTargets.get(taskInfo.taskId)) {
+                // has children, so not a leaf. Skip.
+                return false;
+            }
+            if (taskInfo.hasParentTask()) {
+                mChildTaskTargets.put(taskInfo.parentTaskId, true);
+            }
+            return true;
+        }
+    }
+
+
+    private static int newModeToLegacyMode(int newMode) {
+        switch (newMode) {
+            case WindowManager.TRANSIT_OPEN:
+            case WindowManager.TRANSIT_TO_FRONT:
+                return MODE_OPENING;
+            case WindowManager.TRANSIT_CLOSE:
+            case WindowManager.TRANSIT_TO_BACK:
+                return MODE_CLOSING;
+            default:
+                return MODE_CHANGING;
+        }
+    }
+
+    /**
+     * Very similar to Transitions#setupAnimHierarchy but specialized for leashes.
+     */
+    @SuppressLint("NewApi")
+    private static void setupLeash(@NonNull SurfaceControl leash,
+            @NonNull TransitionInfo.Change change, int layer,
+            @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t) {
+        final boolean isOpening = TransitionUtil.isOpeningType(info.getType());
+        // Put animating stuff above this line and put static stuff below it.
+        int zSplitLine = info.getChanges().size();
+        // changes should be ordered top-to-bottom in z
+        final int mode = change.getMode();
+
+        final int rootIdx = TransitionUtil.rootIndexFor(change, info);
+        t.reparent(leash, info.getRoot(rootIdx).getLeash());
+        final Rect absBounds =
+                (mode == TRANSIT_OPEN) ? change.getEndAbsBounds() : change.getStartAbsBounds();
+        t.setPosition(leash, absBounds.left - info.getRoot(rootIdx).getOffset().x,
+                absBounds.top - info.getRoot(rootIdx).getOffset().y);
+
+        // Put all the OPEN/SHOW on top
+        if (TransitionUtil.isOpeningType(mode)) {
+            if (isOpening) {
+                t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
+                if ((change.getFlags() & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) == 0) {
+                    // if transferred, it should be left visible.
+                    t.setAlpha(leash, 0.f);
+                }
+            } else {
+                // put on bottom and leave it visible
+                t.setLayer(leash, zSplitLine - layer);
+            }
+        } else if (TransitionUtil.isClosingType(mode)) {
+            if (isOpening) {
+                // put on bottom and leave visible
+                t.setLayer(leash, zSplitLine - layer);
+            } else {
+                // put on top
+                t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
+            }
+        } else { // CHANGE
+            t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
+        }
+    }
+
+    @SuppressLint("NewApi")
+    private static SurfaceControl createLeash(TransitionInfo info, TransitionInfo.Change change,
+            int order, SurfaceControl.Transaction t) {
+        // TODO: once we can properly sync transactions across process, then get rid of this leash.
+        if (change.getParent() != null && (change.getFlags() & FLAG_IS_WALLPAPER) != 0) {
+            // Special case for wallpaper atm. Normally these are left alone; but, a quirk of
+            // making leashes means we have to handle them specially.
+            return change.getLeash();
+        }
+        final int rootIdx = TransitionUtil.rootIndexFor(change, info);
+        SurfaceControl leashSurface = new SurfaceControl.Builder()
+                .setName(change.getLeash().toString() + "_transition-leash")
+                .setContainerLayer()
+                // Initial the surface visible to respect the visibility of the original surface.
+                .setHidden(false)
+                .setParent(info.getRoot(rootIdx).getLeash())
+                .build();
+        // Copied Transitions setup code (which expects bottom-to-top order, so we swap here)
+        setupLeash(leashSurface, change, info.getChanges().size() - order, info, t);
+        t.reparent(change.getLeash(), leashSurface);
+        t.setAlpha(change.getLeash(), 1.0f);
+        t.show(change.getLeash());
+        t.setPosition(change.getLeash(), 0, 0);
+        t.setLayer(change.getLeash(), 0);
+        return leashSurface;
+    }
+
+    /**
+     * Creates a new RemoteAnimationTarget from the provided change info
+     */
+    public static RemoteAnimationTarget newTarget(TransitionInfo.Change change, int order,
+            TransitionInfo info, SurfaceControl.Transaction t,
+            @Nullable ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
+        final SurfaceControl leash = createLeash(info, change, order, t);
+        if (leashMap != null) {
+            leashMap.put(change.getLeash(), leash);
+        }
+        return newTarget(change, order, leash);
+    }
+
+    /**
+     * Creates a new RemoteAnimationTarget from the provided change and leash
+     */
+    public static RemoteAnimationTarget newTarget(TransitionInfo.Change change, int order,
+            SurfaceControl leash) {
+        int taskId;
+        boolean isNotInRecents;
+        ActivityManager.RunningTaskInfo taskInfo;
+        WindowConfiguration windowConfiguration;
+
+        taskInfo = change.getTaskInfo();
+        if (taskInfo != null) {
+            taskId = taskInfo.taskId;
+            isNotInRecents = !taskInfo.isRunning;
+            windowConfiguration = taskInfo.configuration.windowConfiguration;
+        } else {
+            taskId = INVALID_TASK_ID;
+            isNotInRecents = true;
+            windowConfiguration = new WindowConfiguration();
+        }
+
+        Rect localBounds = new Rect(change.getEndAbsBounds());
+        localBounds.offsetTo(change.getEndRelOffset().x, change.getEndRelOffset().y);
+
+        RemoteAnimationTarget target = new RemoteAnimationTarget(
+                taskId,
+                newModeToLegacyMode(change.getMode()),
+                // TODO: once we can properly sync transactions across process,
+                // then get rid of this leash.
+                leash,
+                (change.getFlags() & TransitionInfo.FLAG_TRANSLUCENT) != 0,
+                null,
+                // TODO(shell-transitions): we need to send content insets? evaluate how its used.
+                new Rect(0, 0, 0, 0),
+                order,
+                null,
+                localBounds,
+                new Rect(change.getEndAbsBounds()),
+                windowConfiguration,
+                isNotInRecents,
+                null,
+                new Rect(change.getStartAbsBounds()),
+                taskInfo,
+                change.getAllowEnterPip(),
+                (change.getFlags() & FLAG_IS_DIVIDER_BAR) != 0
+                        ? TYPE_DOCK_DIVIDER : INVALID_WINDOW_TYPE
+        );
+        target.setWillShowImeOnTarget(
+                (change.getFlags() & TransitionInfo.FLAG_WILL_IME_SHOWN) != 0);
+        target.setRotationChange(change.getEndRotation() - change.getStartRotation());
+        return target;
+    }
+
+    /**
+     * Finds the "correct" root idx for a change. The change's end display is prioritized, then
+     * the start display. If there is no display, it will fallback on the 0th root in the
+     * transition. There MUST be at-least 1 root in the transition (ie. it's not a no-op).
+     */
+    public static int rootIndexFor(@NonNull TransitionInfo.Change change,
+            @NonNull TransitionInfo info) {
+        int rootIdx = info.findRootIndex(change.getEndDisplayId());
+        if (rootIdx >= 0) return rootIdx;
+        rootIdx = info.findRootIndex(change.getStartDisplayId());
+        if (rootIdx >= 0) return rootIdx;
+        return 0;
+    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
index 9224b3c..6b7ca42 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
@@ -193,6 +193,7 @@
         private final DragDetector mDragDetector;
 
         private int mDragPointerId = -1;
+        private boolean mIsDragging;
 
         private CaptionTouchEventListener(
                 RunningTaskInfo taskInfo,
@@ -223,19 +224,15 @@
             if (v.getId() != R.id.caption) {
                 return false;
             }
-            mDragDetector.onMotionEvent(e);
-
-            if (e.getAction() != MotionEvent.ACTION_DOWN) {
-                return false;
+            if (e.getAction() == MotionEvent.ACTION_DOWN) {
+                final RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
+                if (!taskInfo.isFocused) {
+                    final WindowContainerTransaction wct = new WindowContainerTransaction();
+                    wct.reorder(mTaskToken, true /* onTop */);
+                    mSyncQueue.queue(wct);
+                }
             }
-            final RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
-            if (taskInfo.isFocused) {
-                return false;
-            }
-            final WindowContainerTransaction wct = new WindowContainerTransaction();
-            wct.reorder(mTaskToken, true /* onTop */);
-            mSyncQueue.queue(wct);
-            return true;
+            return mDragDetector.onMotionEvent(e);
         }
 
         /**
@@ -253,20 +250,24 @@
                     mDragPointerId = e.getPointerId(0);
                     mDragPositioningCallback.onDragPositioningStart(
                             0 /* ctrlType */, e.getRawX(0), e.getRawY(0));
-                    break;
+                    mIsDragging = false;
+                    return false;
                 }
                 case MotionEvent.ACTION_MOVE: {
                     int dragPointerIdx = e.findPointerIndex(mDragPointerId);
                     mDragPositioningCallback.onDragPositioningMove(
                             e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx));
-                    break;
+                    mIsDragging = true;
+                    return true;
                 }
                 case MotionEvent.ACTION_UP:
                 case MotionEvent.ACTION_CANCEL: {
                     int dragPointerIdx = e.findPointerIndex(mDragPointerId);
                     mDragPositioningCallback.onDragPositioningEnd(
                             e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx));
-                    break;
+                    final boolean wasDragging = mIsDragging;
+                    mIsDragging = false;
+                    return wasDragging;
                 }
             }
             return true;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index 766c4cd..6b45149 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -20,10 +20,14 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 
+import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
+
 import android.app.ActivityManager;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.ActivityTaskManager;
 import android.content.Context;
+import android.graphics.Rect;
 import android.hardware.input.InputManager;
 import android.os.Handler;
 import android.os.Looper;
@@ -37,7 +41,6 @@
 import android.view.SurfaceControl;
 import android.view.View;
 import android.window.WindowContainerToken;
-import android.window.WindowContainerTransaction;
 
 import androidx.annotation.Nullable;
 
@@ -50,6 +53,7 @@
 import com.android.wm.shell.desktopmode.DesktopModeStatus;
 import com.android.wm.shell.desktopmode.DesktopTasksController;
 import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
+import com.android.wm.shell.splitscreen.SplitScreenController;
 
 import java.util.Optional;
 
@@ -80,6 +84,8 @@
     private final InputMonitorFactory mInputMonitorFactory;
     private TaskOperations mTaskOperations;
 
+    private Optional<SplitScreenController> mSplitScreenController;
+
     public DesktopModeWindowDecorViewModel(
             Context context,
             Handler mainHandler,
@@ -88,7 +94,8 @@
             DisplayController displayController,
             SyncTransactionQueue syncQueue,
             Optional<DesktopModeController> desktopModeController,
-            Optional<DesktopTasksController> desktopTasksController) {
+            Optional<DesktopTasksController> desktopTasksController,
+            Optional<SplitScreenController> splitScreenController) {
         this(
                 context,
                 mainHandler,
@@ -98,6 +105,7 @@
                 syncQueue,
                 desktopModeController,
                 desktopTasksController,
+                splitScreenController,
                 new DesktopModeWindowDecoration.Factory(),
                 new InputMonitorFactory());
     }
@@ -112,6 +120,7 @@
             SyncTransactionQueue syncQueue,
             Optional<DesktopModeController> desktopModeController,
             Optional<DesktopTasksController> desktopTasksController,
+            Optional<SplitScreenController> splitScreenController,
             DesktopModeWindowDecoration.Factory desktopModeWindowDecorFactory,
             InputMonitorFactory inputMonitorFactory) {
         mContext = context;
@@ -120,6 +129,7 @@
         mActivityTaskManager = mContext.getSystemService(ActivityTaskManager.class);
         mTaskOrganizer = taskOrganizer;
         mDisplayController = displayController;
+        mSplitScreenController = splitScreenController;
         mSyncQueue = syncQueue;
         mDesktopModeController = desktopModeController;
         mDesktopTasksController = desktopTasksController;
@@ -213,6 +223,7 @@
         private final DragPositioningCallback mDragPositioningCallback;
         private final DragDetector mDragDetector;
 
+        private boolean mIsDragging;
         private int mDragPointerId = -1;
 
         private DesktopModeTouchEventListener(
@@ -230,6 +241,15 @@
             final int id = v.getId();
             if (id == R.id.close_window || id == R.id.close_button) {
                 mTaskOperations.closeTask(mTaskToken);
+                if (mSplitScreenController.isPresent()
+                        && mSplitScreenController.get().isSplitScreenVisible()) {
+                    int remainingTaskPosition = mTaskId == mSplitScreenController.get()
+                            .getTaskInfo(SPLIT_POSITION_TOP_OR_LEFT).taskId
+                            ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT;
+                    ActivityManager.RunningTaskInfo remainingTask = mSplitScreenController.get()
+                            .getTaskInfo(remainingTaskPosition);
+                    mSplitScreenController.get().moveTaskToFullscreen(remainingTask.taskId);
+                }
             } else if (id == R.id.back_button) {
                 mTaskOperations.injectBackKey();
             } else if (id == R.id.caption_handle) {
@@ -254,26 +274,7 @@
             if (id != R.id.caption_handle && id != R.id.desktop_mode_caption) {
                 return false;
             }
-            switch (e.getAction()) {
-                case MotionEvent.ACTION_DOWN:
-                    mDragDetector.onMotionEvent(e);
-                    final RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
-                    if (taskInfo.isFocused) {
-                        return mDragDetector.isDragEvent();
-                    }
-                    final WindowContainerTransaction wct = new WindowContainerTransaction();
-                    wct.reorder(mTaskToken, true /* onTop */);
-                    mSyncQueue.queue(wct);
-                    return false;
-                case MotionEvent.ACTION_UP:
-                case MotionEvent.ACTION_CANCEL:
-                    boolean res = mDragDetector.isDragEvent();
-                    mDragDetector.onMotionEvent(e);
-                    return res;
-                default:
-                    mDragDetector.onMotionEvent(e);
-                    return mDragDetector.isDragEvent();
-            }
+            return mDragDetector.onMotionEvent(e);
         }
 
         /**
@@ -297,13 +298,15 @@
                     mDragPointerId = e.getPointerId(0);
                     mDragPositioningCallback.onDragPositioningStart(
                             0 /* ctrlType */, e.getRawX(0), e.getRawY(0));
-                    break;
+                    mIsDragging = false;
+                    return false;
                 }
                 case MotionEvent.ACTION_MOVE: {
                     final int dragPointerIdx = e.findPointerIndex(mDragPointerId);
                     mDragPositioningCallback.onDragPositioningMove(
                             e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx));
-                    break;
+                    mIsDragging = true;
+                    return true;
                 }
                 case MotionEvent.ACTION_UP:
                 case MotionEvent.ACTION_CANCEL: {
@@ -320,7 +323,9 @@
                                     c -> c.moveToFullscreen(taskInfo));
                         }
                     }
-                    break;
+                    final boolean wasDragging = mIsDragging;
+                    mIsDragging = false;
+                    return wasDragging;
                 }
             }
             return true;
@@ -401,14 +406,14 @@
      * @param ev the {@link MotionEvent} received by {@link EventReceiver}
      */
     private void handleReceivedMotionEvent(MotionEvent ev, InputMonitor inputMonitor) {
+        final DesktopModeWindowDecoration relevantDecor = getRelevantWindowDecor(ev);
         if (DesktopModeStatus.isProto2Enabled()) {
-            final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
-            if (focusedDecor == null
-                    || focusedDecor.mTaskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
-                handleCaptionThroughStatusBar(ev);
+            if (relevantDecor == null
+                    || relevantDecor.mTaskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
+                handleCaptionThroughStatusBar(ev, relevantDecor);
             }
         }
-        handleEventOutsideFocusedCaption(ev);
+        handleEventOutsideFocusedCaption(ev, relevantDecor);
         // Prevent status bar from reacting to a caption drag.
         if (DesktopModeStatus.isProto2Enabled()) {
             if (mTransitionDragActive) {
@@ -422,16 +427,16 @@
     }
 
     // If an UP/CANCEL action is received outside of caption bounds, turn off handle menu
-    private void handleEventOutsideFocusedCaption(MotionEvent ev) {
+    private void handleEventOutsideFocusedCaption(MotionEvent ev,
+            DesktopModeWindowDecoration relevantDecor) {
         final int action = ev.getActionMasked();
         if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
-            final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
-            if (focusedDecor == null) {
+            if (relevantDecor == null) {
                 return;
             }
 
             if (!mTransitionDragActive) {
-                focusedDecor.closeHandleMenuIfNeeded(ev);
+                relevantDecor.closeHandleMenuIfNeeded(ev);
             }
         }
     }
@@ -441,39 +446,38 @@
      * Perform caption actions if not able to through normal means.
      * Turn on desktop mode if handle is dragged below status bar.
      */
-    private void handleCaptionThroughStatusBar(MotionEvent ev) {
+    private void handleCaptionThroughStatusBar(MotionEvent ev,
+            DesktopModeWindowDecoration relevantDecor) {
         switch (ev.getActionMasked()) {
             case MotionEvent.ACTION_DOWN: {
                 // Begin drag through status bar if applicable.
-                final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
-                if (focusedDecor != null) {
+                if (relevantDecor != null) {
                     boolean dragFromStatusBarAllowed = false;
                     if (DesktopModeStatus.isProto2Enabled()) {
                         // In proto2 any full screen task can be dragged to freeform
-                        dragFromStatusBarAllowed = focusedDecor.mTaskInfo.getWindowingMode()
+                        dragFromStatusBarAllowed = relevantDecor.mTaskInfo.getWindowingMode()
                                 == WINDOWING_MODE_FULLSCREEN;
                     }
 
-                    if (dragFromStatusBarAllowed && focusedDecor.checkTouchEventInHandle(ev)) {
+                    if (dragFromStatusBarAllowed && relevantDecor.checkTouchEventInHandle(ev)) {
                         mTransitionDragActive = true;
                     }
                 }
                 break;
             }
             case MotionEvent.ACTION_UP: {
-                final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
-                if (focusedDecor == null) {
+                if (relevantDecor == null) {
                     mTransitionDragActive = false;
                     return;
                 }
                 if (mTransitionDragActive) {
                     mTransitionDragActive = false;
                     final int statusBarHeight = mDisplayController
-                            .getDisplayLayout(focusedDecor.mTaskInfo.displayId).stableInsets().top;
+                            .getDisplayLayout(relevantDecor.mTaskInfo.displayId).stableInsets().top;
                     if (ev.getY() > statusBarHeight) {
                         if (DesktopModeStatus.isProto2Enabled()) {
                             mDesktopTasksController.ifPresent(
-                                    c -> c.moveToDesktop(focusedDecor.mTaskInfo));
+                                    c -> c.moveToDesktop(relevantDecor.mTaskInfo));
                         } else if (DesktopModeStatus.isProto1Enabled()) {
                             mDesktopModeController.ifPresent(c -> c.setDesktopModeActive(true));
                         }
@@ -481,7 +485,7 @@
                         return;
                     }
                 }
-                focusedDecor.checkClickEvent(ev);
+                relevantDecor.checkClickEvent(ev);
                 break;
             }
             case MotionEvent.ACTION_CANCEL: {
@@ -491,6 +495,38 @@
     }
 
     @Nullable
+    private DesktopModeWindowDecoration getRelevantWindowDecor(MotionEvent ev) {
+        if (mSplitScreenController.isPresent()
+                && mSplitScreenController.get().isSplitScreenVisible()) {
+            // We can't look at focused task here as only one task will have focus.
+            return getSplitScreenDecor(ev);
+        } else {
+            return getFocusedDecor();
+        }
+    }
+
+    @Nullable
+    private DesktopModeWindowDecoration getSplitScreenDecor(MotionEvent ev) {
+        ActivityManager.RunningTaskInfo topOrLeftTask =
+                mSplitScreenController.get().getTaskInfo(SPLIT_POSITION_TOP_OR_LEFT);
+        ActivityManager.RunningTaskInfo bottomOrRightTask =
+                mSplitScreenController.get().getTaskInfo(SPLIT_POSITION_BOTTOM_OR_RIGHT);
+        if (topOrLeftTask != null && topOrLeftTask.getConfiguration()
+                .windowConfiguration.getBounds().contains((int) ev.getX(), (int) ev.getY())) {
+            return mWindowDecorByTaskId.get(topOrLeftTask.taskId);
+        } else if (bottomOrRightTask != null && bottomOrRightTask.getConfiguration()
+                .windowConfiguration.getBounds().contains((int) ev.getX(), (int) ev.getY())) {
+            Rect bottomOrRightBounds = bottomOrRightTask.getConfiguration().windowConfiguration
+                    .getBounds();
+            ev.offsetLocation(-bottomOrRightBounds.left, -bottomOrRightBounds.top);
+            return mWindowDecorByTaskId.get(bottomOrRightTask.taskId);
+        } else {
+            return null;
+        }
+
+    }
+
+    @Nullable
     private DesktopModeWindowDecoration getFocusedDecor() {
         final int size = mWindowDecorByTaskId.size();
         DesktopModeWindowDecoration focusedDecor = null;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 0779f1d..72da108 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -74,6 +74,8 @@
     private boolean mDesktopActive;
     private AdditionalWindow mHandleMenu;
     private final int mHandleMenuWidthId = R.dimen.freeform_decor_caption_menu_width;
+    private final int mHandleMenuShadowRadiusId = R.dimen.caption_menu_shadow_radius;
+    private final int mHandleMenuCornerRadiusId = R.dimen.caption_menu_corner_radius;
     private PointF mHandleMenuPosition = new PointF();
 
     DesktopModeWindowDecoration(
@@ -353,19 +355,16 @@
                 .windowConfiguration.getBounds().width();
         final int menuWidth = loadDimensionPixelSize(resources, mHandleMenuWidthId);
         final int menuHeight = loadDimensionPixelSize(resources, mCaptionMenuHeightId);
-
-        // Elevation gives the appearance of a changed x/y coordinate; this is to fix that
-        int elevationOffset = 2 * loadDimensionPixelSize(resources,
-                R.dimen.caption_menu_elevation);
+        final int shadowRadius = loadDimensionPixelSize(resources, mHandleMenuShadowRadiusId);
+        final int cornerRadius = loadDimensionPixelSize(resources, mHandleMenuCornerRadiusId);
 
         final int x = mRelayoutParams.mCaptionX + (captionWidth / 2) - (menuWidth / 2)
-                - mResult.mDecorContainerOffsetX - elevationOffset;
-        final int y =
-                mRelayoutParams.mCaptionY - mResult.mDecorContainerOffsetY - elevationOffset;
+                - mResult.mDecorContainerOffsetX;
+        final int y = mRelayoutParams.mCaptionY - mResult.mDecorContainerOffsetY;
         mHandleMenuPosition.set(x, y);
         String namePrefix = "Caption Menu";
         mHandleMenu = addWindow(R.layout.desktop_mode_decor_handle_menu, namePrefix, t, x, y,
-                menuWidth, menuHeight, 2 * elevationOffset);
+                menuWidth, menuHeight, shadowRadius, cornerRadius);
         mSyncQueue.runInSync(transaction -> {
             transaction.merge(t);
             t.close();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java
index cf1850b..65b5a7a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java
@@ -56,10 +56,15 @@
      * {@link #mEventHandler} handles the previous down event if the event shouldn't be passed
     */
     boolean onMotionEvent(MotionEvent ev) {
+        final boolean isTouchScreen =
+                (ev.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN;
+        if (!isTouchScreen) {
+            // Only touches generate noisy moves, so mouse/trackpad events don't need to filtered
+            // to take the slop threshold into consideration.
+            return mEventHandler.handleMotionEvent(ev);
+        }
         switch (ev.getActionMasked()) {
             case ACTION_DOWN: {
-                // Only touch screens generate noisy moves.
-                mIsDragEvent = (ev.getSource() & SOURCE_TOUCHSCREEN) != SOURCE_TOUCHSCREEN;
                 mDragPointerId = ev.getPointerId(0);
                 float rawX = ev.getRawX(0);
                 float rawY = ev.getRawY(0);
@@ -72,8 +77,12 @@
                     int dragPointerIndex = ev.findPointerIndex(mDragPointerId);
                     float dx = ev.getRawX(dragPointerIndex) - mInputDownPoint.x;
                     float dy = ev.getRawY(dragPointerIndex) - mInputDownPoint.y;
+                    // Touches generate noisy moves, so only once the move is past the touch
+                    // slop threshold should it be considered a drag.
                     mIsDragEvent = Math.hypot(dx, dy) > mTouchSlop;
                 }
+                // The event handler should only be notified about 'move' events if a drag has been
+                // detected.
                 if (mIsDragEvent) {
                     return mEventHandler.handleMotionEvent(ev);
                 } else {
@@ -94,10 +103,6 @@
         mTouchSlop = touchSlop;
     }
 
-    boolean isDragEvent() {
-        return mIsDragEvent;
-    }
-
     private void resetState() {
         mIsDragEvent = false;
         mInputDownPoint.set(0, 0);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/OWNERS
new file mode 100644
index 0000000..4417209
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/OWNERS
@@ -0,0 +1 @@
+jorgegil@google.com
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java
index a3d364a..0bce3ac 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java
@@ -40,6 +40,7 @@
     private final DisplayController mDisplayController;
     private final WindowDecoration mWindowDecoration;
 
+    private final Rect mTempBounds = new Rect();
     private final Rect mTaskBoundsAtDragStart = new Rect();
     private final PointF mRepositionStartPoint = new PointF();
     private final Rect mRepositionTaskBounds = new Rect();
@@ -117,17 +118,32 @@
         final float deltaX = x - mRepositionStartPoint.x;
         final float deltaY = y - mRepositionStartPoint.y;
         mRepositionTaskBounds.set(mTaskBoundsAtDragStart);
+
+        final Rect stableBounds = mTempBounds;
+        // Make sure the new resizing destination in any direction falls within the stable bounds.
+        // If not, set the bounds back to the old location that was valid to avoid conflicts with
+        // some regions such as the gesture area.
+        mDisplayController.getDisplayLayout(mWindowDecoration.mDisplay.getDisplayId())
+                .getStableBounds(stableBounds);
         if ((mCtrlType & CTRL_TYPE_LEFT) != 0) {
-            mRepositionTaskBounds.left += deltaX;
+            final int candidateLeft = mRepositionTaskBounds.left + (int) deltaX;
+            mRepositionTaskBounds.left = (candidateLeft > stableBounds.left)
+                    ? candidateLeft : oldLeft;
         }
         if ((mCtrlType & CTRL_TYPE_RIGHT) != 0) {
-            mRepositionTaskBounds.right += deltaX;
+            final int candidateRight = mRepositionTaskBounds.right + (int) deltaX;
+            mRepositionTaskBounds.right = (candidateRight < stableBounds.right)
+                    ? candidateRight : oldRight;
         }
         if ((mCtrlType & CTRL_TYPE_TOP) != 0) {
-            mRepositionTaskBounds.top += deltaY;
+            final int candidateTop = mRepositionTaskBounds.top + (int) deltaY;
+            mRepositionTaskBounds.top = (candidateTop > stableBounds.top)
+                    ? candidateTop : oldTop;
         }
         if ((mCtrlType & CTRL_TYPE_BOTTOM) != 0) {
-            mRepositionTaskBounds.bottom += deltaY;
+            final int candidateBottom = mRepositionTaskBounds.bottom + (int) deltaY;
+            mRepositionTaskBounds.bottom = (candidateBottom < stableBounds.bottom)
+                    ? candidateBottom : oldBottom;
         }
         if (mCtrlType == CTRL_TYPE_UNDEFINED) {
             mRepositionTaskBounds.offset((int) deltaX, (int) deltaY);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index 91b0aa1..7a7ac47 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -391,11 +391,12 @@
      * @param yPos y position of new window
      * @param width width of new window
      * @param height height of new window
-     * @param cropPadding padding to add to window crop to ensure shadows display properly
-     * @return
+     * @param shadowRadius radius of the shadow of the new window
+     * @param cornerRadius radius of the corners of the new window
+     * @return the {@link AdditionalWindow} that was added.
      */
     AdditionalWindow addWindow(int layoutId, String namePrefix, SurfaceControl.Transaction t,
-            int xPos, int yPos, int width, int height, int cropPadding) {
+            int xPos, int yPos, int width, int height, int shadowRadius, int cornerRadius) {
         final SurfaceControl.Builder builder = mSurfaceControlBuilderSupplier.get();
         SurfaceControl windowSurfaceControl = builder
                 .setName(namePrefix + " of Task=" + mTaskInfo.taskId)
@@ -404,9 +405,10 @@
                 .build();
         View v = LayoutInflater.from(mDecorWindowContext).inflate(layoutId, null);
 
-        t.setPosition(
-                windowSurfaceControl, xPos, yPos)
-                .setWindowCrop(windowSurfaceControl, width + cropPadding, height + cropPadding)
+        t.setPosition(windowSurfaceControl, xPos, yPos)
+                .setWindowCrop(windowSurfaceControl, width, height)
+                .setShadowRadius(windowSurfaceControl, shadowRadius)
+                .setCornerRadius(windowSurfaceControl, cornerRadius)
                 .show(windowSurfaceControl);
         final WindowManager.LayoutParams lp =
                 new WindowManager.LayoutParams(width, height,
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipDragThenSnapTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipDragThenSnapTest.kt
new file mode 100644
index 0000000..53ce393
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipDragThenSnapTest.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.wm.shell.flicker.pip
+
+import android.platform.test.annotations.Postsubmit
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.graphics.Rect
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.helpers.setRotation
+import com.android.server.wm.flicker.testapp.ActivityOptions
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test the snapping of a PIP window via dragging, releasing, and checking its final location.
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class PipDragThenSnapTest(flicker: FlickerTest) : PipTransition(flicker){
+    // represents the direction in which the pip window should be snapping
+    private var willSnapRight: Boolean = true
+
+    override val transition: FlickerBuilder.() -> Unit
+        get() = {
+            val stringExtras: Map<String, String> =
+                mapOf(ActivityOptions.Pip.EXTRA_ENTER_PIP to "true")
+
+            // cache the starting bounds here
+            val startBounds = Rect()
+
+            setup {
+                // Launch the PIP activity and wait for it to enter PiP mode
+                setRotation(Rotation.ROTATION_0)
+                RemoveAllTasksButHomeRule.removeAllTasksButHome()
+                pipApp.launchViaIntentAndWaitForPip(wmHelper, stringExtras = stringExtras)
+
+                // get the initial region bounds and cache them
+                val initRegion = pipApp.getWindowRect(wmHelper)
+                startBounds
+                        .set(initRegion.left, initRegion.top, initRegion.right, initRegion.bottom)
+
+                // drag the pip window away from the edge
+                pipApp.dragPipWindowAwayFromEdge(wmHelper, 50)
+
+                // determine the direction in which the snapping should occur
+                willSnapRight = pipApp.isCloserToRightEdge(wmHelper)
+            }
+            transitions {
+                // continue the transition until the PIP snaps
+                pipApp.waitForPipToSnapTo(wmHelper, startBounds)
+            }
+        }
+
+    /**
+     * Checks that the visible region area of [pipApp] moves to closest edge during the animation.
+     */
+    @Postsubmit
+    @Test
+    fun pipLayerMovesToClosestEdge() {
+        flicker.assertLayers {
+            val pipLayerList = layers { pipApp.layerMatchesAnyOf(it) && it.isVisible }
+            pipLayerList.zipWithNext { previous, current ->
+                if (willSnapRight) {
+                    current.visibleRegion.isToTheRight(previous.visibleRegion.region)
+                } else {
+                    previous.visibleRegion.isToTheRight(current.visibleRegion.region)
+                }
+            }
+        }
+    }
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): List<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests(
+                supportedRotations = listOf(Rotation.ROTATION_0)
+            )
+        }
+    }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromTaskbar.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromTaskbar.kt
index da80c6f..5c99209 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromTaskbar.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromTaskbar.kt
@@ -80,7 +80,8 @@
     @IwTest(focusArea = "sysui")
     @Presubmit
     @Test
-    fun cujCompleted() = flicker.splitScreenEntered(primaryApp, secondaryApp, fromOtherApp = false)
+    fun cujCompleted() = flicker.splitScreenEntered(primaryApp, secondaryApp, fromOtherApp = false,
+            appExistAtStart = false)
 
     @Presubmit
     @Test
diff --git a/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml b/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml
index fac0461..47a116b 100644
--- a/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml
@@ -20,6 +20,7 @@
     package="com.android.wm.shell.tests">
 
     <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
+    <uses-permission android:name="android.permission.VIBRATE"/>
 
     <application android:debuggable="true" android:largeHeap="true">
         <uses-library android:name="android.test.mock" />
diff --git a/libs/WindowManager/Shell/tests/unittest/res/values/dimen.xml b/libs/WindowManager/Shell/tests/unittest/res/values/dimen.xml
index 27d40b2..aa1b241 100644
--- a/libs/WindowManager/Shell/tests/unittest/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/tests/unittest/res/values/dimen.xml
@@ -24,4 +24,6 @@
     <dimen name="test_window_decor_bottom_outset">40dp</dimen>
     <dimen name="test_window_decor_shadow_radius">5dp</dimen>
     <dimen name="test_window_decor_resize_handle">10dp</dimen>
+    <dimen name="test_caption_menu_shadow_radius">4dp</dimen>
+    <dimen name="test_caption_menu_corner_radius">20dp</dimen>
 </resources>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TransitionInfoBuilder.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TransitionInfoBuilder.java
index 35c374d..26b787f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TransitionInfoBuilder.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TransitionInfoBuilder.java
@@ -30,6 +30,7 @@
  */
 public class TransitionInfoBuilder {
     final TransitionInfo mInfo;
+    static final int DISPLAY_ID = 0;
 
     public TransitionInfoBuilder(@WindowManager.TransitionType int type) {
         this(type, 0 /* flags */);
@@ -38,7 +39,7 @@
     public TransitionInfoBuilder(@WindowManager.TransitionType int type,
             @WindowManager.TransitionFlags int flags) {
         mInfo = new TransitionInfo(type, flags);
-        mInfo.setRootLeash(createMockSurface(true /* valid */), 0, 0);
+        mInfo.addRootLeash(DISPLAY_ID, createMockSurface(true /* valid */), 0, 0);
     }
 
     public TransitionInfoBuilder addChange(@WindowManager.TransitionType int mode,
@@ -61,6 +62,7 @@
     }
 
     public TransitionInfoBuilder addChange(TransitionInfo.Change change) {
+        change.setDisplayId(DISPLAY_ID, DISPLAY_ID);
         mInfo.addChange(change);
         return this;
     }
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 5a4a44f..6dae479 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
@@ -422,7 +422,7 @@
         RemoteAnimationTarget animationTarget = createAnimationTarget();
         RemoteAnimationTarget[] targets = new RemoteAnimationTarget[]{animationTarget};
         if (mController.mBackAnimationAdapter != null) {
-            mController.mBackAnimationAdapter.getRunner().onAnimationStart(type,
+            mController.mBackAnimationAdapter.getRunner().onAnimationStart(
                     targets, null, null, mBackAnimationFinishedCallback);
             mShellExecutor.flushAll();
         }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/CustomizeActivityAnimationTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/CustomizeActivityAnimationTest.java
new file mode 100644
index 0000000..2814ef9
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/CustomizeActivityAnimationTest.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.back;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.app.WindowConfiguration;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.RemoteException;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.Choreographer;
+import android.view.RemoteAnimationTarget;
+import android.view.SurfaceControl;
+import android.view.animation.Animation;
+import android.window.BackNavigationInfo;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.ShellTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@SmallTest
+@TestableLooper.RunWithLooper
+@RunWith(AndroidTestingRunner.class)
+public class CustomizeActivityAnimationTest extends ShellTestCase {
+    private static final int BOUND_SIZE = 100;
+    @Mock
+    private BackAnimationBackground mBackAnimationBackground;
+    @Mock
+    private Animation mMockCloseAnimation;
+    @Mock
+    private Animation mMockOpenAnimation;
+
+    private CustomizeActivityAnimation mCustomizeActivityAnimation;
+
+    @Before
+    public void setUp() throws Exception {
+        mCustomizeActivityAnimation = new CustomizeActivityAnimation(mContext,
+                mBackAnimationBackground, mock(SurfaceControl.Transaction.class),
+                mock(Choreographer.class));
+        spyOn(mCustomizeActivityAnimation);
+        spyOn(mCustomizeActivityAnimation.mCustomAnimationLoader);
+        doReturn(mMockCloseAnimation).when(mCustomizeActivityAnimation.mCustomAnimationLoader)
+                .load(any(), eq(false));
+        doReturn(mMockOpenAnimation).when(mCustomizeActivityAnimation.mCustomAnimationLoader)
+                .load(any(), eq(true));
+    }
+
+    RemoteAnimationTarget createAnimationTarget(boolean open) {
+        SurfaceControl topWindowLeash = new SurfaceControl();
+        return new RemoteAnimationTarget(1,
+                open ? RemoteAnimationTarget.MODE_OPENING : RemoteAnimationTarget.MODE_CLOSING,
+                topWindowLeash, false, new Rect(), new Rect(), -1,
+                new Point(0, 0), new Rect(0, 0, BOUND_SIZE, BOUND_SIZE), new Rect(),
+                new WindowConfiguration(), true, null, null, null, false, -1);
+    }
+
+    @Test
+    public void receiveFinishAfterInvoke() throws InterruptedException {
+        mCustomizeActivityAnimation.prepareNextAnimation(
+                new BackNavigationInfo.CustomAnimationInfo("TestPackage"));
+        final RemoteAnimationTarget close = createAnimationTarget(false);
+        final RemoteAnimationTarget open = createAnimationTarget(true);
+        // start animation with remote animation targets
+        final CountDownLatch finishCalled = new CountDownLatch(1);
+        final Runnable finishCallback = finishCalled::countDown;
+        mCustomizeActivityAnimation.mBackAnimationRunner.startAnimation(
+                new RemoteAnimationTarget[]{close, open}, null, null, finishCallback);
+        verify(mMockCloseAnimation).initialize(eq(BOUND_SIZE), eq(BOUND_SIZE),
+                eq(BOUND_SIZE), eq(BOUND_SIZE));
+        verify(mMockOpenAnimation).initialize(eq(BOUND_SIZE), eq(BOUND_SIZE),
+                eq(BOUND_SIZE), eq(BOUND_SIZE));
+
+        try {
+            mCustomizeActivityAnimation.mBackAnimationRunner.getCallback().onBackInvoked();
+        } catch (RemoteException r) {
+            fail("onBackInvoked throw remote exception");
+        }
+        verify(mCustomizeActivityAnimation).onGestureCommitted();
+        finishCalled.await(1, TimeUnit.SECONDS);
+    }
+
+    @Test
+    public void receiveFinishAfterCancel() throws InterruptedException {
+        mCustomizeActivityAnimation.prepareNextAnimation(
+                new BackNavigationInfo.CustomAnimationInfo("TestPackage"));
+        final RemoteAnimationTarget close = createAnimationTarget(false);
+        final RemoteAnimationTarget open = createAnimationTarget(true);
+        // start animation with remote animation targets
+        final CountDownLatch finishCalled = new CountDownLatch(1);
+        final Runnable finishCallback = finishCalled::countDown;
+        mCustomizeActivityAnimation.mBackAnimationRunner.startAnimation(
+                new RemoteAnimationTarget[]{close, open}, null, null, finishCallback);
+        verify(mMockCloseAnimation).initialize(eq(BOUND_SIZE), eq(BOUND_SIZE),
+                eq(BOUND_SIZE), eq(BOUND_SIZE));
+        verify(mMockOpenAnimation).initialize(eq(BOUND_SIZE), eq(BOUND_SIZE),
+                eq(BOUND_SIZE), eq(BOUND_SIZE));
+
+        try {
+            mCustomizeActivityAnimation.mBackAnimationRunner.getCallback().onBackCancelled();
+        } catch (RemoteException r) {
+            fail("onBackCancelled throw remote exception");
+        }
+        finishCalled.await(1, TimeUnit.SECONDS);
+    }
+
+    @Test
+    public void receiveFinishWithoutAnimationAfterInvoke() throws InterruptedException {
+        mCustomizeActivityAnimation.prepareNextAnimation(
+                new BackNavigationInfo.CustomAnimationInfo("TestPackage"));
+        // start animation without any remote animation targets
+        final CountDownLatch finishCalled = new CountDownLatch(1);
+        final Runnable finishCallback = finishCalled::countDown;
+        mCustomizeActivityAnimation.mBackAnimationRunner.startAnimation(
+                new RemoteAnimationTarget[]{}, null, null, finishCallback);
+
+        try {
+            mCustomizeActivityAnimation.mBackAnimationRunner.getCallback().onBackInvoked();
+        } catch (RemoteException r) {
+            fail("onBackInvoked throw remote exception");
+        }
+        verify(mCustomizeActivityAnimation).onGestureCommitted();
+        finishCalled.await(1, TimeUnit.SECONDS);
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TabletopModeControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TabletopModeControllerTest.java
new file mode 100644
index 0000000..96d202c
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TabletopModeControllerTest.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.common;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static com.android.wm.shell.common.DevicePostureController.DEVICE_POSTURE_CLOSED;
+import static com.android.wm.shell.common.DevicePostureController.DEVICE_POSTURE_HALF_OPENED;
+import static com.android.wm.shell.common.DevicePostureController.DEVICE_POSTURE_OPENED;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.Surface;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.ShellTestCase;
+import com.android.wm.shell.TestShellExecutor;
+import com.android.wm.shell.sysui.ShellInit;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for {@link TabletopModeController}.
+ */
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+@SmallTest
+public class TabletopModeControllerTest extends ShellTestCase {
+    // It's considered tabletop mode if the display rotation angle matches what's in this array.
+    // It's defined as com.android.internal.R.array.config_deviceTabletopRotations on real devices.
+    private static final int[] TABLETOP_MODE_ROTATIONS = new int[] {
+            90 /* Surface.ROTATION_90 */,
+            270 /* Surface.ROTATION_270 */
+    };
+
+    private TestShellExecutor mMainExecutor;
+
+    private Configuration mConfiguration;
+
+    private TabletopModeController mPipTabletopController;
+
+    @Mock
+    private Context mContext;
+
+    @Mock
+    private ShellInit mShellInit;
+
+    @Mock
+    private Resources mResources;
+
+    @Mock
+    private DevicePostureController mDevicePostureController;
+
+    @Mock
+    private DisplayController mDisplayController;
+
+    @Mock
+    private TabletopModeController.OnTabletopModeChangedListener mOnTabletopModeChangedListener;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mResources.getIntArray(com.android.internal.R.array.config_deviceTabletopRotations))
+                .thenReturn(TABLETOP_MODE_ROTATIONS);
+        when(mContext.getResources()).thenReturn(mResources);
+        mMainExecutor = new TestShellExecutor();
+        mConfiguration = new Configuration();
+        mPipTabletopController = new TabletopModeController(mContext, mShellInit,
+                mDevicePostureController, mDisplayController, mMainExecutor);
+        mPipTabletopController.onInit();
+    }
+
+    @Test
+    public void instantiateController_addInitCallback() {
+        verify(mShellInit, times(1)).addInitCallback(any(), eq(mPipTabletopController));
+    }
+
+    @Test
+    public void registerOnTabletopModeChangedListener_notInTabletopMode_callbackFalse() {
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
+        mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_0);
+        mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+        mPipTabletopController.registerOnTabletopModeChangedListener(
+                mOnTabletopModeChangedListener);
+
+        verify(mOnTabletopModeChangedListener, times(1))
+                .onTabletopModeChanged(false);
+    }
+
+    @Test
+    public void registerOnTabletopModeChangedListener_inTabletopMode_callbackTrue() {
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
+        mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
+        mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+        mPipTabletopController.registerOnTabletopModeChangedListener(
+                mOnTabletopModeChangedListener);
+
+        verify(mOnTabletopModeChangedListener, times(1))
+                .onTabletopModeChanged(true);
+    }
+
+    @Test
+    public void registerOnTabletopModeChangedListener_notInTabletopModeTwice_callbackOnce() {
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
+        mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
+        mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+        mPipTabletopController.registerOnTabletopModeChangedListener(
+                mOnTabletopModeChangedListener);
+        clearInvocations(mOnTabletopModeChangedListener);
+        mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_0);
+        mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+        verifyZeroInteractions(mOnTabletopModeChangedListener);
+    }
+
+    // Test cases starting from folded state (DEVICE_POSTURE_CLOSED)
+    @Test
+    public void foldedRotation90_halfOpen_scheduleTabletopModeChange() {
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
+        mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
+        mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
+
+        assertTrue(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
+    }
+
+    @Test
+    public void foldedRotation0_halfOpen_noScheduleTabletopModeChange() {
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
+        mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_0);
+        mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
+
+        assertFalse(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
+    }
+
+    @Test
+    public void foldedRotation90_halfOpenThenUnfold_cancelTabletopModeChange() {
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
+        mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
+        mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_OPENED);
+
+        assertFalse(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
+    }
+
+    @Test
+    public void foldedRotation90_halfOpenThenFold_cancelTabletopModeChange() {
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
+        mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
+        mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
+
+        assertFalse(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
+    }
+
+    @Test
+    public void foldedRotation90_halfOpenThenRotate_cancelTabletopModeChange() {
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
+        mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
+        mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
+        mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_0);
+        mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+        assertFalse(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
+    }
+
+    // Test cases starting from unfolded state (DEVICE_POSTURE_OPENED)
+    @Test
+    public void unfoldedRotation90_halfOpen_scheduleTabletopModeChange() {
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_OPENED);
+        mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
+        mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
+
+        assertTrue(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
+    }
+
+    @Test
+    public void unfoldedRotation0_halfOpen_noScheduleTabletopModeChange() {
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_OPENED);
+        mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_0);
+        mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
+
+        assertFalse(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
+    }
+
+    @Test
+    public void unfoldedRotation90_halfOpenThenUnfold_cancelTabletopModeChange() {
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_OPENED);
+        mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
+        mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_OPENED);
+
+        assertFalse(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
+    }
+
+    @Test
+    public void unfoldedRotation90_halfOpenThenFold_cancelTabletopModeChange() {
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_OPENED);
+        mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
+        mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_CLOSED);
+
+        assertFalse(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
+    }
+
+    @Test
+    public void unfoldedRotation90_halfOpenThenRotate_cancelTabletopModeChange() {
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_OPENED);
+        mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_90);
+        mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+        mPipTabletopController.onDevicePostureChanged(DEVICE_POSTURE_HALF_OPENED);
+        mConfiguration.windowConfiguration.setDisplayRotation(Surface.ROTATION_0);
+        mPipTabletopController.onDisplayConfigurationChanged(DEFAULT_DISPLAY, mConfiguration);
+
+        assertFalse(mMainExecutor.hasCallback(mPipTabletopController.mOnEnterTabletopModeCallback));
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
index e8784d7..bc0d93a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
@@ -475,6 +475,36 @@
         verify(mMockRestartDialogLayout).updateVisibility(true);
     }
 
+    @Test
+    public void testRestartLayoutRecreatedIfNeeded() {
+        final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID,
+                /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN);
+        doReturn(true).when(mMockRestartDialogLayout)
+                .needsToBeRecreated(any(TaskInfo.class),
+                        any(ShellTaskOrganizer.TaskListener.class));
+
+        mController.onCompatInfoChanged(taskInfo, mMockTaskListener);
+        mController.onCompatInfoChanged(taskInfo, mMockTaskListener);
+
+        verify(mMockRestartDialogLayout, times(2))
+                .createLayout(anyBoolean());
+    }
+
+    @Test
+    public void testRestartLayoutNotRecreatedIfNotNeeded() {
+        final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID,
+                /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN);
+        doReturn(false).when(mMockRestartDialogLayout)
+                .needsToBeRecreated(any(TaskInfo.class),
+                        any(ShellTaskOrganizer.TaskListener.class));
+
+        mController.onCompatInfoChanged(taskInfo, mMockTaskListener);
+        mController.onCompatInfoChanged(taskInfo, mMockTaskListener);
+
+        verify(mMockRestartDialogLayout, times(1))
+                .createLayout(anyBoolean());
+    }
+
     private static TaskInfo createTaskInfo(int displayId, int taskId, boolean hasSizeCompat,
             @CameraCompatControlState int cameraCompatControlState) {
         RunningTaskInfo taskInfo = new RunningTaskInfo();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
index b6dbcf2..523cb66 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
@@ -48,7 +48,6 @@
 import com.android.wm.shell.ShellTestCase;
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.ShellExecutor;
-import com.android.wm.shell.splitscreen.SplitScreenController;
 import com.android.wm.shell.sysui.ShellController;
 import com.android.wm.shell.sysui.ShellInit;
 
@@ -82,7 +81,7 @@
     @Mock
     private ShellExecutor mMainExecutor;
     @Mock
-    private SplitScreenController mSplitScreenController;
+    private WindowManager mWindowManager;
 
     private DragAndDropController mController;
 
@@ -100,11 +99,6 @@
     }
 
     @Test
-    public void instantiateController_registerConfigChangeListener() {
-        verify(mShellController, times(1)).addConfigurationChangeListener(any());
-    }
-
-    @Test
     public void testIgnoreNonDefaultDisplays() {
         final int nonDefaultDisplayId = 12345;
         final View dragLayout = mock(View.class);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java
index ec264a6..addc233 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java
@@ -55,25 +55,28 @@
     private static final float MAX_ASPECT_RATIO = 2f;
     private static final int DEFAULT_MIN_EDGE_SIZE = 100;
 
+    /** The minimum possible size of the override min size's width or height */
+    private static final int OVERRIDABLE_MIN_SIZE = 40;
+
     private PipBoundsAlgorithm mPipBoundsAlgorithm;
     private DisplayInfo mDefaultDisplayInfo;
-    private PipBoundsState mPipBoundsState;
-    private PipSizeSpecHandler mPipSizeSpecHandler;
+    private PipBoundsState mPipBoundsState; private PipSizeSpecHandler mPipSizeSpecHandler;
+    private PipDisplayLayoutState mPipDisplayLayoutState;
 
 
     @Before
     public void setUp() throws Exception {
         initializeMockResources();
-        mPipSizeSpecHandler = new PipSizeSpecHandler(mContext);
-        mPipBoundsState = new PipBoundsState(mContext, mPipSizeSpecHandler);
+        mPipDisplayLayoutState = new PipDisplayLayoutState(mContext);
+        mPipSizeSpecHandler = new PipSizeSpecHandler(mContext, mPipDisplayLayoutState);
+        mPipBoundsState = new PipBoundsState(mContext, mPipSizeSpecHandler, mPipDisplayLayoutState);
         mPipBoundsAlgorithm = new PipBoundsAlgorithm(mContext, mPipBoundsState,
                 new PipSnapAlgorithm(), new PipKeepClearAlgorithmInterface() {},
                 mPipSizeSpecHandler);
 
         DisplayLayout layout =
                 new DisplayLayout(mDefaultDisplayInfo, mContext.getResources(), true, true);
-        mPipBoundsState.setDisplayLayout(layout);
-        mPipSizeSpecHandler.setDisplayLayout(layout);
+        mPipDisplayLayoutState.setDisplayLayout(layout);
     }
 
     private void initializeMockResources() {
@@ -88,6 +91,9 @@
                 R.dimen.default_minimal_size_pip_resizable_task,
                 DEFAULT_MIN_EDGE_SIZE);
         res.addOverride(
+                R.dimen.overridable_minimal_size_pip_resizable_task,
+                OVERRIDABLE_MIN_SIZE);
+        res.addOverride(
                 R.string.config_defaultPictureInPictureScreenEdgeInsets,
                 "16x16");
         res.addOverride(
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java
index 341a451..f320004 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java
@@ -27,11 +27,13 @@
 import android.graphics.Rect;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
+import android.testing.TestableResources;
 import android.util.Size;
 
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.util.function.TriConsumer;
+import com.android.wm.shell.R;
 import com.android.wm.shell.ShellTestCase;
 import com.android.wm.shell.pip.phone.PipSizeSpecHandler;
 
@@ -52,13 +54,23 @@
     private static final Size DEFAULT_SIZE = new Size(10, 10);
     private static final float DEFAULT_SNAP_FRACTION = 1.0f;
 
+    /** The minimum possible size of the override min size's width or height */
+    private static final int OVERRIDABLE_MIN_SIZE = 40;
+
     private PipBoundsState mPipBoundsState;
     private ComponentName mTestComponentName1;
     private ComponentName mTestComponentName2;
 
     @Before
     public void setUp() {
-        mPipBoundsState = new PipBoundsState(mContext, new PipSizeSpecHandler(mContext));
+        final TestableResources res = mContext.getOrCreateTestableResources();
+        res.addOverride(
+                R.dimen.overridable_minimal_size_pip_resizable_task,
+                OVERRIDABLE_MIN_SIZE);
+
+        PipDisplayLayoutState pipDisplayLayoutState = new PipDisplayLayoutState(mContext);
+        mPipBoundsState = new PipBoundsState(mContext,
+                new PipSizeSpecHandler(mContext, pipDisplayLayoutState), pipDisplayLayoutState);
         mTestComponentName1 = new ComponentName(mContext, "component1");
         mTestComponentName2 = new ComponentName(mContext, "component2");
     }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
index e907cd3..15bb10e 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
@@ -88,6 +88,7 @@
     private PipTransitionState mPipTransitionState;
     private PipBoundsAlgorithm mPipBoundsAlgorithm;
     private PipSizeSpecHandler mPipSizeSpecHandler;
+    private PipDisplayLayoutState mPipDisplayLayoutState;
 
     private ComponentName mComponent1;
     private ComponentName mComponent2;
@@ -97,15 +98,16 @@
         MockitoAnnotations.initMocks(this);
         mComponent1 = new ComponentName(mContext, "component1");
         mComponent2 = new ComponentName(mContext, "component2");
-        mPipSizeSpecHandler = new PipSizeSpecHandler(mContext);
-        mPipBoundsState = new PipBoundsState(mContext, mPipSizeSpecHandler);
+        mPipDisplayLayoutState = new PipDisplayLayoutState(mContext);
+        mPipSizeSpecHandler = new PipSizeSpecHandler(mContext, mPipDisplayLayoutState);
+        mPipBoundsState = new PipBoundsState(mContext, mPipSizeSpecHandler, mPipDisplayLayoutState);
         mPipTransitionState = new PipTransitionState();
         mPipBoundsAlgorithm = new PipBoundsAlgorithm(mContext, mPipBoundsState,
                 new PipSnapAlgorithm(), new PipKeepClearAlgorithmInterface() {},
                 mPipSizeSpecHandler);
         mMainExecutor = new TestShellExecutor();
         mPipTaskOrganizer = new PipTaskOrganizer(mContext, mMockSyncTransactionQueue,
-                mPipTransitionState, mPipBoundsState, mPipSizeSpecHandler,
+                mPipTransitionState, mPipBoundsState, mPipDisplayLayoutState,
                 mPipBoundsAlgorithm, mMockPhonePipMenuController, mMockPipAnimationController,
                 mMockPipSurfaceTransactionHelper, mMockPipTransitionController,
                 mMockPipParamsChangedForwarder, mMockOptionalSplitScreen, mMockDisplayController,
@@ -259,8 +261,7 @@
         final DisplayInfo info = new DisplayInfo();
         DisplayLayout layout = new DisplayLayout(info,
                 mContext.getResources(), true, true);
-        mPipBoundsState.setDisplayLayout(layout);
-        mPipSizeSpecHandler.setDisplayLayout(layout);
+        mPipDisplayLayoutState.setDisplayLayout(layout);
         mPipTaskOrganizer.setOneShotAnimationType(PipAnimationController.ANIM_TYPE_ALPHA);
         mPipTaskOrganizer.setSurfaceControlTransactionFactory(
                 MockSurfaceControlHelper::createMockSurfaceControlTransaction);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
index 4a68287..108e273 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
@@ -53,12 +53,14 @@
 import com.android.wm.shell.common.DisplayInsetsController;
 import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.TabletopModeController;
 import com.android.wm.shell.common.TaskStackListenerImpl;
 import com.android.wm.shell.onehanded.OneHandedController;
 import com.android.wm.shell.pip.PipAnimationController;
 import com.android.wm.shell.pip.PipAppOpsListener;
 import com.android.wm.shell.pip.PipBoundsAlgorithm;
 import com.android.wm.shell.pip.PipBoundsState;
+import com.android.wm.shell.pip.PipDisplayLayoutState;
 import com.android.wm.shell.pip.PipMediaController;
 import com.android.wm.shell.pip.PipParamsChangedForwarder;
 import com.android.wm.shell.pip.PipSnapAlgorithm;
@@ -108,11 +110,13 @@
     @Mock private WindowManagerShellWrapper mMockWindowManagerShellWrapper;
     @Mock private PipBoundsState mMockPipBoundsState;
     @Mock private PipSizeSpecHandler mMockPipSizeSpecHandler;
+    @Mock private PipDisplayLayoutState mMockPipDisplayLayoutState;
     @Mock private TaskStackListenerImpl mMockTaskStackListener;
     @Mock private ShellExecutor mMockExecutor;
     @Mock private Optional<OneHandedController> mMockOneHandedController;
     @Mock private PipParamsChangedForwarder mMockPipParamsChangedForwarder;
     @Mock private DisplayInsetsController mMockDisplayInsetsController;
+    @Mock private TabletopModeController mMockTabletopModeController;
 
     @Mock private DisplayLayout mMockDisplayLayout1;
     @Mock private DisplayLayout mMockDisplayLayout2;
@@ -130,11 +134,12 @@
         mPipController = new PipController(mContext, mShellInit, mMockShellCommandHandler,
                 mShellController, mMockDisplayController, mMockPipAnimationController,
                 mMockPipAppOpsListener, mMockPipBoundsAlgorithm, mMockPipKeepClearAlgorithm,
-                mMockPipBoundsState, mMockPipSizeSpecHandler, mMockPipMotionHelper,
-                mMockPipMediaController, mMockPhonePipMenuController, mMockPipTaskOrganizer,
-                mMockPipTransitionState, mMockPipTouchHandler, mMockPipTransitionController,
-                mMockWindowManagerShellWrapper, mMockTaskStackListener,
-                mMockPipParamsChangedForwarder, mMockDisplayInsetsController,
+                mMockPipBoundsState, mMockPipSizeSpecHandler, mMockPipDisplayLayoutState,
+                mMockPipMotionHelper, mMockPipMediaController, mMockPhonePipMenuController,
+                mMockPipTaskOrganizer, mMockPipTransitionState, mMockPipTouchHandler,
+                mMockPipTransitionController, mMockWindowManagerShellWrapper,
+                mMockTaskStackListener, mMockPipParamsChangedForwarder,
+                mMockDisplayInsetsController, mMockTabletopModeController,
                 mMockOneHandedController, mMockExecutor);
         mShellInit.init();
         when(mMockPipBoundsAlgorithm.getSnapAlgorithm()).thenReturn(mMockPipSnapAlgorithm);
@@ -221,11 +226,12 @@
         assertNull(PipController.create(spyContext, shellInit, mMockShellCommandHandler,
                 mShellController, mMockDisplayController, mMockPipAnimationController,
                 mMockPipAppOpsListener, mMockPipBoundsAlgorithm, mMockPipKeepClearAlgorithm,
-                mMockPipBoundsState, mMockPipSizeSpecHandler, mMockPipMotionHelper,
-                mMockPipMediaController, mMockPhonePipMenuController, mMockPipTaskOrganizer,
-                mMockPipTransitionState, mMockPipTouchHandler, mMockPipTransitionController,
-                mMockWindowManagerShellWrapper, mMockTaskStackListener,
-                mMockPipParamsChangedForwarder, mMockDisplayInsetsController,
+                mMockPipBoundsState, mMockPipSizeSpecHandler, mMockPipDisplayLayoutState,
+                mMockPipMotionHelper, mMockPipMediaController, mMockPhonePipMenuController,
+                mMockPipTaskOrganizer, mMockPipTransitionState, mMockPipTouchHandler,
+                mMockPipTransitionController, mMockWindowManagerShellWrapper,
+                mMockTaskStackListener, mMockPipParamsChangedForwarder,
+                mMockDisplayInsetsController, mMockTabletopModeController,
                 mMockOneHandedController, mMockExecutor));
     }
 
@@ -283,8 +289,8 @@
         when(mMockPipBoundsState.getMinSize()).thenReturn(new Point(1, 1));
         when(mMockPipBoundsState.getMaxSize()).thenReturn(new Point(MAX_VALUE, MAX_VALUE));
         when(mMockPipBoundsState.getBounds()).thenReturn(bounds);
-        when(mMockPipBoundsState.getDisplayId()).thenReturn(displayId);
-        when(mMockPipBoundsState.getDisplayLayout()).thenReturn(mMockDisplayLayout1);
+        when(mMockPipDisplayLayoutState.getDisplayId()).thenReturn(displayId);
+        when(mMockPipDisplayLayoutState.getDisplayLayout()).thenReturn(mMockDisplayLayout1);
         when(mMockDisplayController.getDisplayLayout(displayId)).thenReturn(mMockDisplayLayout2);
 
         when(mMockPipTaskOrganizer.isInPip()).thenReturn(true);
@@ -299,8 +305,8 @@
         final int displayId = 1;
         final Rect bounds = new Rect(0, 0, 10, 10);
         when(mMockPipBoundsAlgorithm.getDefaultBounds()).thenReturn(bounds);
-        when(mMockPipBoundsState.getDisplayId()).thenReturn(displayId);
-        when(mMockPipBoundsState.getDisplayLayout()).thenReturn(mMockDisplayLayout1);
+        when(mMockPipDisplayLayoutState.getDisplayId()).thenReturn(displayId);
+        when(mMockPipDisplayLayoutState.getDisplayLayout()).thenReturn(mMockDisplayLayout1);
         when(mMockDisplayController.getDisplayLayout(displayId)).thenReturn(mMockDisplayLayout2);
 
         when(mMockPipTaskOrganizer.isInPip()).thenReturn(false);
@@ -314,7 +320,7 @@
     public void onKeepClearAreasChanged_featureDisabled_pipBoundsStateDoesntChange() {
         final int displayId = 1;
         final Rect keepClearArea = new Rect(0, 0, 10, 10);
-        when(mMockPipBoundsState.getDisplayId()).thenReturn(displayId);
+        when(mMockPipDisplayLayoutState.getDisplayId()).thenReturn(displayId);
 
         mPipController.mDisplaysChangedListener.onKeepClearAreasChanged(
                 displayId, Set.of(keepClearArea), Set.of());
@@ -327,7 +333,7 @@
         mPipController.setEnablePipKeepClearAlgorithm(true);
         final int displayId = 1;
         final Rect keepClearArea = new Rect(0, 0, 10, 10);
-        when(mMockPipBoundsState.getDisplayId()).thenReturn(displayId);
+        when(mMockPipDisplayLayoutState.getDisplayId()).thenReturn(displayId);
 
         mPipController.mDisplaysChangedListener.onKeepClearAreasChanged(
                 displayId, Set.of(keepClearArea), Set.of());
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipResizeGestureHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipResizeGestureHandlerTest.java
index c7b9eb3..5b62a94 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipResizeGestureHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipResizeGestureHandlerTest.java
@@ -37,6 +37,7 @@
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.pip.PipBoundsAlgorithm;
 import com.android.wm.shell.pip.PipBoundsState;
+import com.android.wm.shell.pip.PipDisplayLayoutState;
 import com.android.wm.shell.pip.PipKeepClearAlgorithmInterface;
 import com.android.wm.shell.pip.PipSnapAlgorithm;
 import com.android.wm.shell.pip.PipTaskOrganizer;
@@ -87,11 +88,14 @@
 
     private PipSizeSpecHandler mPipSizeSpecHandler;
 
+    private PipDisplayLayoutState mPipDisplayLayoutState;
+
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-        mPipSizeSpecHandler = new PipSizeSpecHandler(mContext);
-        mPipBoundsState = new PipBoundsState(mContext, mPipSizeSpecHandler);
+        mPipDisplayLayoutState = new PipDisplayLayoutState(mContext);
+        mPipSizeSpecHandler = new PipSizeSpecHandler(mContext, mPipDisplayLayoutState);
+        mPipBoundsState = new PipBoundsState(mContext, mPipSizeSpecHandler, mPipDisplayLayoutState);
         final PipSnapAlgorithm pipSnapAlgorithm = new PipSnapAlgorithm();
         final PipKeepClearAlgorithmInterface pipKeepClearAlgorithm =
                 new PipKeepClearAlgorithmInterface() {};
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipSizeSpecHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipSizeSpecHandlerTest.java
index d9ff7d1..390c830 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipSizeSpecHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipSizeSpecHandlerTest.java
@@ -33,6 +33,7 @@
 import com.android.dx.mockito.inline.extended.StaticMockitoSession;
 import com.android.wm.shell.ShellTestCase;
 import com.android.wm.shell.common.DisplayLayout;
+import com.android.wm.shell.pip.PipDisplayLayoutState;
 
 import org.junit.After;
 import org.junit.Assert;
@@ -74,6 +75,7 @@
     @Mock private Context mContext;
     @Mock private Resources mResources;
 
+    private PipDisplayLayoutState mPipDisplayLayoutState;
     private PipSizeSpecHandler mPipSizeSpecHandler;
 
     /**
@@ -137,7 +139,6 @@
     @Before
     public void setUp() {
         initExpectedSizes();
-        setUpStaticSystemPropertiesSession();
 
         when(mResources.getDimensionPixelSize(anyInt())).thenReturn(DEFAULT_MIN_EDGE_SIZE);
         when(mResources.getFloat(anyInt())).thenReturn(OPTIMIZED_ASPECT_RATIO);
@@ -148,11 +149,6 @@
         // set up the mock context for spec handler specifically
         when(mContext.getResources()).thenReturn(mResources);
 
-        mPipSizeSpecHandler = new PipSizeSpecHandler(mContext);
-
-        // no overridden min edge size by default
-        mPipSizeSpecHandler.setOverrideMinSize(null);
-
         DisplayInfo displayInfo = new DisplayInfo();
         displayInfo.logicalWidth = DISPLAY_EDGE_SIZE;
         displayInfo.logicalHeight = DISPLAY_EDGE_SIZE;
@@ -161,7 +157,14 @@
         // this is done to avoid unnecessary mocking while allowing for custom display dimensions
         DisplayLayout displayLayout = new DisplayLayout(displayInfo, getContext().getResources(),
                 false, false);
-        mPipSizeSpecHandler.setDisplayLayout(displayLayout);
+        mPipDisplayLayoutState = new PipDisplayLayoutState(mContext);
+        mPipDisplayLayoutState.setDisplayLayout(displayLayout);
+
+        setUpStaticSystemPropertiesSession();
+        mPipSizeSpecHandler = new PipSizeSpecHandler(mContext, mPipDisplayLayoutState);
+
+        // no overridden min edge size by default
+        mPipSizeSpecHandler.setOverrideMinSize(null);
     }
 
     @After
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java
index 5c4863f..d36060f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java
@@ -35,6 +35,7 @@
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.pip.PipBoundsAlgorithm;
 import com.android.wm.shell.pip.PipBoundsState;
+import com.android.wm.shell.pip.PipDisplayLayoutState;
 import com.android.wm.shell.pip.PipKeepClearAlgorithmInterface;
 import com.android.wm.shell.pip.PipSnapAlgorithm;
 import com.android.wm.shell.pip.PipTaskOrganizer;
@@ -92,6 +93,7 @@
     private PipMotionHelper mMotionHelper;
     private PipResizeGestureHandler mPipResizeGestureHandler;
     private PipSizeSpecHandler mPipSizeSpecHandler;
+    private PipDisplayLayoutState mPipDisplayLayoutState;
 
     private DisplayLayout mDisplayLayout;
     private Rect mInsetBounds;
@@ -105,8 +107,9 @@
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-        mPipSizeSpecHandler = new PipSizeSpecHandler(mContext);
-        mPipBoundsState = new PipBoundsState(mContext, mPipSizeSpecHandler);
+        mPipDisplayLayoutState = new PipDisplayLayoutState(mContext);
+        mPipSizeSpecHandler = new PipSizeSpecHandler(mContext, mPipDisplayLayoutState);
+        mPipBoundsState = new PipBoundsState(mContext, mPipSizeSpecHandler, mPipDisplayLayoutState);
         mPipSnapAlgorithm = new PipSnapAlgorithm();
         mPipBoundsAlgorithm = new PipBoundsAlgorithm(mContext, mPipBoundsState, mPipSnapAlgorithm,
                 new PipKeepClearAlgorithmInterface() {}, mPipSizeSpecHandler);
@@ -124,8 +127,7 @@
         mPipTouchHandler.setPipResizeGestureHandler(mPipResizeGestureHandler);
 
         mDisplayLayout = new DisplayLayout(mContext, mContext.getDisplay());
-        mPipBoundsState.setDisplayLayout(mDisplayLayout);
-        mPipSizeSpecHandler.setDisplayLayout(mDisplayLayout);
+        mPipDisplayLayoutState.setDisplayLayout(mDisplayLayout);
         mInsetBounds = new Rect(mPipBoundsState.getDisplayBounds().left + INSET,
                 mPipBoundsState.getDisplayBounds().top + INSET,
                 mPipBoundsState.getDisplayBounds().right - INSET,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/tv/TvPipGravityTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/tv/TvPipGravityTest.java
index 30096cb..f9b7723 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/tv/TvPipGravityTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/tv/TvPipGravityTest.java
@@ -26,6 +26,7 @@
 import android.view.Gravity;
 
 import com.android.wm.shell.ShellTestCase;
+import com.android.wm.shell.pip.PipDisplayLayoutState;
 import com.android.wm.shell.pip.PipSnapAlgorithm;
 import com.android.wm.shell.pip.phone.PipSizeSpecHandler;
 
@@ -47,6 +48,7 @@
     private TvPipBoundsState mTvPipBoundsState;
     private TvPipBoundsAlgorithm mTvPipBoundsAlgorithm;
     private PipSizeSpecHandler mPipSizeSpecHandler;
+    private PipDisplayLayoutState mPipDisplayLayoutState;
 
     @Before
     public void setUp() {
@@ -54,8 +56,10 @@
             return;
         }
         MockitoAnnotations.initMocks(this);
-        mPipSizeSpecHandler = new PipSizeSpecHandler(mContext);
-        mTvPipBoundsState = new TvPipBoundsState(mContext, mPipSizeSpecHandler);
+        mPipDisplayLayoutState = new PipDisplayLayoutState(mContext);
+        mPipSizeSpecHandler = new PipSizeSpecHandler(mContext, mPipDisplayLayoutState);
+        mTvPipBoundsState = new TvPipBoundsState(mContext, mPipSizeSpecHandler,
+                mPipDisplayLayoutState);
         mTvPipBoundsAlgorithm = new TvPipBoundsAlgorithm(mContext, mTvPipBoundsState,
                 mMockPipSnapAlgorithm, mPipSizeSpecHandler);
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
index ed0ac5f..2edec7d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
@@ -35,6 +35,7 @@
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -249,7 +250,7 @@
 
     @Test
     @UiThreadTest
-    public void testEnterRecents() {
+    public void testEnterRecentsAndCommit() {
         enterSplit();
 
         ActivityManager.RunningTaskInfo homeTask = new TestRunningTaskInfoBuilder()
@@ -261,60 +262,61 @@
         TransitionRequestInfo request = new TransitionRequestInfo(TRANSIT_TO_FRONT, homeTask, null);
         IBinder transition = mock(IBinder.class);
         WindowContainerTransaction result = mStageCoordinator.handleRequest(transition, request);
-
-        assertTrue(result.isEmpty());
+        // Don't handle recents opening
+        assertNull(result);
 
         // make sure we haven't made any local changes yet (need to wait until transition is ready)
         assertTrue(mStageCoordinator.isSplitScreenVisible());
 
-        // simulate the transition
-        TransitionInfo info = new TransitionInfoBuilder(TRANSIT_TO_FRONT, 0)
-                .addChange(TRANSIT_TO_FRONT, homeTask)
-                .addChange(TRANSIT_TO_BACK, mMainChild)
-                .addChange(TRANSIT_TO_BACK, mSideChild)
-                .build();
+        // simulate the start of recents transition
         mMainStage.onTaskVanished(mMainChild);
         mSideStage.onTaskVanished(mSideChild);
-        mStageCoordinator.startAnimation(transition, info,
-                mock(SurfaceControl.Transaction.class),
-                mock(SurfaceControl.Transaction.class),
-                mock(Transitions.TransitionFinishCallback.class));
+        mStageCoordinator.onRecentsInSplitAnimationStart(mock(SurfaceControl.Transaction.class));
         assertTrue(mStageCoordinator.isSplitScreenVisible());
+
+        // Make sure it cleans-up if recents doesn't restore
+        WindowContainerTransaction commitWCT = new WindowContainerTransaction();
+        mStageCoordinator.onRecentsInSplitAnimationFinish(commitWCT,
+                mock(SurfaceControl.Transaction.class));
+        assertFalse(mStageCoordinator.isSplitScreenVisible());
     }
 
     @Test
     @UiThreadTest
-    public void testDismissFromBeingOccluded() {
+    public void testEnterRecentsAndRestore() {
         enterSplit();
 
-        ActivityManager.RunningTaskInfo normalTask = new TestRunningTaskInfoBuilder()
+        ActivityManager.RunningTaskInfo homeTask = new TestRunningTaskInfoBuilder()
                 .setWindowingMode(WINDOWING_MODE_FULLSCREEN)
+                .setActivityType(ACTIVITY_TYPE_HOME)
                 .build();
 
-        // Create a request to bring a normal task forward
-        TransitionRequestInfo request =
-                new TransitionRequestInfo(TRANSIT_TO_FRONT, normalTask, null);
+        // Create a request to bring home forward
+        TransitionRequestInfo request = new TransitionRequestInfo(TRANSIT_TO_FRONT, homeTask, null);
         IBinder transition = mock(IBinder.class);
         WindowContainerTransaction result = mStageCoordinator.handleRequest(transition, request);
-
-        assertTrue(containsSplitExit(result));
+        // Don't handle recents opening
+        assertNull(result);
 
         // make sure we haven't made any local changes yet (need to wait until transition is ready)
         assertTrue(mStageCoordinator.isSplitScreenVisible());
 
-        // simulate the transition
-        TransitionInfo info = new TransitionInfoBuilder(TRANSIT_TO_FRONT, 0)
-                .addChange(TRANSIT_TO_FRONT, normalTask)
-                .addChange(TRANSIT_TO_BACK, mMainChild)
-                .addChange(TRANSIT_TO_BACK, mSideChild)
-                .build();
+        // simulate the start of recents transition
         mMainStage.onTaskVanished(mMainChild);
         mSideStage.onTaskVanished(mSideChild);
-        mStageCoordinator.startAnimation(transition, info,
-                mock(SurfaceControl.Transaction.class),
-                mock(SurfaceControl.Transaction.class),
-                mock(Transitions.TransitionFinishCallback.class));
-        assertFalse(mStageCoordinator.isSplitScreenVisible());
+        mStageCoordinator.onRecentsInSplitAnimationStart(mock(SurfaceControl.Transaction.class));
+        assertTrue(mStageCoordinator.isSplitScreenVisible());
+
+        // Make sure we remain in split after recents restores.
+        WindowContainerTransaction restoreWCT = new WindowContainerTransaction();
+        restoreWCT.reorder(mMainChild.token, true /* toTop */);
+        restoreWCT.reorder(mSideChild.token, true /* toTop */);
+        // simulate the restoreWCT being applied:
+        mMainStage.onTaskAppeared(mMainChild, mock(SurfaceControl.class));
+        mSideStage.onTaskAppeared(mSideChild, mock(SurfaceControl.class));
+        mStageCoordinator.onRecentsInSplitAnimationFinish(restoreWCT,
+                mock(SurfaceControl.Transaction.class));
+        assertTrue(mStageCoordinator.isSplitScreenVisible());
     }
 
     @Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index 0bb809d..2e2e49e 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -134,6 +134,7 @@
         when(mSplitLayout.getBounds2()).thenReturn(mBounds2);
         when(mSplitLayout.getRootBounds()).thenReturn(mRootBounds);
         when(mSplitLayout.isLandscape()).thenReturn(false);
+        when(mSplitLayout.applyTaskChanges(any(), any(), any())).thenReturn(true);
 
         mRootTask = new TestRunningTaskInfoBuilder().build();
         mRootLeash = new SurfaceControl.Builder(mSurfaceSession).setName("test").build();
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 6c9b186..44f1f01 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
@@ -62,6 +62,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.RemoteException;
+import android.util.ArraySet;
 import android.view.Surface;
 import android.view.SurfaceControl;
 import android.view.WindowManager;
@@ -99,6 +100,7 @@
 import org.mockito.InOrder;
 
 import java.util.ArrayList;
+import java.util.function.Function;
 
 /**
  * Tests for the shell transitions.
@@ -563,6 +565,95 @@
         assertEquals(0, mDefaultHandler.activeCount());
     }
 
+
+    @Test
+    public void testTransitionMergingOnFinish() {
+        final Transitions transitions = createTestTransitions();
+        transitions.replaceDefaultHandlerForTest(mDefaultHandler);
+
+        // The current transition.
+        final IBinder transitToken1 = new Binder();
+        requestStartTransition(transitions, transitToken1);
+        onTransitionReady(transitions, transitToken1);
+
+        // The next ready transition.
+        final IBinder transitToken2 = new Binder();
+        requestStartTransition(transitions, transitToken2);
+        onTransitionReady(transitions, transitToken2);
+
+        // The non-ready merge candidate.
+        final IBinder transitTokenNotReady = new Binder();
+        requestStartTransition(transitions, transitTokenNotReady);
+
+        mDefaultHandler.setSimulateMerge(true);
+        mDefaultHandler.mFinishes.get(0).onTransitionFinished(null /* wct */, null /* wctCB */);
+
+        // Make sure that the non-ready transition is not merged.
+        assertEquals(0, mDefaultHandler.mergeCount());
+    }
+
+    @Test
+    public void testInterleavedMerging() {
+        Transitions transitions = createTestTransitions();
+        transitions.replaceDefaultHandlerForTest(mDefaultHandler);
+
+        Function<Boolean, IBinder> startATransition = (doMerge) -> {
+            IBinder token = new Binder();
+            if (doMerge) {
+                mDefaultHandler.setShouldMerge(token);
+            }
+            transitions.requestStartTransition(token,
+                    new TransitionRequestInfo(TRANSIT_OPEN, null /* trigger */, null /* remote */));
+            TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN)
+                    .addChange(TRANSIT_OPEN).addChange(TRANSIT_CLOSE).build();
+            transitions.onTransitionReady(token, info, mock(SurfaceControl.Transaction.class),
+                    mock(SurfaceControl.Transaction.class));
+            return token;
+        };
+
+        IBinder transitToken1 = startATransition.apply(false);
+        // merge first one
+        IBinder transitToken2 = startATransition.apply(true);
+        assertEquals(1, mDefaultHandler.activeCount());
+        assertEquals(1, mDefaultHandler.mergeCount());
+
+        // don't merge next one
+        IBinder transitToken3 = startATransition.apply(false);
+        // make sure nothing happened (since it wasn't merged)
+        assertEquals(1, mDefaultHandler.activeCount());
+        assertEquals(1, mDefaultHandler.mergeCount());
+
+        // make a mergable
+        IBinder transitToken4 = startATransition.apply(true);
+        // make sure nothing happened since there is a non-mergable pending.
+        assertEquals(1, mDefaultHandler.activeCount());
+        assertEquals(1, mDefaultHandler.mergeCount());
+
+        // Queue up another mergable
+        IBinder transitToken5 = startATransition.apply(true);
+
+        // Queue up a non-mergable
+        IBinder transitToken6 = startATransition.apply(false);
+
+        // Our active now looks like: [playing, merged]
+        //           and ready queue: [non-mergable, mergable, mergable, non-mergable]
+        // finish the playing one
+        mDefaultHandler.finishOne();
+        mMainExecutor.flushAll();
+        // Now we should have the non-mergable playing now with 2 merged:
+        //    active: [playing, merged, merged]   queue: [non-mergable]
+        assertEquals(1, mDefaultHandler.activeCount());
+        assertEquals(2, mDefaultHandler.mergeCount());
+
+        mDefaultHandler.finishOne();
+        mMainExecutor.flushAll();
+        assertEquals(1, mDefaultHandler.activeCount());
+        assertEquals(0, mDefaultHandler.mergeCount());
+
+        mDefaultHandler.finishOne();
+        mMainExecutor.flushAll();
+    }
+
     @Test
     public void testTransitionOrderMatchesCore() {
         Transitions transitions = createTestTransitions();
@@ -989,6 +1080,7 @@
         ArrayList<Transitions.TransitionFinishCallback> mFinishes = new ArrayList<>();
         final ArrayList<IBinder> mMerged = new ArrayList<>();
         boolean mSimulateMerge = false;
+        final ArraySet<IBinder> mShouldMerge = new ArraySet<>();
 
         @Override
         public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
@@ -1003,7 +1095,7 @@
         public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
                 @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget,
                 @NonNull Transitions.TransitionFinishCallback finishCallback) {
-            if (!mSimulateMerge) return;
+            if (!(mSimulateMerge || mShouldMerge.contains(transition))) return;
             mMerged.add(transition);
             finishCallback.onTransitionFinished(null /* wct */, null /* wctCB */);
         }
@@ -1019,12 +1111,23 @@
             mSimulateMerge = sim;
         }
 
+        void setShouldMerge(IBinder toMerge) {
+            mShouldMerge.add(toMerge);
+        }
+
         void finishAll() {
             final ArrayList<Transitions.TransitionFinishCallback> finishes = mFinishes;
             mFinishes = new ArrayList<>();
             for (int i = finishes.size() - 1; i >= 0; --i) {
                 finishes.get(i).onTransitionFinished(null /* wct */, null /* wctCB */);
             }
+            mShouldMerge.clear();
+        }
+
+        void finishOne() {
+            Transitions.TransitionFinishCallback fin = mFinishes.remove(0);
+            mMerged.clear();
+            fin.onTransitionFinished(null /* wct */, null /* wctCB */);
         }
 
         int activeCount() {
@@ -1036,6 +1139,21 @@
         }
     }
 
+    private static void requestStartTransition(Transitions transitions, IBinder token) {
+        transitions.requestStartTransition(token,
+                new TransitionRequestInfo(TRANSIT_OPEN, null /* trigger */, null /* remote */));
+    }
+
+    private static void onTransitionReady(Transitions transitions, IBinder token) {
+        transitions.onTransitionReady(token, createTransitionInfo(),
+                mock(SurfaceControl.Transaction.class), mock(SurfaceControl.Transaction.class));
+    }
+
+    private static TransitionInfo createTransitionInfo() {
+        return new TransitionInfoBuilder(TRANSIT_OPEN)
+                .addChange(TRANSIT_OPEN).addChange(TRANSIT_CLOSE).build();
+    }
+
     private static SurfaceControl createMockSurface(boolean valid) {
         SurfaceControl sc = mock(SurfaceControl.class);
         doReturn(valid).when(sc).isValid();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java
index 3550721..1d1aa79 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java
@@ -49,6 +49,7 @@
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.desktopmode.DesktopModeController;
 import com.android.wm.shell.desktopmode.DesktopTasksController;
+import com.android.wm.shell.splitscreen.SplitScreenController;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -73,6 +74,7 @@
     @Mock private Choreographer mMainChoreographer;
     @Mock private ShellTaskOrganizer mTaskOrganizer;
     @Mock private DisplayController mDisplayController;
+    @Mock private SplitScreenController mSplitScreenController;
     @Mock private SyncTransactionQueue mSyncQueue;
     @Mock private DesktopModeController mDesktopModeController;
     @Mock private DesktopTasksController mDesktopTasksController;
@@ -98,6 +100,7 @@
                 mSyncQueue,
                 Optional.of(mDesktopModeController),
                 Optional.of(mDesktopTasksController),
+                Optional.of(mSplitScreenController),
                 mDesktopModeWindowDecorFactory,
                 mMockInputMonitorFactory
             );
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/TaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/TaskPositionerTest.kt
index 8f66f4e..94c064b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/TaskPositionerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/TaskPositionerTest.kt
@@ -5,13 +5,16 @@
 import android.graphics.Rect
 import android.os.IBinder
 import android.testing.AndroidTestingRunner
+import android.view.Display
 import android.window.WindowContainerToken
+import android.window.WindowContainerTransaction
 import android.window.WindowContainerTransaction.Change.CHANGE_DRAG_RESIZING
 import androidx.test.filters.SmallTest
 import com.android.wm.shell.common.DisplayController
 import com.android.wm.shell.common.DisplayLayout
 import com.android.wm.shell.ShellTaskOrganizer
 import com.android.wm.shell.ShellTestCase
+import com.android.wm.shell.windowdecor.TaskPositioner.CTRL_TYPE_BOTTOM
 import com.android.wm.shell.windowdecor.TaskPositioner.CTRL_TYPE_RIGHT
 import com.android.wm.shell.windowdecor.TaskPositioner.CTRL_TYPE_TOP
 import com.android.wm.shell.windowdecor.TaskPositioner.CTRL_TYPE_UNDEFINED
@@ -19,10 +22,11 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.any
 import org.mockito.Mockito.argThat
 import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when`
 import org.mockito.MockitoAnnotations
 
 /**
@@ -51,6 +55,8 @@
     private lateinit var mockDisplayController: DisplayController
     @Mock
     private lateinit var mockDisplayLayout: DisplayLayout
+    @Mock
+    private lateinit var mockDisplay: Display
 
     private lateinit var taskPositioner: TaskPositioner
 
@@ -68,6 +74,9 @@
         `when`(taskToken.asBinder()).thenReturn(taskBinder)
         `when`(mockDisplayController.getDisplayLayout(DISPLAY_ID)).thenReturn(mockDisplayLayout)
         `when`(mockDisplayLayout.densityDpi()).thenReturn(DENSITY_DPI)
+        `when`(mockDisplayLayout.getStableBounds(any())).thenAnswer { i ->
+            (i.arguments.first() as Rect).set(STABLE_BOUNDS)
+        }
 
         mockWindowDecoration.mTaskInfo = ActivityManager.RunningTaskInfo().apply {
             taskId = TASK_ID
@@ -78,6 +87,8 @@
             displayId = DISPLAY_ID
             configuration.windowConfiguration.bounds = STARTING_BOUNDS
         }
+        mockWindowDecoration.mDisplay = mockDisplay
+        `when`(mockDisplay.displayId).thenAnswer { DISPLAY_ID }
     }
 
     @Test
@@ -451,6 +462,72 @@
         })
     }
 
+    fun testDragResize_toDisallowedBounds_freezesAtLimit() {
+        taskPositioner.onDragPositioningStart(
+                CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, // Resize right-bottom corner
+                STARTING_BOUNDS.right.toFloat(),
+                STARTING_BOUNDS.bottom.toFloat()
+        )
+
+        // Resize the task by 10px to the right and bottom, a valid destination
+        val newBounds = Rect(
+                STARTING_BOUNDS.left,
+                STARTING_BOUNDS.top,
+                STARTING_BOUNDS.right + 10,
+                STARTING_BOUNDS.bottom + 10)
+        taskPositioner.onDragPositioningMove(
+                newBounds.right.toFloat(),
+                newBounds.bottom.toFloat()
+        )
+
+        // Resize the task by another 10px to the right (allowed) and to just in the disallowed
+        // area of the Y coordinate.
+        val newBounds2 = Rect(
+                newBounds.left,
+                newBounds.top,
+                newBounds.right + 10,
+                DISALLOWED_RESIZE_AREA.top
+        )
+        taskPositioner.onDragPositioningMove(
+                newBounds2.right.toFloat(),
+                newBounds2.bottom.toFloat()
+        )
+
+        taskPositioner.onDragPositioningEnd(newBounds2.right.toFloat(), newBounds2.bottom.toFloat())
+
+        // The first resize falls in the allowed area, verify there's a change for it.
+        verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+            return@argThat wct.changes.any { (token, change) ->
+                token == taskBinder && change.ofBounds(newBounds)
+            }
+        })
+        // The second resize falls in the disallowed area, verify there's no change for it.
+        verify(mockShellTaskOrganizer, never()).applyTransaction(argThat { wct ->
+            return@argThat wct.changes.any { (token, change) ->
+                token == taskBinder && change.ofBounds(newBounds2)
+            }
+        })
+        // Instead, there should be a change for its allowed portion (the X movement) with the Y
+        // staying frozen in the last valid resize position.
+        verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+            return@argThat wct.changes.any { (token, change) ->
+                token == taskBinder && change.ofBounds(
+                        Rect(
+                                newBounds2.left,
+                                newBounds2.top,
+                                newBounds2.right,
+                                newBounds.bottom // Stayed at the first resize destination.
+                        )
+                )
+            }
+        })
+    }
+
+    private fun WindowContainerTransaction.Change.ofBounds(bounds: Rect): Boolean {
+        return ((windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0) &&
+                bounds == configuration.windowConfiguration.bounds
+    }
+
     companion object {
         private const val TASK_ID = 5
         private const val MIN_WIDTH = 10
@@ -458,6 +535,19 @@
         private const val DENSITY_DPI = 20
         private const val DEFAULT_MIN = 40
         private const val DISPLAY_ID = 1
+        private const val NAVBAR_HEIGHT = 50
+        private val DISPLAY_BOUNDS = Rect(0, 0, 2400, 1600)
         private val STARTING_BOUNDS = Rect(0, 0, 100, 100)
+        private val DISALLOWED_RESIZE_AREA = Rect(
+                DISPLAY_BOUNDS.left,
+                DISPLAY_BOUNDS.bottom - NAVBAR_HEIGHT,
+                DISPLAY_BOUNDS.right,
+                DISPLAY_BOUNDS.bottom)
+        private val STABLE_BOUNDS = Rect(
+                DISPLAY_BOUNDS.left,
+                DISPLAY_BOUNDS.top,
+                DISPLAY_BOUNDS.right,
+                DISPLAY_BOUNDS.bottom - NAVBAR_HEIGHT
+        )
     }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index b80edce..7e39b5b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -108,6 +108,8 @@
     private SurfaceControl.Transaction mMockSurfaceControlAddWindowT;
     private WindowDecoration.RelayoutParams mRelayoutParams = new WindowDecoration.RelayoutParams();
     private int mCaptionMenuWidthId;
+    private int mCaptionMenuShadowRadiusId;
+    private int mCaptionMenuCornerRadiusId;
 
     @Before
     public void setUp() {
@@ -118,6 +120,8 @@
         mRelayoutParams.mLayoutResId = 0;
         mRelayoutParams.mCaptionHeightId = R.dimen.test_freeform_decor_caption_height;
         mCaptionMenuWidthId = R.dimen.test_freeform_decor_caption_menu_width;
+        mCaptionMenuShadowRadiusId = R.dimen.test_caption_menu_shadow_radius;
+        mCaptionMenuCornerRadiusId = R.dimen.test_caption_menu_corner_radius;
         mRelayoutParams.mShadowRadiusId = R.dimen.test_window_decor_shadow_radius;
 
         doReturn(mMockSurfaceControlViewHost).when(mMockSurfaceControlViewHostFactory)
@@ -431,7 +435,19 @@
         verify(additionalWindowSurfaceBuilder).setParent(decorContainerSurface);
         verify(additionalWindowSurfaceBuilder).build();
         verify(mMockSurfaceControlAddWindowT).setPosition(additionalWindowSurface, 20, 40);
-        verify(mMockSurfaceControlAddWindowT).setWindowCrop(additionalWindowSurface, 442, 74);
+        final int width = WindowDecoration.loadDimensionPixelSize(
+                mContext.getResources(), mCaptionMenuWidthId);
+        final int height = WindowDecoration.loadDimensionPixelSize(
+                mContext.getResources(), mRelayoutParams.mCaptionHeightId);
+        verify(mMockSurfaceControlAddWindowT).setWindowCrop(additionalWindowSurface, width, height);
+        final int shadowRadius = WindowDecoration.loadDimensionPixelSize(mContext.getResources(),
+                mCaptionMenuShadowRadiusId);
+        verify(mMockSurfaceControlAddWindowT)
+                .setShadowRadius(additionalWindowSurface, shadowRadius);
+        final int cornerRadius = WindowDecoration.loadDimensionPixelSize(mContext.getResources(),
+                mCaptionMenuCornerRadiusId);
+        verify(mMockSurfaceControlAddWindowT)
+                .setCornerRadius(additionalWindowSurface, cornerRadius);
         verify(mMockSurfaceControlAddWindowT).show(additionalWindowSurface);
         verify(mMockSurfaceControlViewHostFactory, Mockito.times(2))
                 .create(any(), eq(defaultDisplay), any());
@@ -559,13 +575,15 @@
             int y = mRelayoutParams.mCaptionY;
             int width = loadDimensionPixelSize(resources, mCaptionMenuWidthId);
             int height = loadDimensionPixelSize(resources, mRelayoutParams.mCaptionHeightId);
+            int shadowRadius = loadDimensionPixelSize(resources, mCaptionMenuShadowRadiusId);
+            int cornerRadius = loadDimensionPixelSize(resources, mCaptionMenuCornerRadiusId);
             String name = "Test Window";
             WindowDecoration.AdditionalWindow additionalWindow =
                     addWindow(R.layout.desktop_mode_decor_handle_menu, name,
                             mMockSurfaceControlAddWindowT,
                             x - mRelayoutResult.mDecorContainerOffsetX,
                             y - mRelayoutResult.mDecorContainerOffsetY,
-                            width, height, 10);
+                            width, height, shadowRadius, cornerRadius);
             return additionalWindow;
         }
     }
diff --git a/libs/dream/OWNERS b/libs/dream/OWNERS
new file mode 100644
index 0000000..a4b0127
--- /dev/null
+++ b/libs/dream/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/dreams/OWNERS
\ No newline at end of file
diff --git a/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightDreamManager.java b/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightDreamManager.java
index 5ecec4d..3125f08 100644
--- a/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightDreamManager.java
+++ b/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightDreamManager.java
@@ -72,6 +72,7 @@
     public static final int AMBIENT_LIGHT_MODE_LOW_LIGHT = 2;
 
     private final DreamManager mDreamManager;
+    private final LowLightTransitionCoordinator mLowLightTransitionCoordinator;
 
     @Nullable
     private final ComponentName mLowLightDreamComponent;
@@ -81,8 +82,10 @@
     @Inject
     public LowLightDreamManager(
             DreamManager dreamManager,
+            LowLightTransitionCoordinator lowLightTransitionCoordinator,
             @Named(LOW_LIGHT_DREAM_COMPONENT) @Nullable ComponentName lowLightDreamComponent) {
         mDreamManager = dreamManager;
+        mLowLightTransitionCoordinator = lowLightTransitionCoordinator;
         mLowLightDreamComponent = lowLightDreamComponent;
     }
 
@@ -111,7 +114,9 @@
 
         mAmbientLightMode = ambientLightMode;
 
-        mDreamManager.setSystemDreamComponent(mAmbientLightMode == AMBIENT_LIGHT_MODE_LOW_LIGHT
-                ? mLowLightDreamComponent : null);
+        boolean shouldEnterLowLight = mAmbientLightMode == AMBIENT_LIGHT_MODE_LOW_LIGHT;
+        mLowLightTransitionCoordinator.notifyBeforeLowLightTransition(shouldEnterLowLight,
+                () -> mDreamManager.setSystemDreamComponent(
+                        shouldEnterLowLight ? mLowLightDreamComponent : null));
     }
 }
diff --git a/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightTransitionCoordinator.java b/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightTransitionCoordinator.java
new file mode 100644
index 0000000..874a2d5
--- /dev/null
+++ b/libs/dream/lowlight/src/com/android/dream/lowlight/LowLightTransitionCoordinator.java
@@ -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.dream.lowlight;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.annotation.Nullable;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Helper class that allows listening and running animations before entering or exiting low light.
+ */
+@Singleton
+public class LowLightTransitionCoordinator {
+    /**
+     * Listener that is notified before low light entry.
+     */
+    public interface LowLightEnterListener {
+        /**
+         * Callback that is notified before the device enters low light.
+         *
+         * @return an optional animator that will be waited upon before entering low light.
+         */
+        Animator onBeforeEnterLowLight();
+    }
+
+    /**
+     * Listener that is notified before low light exit.
+     */
+    public interface LowLightExitListener {
+        /**
+         * Callback that is notified before the device exits low light.
+         *
+         * @return an optional animator that will be waited upon before exiting low light.
+         */
+        Animator onBeforeExitLowLight();
+    }
+
+    private LowLightEnterListener mLowLightEnterListener;
+    private LowLightExitListener mLowLightExitListener;
+
+    @Inject
+    public LowLightTransitionCoordinator() {
+    }
+
+    /**
+     * Sets the listener for the low light enter event.
+     *
+     * Only one listener can be set at a time. This method will overwrite any previously set
+     * listener. Null can be used to unset the listener.
+     */
+    public void setLowLightEnterListener(@Nullable LowLightEnterListener lowLightEnterListener) {
+        mLowLightEnterListener = lowLightEnterListener;
+    }
+
+    /**
+     * Sets the listener for the low light exit event.
+     *
+     * Only one listener can be set at a time. This method will overwrite any previously set
+     * listener. Null can be used to unset the listener.
+     */
+    public void setLowLightExitListener(@Nullable LowLightExitListener lowLightExitListener) {
+        mLowLightExitListener = lowLightExitListener;
+    }
+
+    /**
+     * Notifies listeners that the device is about to enter or exit low light.
+     *
+     * @param entering true if listeners should be notified before entering low light, false if this
+     *                 is notifying before exiting.
+     * @param callback callback that will be run after listeners complete.
+     */
+    void notifyBeforeLowLightTransition(boolean entering, Runnable callback) {
+        Animator animator = null;
+
+        if (entering && mLowLightEnterListener != null) {
+            animator = mLowLightEnterListener.onBeforeEnterLowLight();
+        } else if (!entering && mLowLightExitListener != null) {
+            animator = mLowLightExitListener.onBeforeExitLowLight();
+        }
+
+        // If the listener returned an animator to indicate it was running an animation, run the
+        // callback after the animation completes, otherwise call the callback directly.
+        if (animator != null) {
+            animator.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animator) {
+                    callback.run();
+                }
+            });
+        } else {
+            callback.run();
+        }
+    }
+}
diff --git a/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightDreamManagerTest.java b/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightDreamManagerTest.java
index 91a170f..4b95d8c 100644
--- a/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightDreamManagerTest.java
+++ b/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightDreamManagerTest.java
@@ -21,7 +21,10 @@
 import static com.android.dream.lowlight.LowLightDreamManager.AMBIENT_LIGHT_MODE_UNKNOWN;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
@@ -44,44 +47,52 @@
     private DreamManager mDreamManager;
 
     @Mock
+    private LowLightTransitionCoordinator mTransitionCoordinator;
+
+    @Mock
     private ComponentName mDreamComponent;
 
+    LowLightDreamManager mLowLightDreamManager;
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+
+        // Automatically run any provided Runnable to mTransitionCoordinator to simplify testing.
+        doAnswer(invocation -> {
+            ((Runnable) invocation.getArgument(1)).run();
+            return null;
+        }).when(mTransitionCoordinator).notifyBeforeLowLightTransition(anyBoolean(),
+                any(Runnable.class));
+
+        mLowLightDreamManager = new LowLightDreamManager(mDreamManager, mTransitionCoordinator,
+                mDreamComponent);
     }
 
     @Test
     public void setAmbientLightMode_lowLight_setSystemDream() {
-        final LowLightDreamManager lowLightDreamManager = new LowLightDreamManager(mDreamManager,
-                mDreamComponent);
+        mLowLightDreamManager.setAmbientLightMode(AMBIENT_LIGHT_MODE_LOW_LIGHT);
 
-        lowLightDreamManager.setAmbientLightMode(AMBIENT_LIGHT_MODE_LOW_LIGHT);
-
+        verify(mTransitionCoordinator).notifyBeforeLowLightTransition(eq(true), any());
         verify(mDreamManager).setSystemDreamComponent(mDreamComponent);
     }
 
     @Test
     public void setAmbientLightMode_regularLight_clearSystemDream() {
-        final LowLightDreamManager lowLightDreamManager = new LowLightDreamManager(mDreamManager,
-                mDreamComponent);
+        mLowLightDreamManager.setAmbientLightMode(AMBIENT_LIGHT_MODE_REGULAR);
 
-        lowLightDreamManager.setAmbientLightMode(AMBIENT_LIGHT_MODE_REGULAR);
-
+        verify(mTransitionCoordinator).notifyBeforeLowLightTransition(eq(false), any());
         verify(mDreamManager).setSystemDreamComponent(null);
     }
 
     @Test
     public void setAmbientLightMode_defaultUnknownMode_clearSystemDream() {
-        final LowLightDreamManager lowLightDreamManager = new LowLightDreamManager(mDreamManager,
-                mDreamComponent);
-
         // Set to low light first.
-        lowLightDreamManager.setAmbientLightMode(AMBIENT_LIGHT_MODE_LOW_LIGHT);
+        mLowLightDreamManager.setAmbientLightMode(AMBIENT_LIGHT_MODE_LOW_LIGHT);
         clearInvocations(mDreamManager);
 
         // Return to default unknown mode.
-        lowLightDreamManager.setAmbientLightMode(AMBIENT_LIGHT_MODE_UNKNOWN);
+        mLowLightDreamManager.setAmbientLightMode(AMBIENT_LIGHT_MODE_UNKNOWN);
 
         verify(mDreamManager).setSystemDreamComponent(null);
     }
@@ -89,7 +100,7 @@
     @Test
     public void setAmbientLightMode_dreamComponentNotSet_doNothing() {
         final LowLightDreamManager lowLightDreamManager = new LowLightDreamManager(mDreamManager,
-                null /*dream component*/);
+                mTransitionCoordinator, null /*dream component*/);
 
         lowLightDreamManager.setAmbientLightMode(AMBIENT_LIGHT_MODE_LOW_LIGHT);
 
diff --git a/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightTransitionCoordinatorTest.java b/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightTransitionCoordinatorTest.java
new file mode 100644
index 0000000..81e1e33
--- /dev/null
+++ b/libs/dream/lowlight/tests/src/com.android.dream.lowlight/LowLightTransitionCoordinatorTest.java
@@ -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.dream.lowlight;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import android.animation.Animator;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class LowLightTransitionCoordinatorTest {
+    @Mock
+    private LowLightTransitionCoordinator.LowLightEnterListener mEnterListener;
+
+    @Mock
+    private LowLightTransitionCoordinator.LowLightExitListener mExitListener;
+
+    @Mock
+    private Animator mAnimator;
+
+    @Captor
+    private ArgumentCaptor<Animator.AnimatorListener> mAnimatorListenerCaptor;
+
+    @Mock
+    private Runnable mRunnable;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void onEnterCalledOnListeners() {
+        LowLightTransitionCoordinator coordinator = new LowLightTransitionCoordinator();
+
+        coordinator.setLowLightEnterListener(mEnterListener);
+
+        coordinator.notifyBeforeLowLightTransition(true, mRunnable);
+
+        verify(mEnterListener).onBeforeEnterLowLight();
+        verify(mRunnable).run();
+    }
+
+    @Test
+    public void onExitCalledOnListeners() {
+        LowLightTransitionCoordinator coordinator = new LowLightTransitionCoordinator();
+
+        coordinator.setLowLightExitListener(mExitListener);
+
+        coordinator.notifyBeforeLowLightTransition(false, mRunnable);
+
+        verify(mExitListener).onBeforeExitLowLight();
+        verify(mRunnable).run();
+    }
+
+    @Test
+    public void listenerNotCalledAfterRemoval() {
+        LowLightTransitionCoordinator coordinator = new LowLightTransitionCoordinator();
+
+        coordinator.setLowLightEnterListener(mEnterListener);
+        coordinator.setLowLightEnterListener(null);
+
+        coordinator.notifyBeforeLowLightTransition(true, mRunnable);
+
+        verifyZeroInteractions(mEnterListener);
+        verify(mRunnable).run();
+    }
+
+    @Test
+    public void runnableCalledAfterAnimationEnds() {
+        when(mEnterListener.onBeforeEnterLowLight()).thenReturn(mAnimator);
+
+        LowLightTransitionCoordinator coordinator = new LowLightTransitionCoordinator();
+        coordinator.setLowLightEnterListener(mEnterListener);
+
+        coordinator.notifyBeforeLowLightTransition(true, mRunnable);
+
+        // Animator listener is added and the runnable is not run yet.
+        verify(mAnimator).addListener(mAnimatorListenerCaptor.capture());
+        verifyZeroInteractions(mRunnable);
+
+        // Runnable is run once the animation ends.
+        mAnimatorListenerCaptor.getValue().onAnimationEnd(null);
+        verify(mRunnable).run();
+    }
+}
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index bcbe706..3b12972 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -332,11 +332,13 @@
         "jni/android_graphics_Matrix.cpp",
         "jni/android_graphics_Picture.cpp",
         "jni/android_graphics_DisplayListCanvas.cpp",
+        "jni/android_graphics_Mesh.cpp",
         "jni/android_graphics_RenderNode.cpp",
         "jni/android_nio_utils.cpp",
         "jni/android_util_PathParser.cpp",
 
         "jni/Bitmap.cpp",
+        "jni/BufferUtils.cpp",
         "jni/HardwareBufferHelpers.cpp",
         "jni/BitmapFactory.cpp",
         "jni/ByteBufferStreamAdaptor.cpp",
@@ -351,7 +353,6 @@
         "jni/ImageDecoder.cpp",
         "jni/Interpolator.cpp",
         "jni/MeshSpecification.cpp",
-        "jni/Mesh.cpp",
         "jni/MaskFilter.cpp",
         "jni/NinePatch.cpp",
         "jni/NinePatchPeeker.cpp",
@@ -374,6 +375,7 @@
         "jni/text/LineBreaker.cpp",
         "jni/text/MeasuredText.cpp",
         "jni/text/TextShaper.cpp",
+        "jni/text/GraphemeBreak.cpp",
     ],
 
     header_libs: [
@@ -535,9 +537,11 @@
         "AnimatorManager.cpp",
         "CanvasTransform.cpp",
         "DamageAccumulator.cpp",
+        "Gainmap.cpp",
         "Interpolator.cpp",
         "LightingInfo.cpp",
         "Matrix.cpp",
+        "Mesh.cpp",
         "MemoryPolicy.cpp",
         "PathParser.cpp",
         "Properties.cpp",
diff --git a/libs/hwui/DisplayListOps.in b/libs/hwui/DisplayListOps.in
index e2127ef..a18ba1c 100644
--- a/libs/hwui/DisplayListOps.in
+++ b/libs/hwui/DisplayListOps.in
@@ -52,4 +52,5 @@
 X(DrawVectorDrawable)
 X(DrawRippleDrawable)
 X(DrawWebView)
-X(DrawMesh)
+X(DrawSkMesh)
+X(DrawMesh)
\ No newline at end of file
diff --git a/libs/hwui/Gainmap.cpp b/libs/hwui/Gainmap.cpp
new file mode 100644
index 0000000..30f401e
--- /dev/null
+++ b/libs/hwui/Gainmap.cpp
@@ -0,0 +1,32 @@
+/**
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "Gainmap.h"
+
+namespace android::uirenderer {
+
+sp<Gainmap> Gainmap::allocateHardwareGainmap(const sp<Gainmap>& srcGainmap) {
+    auto gainmap = sp<Gainmap>::make();
+    gainmap->info = srcGainmap->info;
+    const SkBitmap skSrcBitmap = srcGainmap->bitmap->getSkBitmap();
+    sk_sp<Bitmap> skBitmap(Bitmap::allocateHardwareBitmap(skSrcBitmap));
+    if (!skBitmap.get()) {
+        return nullptr;
+    }
+    gainmap->bitmap = std::move(skBitmap);
+    return gainmap;
+}
+
+}  // namespace android::uirenderer
\ No newline at end of file
diff --git a/libs/hwui/Gainmap.h b/libs/hwui/Gainmap.h
index 765f98a..3bc183a 100644
--- a/libs/hwui/Gainmap.h
+++ b/libs/hwui/Gainmap.h
@@ -27,6 +27,7 @@
 public:
     SkGainmapInfo info;
     sk_sp<Bitmap> bitmap;
+    static sp<Gainmap> allocateHardwareGainmap(const sp<Gainmap>& srcGainmap);
 };
 
 }  // namespace android::uirenderer
diff --git a/libs/hwui/MemoryPolicy.h b/libs/hwui/MemoryPolicy.h
index 2f0f7f5..41ced8c 100644
--- a/libs/hwui/MemoryPolicy.h
+++ b/libs/hwui/MemoryPolicy.h
@@ -53,8 +53,8 @@
     // Whether or not to only purge scratch resources when triggering UI Hidden or background
     // collection
     bool purgeScratchOnly = true;
-    // Whether or not to trigger releasing GPU context when all contexts are stopped
-    bool releaseContextOnStoppedOnly = true;
+    // EXPERIMENTAL: Whether or not to trigger releasing GPU context when all contexts are stopped
+    bool releaseContextOnStoppedOnly = false;
 };
 
 const MemoryPolicy& loadMemoryPolicy();
diff --git a/libs/hwui/Mesh.cpp b/libs/hwui/Mesh.cpp
new file mode 100644
index 0000000..e59bc95
--- /dev/null
+++ b/libs/hwui/Mesh.cpp
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+
+#include "Mesh.h"
+
+#include <GLES/gl.h>
+#include <SkMesh.h>
+
+#include "SafeMath.h"
+
+static size_t min_vcount_for_mode(SkMesh::Mode mode) {
+    switch (mode) {
+        case SkMesh::Mode::kTriangles:
+            return 3;
+        case SkMesh::Mode::kTriangleStrip:
+            return 3;
+    }
+}
+
+// Re-implementation of SkMesh::validate to validate user side that their mesh is valid.
+std::tuple<bool, SkString> Mesh::validate() {
+#define FAIL_MESH_VALIDATE(...) return std::make_tuple(false, SkStringPrintf(__VA_ARGS__))
+    if (!mMeshSpec) {
+        FAIL_MESH_VALIDATE("MeshSpecification is required.");
+    }
+    if (mVertexBufferData.empty()) {
+        FAIL_MESH_VALIDATE("VertexBuffer is required.");
+    }
+
+    auto meshStride = mMeshSpec->stride();
+    auto meshMode = SkMesh::Mode(mMode);
+    SafeMath sm;
+    size_t vsize = sm.mul(meshStride, mVertexCount);
+    if (sm.add(vsize, mVertexOffset) > mVertexBufferData.size()) {
+        FAIL_MESH_VALIDATE(
+                "The vertex buffer offset and vertex count reads beyond the end of the"
+                " vertex buffer.");
+    }
+
+    if (mVertexOffset % meshStride != 0) {
+        FAIL_MESH_VALIDATE("The vertex offset (%zu) must be a multiple of the vertex stride (%zu).",
+                           mVertexOffset, meshStride);
+    }
+
+    if (size_t uniformSize = mMeshSpec->uniformSize()) {
+        if (!mBuilder->fUniforms || mBuilder->fUniforms->size() < uniformSize) {
+            FAIL_MESH_VALIDATE("The uniform data is %zu bytes but must be at least %zu.",
+                               mBuilder->fUniforms->size(), uniformSize);
+        }
+    }
+
+    auto modeToStr = [](SkMesh::Mode m) {
+        switch (m) {
+            case SkMesh::Mode::kTriangles:
+                return "triangles";
+            case SkMesh::Mode::kTriangleStrip:
+                return "triangle-strip";
+        }
+    };
+    if (!mIndexBufferData.empty()) {
+        if (mIndexCount < min_vcount_for_mode(meshMode)) {
+            FAIL_MESH_VALIDATE("%s mode requires at least %zu indices but index count is %zu.",
+                               modeToStr(meshMode), min_vcount_for_mode(meshMode), mIndexCount);
+        }
+        size_t isize = sm.mul(sizeof(uint16_t), mIndexCount);
+        if (sm.add(isize, mIndexOffset) > mIndexBufferData.size()) {
+            FAIL_MESH_VALIDATE(
+                    "The index buffer offset and index count reads beyond the end of the"
+                    " index buffer.");
+        }
+        // If we allow 32 bit indices then this should enforce 4 byte alignment in that case.
+        if (!SkIsAlign2(mIndexOffset)) {
+            FAIL_MESH_VALIDATE("The index offset must be a multiple of 2.");
+        }
+    } else {
+        if (mVertexCount < min_vcount_for_mode(meshMode)) {
+            FAIL_MESH_VALIDATE("%s mode requires at least %zu vertices but vertex count is %zu.",
+                               modeToStr(meshMode), min_vcount_for_mode(meshMode), mVertexCount);
+        }
+        SkASSERT(!fICount);
+        SkASSERT(!fIOffset);
+    }
+
+    if (!sm.ok()) {
+        FAIL_MESH_VALIDATE("Overflow");
+    }
+#undef FAIL_MESH_VALIDATE
+    return {true, {}};
+}
diff --git a/libs/hwui/Mesh.h b/libs/hwui/Mesh.h
new file mode 100644
index 0000000..13e3c8e
--- /dev/null
+++ b/libs/hwui/Mesh.h
@@ -0,0 +1,199 @@
+/*
+ * 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.
+ */
+
+#ifndef MESH_H_
+#define MESH_H_
+
+#include <GrDirectContext.h>
+#include <SkMesh.h>
+#include <jni.h>
+#include <log/log.h>
+
+#include <utility>
+
+class MeshUniformBuilder {
+public:
+    struct MeshUniform {
+        template <typename T>
+        std::enable_if_t<std::is_trivially_copyable<T>::value, MeshUniform> operator=(
+                const T& val) {
+            if (!fVar) {
+                LOG_FATAL("Assigning to missing variable");
+            } else if (sizeof(val) != fVar->sizeInBytes()) {
+                LOG_FATAL("Incorrect value size");
+            } else {
+                void* dst = reinterpret_cast<void*>(
+                        reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
+                memcpy(dst, &val, sizeof(val));
+            }
+        }
+
+        MeshUniform& operator=(const SkMatrix& val) {
+            if (!fVar) {
+                LOG_FATAL("Assigning to missing variable");
+            } else if (fVar->sizeInBytes() != 9 * sizeof(float)) {
+                LOG_FATAL("Incorrect value size");
+            } else {
+                float* data = reinterpret_cast<float*>(
+                        reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
+                data[0] = val.get(0);
+                data[1] = val.get(3);
+                data[2] = val.get(6);
+                data[3] = val.get(1);
+                data[4] = val.get(4);
+                data[5] = val.get(7);
+                data[6] = val.get(2);
+                data[7] = val.get(5);
+                data[8] = val.get(8);
+            }
+            return *this;
+        }
+
+        template <typename T>
+        bool set(const T val[], const int count) {
+            static_assert(std::is_trivially_copyable<T>::value, "Value must be trivial copyable");
+            if (!fVar) {
+                LOG_FATAL("Assigning to missing variable");
+                return false;
+            } else if (sizeof(T) * count != fVar->sizeInBytes()) {
+                LOG_FATAL("Incorrect value size");
+                return false;
+            } else {
+                void* dst = reinterpret_cast<void*>(
+                        reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
+                memcpy(dst, val, sizeof(T) * count);
+            }
+            return true;
+        }
+
+        MeshUniformBuilder* fOwner;
+        const SkRuntimeEffect::Uniform* fVar;
+    };
+    MeshUniform uniform(std::string_view name) { return {this, fMeshSpec->findUniform(name)}; }
+
+    explicit MeshUniformBuilder(sk_sp<SkMeshSpecification> meshSpec) {
+        fMeshSpec = sk_sp(meshSpec);
+        fUniforms = (SkData::MakeZeroInitialized(meshSpec->uniformSize()));
+    }
+
+    sk_sp<SkData> fUniforms;
+
+private:
+    void* writableUniformData() {
+        if (!fUniforms->unique()) {
+            fUniforms = SkData::MakeWithCopy(fUniforms->data(), fUniforms->size());
+        }
+        return fUniforms->writable_data();
+    }
+
+    sk_sp<SkMeshSpecification> fMeshSpec;
+};
+
+class Mesh {
+public:
+    Mesh(const sk_sp<SkMeshSpecification>& meshSpec, int mode,
+         std::vector<uint8_t>&& vertexBufferData, jint vertexCount, jint vertexOffset,
+         std::unique_ptr<MeshUniformBuilder> builder, const SkRect& bounds)
+            : mMeshSpec(meshSpec)
+            , mMode(mode)
+            , mVertexBufferData(std::move(vertexBufferData))
+            , mVertexCount(vertexCount)
+            , mVertexOffset(vertexOffset)
+            , mBuilder(std::move(builder))
+            , mBounds(bounds) {}
+
+    Mesh(const sk_sp<SkMeshSpecification>& meshSpec, int mode,
+         std::vector<uint8_t>&& vertexBufferData, jint vertexCount, jint vertexOffset,
+         std::vector<uint8_t>&& indexBuffer, jint indexCount, jint indexOffset,
+         std::unique_ptr<MeshUniformBuilder> builder, const SkRect& bounds)
+            : mMeshSpec(meshSpec)
+            , mMode(mode)
+            , mVertexBufferData(std::move(vertexBufferData))
+            , mVertexCount(vertexCount)
+            , mVertexOffset(vertexOffset)
+            , mIndexBufferData(std::move(indexBuffer))
+            , mIndexCount(indexCount)
+            , mIndexOffset(indexOffset)
+            , mBuilder(std::move(builder))
+            , mBounds(bounds) {}
+
+    Mesh(Mesh&&) = default;
+
+    Mesh& operator=(Mesh&&) = default;
+
+    [[nodiscard]] std::tuple<bool, SkString> validate();
+
+    void updateSkMesh(GrDirectContext* context) const {
+        GrDirectContext::DirectContextID genId = GrDirectContext::DirectContextID();
+        if (context) {
+            genId = context->directContextID();
+        }
+
+        if (mIsDirty || genId != mGenerationId) {
+            auto vb = SkMesh::MakeVertexBuffer(
+                    context, reinterpret_cast<const void*>(mVertexBufferData.data()),
+                    mVertexBufferData.size());
+            auto meshMode = SkMesh::Mode(mMode);
+            if (!mIndexBufferData.empty()) {
+                auto ib = SkMesh::MakeIndexBuffer(
+                        context, reinterpret_cast<const void*>(mIndexBufferData.data()),
+                        mIndexBufferData.size());
+                mMesh = SkMesh::MakeIndexed(mMeshSpec, meshMode, vb, mVertexCount, mVertexOffset,
+                                            ib, mIndexCount, mIndexOffset, mBuilder->fUniforms,
+                                            mBounds)
+                                .mesh;
+            } else {
+                mMesh = SkMesh::Make(mMeshSpec, meshMode, vb, mVertexCount, mVertexOffset,
+                                     mBuilder->fUniforms, mBounds)
+                                .mesh;
+            }
+            mIsDirty = false;
+            mGenerationId = genId;
+        }
+    }
+
+    SkMesh& getSkMesh() const {
+        LOG_FATAL_IF(mIsDirty,
+                     "Attempt to obtain SkMesh when Mesh is dirty, did you "
+                     "forget to call updateSkMesh with a GrDirectContext? "
+                     "Defensively creating a CPU mesh");
+        return mMesh;
+    }
+
+    void markDirty() { mIsDirty = true; }
+
+    MeshUniformBuilder* uniformBuilder() { return mBuilder.get(); }
+
+private:
+    sk_sp<SkMeshSpecification> mMeshSpec;
+    int mMode = 0;
+
+    std::vector<uint8_t> mVertexBufferData;
+    size_t mVertexCount = 0;
+    size_t mVertexOffset = 0;
+
+    std::vector<uint8_t> mIndexBufferData;
+    size_t mIndexCount = 0;
+    size_t mIndexOffset = 0;
+
+    std::unique_ptr<MeshUniformBuilder> mBuilder;
+    SkRect mBounds{};
+
+    mutable SkMesh mMesh{};
+    mutable bool mIsDirty = true;
+    mutable GrDirectContext::DirectContextID mGenerationId = GrDirectContext::DirectContextID();
+};
+#endif  // MESH_H_
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 659aec0..0b58406 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -24,6 +24,7 @@
 #include <experimental/type_traits>
 #include <utility>
 
+#include "Mesh.h"
 #include "SkAndroidFrameworkUtils.h"
 #include "SkBlendMode.h"
 #include "SkCanvas.h"
@@ -502,14 +503,14 @@
         c->drawVertices(vertices, mode, paint);
     }
 };
-struct DrawMesh final : Op {
-    static const auto kType = Type::DrawMesh;
-    DrawMesh(const SkMesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint)
+struct DrawSkMesh final : Op {
+    static const auto kType = Type::DrawSkMesh;
+    DrawSkMesh(const SkMesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint)
             : cpuMesh(mesh), blender(std::move(blender)), paint(paint) {
         isGpuBased = false;
     }
 
-    SkMesh cpuMesh;
+    const SkMesh& cpuMesh;
     mutable SkMesh gpuMesh;
     sk_sp<SkBlender> blender;
     SkPaint paint;
@@ -517,6 +518,7 @@
     mutable GrDirectContext::DirectContextID contextId;
     void draw(SkCanvas* c, const SkMatrix&) const {
         GrDirectContext* directContext = c->recordingContext()->asDirectContext();
+
         GrDirectContext::DirectContextID id = directContext->directContextID();
         if (!isGpuBased || contextId != id) {
             sk_sp<SkMesh::VertexBuffer> vb =
@@ -543,6 +545,18 @@
         c->drawMesh(gpuMesh, blender, paint);
     }
 };
+
+struct DrawMesh final : Op {
+    static const auto kType = Type::DrawMesh;
+    DrawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint)
+            : mesh(mesh), blender(std::move(blender)), paint(paint) {}
+
+    const Mesh& mesh;
+    sk_sp<SkBlender> blender;
+    SkPaint paint;
+
+    void draw(SkCanvas* c, const SkMatrix&) const { c->drawMesh(mesh.getSkMesh(), blender, paint); }
+};
 struct DrawAtlas final : Op {
     static const auto kType = Type::DrawAtlas;
     DrawAtlas(const SkImage* atlas, int count, SkBlendMode mode, const SkSamplingOptions& sampling,
@@ -859,6 +873,10 @@
 }
 void DisplayListData::drawMesh(const SkMesh& mesh, const sk_sp<SkBlender>& blender,
                                const SkPaint& paint) {
+    this->push<DrawSkMesh>(0, mesh, blender, paint);
+}
+void DisplayListData::drawMesh(const Mesh& mesh, const sk_sp<SkBlender>& blender,
+                               const SkPaint& paint) {
     this->push<DrawMesh>(0, mesh, blender, paint);
 }
 void DisplayListData::drawAtlas(const SkImage* atlas, const SkRSXform xforms[], const SkRect texs[],
@@ -1205,6 +1223,9 @@
                                  const SkPaint& paint) {
     fDL->drawMesh(mesh, blender, paint);
 }
+void RecordingCanvas::drawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint) {
+    fDL->drawMesh(mesh, blender, paint);
+}
 void RecordingCanvas::onDrawAtlas2(const SkImage* atlas, const SkRSXform xforms[],
                                    const SkRect texs[], const SkColor colors[], int count,
                                    SkBlendMode bmode, const SkSamplingOptions& sampling,
@@ -1223,5 +1244,14 @@
     fDL->drawWebView(drawable);
 }
 
+[[nodiscard]] const SkMesh& DrawMeshPayload::getSkMesh() const {
+    LOG_FATAL_IF(!meshWrapper && !mesh, "One of Mesh or Mesh must be non-null");
+    if (meshWrapper) {
+        return meshWrapper->getSkMesh();
+    } else {
+        return *mesh;
+    }
+}
+
 }  // namespace uirenderer
 }  // namespace android
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 8409e13..1f4ba5d 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -28,6 +28,7 @@
 #include <log/log.h>
 
 #include <cstdlib>
+#include <utility>
 #include <vector>
 
 #include "CanvasTransform.h"
@@ -40,6 +41,7 @@
 
 enum class SkBlendMode;
 class SkRRect;
+class Mesh;
 
 namespace android {
 namespace uirenderer {
@@ -66,6 +68,18 @@
 
 static_assert(sizeof(DisplayListOp) == 4);
 
+class DrawMeshPayload {
+public:
+    explicit DrawMeshPayload(const SkMesh* mesh) : mesh(mesh) {}
+    explicit DrawMeshPayload(const Mesh* meshWrapper) : meshWrapper(meshWrapper) {}
+
+    [[nodiscard]] const SkMesh& getSkMesh() const;
+
+private:
+    const SkMesh* mesh = nullptr;
+    const Mesh* meshWrapper = nullptr;
+};
+
 struct DrawImagePayload {
     explicit DrawImagePayload(Bitmap& bitmap)
             : image(bitmap.makeImage()), palette(bitmap.palette()) {
@@ -143,6 +157,7 @@
     void drawDRRect(const SkRRect&, const SkRRect&, const SkPaint&);
 
     void drawMesh(const SkMesh&, const sk_sp<SkBlender>&, const SkPaint&);
+    void drawMesh(const Mesh&, const sk_sp<SkBlender>&, const SkPaint&);
 
     void drawAnnotation(const SkRect&, const char*, SkData*);
     void drawDrawable(SkDrawable*, const SkMatrix*);
@@ -247,6 +262,7 @@
                      SkBlendMode, const SkSamplingOptions&, const SkRect*, const SkPaint*) override;
     void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override;
 
+    void drawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint);
     void drawVectorDrawable(VectorDrawableRoot* tree);
     void drawWebView(skiapipeline::FunctorDrawable*);
 
diff --git a/libs/hwui/SafeMath.h b/libs/hwui/SafeMath.h
new file mode 100644
index 0000000..4d6adf5
--- /dev/null
+++ b/libs/hwui/SafeMath.h
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+#ifndef SkSafeMath_DEFINED
+#define SkSafeMath_DEFINED
+
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+
+// Copy of Skia's SafeMath API used to validate Mesh parameters to support
+// deferred creation of SkMesh instances on RenderThread.
+// SafeMath always check that a series of operations do not overflow.
+// This must be correct for all platforms, because this is a check for safety at runtime.
+
+class SafeMath {
+public:
+    SafeMath() = default;
+
+    bool ok() const { return fOK; }
+    explicit operator bool() const { return fOK; }
+
+    size_t mul(size_t x, size_t y) {
+        return sizeof(size_t) == sizeof(uint64_t) ? mul64(x, y) : mul32(x, y);
+    }
+
+    size_t add(size_t x, size_t y) {
+        size_t result = x + y;
+        fOK &= result >= x;
+        return result;
+    }
+
+    /**
+     *  Return a + b, unless this result is an overflow/underflow. In those cases, fOK will
+     *  be set to false, and it is undefined what this returns.
+     */
+    int addInt(int a, int b) {
+        if (b < 0 && a < std::numeric_limits<int>::min() - b) {
+            fOK = false;
+            return a;
+        } else if (b > 0 && a > std::numeric_limits<int>::max() - b) {
+            fOK = false;
+            return a;
+        }
+        return a + b;
+    }
+
+    // These saturate to their results
+    static size_t Add(size_t x, size_t y) {
+        SafeMath tmp;
+        size_t sum = tmp.add(x, y);
+        return tmp.ok() ? sum : SIZE_MAX;
+    }
+
+    static size_t Mul(size_t x, size_t y) {
+        SafeMath tmp;
+        size_t prod = tmp.mul(x, y);
+        return tmp.ok() ? prod : SIZE_MAX;
+    }
+
+private:
+    uint32_t mul32(uint32_t x, uint32_t y) {
+        uint64_t bx = x;
+        uint64_t by = y;
+        uint64_t result = bx * by;
+        fOK &= result >> 32 == 0;
+        // Overflow information is capture in fOK. Return the result modulo 2^32.
+        return (uint32_t)result;
+    }
+
+    uint64_t mul64(uint64_t x, uint64_t y) {
+        if (x <= std::numeric_limits<uint64_t>::max() >> 32 &&
+            y <= std::numeric_limits<uint64_t>::max() >> 32) {
+            return x * y;
+        } else {
+            auto hi = [](uint64_t x) { return x >> 32; };
+            auto lo = [](uint64_t x) { return x & 0xFFFFFFFF; };
+
+            uint64_t lx_ly = lo(x) * lo(y);
+            uint64_t hx_ly = hi(x) * lo(y);
+            uint64_t lx_hy = lo(x) * hi(y);
+            uint64_t hx_hy = hi(x) * hi(y);
+            uint64_t result = 0;
+            result = this->add(lx_ly, (hx_ly << 32));
+            result = this->add(result, (lx_hy << 32));
+            fOK &= (hx_hy + (hx_ly >> 32) + (lx_hy >> 32)) == 0;
+
+            return result;
+        }
+    }
+    bool fOK = true;
+};
+
+#endif  // SkSafeMath_DEFINED
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index d0124f5..7a12769 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -39,21 +39,22 @@
 #include <SkShader.h>
 #include <SkTextBlob.h>
 #include <SkVertices.h>
+#include <log/log.h>
+#include <ui/FatVector.h>
 
 #include <memory>
 #include <optional>
 #include <utility>
 
 #include "CanvasProperty.h"
+#include "Mesh.h"
 #include "NinePatchUtils.h"
 #include "VectorDrawable.h"
 #include "hwui/Bitmap.h"
 #include "hwui/MinikinUtils.h"
 #include "hwui/PaintFilter.h"
-#include <log/log.h>
 #include "pipeline/skia/AnimatedDrawables.h"
 #include "pipeline/skia/HolePunch.h"
-#include <ui/FatVector.h>
 
 namespace android {
 
@@ -572,8 +573,14 @@
     applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawVertices(vertices, mode, p); });
 }
 
-void SkiaCanvas::drawMesh(const SkMesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint) {
-    mCanvas->drawMesh(mesh, blender, paint);
+void SkiaCanvas::drawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const Paint& paint) {
+    GrDirectContext* context = nullptr;
+    auto recordingContext = mCanvas->recordingContext();
+    if (recordingContext) {
+        context = recordingContext->asDirectContext();
+    }
+    mesh.updateSkMesh(context);
+    mCanvas->drawMesh(mesh.getSkMesh(), blender, paint);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index f2c286a..b785989 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -129,8 +129,7 @@
                          float sweepAngle, bool useCenter, const Paint& paint) override;
     virtual void drawPath(const SkPath& path, const Paint& paint) override;
     virtual void drawVertices(const SkVertices*, SkBlendMode, const Paint& paint) override;
-    virtual void drawMesh(const SkMesh& mesh, sk_sp<SkBlender> blender,
-                          const SkPaint& paint) override;
+    virtual void drawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const Paint& paint) override;
 
     virtual void drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) override;
     virtual void drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const Paint* paint) override;
diff --git a/libs/hwui/apex/LayoutlibLoader.cpp b/libs/hwui/apex/LayoutlibLoader.cpp
index b7a1563..770822a 100644
--- a/libs/hwui/apex/LayoutlibLoader.cpp
+++ b/libs/hwui/apex/LayoutlibLoader.cpp
@@ -66,6 +66,7 @@
 extern int register_android_graphics_text_LineBreaker(JNIEnv* env);
 extern int register_android_graphics_text_MeasuredText(JNIEnv* env);
 extern int register_android_graphics_text_TextShaper(JNIEnv* env);
+extern int register_android_graphics_text_GraphemeBreak(JNIEnv* env);
 
 extern int register_android_util_PathParser(JNIEnv* env);
 extern int register_android_view_DisplayListCanvas(JNIEnv* env);
@@ -125,6 +126,8 @@
         {"android.graphics.text.MeasuredText",
          REG_JNI(register_android_graphics_text_MeasuredText)},
         {"android.graphics.text.TextRunShaper", REG_JNI(register_android_graphics_text_TextShaper)},
+        {"android.graphics.text.GraphemeBreak",
+         REG_JNI(register_android_graphics_text_GraphemeBreak)},
         {"android.util.PathParser", REG_JNI(register_android_util_PathParser)},
 };
 
diff --git a/libs/hwui/apex/jni_runtime.cpp b/libs/hwui/apex/jni_runtime.cpp
index c509ed4..09ae7e7 100644
--- a/libs/hwui/apex/jni_runtime.cpp
+++ b/libs/hwui/apex/jni_runtime.cpp
@@ -77,6 +77,7 @@
 extern int register_android_graphics_text_MeasuredText(JNIEnv* env);
 extern int register_android_graphics_text_LineBreaker(JNIEnv *env);
 extern int register_android_graphics_text_TextShaper(JNIEnv *env);
+extern int register_android_graphics_text_GraphemeBreak(JNIEnv* env);
 extern int register_android_graphics_MeshSpecification(JNIEnv* env);
 extern int register_android_graphics_Mesh(JNIEnv* env);
 
@@ -148,6 +149,7 @@
             REG_JNI(register_android_graphics_text_MeasuredText),
             REG_JNI(register_android_graphics_text_LineBreaker),
             REG_JNI(register_android_graphics_text_TextShaper),
+            REG_JNI(register_android_graphics_text_GraphemeBreak),
             REG_JNI(register_android_graphics_MeshSpecification),
             REG_JNI(register_android_graphics_Mesh),
 
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index ecf6cfc..b3eaa0c 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -463,6 +463,13 @@
     if (hasGainmap() && format == JavaCompressFormat::Jpeg) {
         SkBitmap baseBitmap = getSkBitmap();
         SkBitmap gainmapBitmap = gainmap()->bitmap->getSkBitmap();
+        if (gainmapBitmap.colorType() == SkColorType::kAlpha_8_SkColorType) {
+            SkBitmap greyGainmap;
+            auto greyInfo = gainmapBitmap.info().makeColorType(SkColorType::kGray_8_SkColorType);
+            greyGainmap.setInfo(greyInfo, gainmapBitmap.rowBytes());
+            greyGainmap.setPixelRef(sk_ref_sp(gainmapBitmap.pixelRef()), 0, 0);
+            gainmapBitmap = std::move(greyGainmap);
+        }
         SkJpegEncoder::Options options{.fQuality = quality};
         return SkJpegGainmapEncoder::EncodeHDRGM(stream, baseBitmap.pixmap(), options,
                                                  gainmapBitmap.pixmap(), options, gainmap()->info);
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index 2a20191..44ee31d 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -16,18 +16,17 @@
 
 #pragma once
 
-#include <cutils/compiler.h>
-#include <utils/Functor.h>
 #include <SaveFlags.h>
-
-#include <androidfw/ResourceTypes.h>
-#include "Properties.h"
-#include "pipeline/skia/AnimatedDrawables.h"
-#include "utils/Macros.h"
-
 #include <SkBitmap.h>
 #include <SkCanvas.h>
 #include <SkMatrix.h>
+#include <androidfw/ResourceTypes.h>
+#include <cutils/compiler.h>
+#include <utils/Functor.h>
+
+#include "Properties.h"
+#include "pipeline/skia/AnimatedDrawables.h"
+#include "utils/Macros.h"
 
 class SkAnimatedImage;
 enum class SkBlendMode;
@@ -35,6 +34,7 @@
 class SkRRect;
 class SkRuntimeShaderBuilder;
 class SkVertices;
+class Mesh;
 
 namespace minikin {
 class Font;
@@ -227,7 +227,7 @@
                          float sweepAngle, bool useCenter, const Paint& paint) = 0;
     virtual void drawPath(const SkPath& path, const Paint& paint) = 0;
     virtual void drawVertices(const SkVertices*, SkBlendMode, const Paint& paint) = 0;
-    virtual void drawMesh(const SkMesh& mesh, sk_sp<SkBlender>, const SkPaint& paint) = 0;
+    virtual void drawMesh(const Mesh& mesh, sk_sp<SkBlender>, const Paint& paint) = 0;
 
     // Bitmap-based
     virtual void drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) = 0;
diff --git a/libs/hwui/hwui/ImageDecoder.cpp b/libs/hwui/hwui/ImageDecoder.cpp
index 8266beb..9a06be0 100644
--- a/libs/hwui/hwui/ImageDecoder.cpp
+++ b/libs/hwui/hwui/ImageDecoder.cpp
@@ -498,7 +498,7 @@
     return result;
 }
 
-SkCodec::Result ImageDecoder::extractGainmap(Bitmap* destination) {
+SkCodec::Result ImageDecoder::extractGainmap(Bitmap* destination, bool isShared) {
     ATRACE_CALL();
     SkGainmapInfo gainmapInfo;
     std::unique_ptr<SkStream> gainmapStream;
@@ -553,9 +553,12 @@
         return SkCodec::kInternalError;
     }
 
-    // TODO: We don't currently parcel the gainmap, but if we should then also support
-    // the shared allocator
-    sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bm);
+    sk_sp<Bitmap> nativeBitmap;
+    if (isShared) {
+        nativeBitmap = Bitmap::allocateAshmemBitmap(&bm);
+    } else {
+        nativeBitmap = Bitmap::allocateHeapBitmap(&bm);
+    }
     if (!nativeBitmap) {
         ALOGE("OOM allocating Bitmap with dimensions %i x %i", bitmapInfo.width(),
               bitmapInfo.height());
diff --git a/libs/hwui/hwui/ImageDecoder.h b/libs/hwui/hwui/ImageDecoder.h
index 97573e1..b3781b5 100644
--- a/libs/hwui/hwui/ImageDecoder.h
+++ b/libs/hwui/hwui/ImageDecoder.h
@@ -79,7 +79,7 @@
     // Set whether the ImageDecoder should handle RestorePrevious frames.
     void setHandleRestorePrevious(bool handle);
 
-    SkCodec::Result extractGainmap(Bitmap* destination);
+    SkCodec::Result extractGainmap(Bitmap* destination, bool isShared);
 
 private:
     // State machine for keeping track of how to handle RestorePrevious (RP)
diff --git a/libs/hwui/jni/Bitmap.cpp b/libs/hwui/jni/Bitmap.cpp
index 3f9c4bd..6ee7576 100644
--- a/libs/hwui/jni/Bitmap.cpp
+++ b/libs/hwui/jni/Bitmap.cpp
@@ -386,15 +386,10 @@
             return NULL;
         }
         if (hasGainmap) {
-            auto gainmap = sp<uirenderer::Gainmap>::make();
-            gainmap->info = original.gainmap()->info;
-            const SkBitmap skSrcBitmap = original.gainmap()->bitmap->getSkBitmap();
-            sk_sp<Bitmap> skBitmap(Bitmap::allocateHardwareBitmap(skSrcBitmap));
-            if (!skBitmap.get()) {
-                return NULL;
+            auto gm = uirenderer::Gainmap::allocateHardwareGainmap(original.gainmap());
+            if (gm) {
+                bitmap->setGainmap(std::move(gm));
             }
-            gainmap->bitmap = std::move(skBitmap);
-            bitmap->setGainmap(std::move(gainmap));
         }
         return createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(isMutable));
     }
diff --git a/libs/hwui/jni/BitmapFactory.cpp b/libs/hwui/jni/BitmapFactory.cpp
index 571ab83..c57e6f0 100644
--- a/libs/hwui/jni/BitmapFactory.cpp
+++ b/libs/hwui/jni/BitmapFactory.cpp
@@ -637,7 +637,10 @@
             return nullObjectReturn("Failed to allocate a hardware bitmap");
         }
         if (hasGainmap) {
-            hardwareBitmap->setGainmap(std::move(gainmap));
+            auto gm = uirenderer::Gainmap::allocateHardwareGainmap(gainmap);
+            if (gm) {
+                hardwareBitmap->setGainmap(std::move(gm));
+            }
         }
 
         return bitmap::createBitmap(env, hardwareBitmap.release(), bitmapCreateFlags,
diff --git a/libs/hwui/jni/BitmapRegionDecoder.cpp b/libs/hwui/jni/BitmapRegionDecoder.cpp
index f93be03..aeaa171 100644
--- a/libs/hwui/jni/BitmapRegionDecoder.cpp
+++ b/libs/hwui/jni/BitmapRegionDecoder.cpp
@@ -334,7 +334,10 @@
     if (isHardware) {
         sk_sp<Bitmap> hardwareBitmap = Bitmap::allocateHardwareBitmap(bitmap);
         if (hasGainmap) {
-            hardwareBitmap->setGainmap(std::move(gainmap));
+            auto gm = uirenderer::Gainmap::allocateHardwareGainmap(gainmap);
+            if (gm) {
+                hardwareBitmap->setGainmap(std::move(gm));
+            }
         }
         return bitmap::createBitmap(env, hardwareBitmap.release(), bitmapCreateFlags);
     }
diff --git a/libs/hwui/jni/BufferUtils.cpp b/libs/hwui/jni/BufferUtils.cpp
new file mode 100644
index 0000000..3eb08d7
--- /dev/null
+++ b/libs/hwui/jni/BufferUtils.cpp
@@ -0,0 +1,130 @@
+/*
+ * 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 "BufferUtils.h"
+
+#include "graphics_jni_helpers.h"
+
+static void copyToVector(std::vector<uint8_t>& dst, const void* src, size_t srcSize) {
+    if (src) {
+        dst.resize(srcSize);
+        memcpy(dst.data(), src, srcSize);
+    }
+}
+
+/**
+ * This code is taken and modified from com_google_android_gles_jni_GLImpl.cpp to extract data
+ * from a java.nio.Buffer.
+ */
+static void* getDirectBufferPointer(JNIEnv* env, jobject buffer) {
+    if (buffer == nullptr) {
+        return nullptr;
+    }
+
+    jint position;
+    jint limit;
+    jint elementSizeShift;
+    jlong pointer;
+    pointer = jniGetNioBufferFields(env, buffer, &position, &limit, &elementSizeShift);
+    if (pointer == 0) {
+        jniThrowException(env, "java/lang/IllegalArgumentException",
+                          "Must use a native order direct Buffer");
+        return nullptr;
+    }
+    pointer += position << elementSizeShift;
+    return reinterpret_cast<void*>(pointer);
+}
+
+static void releasePointer(JNIEnv* env, jarray array, void* data, jboolean commit) {
+    env->ReleasePrimitiveArrayCritical(array, data, commit ? 0 : JNI_ABORT);
+}
+
+static void* getPointer(JNIEnv* env, jobject buffer, jarray* array, jint* remaining, jint* offset) {
+    jint position;
+    jint limit;
+    jint elementSizeShift;
+
+    jlong pointer;
+    pointer = jniGetNioBufferFields(env, buffer, &position, &limit, &elementSizeShift);
+    *remaining = (limit - position) << elementSizeShift;
+    if (pointer != 0L) {
+        *array = nullptr;
+        pointer += position << elementSizeShift;
+        return reinterpret_cast<void*>(pointer);
+    }
+
+    *array = jniGetNioBufferBaseArray(env, buffer);
+    *offset = jniGetNioBufferBaseArrayOffset(env, buffer);
+    return nullptr;
+}
+
+/**
+ * This is a copy of
+ * static void android_glBufferData__IILjava_nio_Buffer_2I
+ * from com_google_android_gles_jni_GLImpl.cpp
+ */
+static void setIndirectData(JNIEnv* env, size_t size, jobject data_buf,
+                            std::vector<uint8_t>& result) {
+    jint exception = 0;
+    const char* exceptionType = nullptr;
+    const char* exceptionMessage = nullptr;
+    jarray array = nullptr;
+    jint bufferOffset = 0;
+    jint remaining;
+    void* data = 0;
+    char* dataBase = nullptr;
+
+    if (data_buf) {
+        data = getPointer(env, data_buf, (jarray*)&array, &remaining, &bufferOffset);
+        if (remaining < size) {
+            exception = 1;
+            exceptionType = "java/lang/IllegalArgumentException";
+            exceptionMessage = "remaining() < size < needed";
+            goto exit;
+        }
+    }
+    if (data_buf && data == nullptr) {
+        dataBase = (char*)env->GetPrimitiveArrayCritical(array, (jboolean*)0);
+        data = (void*)(dataBase + bufferOffset);
+    }
+
+    copyToVector(result, data, size);
+
+exit:
+    if (array) {
+        releasePointer(env, array, (void*)dataBase, JNI_FALSE);
+    }
+    if (exception) {
+        jniThrowException(env, exceptionType, exceptionMessage);
+    }
+}
+
+std::vector<uint8_t> copyJavaNioBufferToVector(JNIEnv* env, jobject buffer, size_t size,
+                                               jboolean isDirect) {
+    std::vector<uint8_t> data;
+    if (buffer == nullptr) {
+        jniThrowNullPointerException(env);
+    } else {
+        if (isDirect) {
+            void* directBufferPtr = getDirectBufferPointer(env, buffer);
+            if (directBufferPtr) {
+                copyToVector(data, directBufferPtr, size);
+            }
+        } else {
+            setIndirectData(env, size, buffer, data);
+        }
+    }
+    return data;
+}
diff --git a/libs/hwui/jni/BufferUtils.h b/libs/hwui/jni/BufferUtils.h
new file mode 100644
index 0000000..b43c320
--- /dev/null
+++ b/libs/hwui/jni/BufferUtils.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef BUFFERUTILS_H_
+#define BUFFERUTILS_H_
+
+#include <jni.h>
+
+#include <vector>
+
+/**
+ * Helper method to load a java.nio.Buffer instance into a vector. This handles
+ * both direct and indirect buffers and promptly releases any critical arrays that
+ * have been retrieved in order to avoid potential jni exceptions due to interleaved
+ * jni calls between get/release primitive method invocations.
+ */
+std::vector<uint8_t> copyJavaNioBufferToVector(JNIEnv* env, jobject buffer, size_t size,
+                                               jboolean isDirect);
+
+#endif  // BUFFERUTILS_H_
diff --git a/libs/hwui/jni/ImageDecoder.cpp b/libs/hwui/jni/ImageDecoder.cpp
index fda7080..db1c188 100644
--- a/libs/hwui/jni/ImageDecoder.cpp
+++ b/libs/hwui/jni/ImageDecoder.cpp
@@ -354,7 +354,8 @@
     // cost of RAM
     if (result == SkCodec::kSuccess && !jpostProcess && !preferRamOverQuality) {
         // The gainmap costs RAM to improve quality, so skip this if we're prioritizing RAM instead
-        result = decoder->extractGainmap(nativeBitmap.get());
+        result = decoder->extractGainmap(nativeBitmap.get(),
+                                         allocator == kSharedMemory_Allocator ? true : false);
         jexception = get_and_clear_exception(env);
     }
 
@@ -469,8 +470,10 @@
             if (hwBitmap) {
                 hwBitmap->setImmutable();
                 if (nativeBitmap->hasGainmap()) {
-                    // TODO: Also convert to a HW gainmap image
-                    hwBitmap->setGainmap(nativeBitmap->gainmap());
+                    auto gm = uirenderer::Gainmap::allocateHardwareGainmap(nativeBitmap->gainmap());
+                    if (gm) {
+                        hwBitmap->setGainmap(std::move(gm));
+                    }
                 }
                 return bitmap::createBitmap(env, hwBitmap.release(), bitmapCreateFlags,
                                             ninePatchChunk, ninePatchInsets);
diff --git a/libs/hwui/jni/Interpolator.cpp b/libs/hwui/jni/Interpolator.cpp
index fc3d70b..c71e308 100644
--- a/libs/hwui/jni/Interpolator.cpp
+++ b/libs/hwui/jni/Interpolator.cpp
@@ -24,12 +24,8 @@
 
     AutoJavaFloatArray autoValues(env, valueArray);
     AutoJavaFloatArray autoBlend(env, blendArray, 4);
-#ifdef SK_SCALAR_IS_FLOAT
     SkScalar* scalars = autoValues.ptr();
     SkScalar* blend = autoBlend.ptr();
-#else
-    #error Need to convert float array to SkScalar array before calling the following function.
-#endif
 
     interp->setKeyFrame(index, msec, scalars, blend);
 }
diff --git a/libs/hwui/jni/Mesh.h b/libs/hwui/jni/Mesh.h
deleted file mode 100644
index 61c2260..0000000
--- a/libs/hwui/jni/Mesh.h
+++ /dev/null
@@ -1,265 +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.
- */
-
-#ifndef FRAMEWORKS_BASE_LIBS_HWUI_JNI_MESH_H_
-#define FRAMEWORKS_BASE_LIBS_HWUI_JNI_MESH_H_
-
-#include <SkMesh.h>
-#include <jni.h>
-
-#include <log/log.h>
-#include <utility>
-
-#include "graphics_jni_helpers.h"
-
-#define gIndexByteSize 2
-
-// A smart pointer that provides read only access to Java.nio.Buffer. This handles both
-// direct and indrect buffers, allowing access to the underlying data in both
-// situations. If passed a null buffer, we will throw NullPointerException,
-// and c_data will return nullptr.
-//
-// This class draws from com_google_android_gles_jni_GLImpl.cpp for Buffer to void *
-// conversion.
-class ScopedJavaNioBuffer {
-public:
-    ScopedJavaNioBuffer(JNIEnv* env, jobject buffer, jint size, jboolean isDirect)
-            : mEnv(env), mBuffer(buffer) {
-        if (buffer == nullptr) {
-            mDataBase = nullptr;
-            mData = nullptr;
-            jniThrowNullPointerException(env);
-        } else {
-            mArray = (jarray) nullptr;
-            if (isDirect) {
-                mData = getDirectBufferPointer(mEnv, mBuffer);
-            } else {
-                mData = setIndirectData(size);
-            }
-        }
-    }
-
-    ScopedJavaNioBuffer(ScopedJavaNioBuffer&& rhs) noexcept { *this = std::move(rhs); }
-
-    ~ScopedJavaNioBuffer() { reset(); }
-
-    void reset() {
-        if (mDataBase) {
-            releasePointer(mEnv, mArray, mDataBase, JNI_FALSE);
-            mDataBase = nullptr;
-        }
-    }
-
-    ScopedJavaNioBuffer& operator=(ScopedJavaNioBuffer&& rhs) noexcept {
-        if (this != &rhs) {
-            reset();
-
-            mEnv = rhs.mEnv;
-            mBuffer = rhs.mBuffer;
-            mDataBase = rhs.mDataBase;
-            mData = rhs.mData;
-            mArray = rhs.mArray;
-            rhs.mEnv = nullptr;
-            rhs.mData = nullptr;
-            rhs.mBuffer = nullptr;
-            rhs.mArray = nullptr;
-            rhs.mDataBase = nullptr;
-        }
-        return *this;
-    }
-
-    const void* data() const { return mData; }
-
-private:
-    /**
-     * This code is taken and modified from com_google_android_gles_jni_GLImpl.cpp to extract data
-     * from a java.nio.Buffer.
-     */
-    void* getDirectBufferPointer(JNIEnv* env, jobject buffer) {
-        if (buffer == nullptr) {
-            return nullptr;
-        }
-
-        jint position;
-        jint limit;
-        jint elementSizeShift;
-        jlong pointer;
-        pointer = jniGetNioBufferFields(env, buffer, &position, &limit, &elementSizeShift);
-        if (pointer == 0) {
-            jniThrowException(mEnv, "java/lang/IllegalArgumentException",
-                              "Must use a native order direct Buffer");
-            return nullptr;
-        }
-        pointer += position << elementSizeShift;
-        return reinterpret_cast<void*>(pointer);
-    }
-
-    static void releasePointer(JNIEnv* env, jarray array, void* data, jboolean commit) {
-        env->ReleasePrimitiveArrayCritical(array, data, commit ? 0 : JNI_ABORT);
-    }
-
-    static void* getPointer(JNIEnv* env, jobject buffer, jarray* array, jint* remaining,
-                            jint* offset) {
-        jint position;
-        jint limit;
-        jint elementSizeShift;
-
-        jlong pointer;
-        pointer = jniGetNioBufferFields(env, buffer, &position, &limit, &elementSizeShift);
-        *remaining = (limit - position) << elementSizeShift;
-        if (pointer != 0L) {
-            *array = nullptr;
-            pointer += position << elementSizeShift;
-            return reinterpret_cast<void*>(pointer);
-        }
-
-        *array = jniGetNioBufferBaseArray(env, buffer);
-        *offset = jniGetNioBufferBaseArrayOffset(env, buffer);
-        return nullptr;
-    }
-
-    /**
-     * This is a copy of
-     * static void android_glBufferData__IILjava_nio_Buffer_2I
-     * from com_google_android_gles_jni_GLImpl.cpp
-     */
-    void* setIndirectData(jint size) {
-        jint exception;
-        const char* exceptionType;
-        const char* exceptionMessage;
-        jint bufferOffset = (jint)0;
-        jint remaining;
-        void* tempData;
-
-        if (mBuffer) {
-            tempData =
-                    (void*)getPointer(mEnv, mBuffer, (jarray*)&mArray, &remaining, &bufferOffset);
-            if (remaining < size) {
-                exception = 1;
-                exceptionType = "java/lang/IllegalArgumentException";
-                exceptionMessage = "remaining() < size < needed";
-                goto exit;
-            }
-        }
-        if (mBuffer && tempData == nullptr) {
-            mDataBase = (char*)mEnv->GetPrimitiveArrayCritical(mArray, (jboolean*)0);
-            tempData = (void*)(mDataBase + bufferOffset);
-        }
-        return tempData;
-    exit:
-        if (mArray) {
-            releasePointer(mEnv, mArray, (void*)(mDataBase), JNI_FALSE);
-        }
-        if (exception) {
-            jniThrowException(mEnv, exceptionType, exceptionMessage);
-        }
-        return nullptr;
-    }
-
-    JNIEnv* mEnv;
-
-    // Java Buffer data
-    void* mData;
-    jobject mBuffer;
-
-    // Indirect Buffer Data
-    jarray mArray;
-    char* mDataBase;
-};
-
-class MeshUniformBuilder {
-public:
-    struct MeshUniform {
-        template <typename T>
-        std::enable_if_t<std::is_trivially_copyable<T>::value, MeshUniform> operator=(
-                const T& val) {
-            if (!fVar) {
-                LOG_FATAL("Assigning to missing variable");
-            } else if (sizeof(val) != fVar->sizeInBytes()) {
-                LOG_FATAL("Incorrect value size");
-            } else {
-                void* dst = reinterpret_cast<void*>(
-                    reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
-                memcpy(dst, &val, sizeof(val));
-            }
-        }
-
-        MeshUniform& operator=(const SkMatrix& val) {
-            if (!fVar) {
-                LOG_FATAL("Assigning to missing variable");
-            } else if (fVar->sizeInBytes() != 9 * sizeof(float)) {
-                LOG_FATAL("Incorrect value size");
-            } else {
-                float* data = reinterpret_cast<float*>(
-                    reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
-                data[0] = val.get(0);
-                data[1] = val.get(3);
-                data[2] = val.get(6);
-                data[3] = val.get(1);
-                data[4] = val.get(4);
-                data[5] = val.get(7);
-                data[6] = val.get(2);
-                data[7] = val.get(5);
-                data[8] = val.get(8);
-            }
-            return *this;
-        }
-
-        template <typename T>
-        bool set(const T val[], const int count) {
-            static_assert(std::is_trivially_copyable<T>::value, "Value must be trivial copyable");
-            if (!fVar) {
-                LOG_FATAL("Assigning to missing variable");
-                return false;
-            } else if (sizeof(T) * count != fVar->sizeInBytes()) {
-                LOG_FATAL("Incorrect value size");
-                return false;
-            } else {
-                void* dst = reinterpret_cast<void*>(
-                    reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
-                memcpy(dst, val, sizeof(T) * count);
-            }
-            return true;
-        }
-
-        MeshUniformBuilder* fOwner;
-        const SkRuntimeEffect::Uniform* fVar;
-    };
-    MeshUniform uniform(std::string_view name) { return {this, fMeshSpec->findUniform(name)}; }
-
-    explicit MeshUniformBuilder(sk_sp<SkMeshSpecification> meshSpec) {
-        fMeshSpec = sk_sp(meshSpec);
-        fUniforms = (SkData::MakeZeroInitialized(meshSpec->uniformSize()));
-    }
-
-    sk_sp<SkData> fUniforms;
-
-private:
-    void* writableUniformData() {
-        if (!fUniforms->unique()) {
-            fUniforms = SkData::MakeWithCopy(fUniforms->data(), fUniforms->size());
-        }
-        return fUniforms->writable_data();
-    }
-
-    sk_sp<SkMeshSpecification> fMeshSpec;
-};
-
-struct MeshWrapper {
-    SkMesh mesh;
-    MeshUniformBuilder builder;
-};
-#endif  // FRAMEWORKS_BASE_LIBS_HWUI_JNI_MESH_H_
diff --git a/libs/hwui/jni/Path.cpp b/libs/hwui/jni/Path.cpp
index 3694ce0..a5e0476 100644
--- a/libs/hwui/jni/Path.cpp
+++ b/libs/hwui/jni/Path.cpp
@@ -182,11 +182,7 @@
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         SkPathDirection dir = static_cast<SkPathDirection>(dirHandle);
         AutoJavaFloatArray  afa(env, array, 8);
-#ifdef SK_SCALAR_IS_FLOAT
         const float* src = afa.ptr();
-#else
-        #error Need to convert float array to SkScalar array before calling the following function.
-#endif
         obj->addRoundRect(rect, src, dir);
     }
 
diff --git a/libs/hwui/jni/PathEffect.cpp b/libs/hwui/jni/PathEffect.cpp
index f99bef7..3dbe1a6 100644
--- a/libs/hwui/jni/PathEffect.cpp
+++ b/libs/hwui/jni/PathEffect.cpp
@@ -35,11 +35,7 @@
                                       jfloatArray intervalArray, jfloat phase) {
         AutoJavaFloatArray autoInterval(env, intervalArray);
         int         count = autoInterval.length() & ~1;  // even number
-#ifdef SK_SCALAR_IS_FLOAT
-        SkScalar*   intervals = autoInterval.ptr();
-#else
-        #error Need to convert float array to SkScalar array before calling the following function.
-#endif
+        SkScalar* intervals = autoInterval.ptr();
         SkPathEffect* effect = SkDashPathEffect::Make(intervals, count, phase).release();
         return reinterpret_cast<jlong>(effect);
     }
diff --git a/libs/hwui/jni/Shader.cpp b/libs/hwui/jni/Shader.cpp
index 8a0db1c..75d45e5 100644
--- a/libs/hwui/jni/Shader.cpp
+++ b/libs/hwui/jni/Shader.cpp
@@ -52,12 +52,7 @@
 static jint Color_HSVToColor(JNIEnv* env, jobject, jint alpha, jfloatArray hsvArray)
 {
     AutoJavaFloatArray  autoHSV(env, hsvArray, 3);
-#ifdef SK_SCALAR_IS_FLOAT
-    SkScalar*   hsv = autoHSV.ptr();
-#else
-    #error Need to convert float array to SkScalar array before calling the following function.
-#endif
-
+    SkScalar* hsv = autoHSV.ptr();
     return static_cast<jint>(SkHSVToColor(alpha, hsv));
 }
 
@@ -149,11 +144,7 @@
     std::vector<SkColor4f> colors = convertColorLongs(env, colorArray);
 
     AutoJavaFloatArray autoPos(env, posArray, colors.size());
-#ifdef SK_SCALAR_IS_FLOAT
     SkScalar* pos = autoPos.ptr();
-#else
-    #error Need to convert float array to SkScalar array before calling the following function.
-#endif
 
     sk_sp<SkShader> shader(SkGradientShader::MakeLinear(pts, &colors[0],
                 GraphicsJNI::getNativeColorSpace(colorSpaceHandle), pos, colors.size(),
@@ -193,11 +184,7 @@
     std::vector<SkColor4f> colors = convertColorLongs(env, colorArray);
 
     AutoJavaFloatArray autoPos(env, posArray, colors.size());
-#ifdef SK_SCALAR_IS_FLOAT
     SkScalar* pos = autoPos.ptr();
-#else
-    #error Need to convert float array to SkScalar array before calling the following function.
-#endif
 
     auto colorSpace = GraphicsJNI::getNativeColorSpace(colorSpaceHandle);
     auto skTileMode = static_cast<SkTileMode>(tileMode);
@@ -225,11 +212,7 @@
     std::vector<SkColor4f> colors = convertColorLongs(env, colorArray);
 
     AutoJavaFloatArray autoPos(env, jpositions, colors.size());
-#ifdef SK_SCALAR_IS_FLOAT
     SkScalar* pos = autoPos.ptr();
-#else
-    #error Need to convert float array to SkScalar array before calling the following function.
-#endif
 
     sk_sp<SkShader> shader = SkGradientShader::MakeSweep(x, y, &colors[0],
             GraphicsJNI::getNativeColorSpace(colorSpaceHandle), pos, colors.size(),
diff --git a/libs/hwui/jni/android_graphics_Canvas.cpp b/libs/hwui/jni/android_graphics_Canvas.cpp
index 8a4d4e1..8ba7503 100644
--- a/libs/hwui/jni/android_graphics_Canvas.cpp
+++ b/libs/hwui/jni/android_graphics_Canvas.cpp
@@ -21,7 +21,6 @@
 #else
 #define __ANDROID_API_P__ 28
 #endif
-#include <Mesh.h>
 #include <androidfw/ResourceTypes.h>
 #include <hwui/Canvas.h>
 #include <hwui/Paint.h>
@@ -446,10 +445,10 @@
 
 static void drawMesh(JNIEnv* env, jobject, jlong canvasHandle, jlong meshHandle, jint modeHandle,
                      jlong paintHandle) {
-    const SkMesh mesh = reinterpret_cast<MeshWrapper*>(meshHandle)->mesh;
+    const Mesh* mesh = reinterpret_cast<Mesh*>(meshHandle);
     SkBlendMode blendMode = static_cast<SkBlendMode>(modeHandle);
-    SkPaint* paint = reinterpret_cast<Paint*>(paintHandle);
-    get_canvas(canvasHandle)->drawMesh(mesh, SkBlender::Mode(blendMode), *paint);
+    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
+    get_canvas(canvasHandle)->drawMesh(*mesh, SkBlender::Mode(blendMode), *paint);
 }
 
 static void drawNinePatch(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
diff --git a/libs/hwui/jni/android_graphics_Matrix.cpp b/libs/hwui/jni/android_graphics_Matrix.cpp
index cf6702e..ca667b0 100644
--- a/libs/hwui/jni/android_graphics_Matrix.cpp
+++ b/libs/hwui/jni/android_graphics_Matrix.cpp
@@ -23,8 +23,6 @@
 
 static_assert(sizeof(SkMatrix) == 40, "Unexpected sizeof(SkMatrix), "
         "update size in Matrix.java#NATIVE_ALLOCATION_SIZE and here");
-static_assert(SK_SCALAR_IS_FLOAT, "SK_SCALAR_IS_FLOAT is false, "
-        "only float scalar is supported");
 
 class SkMatrixGlue {
 public:
diff --git a/libs/hwui/jni/Mesh.cpp b/libs/hwui/jni/android_graphics_Mesh.cpp
similarity index 63%
rename from libs/hwui/jni/Mesh.cpp
rename to libs/hwui/jni/android_graphics_Mesh.cpp
index b13d9ba..5cb43e5 100644
--- a/libs/hwui/jni/Mesh.cpp
+++ b/libs/hwui/jni/android_graphics_Mesh.cpp
@@ -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,47 +14,37 @@
  * limitations under the License.
  */
 
-#include <GLES/gl.h>
 #include <Mesh.h>
 #include <SkMesh.h>
+#include <jni.h>
 
+#include <utility>
+
+#include "BufferUtils.h"
 #include "GraphicsJNI.h"
 #include "graphics_jni_helpers.h"
 
+#define gIndexByteSize 2
+
 namespace android {
 
-sk_sp<SkMesh::VertexBuffer> genVertexBuffer(JNIEnv* env, jobject buffer, int size,
-                                            jboolean isDirect) {
-    auto buff = ScopedJavaNioBuffer(env, buffer, size, isDirect);
-    auto vertexBuffer = SkMesh::MakeVertexBuffer(nullptr, buff.data(), size);
-    return vertexBuffer;
-}
-
-sk_sp<SkMesh::IndexBuffer> genIndexBuffer(JNIEnv* env, jobject buffer, int size,
-                                          jboolean isDirect) {
-    auto buff = ScopedJavaNioBuffer(env, buffer, size, isDirect);
-    auto indexBuffer = SkMesh::MakeIndexBuffer(nullptr, buff.data(), size);
-    return indexBuffer;
-}
-
 static jlong make(JNIEnv* env, jobject, jlong meshSpec, jint mode, jobject vertexBuffer,
                   jboolean isDirect, jint vertexCount, jint vertexOffset, jfloat left, jfloat top,
                   jfloat right, jfloat bottom) {
     auto skMeshSpec = sk_ref_sp(reinterpret_cast<SkMeshSpecification*>(meshSpec));
-    sk_sp<SkMesh::VertexBuffer> skVertexBuffer =
-            genVertexBuffer(env, vertexBuffer, vertexCount * skMeshSpec->stride(), isDirect);
-    auto skRect = SkRect::MakeLTRB(left, top, right, bottom);
-    auto meshResult = SkMesh::Make(
-            skMeshSpec, SkMesh::Mode(mode), skVertexBuffer, vertexCount, vertexOffset,
-            SkData::MakeWithCopy(skMeshSpec->uniforms().data(), skMeshSpec->uniformSize()), skRect);
-
-    if (!meshResult.error.isEmpty()) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", meshResult.error.c_str());
+    size_t bufferSize = vertexCount * skMeshSpec->stride();
+    auto buffer = copyJavaNioBufferToVector(env, vertexBuffer, bufferSize, isDirect);
+    if (env->ExceptionCheck()) {
+        return 0;
     }
-
-    auto meshPtr = std::make_unique<MeshWrapper>(
-            MeshWrapper{meshResult.mesh, MeshUniformBuilder(skMeshSpec)});
-    return reinterpret_cast<jlong>(meshPtr.release());
+    auto skRect = SkRect::MakeLTRB(left, top, right, bottom);
+    auto meshPtr = new Mesh(skMeshSpec, mode, std::move(buffer), vertexCount, vertexOffset,
+                            std::make_unique<MeshUniformBuilder>(skMeshSpec), skRect);
+    auto [valid, msg] = meshPtr->validate();
+    if (!valid) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", msg.c_str());
+    }
+    return reinterpret_cast<jlong>(meshPtr);
 }
 
 static jlong makeIndexed(JNIEnv* env, jobject, jlong meshSpec, jint mode, jobject vertexBuffer,
@@ -62,41 +52,26 @@
                          jobject indexBuffer, jboolean isIndexDirect, jint indexCount,
                          jint indexOffset, jfloat left, jfloat top, jfloat right, jfloat bottom) {
     auto skMeshSpec = sk_ref_sp(reinterpret_cast<SkMeshSpecification*>(meshSpec));
-    sk_sp<SkMesh::VertexBuffer> skVertexBuffer =
-            genVertexBuffer(env, vertexBuffer, vertexCount * skMeshSpec->stride(), isVertexDirect);
-    sk_sp<SkMesh::IndexBuffer> skIndexBuffer =
-            genIndexBuffer(env, indexBuffer, indexCount * gIndexByteSize, isIndexDirect);
+    auto vertexBufferSize = vertexCount * skMeshSpec->stride();
+    auto indexBufferSize = indexCount * gIndexByteSize;
+    auto vBuf = copyJavaNioBufferToVector(env, vertexBuffer, vertexBufferSize, isVertexDirect);
+    if (env->ExceptionCheck()) {
+        return 0;
+    }
+    auto iBuf = copyJavaNioBufferToVector(env, indexBuffer, indexBufferSize, isIndexDirect);
+    if (env->ExceptionCheck()) {
+        return 0;
+    }
     auto skRect = SkRect::MakeLTRB(left, top, right, bottom);
-
-    auto meshResult = SkMesh::MakeIndexed(
-            skMeshSpec, SkMesh::Mode(mode), skVertexBuffer, vertexCount, vertexOffset,
-            skIndexBuffer, indexCount, indexOffset,
-            SkData::MakeWithCopy(skMeshSpec->uniforms().data(), skMeshSpec->uniformSize()), skRect);
-
-    if (!meshResult.error.isEmpty()) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", meshResult.error.c_str());
+    auto meshPtr = new Mesh(skMeshSpec, mode, std::move(vBuf), vertexCount, vertexOffset,
+                            std::move(iBuf), indexCount, indexOffset,
+                            std::make_unique<MeshUniformBuilder>(skMeshSpec), skRect);
+    auto [valid, msg] = meshPtr->validate();
+    if (!valid) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", msg.c_str());
     }
-    auto meshPtr = std::make_unique<MeshWrapper>(
-            MeshWrapper{meshResult.mesh, MeshUniformBuilder(skMeshSpec)});
-    return reinterpret_cast<jlong>(meshPtr.release());
-}
 
-static void updateMesh(JNIEnv* env, jobject, jlong meshWrapper, jboolean indexed) {
-    auto wrapper = reinterpret_cast<MeshWrapper*>(meshWrapper);
-    auto mesh = wrapper->mesh;
-    if (indexed) {
-        wrapper->mesh = SkMesh::MakeIndexed(sk_ref_sp(mesh.spec()), mesh.mode(),
-                                            sk_ref_sp(mesh.vertexBuffer()), mesh.vertexCount(),
-                                            mesh.vertexOffset(), sk_ref_sp(mesh.indexBuffer()),
-                                            mesh.indexCount(), mesh.indexOffset(),
-                                            wrapper->builder.fUniforms, mesh.bounds())
-                                .mesh;
-    } else {
-        wrapper->mesh = SkMesh::Make(sk_ref_sp(mesh.spec()), mesh.mode(),
-                                     sk_ref_sp(mesh.vertexBuffer()), mesh.vertexCount(),
-                                     mesh.vertexOffset(), wrapper->builder.fUniforms, mesh.bounds())
-                                .mesh;
-    }
+    return reinterpret_cast<jlong>(meshPtr);
 }
 
 static inline int ThrowIAEFmt(JNIEnv* env, const char* fmt, ...) {
@@ -154,19 +129,21 @@
 static void updateFloatUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring uniformName,
                                 jfloat value1, jfloat value2, jfloat value3, jfloat value4,
                                 jint count) {
-    auto* wrapper = reinterpret_cast<MeshWrapper*>(meshWrapper);
+    auto* wrapper = reinterpret_cast<Mesh*>(meshWrapper);
     ScopedUtfChars name(env, uniformName);
     const float values[4] = {value1, value2, value3, value4};
-    nativeUpdateFloatUniforms(env, &wrapper->builder, name.c_str(), values, count, false);
+    nativeUpdateFloatUniforms(env, wrapper->uniformBuilder(), name.c_str(), values, count, false);
+    wrapper->markDirty();
 }
 
 static void updateFloatArrayUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring jUniformName,
                                      jfloatArray jvalues, jboolean isColor) {
-    auto wrapper = reinterpret_cast<MeshWrapper*>(meshWrapper);
+    auto wrapper = reinterpret_cast<Mesh*>(meshWrapper);
     ScopedUtfChars name(env, jUniformName);
     AutoJavaFloatArray autoValues(env, jvalues, 0, kRO_JNIAccess);
-    nativeUpdateFloatUniforms(env, &wrapper->builder, name.c_str(), autoValues.ptr(),
+    nativeUpdateFloatUniforms(env, wrapper->uniformBuilder(), name.c_str(), autoValues.ptr(),
                               autoValues.length(), isColor);
+    wrapper->markDirty();
 }
 
 static void nativeUpdateIntUniforms(JNIEnv* env, MeshUniformBuilder* builder,
@@ -185,22 +162,24 @@
 
 static void updateIntUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring uniformName,
                               jint value1, jint value2, jint value3, jint value4, jint count) {
-    auto wrapper = reinterpret_cast<MeshWrapper*>(meshWrapper);
+    auto wrapper = reinterpret_cast<Mesh*>(meshWrapper);
     ScopedUtfChars name(env, uniformName);
     const int values[4] = {value1, value2, value3, value4};
-    nativeUpdateIntUniforms(env, &wrapper->builder, name.c_str(), values, count);
+    nativeUpdateIntUniforms(env, wrapper->uniformBuilder(), name.c_str(), values, count);
+    wrapper->markDirty();
 }
 
 static void updateIntArrayUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring uniformName,
                                    jintArray values) {
-    auto wrapper = reinterpret_cast<MeshWrapper*>(meshWrapper);
+    auto wrapper = reinterpret_cast<Mesh*>(meshWrapper);
     ScopedUtfChars name(env, uniformName);
     AutoJavaIntArray autoValues(env, values, 0);
-    nativeUpdateIntUniforms(env, &wrapper->builder, name.c_str(), autoValues.ptr(),
+    nativeUpdateIntUniforms(env, wrapper->uniformBuilder(), name.c_str(), autoValues.ptr(),
                             autoValues.length());
+    wrapper->markDirty();
 }
 
-static void MeshWrapper_destroy(MeshWrapper* wrapper) {
+static void MeshWrapper_destroy(Mesh* wrapper) {
     delete wrapper;
 }
 
@@ -213,7 +192,6 @@
         {"nativeMake", "(JILjava/nio/Buffer;ZIIFFFF)J", (void*)make},
         {"nativeMakeIndexed", "(JILjava/nio/Buffer;ZIILjava/nio/ShortBuffer;ZIIFFFF)J",
          (void*)makeIndexed},
-        {"nativeUpdateMesh", "(JZ)V", (void*)updateMesh},
         {"nativeUpdateUniforms", "(JLjava/lang/String;[FZ)V", (void*)updateFloatArrayUniforms},
         {"nativeUpdateUniforms", "(JLjava/lang/String;FFFFI)V", (void*)updateFloatUniforms},
         {"nativeUpdateUniforms", "(JLjava/lang/String;[I)V", (void*)updateIntArrayUniforms},
@@ -224,4 +202,4 @@
     return 0;
 }
 
-}  // namespace android
+}  // namespace android
\ No newline at end of file
diff --git a/libs/hwui/jni/fonts/Font.cpp b/libs/hwui/jni/fonts/Font.cpp
index f17129c..1af60b2 100644
--- a/libs/hwui/jni/fonts/Font.cpp
+++ b/libs/hwui/jni/fonts/Font.cpp
@@ -108,8 +108,9 @@
         std::move(data), std::string_view(fontPath.c_str(), fontPath.size()),
         fontPtr, fontSize, ttcIndex, builder->axes);
     if (minikinFont == nullptr) {
-        jniThrowException(env, "java/lang/IllegalArgumentException",
-                          "Failed to create internal object. maybe invalid font data.");
+        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+                             "Failed to create internal object. maybe invalid font data. filePath %s",
+                             fontPath.c_str());
         return 0;
     }
     uint32_t localeListId = minikin::registerLocaleList(langTagStr.c_str());
diff --git a/libs/hwui/jni/text/GraphemeBreak.cpp b/libs/hwui/jni/text/GraphemeBreak.cpp
new file mode 100644
index 0000000..55f03bd
--- /dev/null
+++ b/libs/hwui/jni/text/GraphemeBreak.cpp
@@ -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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "GraphemeBreaker"
+
+#include <minikin/GraphemeBreak.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
+
+#include "GraphicsJNI.h"
+
+namespace android {
+
+static void nIsGraphemeBreak(JNIEnv* env, jclass, jfloatArray advances, jcharArray text, jint start,
+                             jint end, jbooleanArray isGraphemeBreak) {
+    if (start > end || env->GetArrayLength(advances) < end ||
+        env->GetArrayLength(isGraphemeBreak) < end - start) {
+        doThrowAIOOBE(env);
+    }
+
+    if (start == end) {
+        return;
+    }
+
+    ScopedFloatArrayRO advancesArray(env, advances);
+    ScopedCharArrayRO textArray(env, text);
+    ScopedBooleanArrayRW isGraphemeBreakArray(env, isGraphemeBreak);
+
+    size_t count = end - start;
+    for (size_t offset = 0; offset < count; ++offset) {
+        bool isBreak = minikin::GraphemeBreak::isGraphemeBreak(advancesArray.get(), textArray.get(),
+                                                               start, end, start + offset);
+        isGraphemeBreakArray[offset] = isBreak ? JNI_TRUE : JNI_FALSE;
+    }
+}
+
+static const JNINativeMethod gMethods[] = {
+        {"nIsGraphemeBreak",
+         "("
+         "[F"  // advances
+         "[C"  // text
+         "I"   // start
+         "I"   // end
+         "[Z"  // isGraphemeBreak
+         ")V",
+         (void*)nIsGraphemeBreak},
+};
+
+int register_android_graphics_text_GraphemeBreak(JNIEnv* env) {
+    return RegisterMethodsOrDie(env, "android/graphics/text/GraphemeBreak", gMethods,
+                                NELEM(gMethods));
+}
+
+}  // namespace android
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
index fcfc4f8..af2d3b3 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
@@ -23,6 +23,7 @@
 #else
 #include "DamageAccumulator.h"
 #endif
+#include "TreeInfo.h"
 #include "VectorDrawable.h"
 #ifdef __ANDROID__
 #include "renderthread/CanvasContext.h"
@@ -102,6 +103,12 @@
         info.prepareTextures = false;
         info.canvasContext.unpinImages();
     }
+
+    auto grContext = info.canvasContext.getGrContext();
+    for (auto mesh : mMeshes) {
+        mesh->updateSkMesh(grContext);
+    }
+
 #endif
 
     bool hasBackwardProjectedNodesHere = false;
@@ -168,6 +175,7 @@
 
     mDisplayList.reset();
 
+    mMeshes.clear();
     mMutableImages.clear();
     mVectorDrawables.clear();
     mAnimatedImages.clear();
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h
index 2a67734..7af31a4 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.h
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h
@@ -18,6 +18,7 @@
 
 #include <deque>
 
+#include "Mesh.h"
 #include "RecordingCanvas.h"
 #include "RenderNodeDrawable.h"
 #include "TreeInfo.h"
@@ -167,6 +168,7 @@
     std::deque<RenderNodeDrawable> mChildNodes;
     std::deque<FunctorDrawable*> mChildFunctors;
     std::vector<SkImage*> mMutableImages;
+    std::vector<const Mesh*> mMeshes;
 
 private:
     std::vector<Pair<VectorDrawableRoot*, SkMatrix>> mVectorDrawables;
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index e1c8877..3ca7eeb 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -321,6 +321,11 @@
     return 0;
 }
 
+void SkiaRecordingCanvas::drawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const Paint& paint) {
+    mDisplayList->mMeshes.push_back(&mesh);
+    mRecorder.drawMesh(mesh, blender, paint);
+}
+
 }  // namespace skiapipeline
 }  // namespace uirenderer
 }  // namespace android
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
index 3fd8fa3..a8e4580 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
@@ -81,6 +81,7 @@
     virtual void drawVectorDrawable(VectorDrawableRoot* vectorDrawable) override;
 
     virtual void enableZ(bool enableZ) override;
+    virtual void drawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const Paint& paint) override;
     virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) override;
     virtual void drawRenderNode(uirenderer::RenderNode* renderNode) override;
 
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 7a7f1ab..0afd949 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -135,7 +135,9 @@
         !mFrameCallbackTaskPending) {
         ATRACE_NAME("queue mFrameCallbackTask");
         mFrameCallbackTaskPending = true;
-        nsecs_t runAt = (frameTimeNanos + mDispatchFrameDelay);
+
+        nsecs_t timeUntilDeadline = frameDeadline - frameTimeNanos;
+        nsecs_t runAt = (frameTimeNanos + (timeUntilDeadline * 0.25f));
         queue().postAt(runAt, [=]() { dispatchFrameCallbacks(); });
     }
 }
@@ -257,7 +259,6 @@
 void RenderThread::setupFrameInterval() {
     nsecs_t frameIntervalNanos = DeviceInfo::getVsyncPeriod();
     mTimeLord.setFrameInterval(frameIntervalNanos);
-    mDispatchFrameDelay = static_cast<nsecs_t>(frameIntervalNanos * .25f);
 }
 
 void RenderThread::requireGlContext() {
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 0a89e5e..c77cd41 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -235,7 +235,6 @@
     bool mFrameCallbackTaskPending;
 
     TimeLord mTimeLord;
-    nsecs_t mDispatchFrameDelay = 4_ms;
     RenderState* mRenderState;
     EglManager* mEglManager;
     WebViewFunctorManager& mFunctorManager;
diff --git a/libs/input/MouseCursorController.cpp b/libs/input/MouseCursorController.cpp
index 24cfc9d..c398405 100644
--- a/libs/input/MouseCursorController.cpp
+++ b/libs/input/MouseCursorController.cpp
@@ -63,24 +63,23 @@
     mLocked.pointerSprite.clear();
 }
 
-bool MouseCursorController::getBounds(float* outMinX, float* outMinY, float* outMaxX,
-                                      float* outMaxY) const {
+std::optional<FloatRect> MouseCursorController::getBounds() const {
     std::scoped_lock lock(mLock);
 
-    return getBoundsLocked(outMinX, outMinY, outMaxX, outMaxY);
+    return getBoundsLocked();
 }
 
-bool MouseCursorController::getBoundsLocked(float* outMinX, float* outMinY, float* outMaxX,
-                                            float* outMaxY) const REQUIRES(mLock) {
+std::optional<FloatRect> MouseCursorController::getBoundsLocked() const REQUIRES(mLock) {
     if (!mLocked.viewport.isValid()) {
-        return false;
+        return {};
     }
 
-    *outMinX = mLocked.viewport.logicalLeft;
-    *outMinY = mLocked.viewport.logicalTop;
-    *outMaxX = mLocked.viewport.logicalRight - 1;
-    *outMaxY = mLocked.viewport.logicalBottom - 1;
-    return true;
+    return FloatRect{
+            static_cast<float>(mLocked.viewport.logicalLeft),
+            static_cast<float>(mLocked.viewport.logicalTop),
+            static_cast<float>(mLocked.viewport.logicalRight - 1),
+            static_cast<float>(mLocked.viewport.logicalBottom - 1),
+    };
 }
 
 void MouseCursorController::move(float deltaX, float deltaY) {
@@ -121,31 +120,19 @@
 }
 
 void MouseCursorController::setPositionLocked(float x, float y) REQUIRES(mLock) {
-    float minX, minY, maxX, maxY;
-    if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
-        if (x <= minX) {
-            mLocked.pointerX = minX;
-        } else if (x >= maxX) {
-            mLocked.pointerX = maxX;
-        } else {
-            mLocked.pointerX = x;
-        }
-        if (y <= minY) {
-            mLocked.pointerY = minY;
-        } else if (y >= maxY) {
-            mLocked.pointerY = maxY;
-        } else {
-            mLocked.pointerY = y;
-        }
-        updatePointerLocked();
-    }
+    const auto bounds = getBoundsLocked();
+    if (!bounds) return;
+
+    mLocked.pointerX = std::max(bounds->left, std::min(bounds->right, x));
+    mLocked.pointerY = std::max(bounds->top, std::min(bounds->bottom, y));
+
+    updatePointerLocked();
 }
 
-void MouseCursorController::getPosition(float* outX, float* outY) const {
+FloatPoint MouseCursorController::getPosition() const {
     std::scoped_lock lock(mLock);
 
-    *outX = mLocked.pointerX;
-    *outY = mLocked.pointerY;
+    return {mLocked.pointerX, mLocked.pointerY};
 }
 
 int32_t MouseCursorController::getDisplayId() const {
@@ -235,10 +222,9 @@
     // Reset cursor position to center if size or display changed.
     if (oldViewport.displayId != viewport.displayId || oldDisplayWidth != newDisplayWidth ||
         oldDisplayHeight != newDisplayHeight) {
-        float minX, minY, maxX, maxY;
-        if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
-            mLocked.pointerX = (minX + maxX) * 0.5f;
-            mLocked.pointerY = (minY + maxY) * 0.5f;
+        if (const auto bounds = getBoundsLocked(); bounds) {
+            mLocked.pointerX = (bounds->left + bounds->right) * 0.5f;
+            mLocked.pointerY = (bounds->top + bounds->bottom) * 0.5f;
             // Reload icon resources for density may be changed.
             loadResourcesLocked(getAdditionalMouseResources);
         } else {
diff --git a/libs/input/MouseCursorController.h b/libs/input/MouseCursorController.h
index db0ab56..26be2a8 100644
--- a/libs/input/MouseCursorController.h
+++ b/libs/input/MouseCursorController.h
@@ -43,12 +43,12 @@
     MouseCursorController(PointerControllerContext& context);
     ~MouseCursorController();
 
-    bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const;
+    std::optional<FloatRect> getBounds() const;
     void move(float deltaX, float deltaY);
     void setButtonState(int32_t buttonState);
     int32_t getButtonState() const;
     void setPosition(float x, float y);
-    void getPosition(float* outX, float* outY) const;
+    FloatPoint getPosition() const;
     int32_t getDisplayId() const;
     void fade(PointerControllerInterface::Transition transition);
     void unfade(PointerControllerInterface::Transition transition);
@@ -102,7 +102,7 @@
 
     } mLocked GUARDED_BY(mLock);
 
-    bool getBoundsLocked(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const;
+    std::optional<FloatRect> getBoundsLocked() const;
     void setPositionLocked(float x, float y);
 
     void updatePointerLocked();
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index fedf58d..544edc2 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -114,16 +114,15 @@
 PointerController::~PointerController() {
     mDisplayInfoListener->onPointerControllerDestroyed();
     mUnregisterWindowInfosListener(mDisplayInfoListener);
-    mContext.getPolicy()->onPointerDisplayIdChanged(ADISPLAY_ID_NONE, 0, 0);
+    mContext.getPolicy()->onPointerDisplayIdChanged(ADISPLAY_ID_NONE, FloatPoint{0, 0});
 }
 
 std::mutex& PointerController::getLock() const {
     return mDisplayInfoListener->mLock;
 }
 
-bool PointerController::getBounds(float* outMinX, float* outMinY, float* outMaxX,
-                                  float* outMaxY) const {
-    return mCursorController.getBounds(outMinX, outMinY, outMaxX, outMaxY);
+std::optional<FloatRect> PointerController::getBounds() const {
+    return mCursorController.getBounds();
 }
 
 void PointerController::move(float deltaX, float deltaY) {
@@ -156,15 +155,13 @@
     mCursorController.setPosition(transformed.x, transformed.y);
 }
 
-void PointerController::getPosition(float* outX, float* outY) const {
+FloatPoint PointerController::getPosition() const {
     const int32_t displayId = mCursorController.getDisplayId();
-    mCursorController.getPosition(outX, outY);
+    const auto p = mCursorController.getPosition();
     {
         std::scoped_lock lock(getLock());
         const auto& transform = getTransformForDisplayLocked(displayId);
-        const auto xy = transform.inverse().transform(*outX, *outY);
-        *outX = xy.x;
-        *outY = xy.y;
+        return FloatPoint{transform.inverse().transform(p.x, p.y)};
     }
 }
 
@@ -262,19 +259,31 @@
 }
 
 void PointerController::setDisplayViewport(const DisplayViewport& viewport) {
-    std::scoped_lock lock(getLock());
+    struct PointerDisplayChangeArgs {
+        int32_t displayId;
+        FloatPoint cursorPosition;
+    };
+    std::optional<PointerDisplayChangeArgs> pointerDisplayChanged;
 
-    bool getAdditionalMouseResources = false;
-    if (mLocked.presentation == PointerController::Presentation::POINTER ||
-        mLocked.presentation == PointerController::Presentation::STYLUS_HOVER) {
-        getAdditionalMouseResources = true;
-    }
-    mCursorController.setDisplayViewport(viewport, getAdditionalMouseResources);
-    if (viewport.displayId != mLocked.pointerDisplayId) {
-        float xPos, yPos;
-        mCursorController.getPosition(&xPos, &yPos);
-        mContext.getPolicy()->onPointerDisplayIdChanged(viewport.displayId, xPos, yPos);
-        mLocked.pointerDisplayId = viewport.displayId;
+    { // acquire lock
+        std::scoped_lock lock(getLock());
+
+        bool getAdditionalMouseResources = false;
+        if (mLocked.presentation == PointerController::Presentation::POINTER ||
+            mLocked.presentation == PointerController::Presentation::STYLUS_HOVER) {
+            getAdditionalMouseResources = true;
+        }
+        mCursorController.setDisplayViewport(viewport, getAdditionalMouseResources);
+        if (viewport.displayId != mLocked.pointerDisplayId) {
+            mLocked.pointerDisplayId = viewport.displayId;
+            pointerDisplayChanged = {viewport.displayId, mCursorController.getPosition()};
+        }
+    } // release lock
+
+    if (pointerDisplayChanged) {
+        // Notify the policy without holding the pointer controller lock.
+        mContext.getPolicy()->onPointerDisplayIdChanged(pointerDisplayChanged->displayId,
+                                                        pointerDisplayChanged->cursorPosition);
     }
 }
 
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index 48d5a57..6d3557c 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -50,12 +50,12 @@
 
     ~PointerController() override;
 
-    virtual bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const;
+    virtual std::optional<FloatRect> getBounds() const;
     virtual void move(float deltaX, float deltaY);
     virtual void setButtonState(int32_t buttonState);
     virtual int32_t getButtonState() const;
     virtual void setPosition(float x, float y);
-    virtual void getPosition(float* outX, float* outY) const;
+    virtual FloatPoint getPosition() const;
     virtual int32_t getDisplayId() const;
     virtual void fade(Transition transition);
     virtual void unfade(Transition transition);
diff --git a/libs/input/PointerControllerContext.h b/libs/input/PointerControllerContext.h
index 96d83a5..f6f5d3b 100644
--- a/libs/input/PointerControllerContext.h
+++ b/libs/input/PointerControllerContext.h
@@ -81,7 +81,7 @@
     virtual PointerIconStyle getDefaultPointerIconId() = 0;
     virtual PointerIconStyle getDefaultStylusIconId() = 0;
     virtual PointerIconStyle getCustomPointerIconId() = 0;
-    virtual void onPointerDisplayIdChanged(int32_t displayId, float xPos, float yPos) = 0;
+    virtual void onPointerDisplayIdChanged(int32_t displayId, const FloatPoint& position) = 0;
 };
 
 /*
diff --git a/libs/input/tests/PointerController_test.cpp b/libs/input/tests/PointerController_test.cpp
index c820d00..2378d42 100644
--- a/libs/input/tests/PointerController_test.cpp
+++ b/libs/input/tests/PointerController_test.cpp
@@ -60,7 +60,7 @@
     virtual PointerIconStyle getDefaultPointerIconId() override;
     virtual PointerIconStyle getDefaultStylusIconId() override;
     virtual PointerIconStyle getCustomPointerIconId() override;
-    virtual void onPointerDisplayIdChanged(int32_t displayId, float xPos, float yPos) override;
+    virtual void onPointerDisplayIdChanged(int32_t displayId, const FloatPoint& position) override;
 
     bool allResourcesAreLoaded();
     bool noResourcesAreLoaded();
@@ -143,8 +143,8 @@
 }
 
 void MockPointerControllerPolicyInterface::onPointerDisplayIdChanged(int32_t displayId,
-                                                                     float /*xPos*/,
-                                                                     float /*yPos*/) {
+                                                                     const FloatPoint& /*position*/
+) {
     latestPointerDisplayId = displayId;
 }
 
diff --git a/location/java/android/location/GnssCapabilities.java b/location/java/android/location/GnssCapabilities.java
index c6f32c2..88f00dc 100644
--- a/location/java/android/location/GnssCapabilities.java
+++ b/location/java/android/location/GnssCapabilities.java
@@ -123,6 +123,21 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface SubHalPowerCapabilityFlags {}
 
+    /** The capability is unknown to be supported or not. */
+    public static final int CAPABILITY_UNKNOWN = 0;
+    /** The capability is supported. */
+    public static final int CAPABILITY_SUPPORTED = 1;
+    /** The capability is not supported. */
+    public static final int CAPABILITY_UNSUPPORTED = 2;
+
+    /** @hide */
+    @IntDef(flag = true, prefix = {"CAPABILITY_"}, value = {CAPABILITY_UNKNOWN,
+            CAPABILITY_SUPPORTED,
+            CAPABILITY_UNSUPPORTED})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface CapabilitySupportType {}
+
+
     /**
      * Returns an empty GnssCapabilities object.
      *
@@ -375,30 +390,25 @@
     }
 
     /**
-     * Returns {@code true} if GNSS chipset supports accumulated delta range, {@code false}
-     * otherwise.
-     *
-     * <p>The value is only known if {@link #isAccumulatedDeltaRangeCapabilityKnown()} is
-     * true.
+     * Returns {@link #CAPABILITY_SUPPORTED} if GNSS chipset supports accumulated delta
+     * range, {@link #CAPABILITY_UNSUPPORTED} if GNSS chipset does not support accumulated
+     * delta range, and {@link #CAPABILITY_UNKNOWN} if it is unknown, which means GNSS
+     * chipset may or may not support accumulated delta range.
      *
      * <p>The accumulated delta range information can be queried in
      * {@link android.location.GnssMeasurement#getAccumulatedDeltaRangeState()},
      * {@link android.location.GnssMeasurement#getAccumulatedDeltaRangeMeters()}, and
      * {@link android.location.GnssMeasurement#getAccumulatedDeltaRangeUncertaintyMeters()}.
      */
-    public boolean hasAccumulatedDeltaRange() {
+    public @CapabilitySupportType int hasAccumulatedDeltaRange() {
         if (!mIsAdrCapabilityKnown) {
-            throw new IllegalStateException("Accumulated delta range capability is unknown.");
+            return CAPABILITY_UNKNOWN;
         }
-        return (mTopFlags & TOP_HAL_CAPABILITY_ACCUMULATED_DELTA_RANGE) != 0;
-    }
-
-    /**
-     * Returns {@code true} if {@link #hasAccumulatedDeltaRange()} is known, {@code false}
-     * otherwise.
-     */
-    public boolean isAccumulatedDeltaRangeCapabilityKnown() {
-        return mIsAdrCapabilityKnown;
+        if ((mTopFlags & TOP_HAL_CAPABILITY_ACCUMULATED_DELTA_RANGE) != 0) {
+            return CAPABILITY_SUPPORTED;
+        } else {
+            return CAPABILITY_UNSUPPORTED;
+        }
     }
 
     /**
@@ -597,9 +607,9 @@
         if (hasMeasurementCorrectionsForDriving()) {
             builder.append("MEASUREMENT_CORRECTIONS_FOR_DRIVING ");
         }
-        if (mIsAdrCapabilityKnown && hasAccumulatedDeltaRange()) {
+        if (hasAccumulatedDeltaRange() == CAPABILITY_SUPPORTED) {
             builder.append("ACCUMULATED_DELTA_RANGE ");
-        } else if (!mIsAdrCapabilityKnown) {
+        } else if (hasAccumulatedDeltaRange() == CAPABILITY_UNKNOWN) {
             builder.append("ACCUMULATED_DELTA_RANGE(unknown) ");
         }
         if (hasMeasurementCorrectionsLosSats()) {
@@ -795,19 +805,17 @@
         /**
          * Sets accumulated delta range capability.
          */
-        public @NonNull Builder setHasAccumulatedDeltaRange(boolean capable) {
-            mIsAdrCapabilityKnown = true;
-            mTopFlags = setFlag(mTopFlags, TOP_HAL_CAPABILITY_ACCUMULATED_DELTA_RANGE,
-                    capable);
-            return this;
-        }
-
-        /**
-         * Clears accumulated delta range capability and sets it as unknown.
-         */
-        public @NonNull Builder clearIsAccumulatedDeltaRangeCapabilityKnown() {
-            mIsAdrCapabilityKnown = false;
-            mTopFlags = setFlag(mTopFlags, TOP_HAL_CAPABILITY_ACCUMULATED_DELTA_RANGE, false);
+        public @NonNull Builder setHasAccumulatedDeltaRange(@CapabilitySupportType int capable) {
+            if (capable == CAPABILITY_UNKNOWN) {
+                mIsAdrCapabilityKnown = false;
+                mTopFlags = setFlag(mTopFlags, TOP_HAL_CAPABILITY_ACCUMULATED_DELTA_RANGE, false);
+            } else if (capable == CAPABILITY_SUPPORTED) {
+                mIsAdrCapabilityKnown = true;
+                mTopFlags = setFlag(mTopFlags, TOP_HAL_CAPABILITY_ACCUMULATED_DELTA_RANGE, true);
+            } else if (capable == CAPABILITY_UNSUPPORTED) {
+                mIsAdrCapabilityKnown = true;
+                mTopFlags = setFlag(mTopFlags, TOP_HAL_CAPABILITY_ACCUMULATED_DELTA_RANGE, false);
+            }
             return this;
         }
 
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index ab3dafe..b0769ab 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -497,24 +497,29 @@
      *   <thead>
      *     <tr>
      *       <td />
-     *       <td colspan="3"><strong>GPS/QZSS</strong></td>
+     *       <td colspan="4"><strong>GPS/QZSS</strong></td>
      *       <td><strong>GLNS</strong></td>
-     *       <td colspan="2"><strong>BDS</strong></td>
+     *       <td colspan="4"><strong>BDS</strong></td>
      *       <td colspan="3"><strong>GAL</strong></td>
      *       <td><strong>SBAS</strong></td>
+     *       <td><strong>IRNSS</strong></td>
      *     </tr>
      *     <tr>
      *       <td><strong>State Flag</strong></td>
      *       <td><strong>L1 C/A</strong></td>
+     *       <td><strong>L1 C(P)</strong></td>
      *       <td><strong>L5I</strong></td>
      *       <td><strong>L5Q</strong></td>
      *       <td><strong>L1OF</strong></td>
      *       <td><strong>B1I (D1)</strong></td>
-     *       <td><strong>B1I &nbsp;(D2)</strong></td>
+     *       <td><strong>B1I (D2)</strong></td>
+     *       <td><strong>B1C (P)</strong></td>
+     *       <td><strong>B2AQ </strong></td>
      *       <td><strong>E1B</strong></td>
      *       <td><strong>E1C</strong></td>
      *       <td><strong>E5AQ</strong></td>
      *       <td><strong>L1 C/A</strong></td>
+     *       <td><strong>L5C</strong></td>
      *     </tr>
      *   </thead>
      *   <tbody>
@@ -532,87 +537,123 @@
      *       <td>0</td>
      *       <td>0</td>
      *       <td>0</td>
+     *       <td>0</td>
+     *       <td>0</td>
+     *       <td>0</td>
+     *       <td>0</td>
      *     </tr>
      *     <tr>
      *       <td>
      *         <strong>STATE_CODE_LOCK</strong>
      *       </td>
      *       <td>1 ms</td>
+     *       <td>10 ms</td>
      *       <td>1 ms</td>
      *       <td>1 ms</td>
      *       <td>1 ms</td>
      *       <td>1 ms</td>
      *       <td>1 ms</td>
+     *       <td>10 ms</td>
+     *       <td>1 ms</td>
      *       <td>-</td>
      *       <td>-</td>
      *       <td>1 ms</td>
      *       <td>1 ms</td>
+     *       <td>1 ms</td>
      *     </tr>
      *     <tr>
      *       <td>
      *         <strong>STATE_SYMBOL_SYNC</strong>
      *       </td>
-     *       <td>20 ms (optional)</td>
+     *       <td>-</td>
+     *       <td>-</td>
      *       <td>10 ms</td>
-     *       <td>1 ms (optional)</td>
+     *       <td>-</td>
      *       <td>10 ms</td>
-     *       <td>20 ms (optional)</td>
+     *       <td>-</td>
      *       <td>2 ms</td>
-     *       <td>4 ms (optional)</td>
-     *       <td>4 ms (optional)</td>
-     *       <td>1 ms (optional)</td>
+     *       <td>-</td>
+     *       <td>-</td>
+     *       <td>-</td>
+     *       <td>-</td>
+     *       <td>-</td>
      *       <td>2 ms</td>
+     *       <td>-</td>
      *     </tr>
      *     <tr>
      *       <td>
      *         <strong>STATE_BIT_SYNC</strong>
      *       </td>
      *       <td>20 ms</td>
+     *       <td>-</td>
      *       <td>20 ms</td>
-     *       <td>1 ms (optional)</td>
+     *       <td>-</td>
      *       <td>20 ms</td>
      *       <td>20 ms</td>
      *       <td>-</td>
+     *       <td>-</td>
+     *       <td>-</td>
      *       <td>8 ms</td>
      *       <td>-</td>
-     *       <td>1 ms (optional)</td>
+     *       <td>-</td>
      *       <td>4 ms</td>
+     *       <td>20 ms</td>
      *     </tr>
      *     <tr>
      *       <td>
      *         <strong>STATE_SUBFRAME_SYNC</strong>
      *       </td>
-     *       <td>6s</td>
-     *       <td>6s</td>
-     *       <td>-</td>
-     *       <td>2 s</td>
      *       <td>6 s</td>
      *       <td>-</td>
+     *       <td>6 s</td>
+     *       <td>-</td>
+     *       <td>-</td>
+     *       <td>6 s</td>
      *       <td>-</td>
      *       <td>-</td>
      *       <td>100 ms</td>
      *       <td>-</td>
+     *       <td>-</td>
+     *       <td>100 ms</td>
+     *       <td>-</td>
+     *       <td>6 s</td>
      *     </tr>
      *     <tr>
      *       <td>
      *         <strong>STATE_TOW_DECODED</strong>
      *       </td>
-     *       <td colspan="2">1 week</td>
+     *       <td>1 week</td>
      *       <td>-</td>
-     *       <td>1 day</td>
-     *       <td colspan="2">1 week</td>
-     *       <td colspan="2">1 week</td>
+     *       <td>1 week</td>
      *       <td>-</td>
+     *       <td>-</td>
+     *       <td>1 week</td>
+     *       <td>1 week</td>
+     *       <td>-</td>
+     *       <td>-</td>
+     *       <td>1 week</td>
+     *       <td>1 week</td>
+     *       <td>-</td>
+     *       <td>1 week</td>
      *       <td>1 week</td>
      *     </tr>
      *     <tr>
      *       <td>
      *         <strong>STATE_TOW_KNOWN</strong>
      *       </td>
-     *       <td colspan="3">1 week</td>
-     *       <td>1 day</td>
-     *       <td colspan="2">1 week</td>
-     *       <td colspan="3">1 week</td>
+     *       <td>1 week</td>
+     *       <td>1 week</td>
+     *       <td>1 week</td>
+     *       <td>1 week</td>
+     *       <td>-</td>
+     *       <td>1 week</td>
+     *       <td>1 week</td>
+     *       <td>1 week</td>
+     *       <td>1 week</td>
+     *       <td>1 week</td>
+     *       <td>1 week</td>
+     *       <td>1 week</td>
+     *       <td>1 week</td>
      *       <td>1 week</td>
      *     </tr>
      *     <tr>
@@ -622,6 +663,7 @@
      *       <td>-</td>
      *       <td>-</td>
      *       <td>-</td>
+     *       <td>-</td>
      *       <td>2 s</td>
      *       <td>-</td>
      *       <td>-</td>
@@ -629,6 +671,9 @@
      *       <td>-</td>
      *       <td>-</td>
      *       <td>-</td>
+     *       <td>-</td>
+     *       <td>-</td>
+     *       <td>-</td>
      *     </tr>
      *     <tr>
      *       <td>
@@ -637,6 +682,7 @@
      *       <td>-</td>
      *       <td>-</td>
      *       <td>-</td>
+     *       <td>-</td>
      *       <td>1 day</td>
      *       <td>-</td>
      *       <td>-</td>
@@ -644,6 +690,9 @@
      *       <td>-</td>
      *       <td>-</td>
      *       <td>-</td>
+     *       <td>-</td>
+     *       <td>-</td>
+     *       <td>-</td>
      *     </tr>
      *     <tr>
      *       <td>
@@ -652,6 +701,7 @@
      *       <td>-</td>
      *       <td>-</td>
      *       <td>-</td>
+     *       <td>-</td>
      *       <td>1 day</td>
      *       <td>-</td>
      *       <td>-</td>
@@ -659,6 +709,9 @@
      *       <td>-</td>
      *       <td>-</td>
      *       <td>-</td>
+     *       <td>-</td>
+     *       <td>-</td>
+     *       <td>-</td>
      *     </tr>
      *     <tr>
      *       <td>
@@ -669,11 +722,15 @@
      *       <td>-</td>
      *       <td>-</td>
      *       <td>-</td>
+     *       <td>-</td>
      *       <td>2 ms</td>
      *       <td>-</td>
      *       <td>-</td>
      *       <td>-</td>
      *       <td>-</td>
+     *       <td>-</td>
+     *       <td>-</td>
+     *       <td>-</td>
      *     </tr>
      *     <tr>
      *       <td>
@@ -684,11 +741,15 @@
      *       <td>-</td>
      *       <td>-</td>
      *       <td>-</td>
+     *       <td>-</td>
      *       <td>600 ms</td>
      *       <td>-</td>
      *       <td>-</td>
      *       <td>-</td>
      *       <td>-</td>
+     *       <td>-</td>
+     *       <td>-</td>
+     *       <td>-</td>
      *     </tr>
      *     <tr>
      *       <td>
@@ -700,10 +761,14 @@
      *       <td>-</td>
      *       <td>-</td>
      *       <td>-</td>
+     *       <td>-</td>
+     *       <td>-</td>
+     *       <td>-</td>
      *       <td>4 ms</td>
      *       <td>4 ms</td>
      *       <td>-</td>
      *       <td>-</td>
+     *       <td>-</td>
      *     </tr>
      *     <tr>
      *       <td>
@@ -716,24 +781,32 @@
      *       <td>-</td>
      *       <td>-</td>
      *       <td>-</td>
+     *       <td>-</td>
+     *       <td>-</td>
+     *       <td>-</td>
      *       <td>100 ms</td>
      *       <td>-</td>
      *       <td>-</td>
+     *       <td>-</td>
      *     </tr>
      *     <tr>
      *       <td>
      *         <strong>STATE_2ND_CODE_LOCK</strong>
      *       </td>
      *       <td>-</td>
-     *       <td>10 ms (optional)</td>
+     *       <td>18000 ms</td>
+     *       <td>10 ms</td>
      *       <td>20 ms</td>
      *       <td>-</td>
      *       <td>-</td>
      *       <td>-</td>
-     *       <td>-</td>
-     *       <td>100 ms (optional)</td>
+     *       <td>18000 ms</td>
      *       <td>100 ms</td>
      *       <td>-</td>
+     *       <td>-</td>
+     *       <td>100 ms</td>
+     *       <td>-</td>
+     *       <td>-</td>
      *     </tr>
      *     <tr>
      *       <td>
@@ -745,10 +818,14 @@
      *       <td>-</td>
      *       <td>-</td>
      *       <td>-</td>
+     *       <td>-</td>
+     *       <td>-</td>
+     *       <td>-</td>
      *       <td>2 s</td>
      *       <td>-</td>
      *       <td>-</td>
      *       <td>-</td>
+     *       <td>-</td>
      *     </tr>
      *     <tr>
      *       <td>
@@ -763,7 +840,11 @@
      *       <td>-</td>
      *       <td>-</td>
      *       <td>-</td>
+     *       <td>-</td>
+     *       <td>-</td>
+     *       <td>-</td>
      *       <td>1 s</td>
+     *       <td>-</td>
      *     </tr>
      *   </tbody>
      * </table>
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 4da4c7f..f9b6ce0 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -9564,7 +9564,10 @@
      * A stream type is considered independent when the volume changes of that type do not
      * affect any other independent volume control stream type.
      * An independent stream type is its own alias when using {@link #getStreamTypeAlias(int)}.
-     * @return list of independent stream types.
+     * @return list of independent stream types, where each value can be one of
+     *     {@link #STREAM_VOICE_CALL}, {@link #STREAM_SYSTEM}, {@link #STREAM_RING},
+     *     {@link #STREAM_MUSIC}, {@link #STREAM_ALARM}, {@link #STREAM_NOTIFICATION},
+     *     {@link #STREAM_DTMF} and {@link #STREAM_ACCESSIBILITY}.
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED)
diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java
index 5bc8c04..0a0a626 100644
--- a/media/java/android/media/MediaCas.java
+++ b/media/java/android/media/MediaCas.java
@@ -436,7 +436,7 @@
                     if (mEventHandler != null) {
                         mEventHandler.sendMessage(
                                 mEventHandler.obtainMessage(
-                                        EventHandler.MSG_CAS_EVENT, event, arg, data));
+                                        EventHandler.MSG_CAS_EVENT, event, arg, toBytes(data)));
                     }
                 }
 
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 9c629bb..b1b7d40 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -1210,7 +1210,7 @@
 
     /**
      * A key describing the desired bitrate mode to be used by an encoder.
-     * Constants are declared in {@link MediaCodecInfo.CodecCapabilities}.
+     * Constants are declared in {@link MediaCodecInfo.EncoderCapabilities}.
      *
      * @see MediaCodecInfo.EncoderCapabilities#isBitrateModeSupported(int)
      */
diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java
index f85bdee..5f5e214 100644
--- a/media/java/android/media/audiopolicy/AudioMix.java
+++ b/media/java/android/media/audiopolicy/AudioMix.java
@@ -252,10 +252,10 @@
         if (o == null || getClass() != o.getClass()) return false;
 
         final AudioMix that = (AudioMix) o;
-        return (this.mRouteFlags == that.mRouteFlags)
-                && (this.mRule == that.mRule)
-                && (this.mMixType == that.mMixType)
-                && (this.mFormat == that.mFormat);
+        return (mRouteFlags == that.mRouteFlags)
+                && (mMixType == that.mMixType)
+                && Objects.equals(mRule, that.mRule)
+                && Objects.equals(mFormat, that.mFormat);
     }
 
     /** @hide */
diff --git a/media/java/android/media/audiopolicy/AudioPolicyConfig.java b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
index 440447e..ce97733 100644
--- a/media/java/android/media/audiopolicy/AudioPolicyConfig.java
+++ b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
@@ -24,6 +24,7 @@
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 
 import java.util.ArrayList;
 import java.util.Objects;
@@ -50,7 +51,8 @@
         mMixes = conf.mMixes;
     }
 
-    AudioPolicyConfig(ArrayList<AudioMix> mixes) {
+    @VisibleForTesting
+    public AudioPolicyConfig(ArrayList<AudioMix> mixes) {
         mMixes = mixes;
     }
 
diff --git a/media/java/android/media/projection/MediaProjection.java b/media/java/android/media/projection/MediaProjection.java
index 9e9012e..9d0662b 100644
--- a/media/java/android/media/projection/MediaProjection.java
+++ b/media/java/android/media/projection/MediaProjection.java
@@ -20,43 +20,73 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.compat.CompatChanges;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
 import android.content.Context;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.VirtualDisplay;
 import android.hardware.display.VirtualDisplayConfig;
+import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.util.ArrayMap;
 import android.util.Log;
+import android.util.Slog;
 import android.view.ContentRecordingSession;
 import android.view.Surface;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.util.Map;
+import java.util.Objects;
 
 /**
  * A token granting applications the ability to capture screen contents and/or
  * record system audio. The exact capabilities granted depend on the type of
  * MediaProjection.
  *
- * <p>
- * A screen capture session can be started through {@link
+ * <p>A screen capture session can be started through {@link
  * MediaProjectionManager#createScreenCaptureIntent}. This grants the ability to
  * capture screen contents, but not system audio.
- * </p>
  */
 public final class MediaProjection {
     private static final String TAG = "MediaProjection";
 
+    /**
+     * Requires an app registers a {@link Callback} before invoking
+     * {@link #createVirtualDisplay(String, int, int, int, int, Surface, VirtualDisplay.Callback,
+     * Handler) createVirtualDisplay}.
+     *
+     * <p>Enabled after version 33 (Android T), so applies to target SDK of 34+ (Android U+).
+     *
+     * @hide
+     */
+    @VisibleForTesting
+    @ChangeId
+    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+    static final long MEDIA_PROJECTION_REQUIRES_CALLBACK = 269849258L; // buganizer id
+
     private final IMediaProjection mImpl;
     private final Context mContext;
-    private final Map<Callback, CallbackRecord> mCallbacks;
-    @Nullable private IMediaProjectionManager mProjectionService = null;
+    private final DisplayManager mDisplayManager;
+    private final IMediaProjectionManager mProjectionService;
+    @NonNull
+    private final Map<Callback, CallbackRecord> mCallbacks = new ArrayMap<>();
 
     /** @hide */
     public MediaProjection(Context context, IMediaProjection impl) {
-        mCallbacks = new ArrayMap<Callback, CallbackRecord>();
+        this(context, impl, IMediaProjectionManager.Stub.asInterface(
+                        ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE)),
+                context.getSystemService(DisplayManager.class));
+    }
+
+    /** @hide */
+    @VisibleForTesting
+    public MediaProjection(Context context, IMediaProjection impl, IMediaProjectionManager service,
+            DisplayManager displayManager) {
         mContext = context;
         mImpl = impl;
         try {
@@ -64,46 +94,44 @@
         } catch (RemoteException e) {
             throw new RuntimeException("Failed to start media projection", e);
         }
+        mProjectionService = service;
+        mDisplayManager = displayManager;
     }
 
     /**
      * Register a listener to receive notifications about when the {@link MediaProjection} or
      * captured content changes state.
-     * <p>
-     * The callback should be registered before invoking
+     *
+     * <p>The callback must be registered before invoking
      * {@link #createVirtualDisplay(String, int, int, int, int, Surface, VirtualDisplay.Callback,
-     * Handler)}
-     * to ensure that any notifications on the callback are not missed.
-     * </p>
+     * Handler)} to ensure that any notifications on the callback are not missed. The client must
+     * implement {@link Callback#onStop()} and clean up any resources it is holding, e.g. the
+     * {@link VirtualDisplay} and {@link Surface}.
      *
      * @param callback The callback to call.
      * @param handler  The handler on which the callback should be invoked, or
      *                 null if the callback should be invoked on the calling thread's looper.
-     * @throws IllegalArgumentException If the given callback is null.
+     * @throws NullPointerException If the given callback is null.
      * @see #unregisterCallback
      */
-    public void registerCallback(Callback callback, Handler handler) {
-        if (callback == null) {
-            throw new IllegalArgumentException("callback should not be null");
-        }
+    public void registerCallback(@NonNull Callback callback, @Nullable Handler handler) {
+        final Callback c = Objects.requireNonNull(callback);
         if (handler == null) {
             handler = new Handler();
         }
-        mCallbacks.put(callback, new CallbackRecord(callback, handler));
+        mCallbacks.put(c, new CallbackRecord(c, handler));
     }
 
     /**
      * Unregister a {@link MediaProjection} listener.
      *
      * @param callback The callback to unregister.
-     * @throws IllegalArgumentException If the given callback is null.
+     * @throws NullPointerException If the given callback is null.
      * @see #registerCallback
      */
-    public void unregisterCallback(Callback callback) {
-        if (callback == null) {
-            throw new IllegalArgumentException("callback should not be null");
-        }
-        mCallbacks.remove(callback);
+    public void unregisterCallback(@NonNull Callback callback) {
+        final Callback c = Objects.requireNonNull(callback);
+        mCallbacks.remove(c);
     }
 
     /**
@@ -122,43 +150,55 @@
         if (surface != null) {
             builder.setSurface(surface);
         }
-        VirtualDisplay virtualDisplay = createVirtualDisplay(builder, callback, handler);
-        return virtualDisplay;
+        return createVirtualDisplay(builder, callback, handler);
     }
 
     /**
      * Creates a {@link android.hardware.display.VirtualDisplay} to capture the
      * contents of the screen.
      *
-     * @param name The name of the virtual display, must be non-empty.
-     * @param width The width of the virtual display in pixels. Must be
-     * greater than 0.
-     * @param height The height of the virtual display in pixels. Must be
-     * greater than 0.
-     * @param dpi The density of the virtual display in dpi. Must be greater
-     * than 0.
-     * @param surface The surface to which the content of the virtual display
-     * should be rendered, or null if there is none initially.
-     * @param flags A combination of virtual display flags. See {@link DisplayManager} for the full
-     * list of flags.
-     * @param callback Callback to call when the virtual display's state
-     * changes, or null if none.
-     * @param handler The {@link android.os.Handler} on which the callback should be
-     * invoked, or null if the callback should be invoked on the calling
-     * thread's main {@link android.os.Looper}.
+     * <p>To correctly clean up resources associated with a capture, the application must register a
+     * {@link Callback} before invocation. The app must override {@link Callback#onStop()} to clean
+     * up (by invoking{@link VirtualDisplay#release()}, {@link Surface#release()} and related
+     * resources).
      *
-     * @see android.hardware.display.VirtualDisplay
+     * @param name     The name of the virtual display, must be non-empty.
+     * @param width    The width of the virtual display in pixels. Must be greater than 0.
+     * @param height   The height of the virtual display in pixels. Must be greater than 0.
+     * @param dpi      The density of the virtual display in dpi. Must be greater than 0.
+     * @param surface  The surface to which the content of the virtual display should be rendered,
+     *                 or null if there is none initially.
+     * @param flags    A combination of virtual display flags. See {@link DisplayManager} for the
+     *                 full list of flags.
+     * @param callback Callback invoked when the virtual display's state changes, or null.
+     * @param handler  The {@link android.os.Handler} on which the callback should be invoked, or
+     *                 null if the callback should be invoked on the calling thread's main
+     *                 {@link android.os.Looper}.
+     * @throws IllegalStateException If the target SDK is
+     *                               {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE U} and
+     *                               up and no {@link Callback}
+     *                               is registered. If the target SDK is less than
+     *                               {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE U}, no
+     *                               exception is thrown.
+     * @see VirtualDisplay
+     * @see VirtualDisplay.Callback
      */
     public VirtualDisplay createVirtualDisplay(@NonNull String name,
             int width, int height, int dpi, int flags, @Nullable Surface surface,
             @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) {
+        if (shouldMediaProjectionRequireCallback()) {
+            if (mCallbacks.isEmpty()) {
+                throw new IllegalStateException(
+                        "Must register a callback before starting capture, to manage resources in"
+                                + " response to MediaProjection states.");
+            }
+        }
         final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width,
                 height, dpi).setFlags(flags);
         if (surface != null) {
             builder.setSurface(surface);
         }
-        VirtualDisplay virtualDisplay = createVirtualDisplay(builder, callback, handler);
-        return virtualDisplay;
+        return createVirtualDisplay(builder, callback, handler);
     }
 
     /**
@@ -191,20 +231,21 @@
             } else {
                 session = ContentRecordingSession.createTaskSession(launchCookie);
             }
-            virtualDisplayConfig.setWindowManagerMirroring(true);
-            final DisplayManager dm = mContext.getSystemService(DisplayManager.class);
-            final VirtualDisplay virtualDisplay = dm.createVirtualDisplay(this,
+            // Pass in the current session details, so they are guaranteed to only be set in
+            // WindowManagerService AFTER a VirtualDisplay is constructed (assuming there are no
+            // errors during set-up).
+            virtualDisplayConfig.setContentRecordingSession(session);
+            virtualDisplayConfig.setWindowManagerMirroringEnabled(true);
+            final VirtualDisplay virtualDisplay = mDisplayManager.createVirtualDisplay(this,
                     virtualDisplayConfig.build(), callback, handler, windowContext);
             if (virtualDisplay == null) {
-                // Since WM handling a new display and DM creating a new VirtualDisplay is async,
-                // WM may have tried to start task recording and encountered an error that required
-                // stopping recording entirely. The VirtualDisplay would then be null when the
-                // MediaProjection is no longer active.
+                // Since WindowManager handling a new display and DisplayManager creating a new
+                // VirtualDisplay is async, WindowManager may have tried to start task recording
+                // and encountered an error that required stopping recording entirely. The
+                // VirtualDisplay would then be null and the MediaProjection is no longer active.
+                Slog.w(TAG, "Failed to create virtual display.");
                 return null;
             }
-            session.setDisplayId(virtualDisplay.getDisplay().getDisplayId());
-            // Successfully set up, so save the current session details.
-            getProjectionService().setContentRecordingSession(session, mImpl);
             return virtualDisplay;
         } catch (RemoteException e) {
             // Can not capture if WMS is not accessible, so bail out.
@@ -212,12 +253,14 @@
         }
     }
 
-    private IMediaProjectionManager getProjectionService() {
-        if (mProjectionService == null) {
-            mProjectionService = IMediaProjectionManager.Stub.asInterface(
-                    ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE));
-        }
-        return mProjectionService;
+    /**
+     * Returns {@code true} when MediaProjection requires the app registers a callback before
+     * beginning to capture via
+     * {@link #createVirtualDisplay(String, int, int, int, int, Surface, VirtualDisplay.Callback,
+     * Handler)}.
+     */
+    private boolean shouldMediaProjectionRequireCallback() {
+        return CompatChanges.isChangeEnabled(MEDIA_PROJECTION_REQUIRES_CALLBACK);
     }
 
     /**
@@ -245,28 +288,26 @@
     public abstract static class Callback {
         /**
          * Called when the MediaProjection session is no longer valid.
-         * <p>
-         * Once a MediaProjection has been stopped, it's up to the application to release any
-         * resources it may be holding (e.g. {@link android.hardware.display.VirtualDisplay}s).
-         * </p>
+         *
+         * <p>Once a MediaProjection has been stopped, it's up to the application to release any
+         * resources it may be holding (e.g. releasing the {@link VirtualDisplay} and
+         * {@link Surface}).
          */
         public void onStop() { }
 
         /**
          * Invoked immediately after capture begins or when the size of the captured region changes,
          * providing the accurate sizing for the streamed capture.
-         * <p>
-         * The given width and height, in pixels, corresponds to the same width and height that
+         *
+         * <p>The given width and height, in pixels, corresponds to the same width and height that
          * would be returned from {@link android.view.WindowMetrics#getBounds()} of the captured
          * region.
-         * </p>
-         * <p>
-         * If the recorded content has a different aspect ratio from either the
+         *
+         * <p>If the recorded content has a different aspect ratio from either the
          * {@link VirtualDisplay} or output {@link Surface}, the captured stream has letterboxing
          * (black bars) around the recorded content. The application can avoid the letterboxing
          * around the recorded content by updating the size of both the {@link VirtualDisplay} and
          * output {@link Surface}:
-         * </p>
          *
          * <pre>
          * &#x40;Override
@@ -291,13 +332,12 @@
         /**
          * Invoked immediately after capture begins or when the visibility of the captured region
          * changes, providing the current visibility of the captured region.
-         * <p>
-         * Applications can take advantage of this callback by showing or hiding the captured
+         *
+         * <p>Applications can take advantage of this callback by showing or hiding the captured
          * content from the output {@link Surface}, based on if the captured region is currently
          * visible to the user.
-         * </p>
-         * <p>
-         * For example, if the user elected to capture a single app (from the activity shown from
+         *
+         * <p>For example, if the user elected to capture a single app (from the activity shown from
          * {@link MediaProjectionManager#createScreenCaptureIntent()}), the following scenarios
          * trigger the callback:
          * <ul>
@@ -314,7 +354,6 @@
          *         captured app, or the user navigates away from the captured app.
          *     </li>
          * </ul>
-         * </p>
          */
         public void onCapturedContentVisibilityChanged(boolean isVisible) { }
     }
@@ -342,7 +381,7 @@
         }
     }
 
-    private final static class CallbackRecord {
+    private static final class CallbackRecord extends Callback {
         private final Callback mCallback;
         private final Handler mHandler;
 
@@ -351,6 +390,8 @@
             mHandler = handler;
         }
 
+
+        @Override
         public void onStop() {
             mHandler.post(new Runnable() {
                 @Override
@@ -360,10 +401,12 @@
             });
         }
 
+        @Override
         public void onCapturedContentResize(int width, int height) {
             mHandler.post(() -> mCallback.onCapturedContentResize(width, height));
         }
 
+        @Override
         public void onCapturedContentVisibilityChanged(boolean isVisible) {
             mHandler.post(() -> mCallback.onCapturedContentVisibilityChanged(isVisible));
         }
diff --git a/media/java/android/media/projection/OWNERS b/media/java/android/media/projection/OWNERS
index 96532d0..2273f81 100644
--- a/media/java/android/media/projection/OWNERS
+++ b/media/java/android/media/projection/OWNERS
@@ -1,3 +1,4 @@
 michaelwr@google.com
 santoscordon@google.com
 chaviw@google.com
+nmusgrave@google.com
diff --git a/media/java/android/media/soundtrigger/SoundTriggerManager.java b/media/java/android/media/soundtrigger/SoundTriggerManager.java
index 0e9ef4c..ae8121a 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerManager.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerManager.java
@@ -94,12 +94,17 @@
             originatorIdentity.packageName = ActivityThread.currentOpPackageName();
 
             try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
-                List<ModuleProperties> modulePropertiesList = soundTriggerService
-                        .listModuleProperties(originatorIdentity);
-                if (!modulePropertiesList.isEmpty()) {
+                ModuleProperties moduleProperties = soundTriggerService
+                        .listModuleProperties(originatorIdentity)
+                        .stream()
+                        .filter(prop -> !prop.getSupportedModelArch()
+                                .equals(SoundTrigger.FAKE_HAL_ARCH))
+                        .findFirst()
+                        .orElse(null);
+                if (moduleProperties != null) {
                     mSoundTriggerSession = soundTriggerService.attachAsOriginator(
                                                 originatorIdentity,
-                                                modulePropertiesList.get(0),
+                                                moduleProperties,
                                                 mBinderToken);
                 } else {
                     mSoundTriggerSession = null;
diff --git a/media/java/android/media/tv/ITvInputClient.aidl b/media/java/android/media/tv/ITvInputClient.aidl
index c52cd59..0f8a00a 100644
--- a/media/java/android/media/tv/ITvInputClient.aidl
+++ b/media/java/android/media/tv/ITvInputClient.aidl
@@ -55,7 +55,7 @@
     void onCueingMessageAvailability(boolean available, int seq);
     void onTimeShiftMode(int mode, int seq);
     void onAvailableSpeeds(in float[] speeds, int seq);
-    void onTvMessage(in String type, in Bundle data, int seq);
+    void onTvMessage(int type, in Bundle data, int seq);
 
     void onTuned(in Uri channelUri, int seq);
     // For the recording session
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index e9aa321..14c020e 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -116,7 +116,10 @@
 
     // For ad request
     void requestAd(in IBinder sessionToken, in AdRequest request, int userId);
-    void notifyAdBuffer(in IBinder sessionToken, in AdBuffer buffer, int userId);
+    void notifyAdBufferReady(in IBinder sessionToken, in AdBuffer buffer, int userId);
+
+    // For TV Message
+    void notifyTvMessage(in IBinder sessionToken, int type, in Bundle data, int userId);
 
     // For TV input hardware binding
     List<TvInputHardwareInfo> getHardwareList();
diff --git a/media/java/android/media/tv/ITvInputSession.aidl b/media/java/android/media/tv/ITvInputSession.aidl
index 82875e5..a7bd8d3 100644
--- a/media/java/android/media/tv/ITvInputSession.aidl
+++ b/media/java/android/media/tv/ITvInputSession.aidl
@@ -75,5 +75,8 @@
 
     // For ad request
     void requestAd(in AdRequest request);
-    void notifyAdBuffer(in AdBuffer buffer);
+    void notifyAdBufferReady(in AdBuffer buffer);
+
+    // For TV messages
+    void notifyTvMessage(int type, in Bundle data);
 }
diff --git a/media/java/android/media/tv/ITvInputSessionCallback.aidl b/media/java/android/media/tv/ITvInputSessionCallback.aidl
index 449c2d6..a52e9a5 100644
--- a/media/java/android/media/tv/ITvInputSessionCallback.aidl
+++ b/media/java/android/media/tv/ITvInputSessionCallback.aidl
@@ -66,5 +66,5 @@
     void onAdBufferConsumed(in AdBuffer buffer);
 
     // For messages sent from the TV input
-    void onTvMessage(in String type, in Bundle data);
+    void onTvMessage(int type, in Bundle data);
 }
diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java
index 465b617..7946baee 100644
--- a/media/java/android/media/tv/ITvInputSessionWrapper.java
+++ b/media/java/android/media/tv/ITvInputSessionWrapper.java
@@ -78,6 +78,7 @@
     private static final int DO_SELECT_AUDIO_PRESENTATION = 29;
     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 final boolean mIsRecordingSession;
     private final HandlerCaller mCaller;
@@ -266,7 +267,7 @@
             }
             case DO_SET_TV_MESSAGE_ENABLED: {
                 SomeArgs args = (SomeArgs) msg.obj;
-                mTvInputSessionImpl.setTvMessageEnabled((String) args.arg1, (Boolean) args.arg2);
+                mTvInputSessionImpl.setTvMessageEnabled((Integer) args.arg1, (Boolean) args.arg2);
                 break;
             }
             case DO_REQUEST_AD: {
@@ -274,7 +275,12 @@
                 break;
             }
             case DO_NOTIFY_AD_BUFFER: {
-                mTvInputSessionImpl.notifyAdBuffer((AdBuffer) msg.obj);
+                mTvInputSessionImpl.notifyAdBufferReady((AdBuffer) msg.obj);
+                break;
+            }
+            case DO_NOTIFY_TV_MESSAGE: {
+                SomeArgs args = (SomeArgs) msg.obj;
+                mTvInputSessionImpl.onTvMessageReceived((String) args.arg1, (Bundle) args.arg2);
                 break;
             }
             default: {
@@ -459,10 +465,15 @@
     }
 
     @Override
-    public void notifyAdBuffer(AdBuffer buffer) {
+    public void notifyAdBufferReady(AdBuffer buffer) {
         mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_NOTIFY_AD_BUFFER, buffer));
     }
 
+    @Override
+    public void notifyTvMessage(int type, Bundle data) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageOO(DO_NOTIFY_TV_MESSAGE, type, data));
+    }
+
     private final class TvInputEventReceiver extends InputEventReceiver {
         TvInputEventReceiver(InputChannel inputChannel, Looper looper) {
             super(inputChannel, looper);
diff --git a/media/java/android/media/tv/TableResponse.java b/media/java/android/media/tv/TableResponse.java
index fb4e99c..c4fc26e 100644
--- a/media/java/android/media/tv/TableResponse.java
+++ b/media/java/android/media/tv/TableResponse.java
@@ -64,7 +64,10 @@
      * @param tableUri The URI of the table in the database.
      * @param version The version number of requested table.
      * @param size The Size number of table in bytes.
+     *
+     * @deprecated use {@link Builder} instead.
      */
+    @Deprecated
     public TableResponse(int requestId, int sequence, @ResponseResult int responseResult,
             @Nullable Uri tableUri, int version, int size) {
         super(RESPONSE_TYPE, requestId, sequence, responseResult);
@@ -76,30 +79,7 @@
     }
 
     /**
-     * Constructs a TableResponse with a table URI.
-     *
-     * @param requestId The ID is used to associate the response with the request.
-     * @param sequence The sequence number which indicates the order of related responses.
-     * @param responseResult The result for the response. It's one of {@link #RESPONSE_RESULT_OK},
-     *                       {@link #RESPONSE_RESULT_CANCEL}, {@link #RESPONSE_RESULT_ERROR}.
-     * @param tableByteArray The byte array which stores the table in bytes. The structure and
-     *                       syntax of the table depends on the table name in
-     *                       {@link TableRequest#getTableName()} and the corresponding standard.
-     * @param version The version number of requested table.
-     * @param size The Size number of table in bytes.
-     */
-    public TableResponse(int requestId, int sequence, @ResponseResult int responseResult,
-            @NonNull byte[] tableByteArray, int version, int size) {
-        super(RESPONSE_TYPE, requestId, sequence, responseResult);
-        mVersion = version;
-        mSize = size;
-        mTableUri = null;
-        mTableByteArray = tableByteArray;
-        mTableSharedMemory = null;
-    }
-
-    /**
-     * Constructs a TableResponse with a table URI.
+     * Constructs a TableResponse.
      *
      * @param requestId The ID is used to associate the response with the request.
      * @param sequence The sequence number which indicates the order of related responses.
@@ -112,17 +92,128 @@
      *                          {@link TableRequest#getTableName()} and the corresponding standard.
      * @param version The version number of requested table.
      * @param size The Size number of table in bytes.
+     * @param tableUri The URI of the table in the database.
+     * @param tableByteArray The byte array which stores the table in bytes. The structure and
+     *                       syntax of the table depends on the table name in
+     * @param tableSharedMemory The shared memory which stores the table. The table size can be
+     *                          large so using a shared memory optimizes the data
+     *                          communication between the table data source and the receiver. The
+     *                          structure syntax of the table depends on the table name in
+     *                          {@link TableRequest#getTableName()} and the corresponding standard.
      */
-    public TableResponse(int requestId, int sequence, @ResponseResult int responseResult,
-            @NonNull SharedMemory tableSharedMemory, int version, int size) {
+    private TableResponse(int requestId, int sequence, @ResponseResult int responseResult,
+            int version, int size, Uri tableUri, byte[] tableByteArray,
+            SharedMemory tableSharedMemory) {
         super(RESPONSE_TYPE, requestId, sequence, responseResult);
         mVersion = version;
         mSize = size;
-        mTableUri = null;
-        mTableByteArray = null;
+        mTableUri = tableUri;
+        mTableByteArray = tableByteArray;
         mTableSharedMemory = tableSharedMemory;
     }
 
+    /**
+     * Builder for {@link TableResponse}.
+     */
+    public static final class Builder {
+        private final int mRequestId;
+        private final int mSequence;
+        @ResponseResult
+        private final int mResponseResult;
+        private final int mVersion;
+        private final int mSize;
+        private Uri mTableUri;
+        private byte[] mTableByteArray;
+        private SharedMemory mTableSharedMemory;
+
+        /**
+         * Constructs a Builder object of {@link TableResponse}.
+         *
+         * @param requestId The ID is used to associate the response with the request.
+         * @param sequence The sequence number which indicates the order of related responses.
+         * @param responseResult The result for the response. It's one of
+         *                       {@link #RESPONSE_RESULT_OK}, {@link #RESPONSE_RESULT_CANCEL},
+         *                       {@link #RESPONSE_RESULT_ERROR}.
+         * @param version The version number of requested table.
+         * @param size The Size number of table in bytes.
+         */
+        public Builder(int requestId, int sequence, @ResponseResult int responseResult, int version,
+                int size) {
+            mRequestId = requestId;
+            mSequence = sequence;
+            mResponseResult = responseResult;
+            mVersion = version;
+            mSize = size;
+        }
+
+        /**
+         * Sets table URI.
+         *
+         * <p>For a single builder instance, at most one of table URI, table byte array, and table
+         * shared memory can be set. If more than one are set, only the last call takes precedence
+         * and others are reset to {@code null}.
+         *
+         * @param uri The URI of the table.
+         */
+        @NonNull
+        public Builder setTableUri(@NonNull Uri uri) {
+            mTableUri = uri;
+            mTableByteArray = null;
+            mTableSharedMemory = null;
+            return this;
+        }
+
+        /**
+         * Sets table byte array.
+         *
+         * <p>For a single builder instance, at most one of table URI, table byte array, and table
+         * shared memory can be set. If more than one are set, only the last call takes precedence
+         * and others are reset to {@code null}.
+         *
+         * @param bytes The byte array which stores the table in bytes. The structure and
+         *              syntax of the table depends on the table name in
+         *              {@link TableRequest#getTableName()} and the corresponding standard.
+         */
+        @NonNull
+        public Builder setTableByteArray(@NonNull byte[] bytes) {
+            mTableByteArray = bytes;
+            mTableUri = null;
+            mTableSharedMemory = null;
+            return this;
+        }
+
+
+        /**
+         * Sets table shared memory.
+         *
+         * <p>For a single builder instance, at most one of table URI, table byte array, and table
+         * shared memory can be set. If more than one are set, only the last call takes precedence
+         * and others are reset to {@code null}.
+         *
+         * @param sharedMemory The shared memory which stores the table. The table size can be
+         *                     large so using a shared memory optimizes the data
+         *                     communication between the table data source and the receiver. The
+         *                     structure syntax of the table depends on the table name in
+         *                     {@link TableRequest#getTableName()} and the corresponding standard.
+         */
+        @NonNull
+        public Builder setTableSharedMemory(@NonNull SharedMemory sharedMemory) {
+            mTableSharedMemory = sharedMemory;
+            mTableUri = null;
+            mTableByteArray = null;
+            return this;
+        }
+
+        /**
+         * Builds a {@link TableResponse} object.
+         */
+        @NonNull
+        public TableResponse build() {
+            return new TableResponse(mRequestId, mSequence, mResponseResult, mVersion, mSize,
+                    mTableUri, mTableByteArray, mTableSharedMemory);
+        }
+    }
+
     TableResponse(Parcel source) {
         super(RESPONSE_TYPE, source);
         String uriString = source.readString();
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 8459538..ef2b5a5 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -22,7 +22,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
-import android.annotation.StringDef;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
@@ -134,16 +133,61 @@
     public @interface VideoUnavailableReason {}
 
     /** Indicates that this TV message contains watermarking data */
-    public static final String TV_MESSAGE_TYPE_WATERMARK = "Watermark";
+    public static final int TV_MESSAGE_TYPE_WATERMARK = 1;
 
     /** Indicates that this TV message contains Closed Captioning data */
-    public static final String TV_MESSAGE_TYPE_CLOSED_CAPTION = "CC";
+    public static final int TV_MESSAGE_TYPE_CLOSED_CAPTION = 2;
+
+    /** Indicates that this TV message contains other data */
+    public static final int TV_MESSAGE_TYPE_OTHER = 1000;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
-    @StringDef({TV_MESSAGE_TYPE_WATERMARK, TV_MESSAGE_TYPE_CLOSED_CAPTION})
+    @IntDef({TV_MESSAGE_TYPE_WATERMARK, TV_MESSAGE_TYPE_CLOSED_CAPTION, TV_MESSAGE_TYPE_OTHER})
     public @interface TvMessageType {}
 
+    /**
+     * This constant is used as a {@link Bundle} key for TV messages. The value of the key
+     * identifies the stream on the TV input source for which the watermark event is relevant to.
+     *
+     * <p> Type: String
+     */
+    public static final String TV_MESSAGE_KEY_STREAM_ID =
+            "android.media.tv.TvInputManager.stream_id";
+
+    /**
+     * This constant is used as a {@link Bundle} key for TV messages. The value of the key
+     * identifies the subtype of the data, such as the format of the CC data. The format
+     * found at this key can then be used to identify how to parse the data at
+     * {@link #TV_MESSAGE_KEY_RAW_DATA}.
+     *
+     * To parse the raw data bsed on the subtype, please refer to the official documentation of the
+     * concerning subtype. For example, for the subtype "ATSC A/335" for watermarking, the
+     * document for A/335 from the ATSC standard details how this data is formatted.
+     *
+     * Some other examples of common formats include:
+     * <ul>
+     *     <li>Watermarking - ATSC A/336</li>
+     *     <li>Closed Captioning - CTA 608-E</li>
+     * </ul>
+     *
+     * <p> Type: String
+     */
+    public static final String TV_MESSAGE_KEY_SUBTYPE =
+            "android.media.tv.TvInputManager.subtype";
+
+    /**
+     * This constant is used as a {@link Bundle} key for TV messages. The value of the key
+     * stores the raw data contained in this TV Message. The format of this data is determined
+     * by the format defined by the subtype, found using the key at
+     * {@link #TV_MESSAGE_KEY_SUBTYPE}. See {@link #TV_MESSAGE_KEY_SUBTYPE} for more
+     * information on how to parse this data.
+     *
+     * <p> Type: byte[]
+     */
+    public static final String TV_MESSAGE_KEY_RAW_DATA =
+            "android.media.tv.TvInputManager.raw_data";
+
     static final int VIDEO_UNAVAILABLE_REASON_START = 0;
     static final int VIDEO_UNAVAILABLE_REASON_END = 18;
 
@@ -793,9 +837,15 @@
          *
          * @param session A {@link TvInputManager.Session} associated with this callback.
          * @param type The type of message received, such as {@link #TV_MESSAGE_TYPE_WATERMARK}
-         * @param data The raw data of the message
+         * @param data The raw data of the message. The bundle keys are:
+         *             {@link TvInputManager#TV_MESSAGE_KEY_STREAM_ID},
+         *             {@link TvInputManager#TV_MESSAGE_KEY_SUBTYPE},
+         *             {@link TvInputManager#TV_MESSAGE_KEY_RAW_DATA}.
+         *             See {@link TvInputManager#TV_MESSAGE_KEY_SUBTYPE} for more information on
+         *             how to parse this data.
+         *
          */
-        public void onTvMessage(Session session, @TvInputManager.TvMessageType String type,
+        public void onTvMessage(Session session, @TvInputManager.TvMessageType int type,
                 Bundle data) {
         }
 
@@ -1074,7 +1124,7 @@
             });
         }
 
-        void postTvMessage(String type, Bundle data) {
+        void postTvMessage(int type, Bundle data) {
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
@@ -1613,7 +1663,7 @@
             }
 
             @Override
-            public void onTvMessage(String type, Bundle data, int seq) {
+            public void onTvMessage(int type, Bundle data, int seq) {
                 synchronized (mSessionCallbackRecordMap) {
                     SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
                     if (record == null) {
@@ -3221,6 +3271,17 @@
         }
 
         /**
+         * Sends TV messages to the service for testing purposes
+         */
+        public void notifyTvMessage(@NonNull @TvMessageType int type, @NonNull Bundle data) {
+            try {
+                mService.notifyTvMessage(mToken, type, data, mUserId);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        /**
          * Starts TV program recording in the current recording session.
          *
          * @param programUri The URI for the TV program to record as a hint, built by
@@ -3624,13 +3685,13 @@
         /**
          * Notifies when the advertisement buffer is filled and ready to be read.
          */
-        public void notifyAdBuffer(AdBuffer buffer) {
+        public void notifyAdBufferReady(AdBuffer buffer) {
             if (mToken == null) {
                 Log.w(TAG, "The session has been already released");
                 return;
             }
             try {
-                mService.notifyAdBuffer(mToken, buffer, mUserId);
+                mService.notifyAdBufferReady(mToken, buffer, mUserId);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 4bc137d..4e380c4 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -1030,9 +1030,14 @@
          *
          * @param type The of message that was sent, such as
          * {@link TvInputManager#TV_MESSAGE_TYPE_WATERMARK}
-         * @param data The data sent with the message.
+         * @param data The raw data of the message. The bundle keys are:
+         *             {@link TvInputManager#TV_MESSAGE_KEY_STREAM_ID},
+         *             {@link TvInputManager#TV_MESSAGE_KEY_SUBTYPE},
+         *             {@link TvInputManager#TV_MESSAGE_KEY_RAW_DATA}.
+         *             See {@link TvInputManager#TV_MESSAGE_KEY_SUBTYPE} for more information on
+         *             how to parse this data.
          */
-        public void notifyTvMessage(@NonNull @TvInputManager.TvMessageType String type,
+        public void notifyTvMessage(@TvInputManager.TvMessageType int type,
                 @NonNull Bundle data) {
             executeOrPostRunnableOnMainThread(new Runnable() {
                 @MainThread
@@ -1351,7 +1356,7 @@
          *
          * @param buffer The {@link AdBuffer} that became ready for playback.
          */
-        public void onAdBuffer(@NonNull AdBuffer buffer) {
+        public void onAdBufferReady(@NonNull AdBuffer buffer) {
         }
 
         /**
@@ -1486,12 +1491,29 @@
         /**
          * Called when the application enables or disables the detection of the specified message
          * type.
-         * @param type The {@link TvInputManager.TvMessageType} of message that was sent.
+         * @param type The type of message received, such as
+         *             {@link TvInputManager#TV_MESSAGE_TYPE_WATERMARK}
          * @param enabled {@code true} if TV message detection is enabled,
          *                {@code false} otherwise.
          */
-        public void onSetTvMessageEnabled(@NonNull @TvInputManager.TvMessageType String type,
-                boolean enabled){
+        public void onSetTvMessageEnabled(@TvInputManager.TvMessageType int type,
+                boolean enabled) {
+        }
+
+        /**
+         * Called when a TV message is received
+         *
+         * @param type The type of message received, such as
+         * {@link TvInputManager#TV_MESSAGE_TYPE_WATERMARK}
+         * @param data The raw data of the message. The bundle keys are:
+         *             {@link TvInputManager#TV_MESSAGE_KEY_STREAM_ID},
+         *             {@link TvInputManager#TV_MESSAGE_KEY_SUBTYPE},
+         *             {@link TvInputManager#TV_MESSAGE_KEY_RAW_DATA}.
+         *             See {@link TvInputManager#TV_MESSAGE_KEY_SUBTYPE} for more information on
+         *             how to parse this data.
+         */
+        public void onTvMessage(@NonNull @TvInputManager.TvMessageType String type,
+                @NonNull Bundle data) {
         }
 
         /**
@@ -1845,9 +1867,9 @@
         }
 
         /**
-         * Calls {@link #onSetTvMessageEnabled(String, boolean)}.
+         * Calls {@link #onSetTvMessageEnabled(int, boolean)}.
          */
-        void setTvMessageEnabled(String type, boolean enabled) {
+        void setTvMessageEnabled(int type, boolean enabled) {
             onSetTvMessageEnabled(type, enabled);
         }
 
@@ -2039,8 +2061,12 @@
             onRequestAd(request);
         }
 
-        void notifyAdBuffer(AdBuffer buffer) {
-            onAdBuffer(buffer);
+        void notifyAdBufferReady(AdBuffer buffer) {
+            onAdBufferReady(buffer);
+        }
+
+        void onTvMessageReceived(String type, Bundle data) {
+            onTvMessage(type, data);
         }
 
         /**
diff --git a/media/java/android/media/tv/TvRecordingInfo.java b/media/java/android/media/tv/TvRecordingInfo.java
index 60ceb83..59915fc 100644
--- a/media/java/android/media/tv/TvRecordingInfo.java
+++ b/media/java/android/media/tv/TvRecordingInfo.java
@@ -131,7 +131,6 @@
      * cause the recording to start later than the specified time. This should cause the actual
      * duration of the recording to decrease.
      */
-    @NonNull
     public long getStartPaddingMillis() {
         return mStartPaddingMillis;
     }
@@ -144,7 +143,6 @@
      * cause the recording to end earlier than the specified time. This should cause the actual
      * duration of the recording to decrease.
      */
-    @NonNull
     public long getEndPaddingMillis() {
         return mEndPaddingMillis;
     }
@@ -176,7 +174,6 @@
      * https://www.oipf.tv/docs/OIPF-T1-R2_Specification-Volume-5-Declarative-Application-Environment-v2_3-2014-01-24.pdf
      * ">Open IPTV Forum Release 2 Specification</a>. It is described in Volume 5, section 7.10.1.1.
      */
-    @NonNull
     @DaysOfWeek
     public int getRepeatDays() {
         return mRepeatDays;
@@ -228,7 +225,6 @@
      * Returns the scheduled start time of the recording in milliseconds since the epoch.
      */
     @IntRange(from = 0)
-    @NonNull
     public long getScheduledStartTimeMillis() {
         return mScheduledStartTimeMillis;
     }
@@ -237,7 +233,6 @@
      * Returns the scheduled duration of the recording in milliseconds since the epoch.
      */
     @IntRange(from = 0)
-    @NonNull
     public long getScheduledDurationMillis() {
         return mScheduledDurationMillis;
     }
@@ -292,7 +287,6 @@
      * <p> Returns -1 for recordings that have not yet started.
      */
     @IntRange(from = -1)
-    @NonNull
     public long getRecordingStartTimeMillis() {
         return mRecordingStartTimeMillis;
     }
@@ -306,7 +300,6 @@
      * <p> Returns -1 for recordings that have not yet started.
      */
     @IntRange(from = -1)
-    @NonNull
     public long getRecordingDurationMillis() {
         return mRecordingDurationMillis;
     }
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index 3ef61f2..8a886832 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -21,6 +21,7 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.content.AttributionSource;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -640,6 +641,20 @@
         }
     }
 
+
+    /**
+     * Sends TV messages to the session for testing purposes
+     *
+     * @hide
+     */
+    @TestApi
+    public void notifyTvMessage(@TvInputManager.TvMessageType int type,
+            @NonNull Bundle data) {
+        if (mSession != null) {
+            mSession.notifyTvMessage(type, data);
+        }
+    }
+
     /**
      * Sets the callback to be invoked when the time shift position is changed.
      *
@@ -723,11 +738,12 @@
     /**
      * Enables or disables TV message detection in the stream of the bound TV input.
      *
-     * @param type The type of {@link android.media.tv.TvInputManager.TvMessageType}
+     * @param type The type of message received, such as
+     *             {@link TvInputManager#TV_MESSAGE_TYPE_WATERMARK}
      * @param enabled {@code true} if you want to enable TV message detection
      *                {@code false} otherwise.
      */
-    public void setTvMessageEnabled(@NonNull @TvInputManager.TvMessageType String type,
+    public void setTvMessageEnabled(@TvInputManager.TvMessageType int type,
             boolean enabled) {
     }
 
@@ -1236,11 +1252,17 @@
          * This is called when a new TV Message has been received.
          *
          * @param inputId The ID of the TV input bound to this view.
-         * @param type The type of {@link android.media.tv.TvInputManager.TvMessageType}
-         * @param data The raw data of the message
+         * @param type The type of message received, such as
+         *             {@link TvInputManager#TV_MESSAGE_TYPE_WATERMARK}
+         * @param data The raw data of the message. The bundle keys are:
+         *             {@link TvInputManager#TV_MESSAGE_KEY_STREAM_ID},
+         *             {@link TvInputManager#TV_MESSAGE_KEY_SUBTYPE},
+         *             {@link TvInputManager#TV_MESSAGE_KEY_RAW_DATA}.
+         *             See {@link TvInputManager#TV_MESSAGE_KEY_SUBTYPE} for more information on
+         *             how to parse this data.
          */
         public void onTvMessage(@NonNull String inputId,
-                @NonNull @TvInputManager.TvMessageType String type, @NonNull Bundle data) {
+                @TvInputManager.TvMessageType int type, @NonNull Bundle data) {
         }
     }
 
@@ -1655,7 +1677,7 @@
         }
 
         @Override
-        public void onTvMessage(Session session, String type, Bundle data) {
+        public void onTvMessage(Session session, int type, Bundle data) {
             if (DEBUG) {
                 Log.d(TAG, "onTvMessage(type=" + type + ", data=" + data + ")");
             }
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppClient.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppClient.aidl
index 36954ad..7739184 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppClient.aidl
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppClient.aidl
@@ -39,7 +39,7 @@
     void onSessionStateChanged(int state, int err, int seq);
     void onBiInteractiveAppCreated(in Uri biIAppUri, in String biIAppId, int seq);
     void onTeletextAppStateChanged(int state, int seq);
-    void onAdBuffer(in AdBuffer buffer, int seq);
+    void onAdBufferReady(in AdBuffer buffer, int seq);
     void onCommandRequest(in String cmdType, in Bundle parameters, int seq);
     void onTimeShiftCommandRequest(in String cmdType, in Bundle parameters, int seq);
     void onSetVideoBounds(in Rect rect, int seq);
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl
index 89847a7..41cbe4a 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl
@@ -94,7 +94,7 @@
     void notifyRecordingStarted(in IBinder sessionToken, in String recordingId, String requestId,
             int userId);
     void notifyRecordingStopped(in IBinder sessionToken, in String recordingId, int userId);
-    void notifyTvMessage(in IBinder sessionToken, in String type, in Bundle data, int userId);
+    void notifyTvMessage(in IBinder sessionToken, in int type, in Bundle data, int userId);
     void setSurface(in IBinder sessionToken, in Surface surface, int userId);
     void dispatchSurfaceChanged(in IBinder sessionToken, int format, int width, int height,
             int userId);
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl
index f17d1b7..052bc3d 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl
@@ -72,7 +72,7 @@
     void notifySignalStrength(int strength);
     void notifyRecordingStarted(in String recordingId, in String requestId);
     void notifyRecordingStopped(in String recordingId);
-    void notifyTvMessage(in String type, in Bundle data);
+    void notifyTvMessage(int type, in Bundle data);
     void setSurface(in Surface surface);
     void dispatchSurfaceChanged(int format, int width, int height);
     void notifyBroadcastInfoResponse(in BroadcastInfoResponse response);
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionCallback.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionCallback.aidl
index 7db8604..9e43e79 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionCallback.aidl
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionCallback.aidl
@@ -38,7 +38,7 @@
     void onSessionStateChanged(int state, int err);
     void onBiInteractiveAppCreated(in Uri biIAppUri, in String biIAppId);
     void onTeletextAppStateChanged(int state);
-    void onAdBuffer(in AdBuffer buffer);
+    void onAdBufferReady(in AdBuffer buffer);
     void onCommandRequest(in String cmdType, in Bundle parameters);
     void onTimeShiftCommandRequest(in String cmdType, in Bundle parameters);
     void onSetVideoBounds(in Rect rect);
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java
index 6eed483..d3f598a 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java
@@ -243,7 +243,7 @@
             }
             case DO_NOTIFY_TV_MESSAGE: {
                 SomeArgs args = (SomeArgs) msg.obj;
-                mSessionImpl.notifyTvMessage((String) args.arg1, (Bundle) args.arg2);
+                mSessionImpl.notifyTvMessage((Integer) args.arg1, (Bundle) args.arg2);
                 args.recycle();
                 break;
             }
@@ -520,7 +520,7 @@
     }
 
     @Override
-    public void notifyTvMessage(String type, Bundle data) {
+    public void notifyTvMessage(int type, Bundle data) {
         mCaller.executeOrSendMessage(
                 mCaller.obtainMessageOO(DO_NOTIFY_TV_MESSAGE, type, data));
     }
@@ -558,7 +558,7 @@
     @Override
     public void notifyRecordingStarted(String recordingId, String requestId) {
         mCaller.executeOrSendMessage(mCaller.obtainMessageOO(
-                DO_NOTIFY_RECORDING_STARTED, recordingId, recordingId));
+                DO_NOTIFY_RECORDING_STARTED, recordingId, requestId));
     }
 
     @Override
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
index 3e31bce3..fc8fe5c 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
@@ -681,14 +681,14 @@
             }
 
             @Override
-            public void onAdBuffer(AdBuffer buffer, int seq) {
+            public void onAdBufferReady(AdBuffer buffer, int seq) {
                 synchronized (mSessionCallbackRecordMap) {
                     SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
                     if (record == null) {
                         Log.e(TAG, "Callback not found for seq " + seq);
                         return;
                     }
-                    record.postAdBuffer(buffer);
+                    record.postAdBufferReady(buffer);
                 }
             }
         };
@@ -1751,7 +1751,7 @@
         /**
          * Notifies Interactive APP session when a new TV message is received.
          */
-        public void notifyTvMessage(String type, Bundle data) {
+        public void notifyTvMessage(int type, Bundle data) {
             if (mToken == null) {
                 Log.w(TAG, "The session has been already released");
                 return;
@@ -2245,12 +2245,12 @@
             });
         }
 
-        void postAdBuffer(AdBuffer buffer) {
+        void postAdBufferReady(AdBuffer buffer) {
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
                     if (mSession.getInputSession() != null) {
-                        mSession.getInputSession().notifyAdBuffer(buffer);
+                        mSession.getInputSession().notifyAdBufferReady(buffer);
                     }
                 }
             });
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppService.java b/media/java/android/media/tv/interactive/TvInteractiveAppService.java
index 1ae82f4..69ff9c6 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppService.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppService.java
@@ -38,6 +38,7 @@
 import android.media.tv.BroadcastInfoRequest;
 import android.media.tv.BroadcastInfoResponse;
 import android.media.tv.TvContentRating;
+import android.media.tv.TvContract;
 import android.media.tv.TvInputInfo;
 import android.media.tv.TvInputManager;
 import android.media.tv.TvRecordingInfo;
@@ -630,6 +631,8 @@
          *                  {@link #requestStartRecording(String, Uri)} is called.
          *                  {@code null} if the recording is not triggered by a
          *                  {@link #requestStartRecording(String, Uri)} request.
+         *                  This ID should be created by the {@link TvInteractiveAppService} and
+         *                  can be any string.
          * @see #onRecordingStopped(String)
          */
         public void onRecordingStarted(@NonNull String recordingId, @Nullable String requestId) {
@@ -708,6 +711,8 @@
          * @param requestId The ID of the request when
          *                  {@link #requestScheduleRecording}  is called.
          *                  {@code null} if the recording is not triggered by a request.
+         *                  This ID should be created by the {@link TvInteractiveAppService} and
+         *                  can be any string.
          */
         public void onRecordingScheduled(@NonNull String recordingId, @Nullable String requestId) {
         }
@@ -914,9 +919,14 @@
          *
          * @param type The type of message received, such as
          * {@link TvInputManager#TV_MESSAGE_TYPE_WATERMARK}
-         * @param data The raw data of the message
+         * @param data The raw data of the message. The bundle keys are:
+         *             {@link TvInputManager#TV_MESSAGE_KEY_STREAM_ID},
+         *             {@link TvInputManager#TV_MESSAGE_KEY_SUBTYPE},
+         *             {@link TvInputManager#TV_MESSAGE_KEY_RAW_DATA}.
+         *             See {@link TvInputManager#TV_MESSAGE_KEY_SUBTYPE} for more information on
+         *             how to parse this data.
          */
-        public void onTvMessage(@NonNull @TvInputManager.TvMessageType String type,
+        public void onTvMessage(@TvInputManager.TvMessageType int type,
                 @NonNull Bundle data) {
         }
 
@@ -1338,8 +1348,12 @@
          * @param requestId The ID of this request which is used to match the corresponding
          *                  response. The request ID in
          *                  {@link #onRecordingStarted(String, String)} for this request is the
-         *                  same as the ID sent here.
-         * @param programUri The URI for the TV program to record.
+         *                  same as the ID sent here. This should be defined by the
+         *                  {@link TvInteractiveAppService} and can be any string.
+         *                  Should this API be called with the same requestId twice, both 
+         *                  requests should be handled regardless by the TV application.
+         * @param programUri The URI for the TV program to record, built by
+         *            {@link TvContract#buildProgramUri(long)}. Can be {@code null}.
          * @see android.media.tv.TvRecordingClient#startRecording(Uri)
          */
         @CallSuper
@@ -1390,7 +1404,10 @@
          * @param requestId The ID of this request which is used to match the corresponding
          *                  response. The request ID in
          *                  {@link #onRecordingScheduled(String, String)} for this request is the
-         *                  same as the ID sent here.
+         *                  same as the ID sent here. This should be defined by the
+         *                  {@link TvInteractiveAppService} and can be any string.
+         *                  Should this API be called with the same requestId twice, both requests
+         *                  should be handled regardless by the TV application.
          * @param inputId The ID of the TV input for the given channel.
          * @param channelUri The URI of a channel to be recorded.
          * @param programUri The URI of the TV program to be recorded.
@@ -1424,7 +1441,10 @@
          * @param requestId The ID of this request which is used to match the corresponding
          *                  response. The request ID in
          *                  {@link #onRecordingScheduled(String, String)} for this request is the
-         *                  same as the ID sent here.
+         *                  same as the ID sent here. This should be defined by the
+         *                  {@link TvInteractiveAppService} and can be any string. Should this API
+         *                  be called with the same requestId twice, both requests should be handled
+         *                  regardless by the TV application.
          * @param inputId The ID of the TV input for the given channel.
          * @param channelUri The URI of a channel to be recorded.
          * @param startTime The start time of the recording in milliseconds since epoch.
@@ -1507,8 +1527,7 @@
          * @param type The type of recording to retrieve.
          */
         @CallSuper
-        public void requestTvRecordingInfoList(@NonNull @TvRecordingInfo.TvRecordingListType
-                int type) {
+        public void requestTvRecordingInfoList(@TvRecordingInfo.TvRecordingListType int type) {
             executeOrPostRunnableOnMainThread(() -> {
                 try {
                     if (DEBUG) {
@@ -1753,7 +1772,7 @@
             onAdResponse(response);
         }
 
-        void notifyTvMessage(String type, Bundle data) {
+        void notifyTvMessage(int type, Bundle data) {
             if (DEBUG) {
                 Log.d(TAG, "notifyTvMessage (type=" + type + ", data= " + data + ")");
             }
@@ -1942,7 +1961,7 @@
          * @param buffer The {@link AdBuffer} to be received
          */
         @CallSuper
-        public void notifyAdBuffer(@NonNull AdBuffer buffer) {
+        public void notifyAdBufferReady(@NonNull AdBuffer buffer) {
             executeOrPostRunnableOnMainThread(new Runnable() {
                 @MainThread
                 @Override
@@ -1950,10 +1969,10 @@
                     try {
                         if (DEBUG) {
                             Log.d(TAG,
-                                    "notifyAdBuffer(buffer=" + buffer + ")");
+                                    "notifyAdBufferReady(buffer=" + buffer + ")");
                         }
                         if (mSessionCallback != null) {
-                            mSessionCallback.onAdBuffer(buffer);
+                            mSessionCallback.onAdBufferReady(buffer);
                         }
                     } catch (RemoteException e) {
                         Log.w(TAG, "error in notifyAdBuffer", e);
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppView.java b/media/java/android/media/tv/interactive/TvInteractiveAppView.java
index 0a8de12..80a1435 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppView.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppView.java
@@ -675,6 +675,8 @@
      * @param requestId The ID of the request when
      *                  {@link TvInteractiveAppService.Session#requestStartRecording(String, Uri)}
      *                  is called. {@code null} if the recording is not triggered by a request.
+     *                  This ID should be created by the {@link TvInteractiveAppService} and
+     *                  can be any string.
      * @see TvInteractiveAppView#notifyRecordingStopped(String)
      */
     public void notifyRecordingStarted(@NonNull String recordingId, @Nullable String requestId) {
@@ -682,7 +684,7 @@
             Log.d(TAG, "notifyRecordingStarted");
         }
         if (mSession != null) {
-            mSession.notifyRecordingStarted(recordingId, recordingId);
+            mSession.notifyRecordingStarted(recordingId, requestId);
         }
     }
 
@@ -922,6 +924,8 @@
      * @param requestId The ID of the request when
      *                  {@link TvInteractiveAppService.Session#requestScheduleRecording} is called.
      *                  {@code null} if the recording is not triggered by a request.
+     *                  This ID should be created by the {@link TvInteractiveAppService} and
+     *                  can be any string.
      */
     public void notifyRecordingScheduled(
             @NonNull String recordingId, @Nullable String requestId) {
@@ -940,9 +944,14 @@
      *
      * @param type The type of message received, such as
      * {@link TvInputManager#TV_MESSAGE_TYPE_WATERMARK}
-     * @param data The raw data of the message
+     * @param data The raw data of the message. The bundle keys are:
+     *             {@link TvInputManager#TV_MESSAGE_KEY_STREAM_ID},
+     *             {@link TvInputManager#TV_MESSAGE_KEY_SUBTYPE},
+     *             {@link TvInputManager#TV_MESSAGE_KEY_RAW_DATA}.
+     *             See {@link TvInputManager#TV_MESSAGE_KEY_SUBTYPE} for more information on
+     *             how to parse this data.
      */
-    public void notifyTvMessage(@NonNull @TvInputManager.TvMessageType String type,
+    public void notifyTvMessage(@NonNull @TvInputManager.TvMessageType int type,
             @NonNull Bundle data) {
         if (DEBUG) {
             Log.d(TAG, "notifyTvMessage type=" + type
@@ -1214,14 +1223,17 @@
         }
 
         /**
-         * This is called when {@link TvInteractiveAppService.Session#requestStartRecording(Uri)}
-         * is called.
+         * This is called when
+         * {@link TvInteractiveAppService.Session#requestStartRecording(String, Uri)} is called.
          *
          * @param iAppServiceId The ID of the TV interactive app service bound to this view.
          * @param requestId The ID of this request which is used to match the corresponding
          *                  response. The request ID in
-         *                  {@link #notifyRecordingStarted(String, String)}
-         *                  for this request should be the same as the ID received here.
+         *                  {@link #notifyRecordingStarted(String, String)}  for this request is the
+         *                  same as the ID sent here. This should be defined by the
+         *                  TIAS and can be any string. Should this API be called with the
+         *                  same requestId twice, both requests should be handled regardless
+         *                  by the TV application.
          * @param programUri The URI of the program to record
          *
          */
@@ -1252,8 +1264,11 @@
          * @param iAppServiceId The ID of the TV interactive app service bound to this view.
          * @param requestId The ID of this request which is used to match the corresponding
          *                  response. The request ID in
-         *                  {@link #notifyRecordingScheduled(String, String)} for this request
-         *                  should be the same as the ID received here.
+         *                  {@link #notifyRecordingScheduled(String, String)} for this request is
+         *                  the same as the ID sent here. This should be defined by the
+         *                  TIAS and can be any string. Should this API be called with the
+         *                  same requestId twice, both requests should be handled regardless
+         *                  by the TV application.
          * @param inputId The ID of the TV input for the given channel.
          * @param channelUri The URI of a channel to be recorded.
          * @param programUri The URI of the TV program to be recorded.
@@ -1276,8 +1291,11 @@
          * @param iAppServiceId The ID of the TV interactive app service bound to this view.
          * @param requestId The ID of this request which is used to match the corresponding
          *                  response. The request ID in
-         *                  {@link #notifyRecordingScheduled(String, String)} for this request
-         *                  should be the same as the ID received here.
+         *                  {@link #notifyRecordingScheduled(String, String)} for this request is
+         *                  the same as the ID sent here. This should be defined by the
+         *                  TIAS and can be any string. Should this API be called with the
+         *                  same requestId twice, both requests should be handled regardless
+         *                  by the TV application.
          * @param inputId The ID of the TV input for the given channel.
          * @param channelUri The URI of a channel to be recorded.
          * @param startTime The start time of the recording in milliseconds since epoch.
@@ -1350,7 +1368,7 @@
          */
         public void onRequestTvRecordingInfoList(
                 @NonNull String iAppServiceId,
-                @NonNull @TvRecordingInfo.TvRecordingListType int type) {
+                @TvRecordingInfo.TvRecordingListType int type) {
         }
     }
 
diff --git a/media/java/android/media/tv/tuner/filter/Filter.java b/media/java/android/media/tv/tuner/filter/Filter.java
index 7e9443b..c39a6db 100644
--- a/media/java/android/media/tv/tuner/filter/Filter.java
+++ b/media/java/android/media/tv/tuner/filter/Filter.java
@@ -32,6 +32,7 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.lang.NullPointerException;
 import java.util.concurrent.Executor;
 
 /**
@@ -271,7 +272,12 @@
                 mExecutor.execute(() -> {
                     synchronized (mCallbackLock) {
                         if (mCallback != null) {
-                            mCallback.onFilterStatusChanged(this, status);
+                            try {
+                                mCallback.onFilterStatusChanged(this, status);
+                            }
+                            catch (NullPointerException e) {
+                                Log.d(TAG, "catch exception:" + e);
+                            }
                         }
                     }
                 });
@@ -285,7 +291,12 @@
                 mExecutor.execute(() -> {
                     synchronized (mCallbackLock) {
                         if (mCallback != null) {
-                            mCallback.onFilterEvent(this, events);
+                            try {
+                                mCallback.onFilterEvent(this, events);
+                            }
+                            catch (NullPointerException e) {
+                                Log.d(TAG, "catch exception:" + e);
+                            }
                         } else {
                             for (FilterEvent event : events) {
                                 if (event instanceof MediaEvent) {
diff --git a/media/java/android/media/tv/tuner/frontend/IptvFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/IptvFrontendSettings.java
index ba75102..65247a1 100644
--- a/media/java/android/media/tv/tuner/frontend/IptvFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/IptvFrontendSettings.java
@@ -34,7 +34,7 @@
  * @hide
  */
 @SystemApi
-public class IptvFrontendSettings extends FrontendSettings {
+public final class IptvFrontendSettings extends FrontendSettings {
     /** @hide */
     @IntDef(prefix = "PROTOCOL_",
             value = {PROTOCOL_UNDEFINED, PROTOCOL_UDP, PROTOCOL_RTP})
@@ -181,14 +181,6 @@
     }
 
     /**
-     * Creates a builder for {@link IptvFrontendSettings}.
-     */
-    @NonNull
-    public static Builder builder() {
-        return new Builder();
-    }
-
-    /**
      * Builder for {@link IptvFrontendSettings}.
      */
     public static final class Builder {
@@ -202,7 +194,7 @@
         private long mBitrate = 0;
         private String mContentUrl = "";
 
-        private Builder() {
+        public Builder() {
         }
 
         /**
@@ -309,8 +301,8 @@
          */
         @NonNull
         public IptvFrontendSettings build() {
-            return new IptvFrontendSettings(mSrcIpAddress, mDstIpAddress, mSrcPort,
-                    mDstPort, mFec, mProtocol, mIgmp, mBitrate, mContentUrl);
+            return new IptvFrontendSettings(mSrcIpAddress, mDstIpAddress, mSrcPort, mDstPort,
+                    mFec, mProtocol, mIgmp, mBitrate, mContentUrl);
         }
     }
 
diff --git a/media/java/android/media/tv/tuner/frontend/IptvFrontendSettingsFec.java b/media/java/android/media/tv/tuner/frontend/IptvFrontendSettingsFec.java
index a70af17..12eebee 100644
--- a/media/java/android/media/tv/tuner/frontend/IptvFrontendSettingsFec.java
+++ b/media/java/android/media/tv/tuner/frontend/IptvFrontendSettingsFec.java
@@ -31,7 +31,7 @@
  * @hide
  */
 @SystemApi
-public class IptvFrontendSettingsFec {
+public final class IptvFrontendSettingsFec {
     /** @hide */
     @IntDef(prefix = "FEC_TYPE_",
             value = {FEC_TYPE_UNDEFINED, FEC_TYPE_COLUMN, FEC_TYPE_ROW, FEC_TYPE_COLUMN_ROW})
@@ -93,14 +93,6 @@
     }
 
     /**
-     * Creates a builder for {@link IptvFrontendSettingsFec}.
-     */
-    @NonNull
-    public static Builder builder() {
-        return new Builder();
-    }
-
-    /**
      * Builder for {@link IptvFrontendSettingsFec}.
      */
     public static final class Builder {
@@ -108,7 +100,7 @@
         private int mFecRowNum;
         private int mFecColNum;
 
-        private Builder() {
+        public Builder() {
         }
 
         /**
diff --git a/media/tests/AudioPolicyTest/Android.bp b/media/tests/AudioPolicyTest/Android.bp
index 63292ce..4624dfe 100644
--- a/media/tests/AudioPolicyTest/Android.bp
+++ b/media/tests/AudioPolicyTest/Android.bp
@@ -14,6 +14,7 @@
         "androidx.test.ext.junit",
         "androidx.test.rules",
         "guava",
+        "guava-android-testlib",
         "hamcrest-library",
         "platform-test-annotations",
     ],
diff --git a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixUnitTests.java b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixUnitTests.java
new file mode 100644
index 0000000..bbca882
--- /dev/null
+++ b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixUnitTests.java
@@ -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.audiopolicytest;
+
+import static android.media.AudioFormat.CHANNEL_OUT_MONO;
+import static android.media.AudioFormat.CHANNEL_OUT_STEREO;
+import static android.media.AudioFormat.ENCODING_PCM_16BIT;
+import static android.media.audiopolicy.AudioMixingRule.MIX_ROLE_INJECTOR;
+import static android.media.audiopolicy.AudioMixingRule.MIX_ROLE_PLAYERS;
+import static android.media.audiopolicy.AudioMixingRule.RULE_MATCH_AUDIO_SESSION_ID;
+import static android.media.audiopolicy.AudioMixingRule.RULE_MATCH_UID;
+
+import android.media.AudioFormat;
+import android.media.audiopolicy.AudioMix;
+import android.media.audiopolicy.AudioMixingRule;
+import android.media.audiopolicy.AudioPolicyConfig;
+import android.os.Parcel;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.google.common.testing.EqualsTester;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Unit tests for AudioMix.
+ *
+ * Run with "atest AudioMixUnitTests".
+ */
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class AudioMixUnitTests {
+    private static final AudioFormat OUTPUT_FORMAT_STEREO_44KHZ_PCM =
+            new AudioFormat.Builder()
+                    .setSampleRate(44000)
+                    .setChannelMask(CHANNEL_OUT_STEREO)
+                    .setEncoding(ENCODING_PCM_16BIT).build();
+    private static final AudioFormat OUTPUT_FORMAT_MONO_16KHZ_PCM =
+            new AudioFormat.Builder()
+                    .setSampleRate(16000)
+                    .setChannelMask(CHANNEL_OUT_MONO)
+                    .setEncoding(ENCODING_PCM_16BIT).build();
+    private static final AudioFormat INPUT_FORMAT_MONO_16KHZ_PCM =
+            new AudioFormat.Builder()
+                    .setSampleRate(16000)
+                    .setChannelMask(AudioFormat.CHANNEL_IN_MONO)
+                    .setEncoding(ENCODING_PCM_16BIT).build();
+
+    @Test
+    public void testEquals() {
+        final EqualsTester equalsTester = new EqualsTester();
+
+        // --- Equality group 1
+        final AudioMix playbackAudioMixWithSessionId42AndUid123 =
+                new AudioMix.Builder(new AudioMixingRule.Builder()
+                        .setTargetMixRole(MIX_ROLE_PLAYERS)
+                        .addMixRule(RULE_MATCH_AUDIO_SESSION_ID, 42)
+                        .addMixRule(RULE_MATCH_UID, 123).build())
+                        .setFormat(OUTPUT_FORMAT_STEREO_44KHZ_PCM)
+                        .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK).build();
+        final AudioMix playbackAudioMixWithUid123AndSessionId42 =
+                new AudioMix.Builder(new AudioMixingRule.Builder()
+                        .setTargetMixRole(MIX_ROLE_PLAYERS)
+                        .addMixRule(RULE_MATCH_UID, 123)
+                        .addMixRule(RULE_MATCH_AUDIO_SESSION_ID, 42).build())
+                        .setFormat(OUTPUT_FORMAT_STEREO_44KHZ_PCM)
+                        .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK).build();
+        equalsTester.addEqualityGroup(
+                playbackAudioMixWithSessionId42AndUid123,
+                playbackAudioMixWithUid123AndSessionId42,
+                writeToAndFromParcel(playbackAudioMixWithSessionId42AndUid123),
+                writeToAndFromParcel(playbackAudioMixWithUid123AndSessionId42));
+
+        // --- Equality group 2
+        final AudioMix recordingAudioMixWithSessionId42AndUid123 =
+                new AudioMix.Builder(new AudioMixingRule.Builder()
+                        .setTargetMixRole(MIX_ROLE_INJECTOR)
+                        .addMixRule(RULE_MATCH_AUDIO_SESSION_ID, 42)
+                        .addMixRule(RULE_MATCH_UID, 123).build())
+                        .setFormat(INPUT_FORMAT_MONO_16KHZ_PCM)
+                        .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK).build();
+        final AudioMix recordingAudioMixWithUid123AndSessionId42 =
+                new AudioMix.Builder(new AudioMixingRule.Builder()
+                        .setTargetMixRole(MIX_ROLE_INJECTOR)
+                        .addMixRule(RULE_MATCH_AUDIO_SESSION_ID, 42)
+                        .addMixRule(RULE_MATCH_UID, 123).build())
+                        .setFormat(INPUT_FORMAT_MONO_16KHZ_PCM)
+                        .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK).build();
+        equalsTester.addEqualityGroup(recordingAudioMixWithSessionId42AndUid123,
+                recordingAudioMixWithUid123AndSessionId42,
+                writeToAndFromParcel(recordingAudioMixWithSessionId42AndUid123),
+                writeToAndFromParcel(recordingAudioMixWithUid123AndSessionId42));
+
+        // --- Equality group 3
+        final AudioMix recordingAudioMixWithSessionId42AndUid123Render =
+                new AudioMix.Builder(new AudioMixingRule.Builder()
+                        .setTargetMixRole(MIX_ROLE_INJECTOR)
+                        .addMixRule(RULE_MATCH_AUDIO_SESSION_ID, 42)
+                        .addMixRule(RULE_MATCH_UID, 123).build())
+                        .setFormat(INPUT_FORMAT_MONO_16KHZ_PCM)
+                        .setRouteFlags(
+                                AudioMix.ROUTE_FLAG_LOOP_BACK | AudioMix.ROUTE_FLAG_RENDER).build();
+        equalsTester.addEqualityGroup(recordingAudioMixWithSessionId42AndUid123Render,
+                writeToAndFromParcel(recordingAudioMixWithSessionId42AndUid123Render));
+
+        // --- Equality group 4
+        final AudioMix playbackAudioMixWithUid123 =
+                new AudioMix.Builder(new AudioMixingRule.Builder()
+                        .setTargetMixRole(MIX_ROLE_PLAYERS)
+                        .addMixRule(RULE_MATCH_UID, 123).build())
+                        .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM)
+                        .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK).build();
+        equalsTester.addEqualityGroup(playbackAudioMixWithUid123,
+                writeToAndFromParcel(playbackAudioMixWithUid123));
+
+        // --- Equality group 5
+        final AudioMix playbackAudioMixWithUid42 =
+                new AudioMix.Builder(new AudioMixingRule.Builder()
+                        .setTargetMixRole(MIX_ROLE_PLAYERS)
+                        .addMixRule(RULE_MATCH_UID, 42).build())
+                        .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM)
+                        .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK).build();
+        equalsTester.addEqualityGroup(playbackAudioMixWithUid42,
+                writeToAndFromParcel(playbackAudioMixWithUid42));
+
+        equalsTester.testEquals();
+    }
+
+    private static AudioMix writeToAndFromParcel(AudioMix audioMix) {
+        AudioPolicyConfig apc = new AudioPolicyConfig(new ArrayList<>(List.of(audioMix)));
+        Parcel parcel = Parcel.obtain();
+        apc.writeToParcel(parcel, /*flags=*/0);
+        parcel.setDataPosition(0);
+        AudioMix unmarshalledMix =
+                AudioPolicyConfig.CREATOR.createFromParcel(parcel).getMixes().get(0);
+        parcel.recycle();
+        return unmarshalledMix;
+    }
+}
diff --git a/media/tests/projection/Android.bp b/media/tests/projection/Android.bp
index 08d9501..e313c46 100644
--- a/media/tests/projection/Android.bp
+++ b/media/tests/projection/Android.bp
@@ -29,7 +29,9 @@
         "mockito-target-extended-minus-junit4",
         "platform-test-annotations",
         "testng",
+        "testables",
         "truth-prebuilt",
+        "platform-compat-test-rules",
     ],
 
     // Needed for mockito-target-extended-minus-junit4
diff --git a/media/tests/projection/AndroidManifest.xml b/media/tests/projection/AndroidManifest.xml
index 62f148c..0c97604 100644
--- a/media/tests/projection/AndroidManifest.xml
+++ b/media/tests/projection/AndroidManifest.xml
@@ -19,6 +19,7 @@
           package="android.media.projection.mediaprojectiontests"
           android:sharedUserId="com.android.uid.test">
     <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
+    <uses-permission android:name="android.permission.MANAGE_MEDIA_PROJECTION" />
 
     <application android:debuggable="true"
                  android:testOnly="true">
diff --git a/media/tests/projection/src/android/media/projection/FakeIMediaProjection.java b/media/tests/projection/src/android/media/projection/FakeIMediaProjection.java
new file mode 100644
index 0000000..3cfc0fe
--- /dev/null
+++ b/media/tests/projection/src/android/media/projection/FakeIMediaProjection.java
@@ -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 android.media.projection;
+
+import android.os.IBinder;
+import android.os.RemoteException;
+
+/**
+ * The connection between MediaProjection and system server is represented by IMediaProjection;
+ * outside the test it is implemented by the system server.
+ */
+public final class FakeIMediaProjection extends IMediaProjection.Stub {
+    boolean mIsStarted = false;
+    IBinder mLaunchCookie = null;
+    IMediaProjectionCallback mIMediaProjectionCallback = null;
+
+    @Override
+    public void start(IMediaProjectionCallback callback) throws RemoteException {
+        mIMediaProjectionCallback = callback;
+        mIsStarted = true;
+    }
+
+    @Override
+    public void stop() throws RemoteException {
+        // Pass along to the client's callback wrapper.
+        mIMediaProjectionCallback.onStop();
+    }
+
+    @Override
+    public boolean canProjectAudio() throws RemoteException {
+        return false;
+    }
+
+    @Override
+    public boolean canProjectVideo() throws RemoteException {
+        return false;
+    }
+
+    @Override
+    public boolean canProjectSecureVideo() throws RemoteException {
+        return false;
+    }
+
+    @Override
+    public int applyVirtualDisplayFlags(int flags) throws RemoteException {
+        return 0;
+    }
+
+    @Override
+    public void registerCallback(IMediaProjectionCallback callback) throws RemoteException {
+
+    }
+
+    @Override
+    public void unregisterCallback(IMediaProjectionCallback callback) throws RemoteException {
+
+    }
+
+    @Override
+    public IBinder getLaunchCookie() throws RemoteException {
+        return mLaunchCookie;
+    }
+
+    @Override
+    public void setLaunchCookie(IBinder launchCookie) throws RemoteException {
+        mLaunchCookie = launchCookie;
+    }
+}
diff --git a/media/tests/projection/src/android/media/projection/MediaProjectionTest.java b/media/tests/projection/src/android/media/projection/MediaProjectionTest.java
new file mode 100644
index 0000000..bf616d7
--- /dev/null
+++ b/media/tests/projection/src/android/media/projection/MediaProjectionTest.java
@@ -0,0 +1,197 @@
+/*
+ * 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.media.projection;
+
+
+import static android.media.projection.MediaProjection.MEDIA_PROJECTION_REQUIRES_CALLBACK;
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
+import static libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
+
+import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import android.annotation.Nullable;
+import android.compat.testing.PlatformCompatChangeRule;
+import android.content.Context;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.VirtualDisplay;
+import android.hardware.display.VirtualDisplayConfig;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+import android.testing.TestableContext;
+import android.view.Display;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+
+/**
+ * Tests for the {@link MediaProjection} class.
+ *
+ * Build/Install/Run:
+ * atest MediaProjectionTests:MediaProjectionTest
+ */
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class MediaProjectionTest {
+    // Values for creating a VirtualDisplay.
+    private static final String VIRTUAL_DISPLAY_NAME = "MEDIA_PROJECTION_VIRTUAL_DISPLAY";
+    private static final int VIRTUAL_DISPLAY_WIDTH = 500;
+    private static final int VIRTUAL_DISPLAY_HEIGHT = 600;
+    private static final int VIRTUAL_DISPLAY_DENSITY = 100;
+    private static final int VIRTUAL_DISPLAY_FLAGS = 0;
+
+    private final Handler mHandler = new Handler(Looper.getMainLooper());
+    // Fake the connection to the system server.
+    private final FakeIMediaProjection mFakeIMediaProjection = new FakeIMediaProjection();
+    // Callback registered by an app.
+    private MediaProjection mMediaProjection;
+
+    @Mock
+    private MediaProjection.Callback mMediaProjectionCallback;
+    @Mock
+    private IMediaProjectionManager mIMediaProjectionManager;
+    @Mock
+    private Display mDisplay;
+    @Mock
+    private VirtualDisplay.Callback mVirtualDisplayCallback;
+    @Mock
+    private VirtualDisplay mVirtualDisplay;
+    @Mock
+    private DisplayManager mDisplayManager;
+
+    @Rule
+    public TestRule compatChangeRule = new PlatformCompatChangeRule();
+
+    @Rule
+    public final TestableContext mTestableContext = new TestableContext(
+            InstrumentationRegistry.getInstrumentation().getTargetContext());
+
+    private MockitoSession mMockingSession;
+
+    @Before
+    public void setup() throws Exception {
+        mMockingSession =
+                mockitoSession()
+                        .initMocks(this)
+                        .strictness(Strictness.LENIENT)
+                        .startMocking();
+
+        doReturn(mock(IBinder.class)).when(mIMediaProjectionManager).asBinder();
+
+        // Support the MediaProjection instance.
+        mFakeIMediaProjection.setLaunchCookie(mock(IBinder.class));
+        mMediaProjection = new MediaProjection(mTestableContext, mFakeIMediaProjection,
+                mIMediaProjectionManager, mDisplayManager);
+
+        // Support creation of the VirtualDisplay.
+        mTestableContext.addMockSystemService(DisplayManager.class, mDisplayManager);
+        doReturn(mDisplay).when(mVirtualDisplay).getDisplay();
+        doReturn(DEFAULT_DISPLAY + 7).when(mDisplay).getDisplayId();
+        doReturn(mVirtualDisplay).when(mDisplayManager).createVirtualDisplay(
+                any(MediaProjection.class), any(VirtualDisplayConfig.class),
+                nullable(VirtualDisplay.Callback.class), nullable(Handler.class),
+                nullable(Context.class));
+    }
+
+    @After
+    public void tearDown() {
+        mMockingSession.finishMocking();
+    }
+
+    @Test
+    public void testConstruction() throws RemoteException {
+        assertThat(mMediaProjection).isNotNull();
+        assertThat(mFakeIMediaProjection.mIsStarted).isTrue();
+    }
+
+    @Test
+    public void testRegisterCallback_null() {
+        assertThrows(NullPointerException.class,
+                () -> mMediaProjection.registerCallback(null, mHandler));
+    }
+
+    @Test
+    public void testUnregisterCallback_null() {
+        mMediaProjection.registerCallback(mMediaProjectionCallback, mHandler);
+        assertThrows(NullPointerException.class,
+                () -> mMediaProjection.unregisterCallback(null));
+    }
+
+    @Test
+    @DisableCompatChanges({MEDIA_PROJECTION_REQUIRES_CALLBACK})
+    public void createVirtualDisplay_noCallbackRequired_missingMediaProjectionCallback() {
+        assertThat(createVirtualDisplay(null)).isNotNull();
+        assertThat(createVirtualDisplay(mVirtualDisplayCallback)).isNotNull();
+    }
+
+    @Test
+    @DisableCompatChanges({MEDIA_PROJECTION_REQUIRES_CALLBACK})
+    public void createVirtualDisplay_noCallbackRequired_givenMediaProjectionCallback() {
+        mMediaProjection.registerCallback(mMediaProjectionCallback, mHandler);
+        assertThat(createVirtualDisplay(null)).isNotNull();
+        assertThat(createVirtualDisplay(mVirtualDisplayCallback)).isNotNull();
+    }
+
+    @Test
+    @EnableCompatChanges({MEDIA_PROJECTION_REQUIRES_CALLBACK})
+    public void createVirtualDisplay_callbackRequired_missingMediaProjectionCallback() {
+        assertThrows(IllegalStateException.class,
+                () -> createVirtualDisplay(mVirtualDisplayCallback));
+    }
+
+    @Test
+    @EnableCompatChanges({MEDIA_PROJECTION_REQUIRES_CALLBACK})
+    public void createVirtualDisplay_callbackRequired_givenMediaProjectionCallback() {
+        mMediaProjection.registerCallback(mMediaProjectionCallback, mHandler);
+        assertThat(createVirtualDisplay(null)).isNotNull();
+        assertThat(createVirtualDisplay(mVirtualDisplayCallback)).isNotNull();
+    }
+
+    private VirtualDisplay createVirtualDisplay(@Nullable VirtualDisplay.Callback callback) {
+        // No recording will take place with a null surface.
+        return mMediaProjection.createVirtualDisplay(
+                VIRTUAL_DISPLAY_NAME, VIRTUAL_DISPLAY_WIDTH,
+                VIRTUAL_DISPLAY_HEIGHT, VIRTUAL_DISPLAY_DENSITY,
+                VIRTUAL_DISPLAY_FLAGS, /* surface = */ null,
+                callback, /* handler= */ mHandler);
+    }
+}
diff --git a/packages/AppPredictionLib/Android.bp b/packages/AppPredictionLib/Android.bp
index 5a68fdc..31c1936 100644
--- a/packages/AppPredictionLib/Android.bp
+++ b/packages/AppPredictionLib/Android.bp
@@ -25,7 +25,7 @@
     name: "app_prediction",
 
     sdk_version: "system_current",
-    min_sdk_version: "system_current",
+    min_sdk_version: "current",
 
     srcs: [
         "src/**/*.java",
diff --git a/packages/CarrierDefaultApp/res/values-af/strings.xml b/packages/CarrierDefaultApp/res/values-af/strings.xml
index 13ae4da..d2e47d8 100644
--- a/packages/CarrierDefaultApp/res/values-af/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-af/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Byvoorbeeld, die aanmeldbladsy behoort dalk nie aan die organisasie wat gewys word nie."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Gaan in elk geval deur blaaier voort"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Prestasiehupstoot"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Verbeter jou 5G-ervaring"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s beveel aan dat jy ’n werkverrigtinghupstootpakket koop. Tik om deur %2$s te koop."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Verbeter jou appervaring"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Tik om %s se webwerf te besoek en meer te wete te kom"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Nie nou nie"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Bestuur"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Koop ’n prestasiehupstoot."</string>
diff --git a/packages/CarrierDefaultApp/res/values-am/strings.xml b/packages/CarrierDefaultApp/res/values-am/strings.xml
index e1f91ce..c27c942 100644
--- a/packages/CarrierDefaultApp/res/values-am/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-am/strings.xml
@@ -15,8 +15,9 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"ለምሳሌ፣ የመግቢያ ገጹ የሚታየው ድርጅት ላይሆን ይችላል።"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"ለማንኛውም በአሳሽ በኩል ይቀጥሉ"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"የአፈጻጸም ጭማሪ"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"የእርስዎን የ5ጂ ተሞክሮ ያሻሽሉ"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s የአፈጻጸም መጨመሪያ ዕቅድ መግዛትን ይመክራል። በ%2$s ለመግዛት መታ ያድርጉ።"</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"የመተግበሪያ ተሞክሮዎን ያሻሽሉ"</string>
+    <!-- no translation found for performance_boost_notification_detail (907363829888387028) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"አሁን አይደለም"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"አስተዳድር"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"የአፈጻጸም ጭማሪ ይግዙ።"</string>
diff --git a/packages/CarrierDefaultApp/res/values-ar/strings.xml b/packages/CarrierDefaultApp/res/values-ar/strings.xml
index c2e5ba8..b11de16 100644
--- a/packages/CarrierDefaultApp/res/values-ar/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ar/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"على سبيل المثال، قد لا تنتمي صفحة تسجيل الدخول إلى المؤسسة المعروضة."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"المتابعة على أي حال عبر المتصفح"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"تطبيق تعزيز الأداء"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"تحسين تجربة شبكة الجيل الخامس"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"‏هناك اقتراح من ‏\"%1$s\" لشراء خطة لتعزيز الأداء. انقر للشراء من خلال ‏\"%2$s\"."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"تحسين تجربة استخدامك للتطبيق"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"‏انقر لزيارة موقع \"%s\" الإلكتروني ومعرفة المزيد."</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"لاحقًا"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"إدارة"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"شراء تطبيق تعزيز الأداء"</string>
diff --git a/packages/CarrierDefaultApp/res/values-as/strings.xml b/packages/CarrierDefaultApp/res/values-as/strings.xml
index 8881940..2144c0b 100644
--- a/packages/CarrierDefaultApp/res/values-as/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-as/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"উদাহৰণস্বৰূপে, আপোনাক দেখুওৱা লগ ইনৰ পৃষ্ঠাটো প্ৰতিষ্ঠানটোৰ নিজা নহ\'বও পাৰে।"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"তথাপিও ব্ৰাউজাৰৰ জৰিয়তে অব্যাহত ৰাখক"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"কাৰ্যক্ষমতা পৰিৱৰ্ধন"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"আপোনাৰ 5G অভিজ্ঞতা উন্নত কৰক"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$sএ এখন কাৰ্যক্ষমতা পৰিৱৰ্ধন অঁচনি ক্ৰয় কৰাৰ চুপাৰিছ কৰে। %2$sৰ জৰিয়তে ক্ৰয় কৰিবলৈ টিপক।"</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"আপোনাৰ এপৰ অভিজ্ঞতা উন্নত কৰক"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"%sৰ ৱেবছাইটটো চাবলৈ আৰু অধিক জানিবলৈ টিপক"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"এতিয়া নহয়"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"পৰিচালনা কৰক"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"এটা কাৰ্যক্ষমতা পৰিৱৰ্ধন ক্ৰয় কৰক।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-az/strings.xml b/packages/CarrierDefaultApp/res/values-az/strings.xml
index f64fcb6..6267b7e 100644
--- a/packages/CarrierDefaultApp/res/values-az/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-az/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Məsələn, giriş səhifəsi göstərilən təşkilata aid olmaya bilər."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Hər bir halda brazuer ilə davam edin"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performans artırması"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"5G təcrübənizi təkmilləşdirin"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s performans artırma planı almağı tövsiyə edir. %2$s ilə almaq üçün toxunun."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Tətbiq təcrübənizi yaxşılaşdırın"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"%s veb-saytına daxil olmaq üçün toxunun və ətraflı məlumat əldə edin"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"İndi yox"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"İdarə edin"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Performans artırması alın."</string>
diff --git a/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml b/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml
index 5533bfd..38fe610 100644
--- a/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Na primer, stranica za prijavljivanje možda ne pripada prikazanoj organizaciji."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Ipak nastavi preko pregledača"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Poboljšanje učinka"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Poboljšajte 5G doživljaj"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s preporučuje kupovinu paketa za poboljšanje performansi. Dodirnite da biste kupili preko %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Poboljšajte doživljaj aplikacije"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Dodirnite da biste posetili veb-sajt %s i saznali više"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne sada"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Upravljaj"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupite poboljšanje učinka."</string>
diff --git a/packages/CarrierDefaultApp/res/values-be/strings.xml b/packages/CarrierDefaultApp/res/values-be/strings.xml
index 0053cda..d92fd1b 100644
--- a/packages/CarrierDefaultApp/res/values-be/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-be/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Напрыклад, старонка ўваходу можа не належаць указанай арганізацыі."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Усё роўна працягнуць праз браўзер"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Павышэнне прадукцыйнасці"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Пашырце магчымасці 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s рэкамендуе купіць план павышэння прадукцыйнасці. Націсніце, каб купіць праз %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Пашырце магчымасці вашай праграмы"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Націсніце, каб наведаць сайт %s\'s і даведацца больш"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не цяпер"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Кіраваць"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Аплаціце павышэнне прадукцыйнасці."</string>
diff --git a/packages/CarrierDefaultApp/res/values-bg/strings.xml b/packages/CarrierDefaultApp/res/values-bg/strings.xml
index a37e0a3..1b574a5 100644
--- a/packages/CarrierDefaultApp/res/values-bg/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-bg/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Например страницата за вход може да не принадлежи на показаната организация."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Продължаване през браузър въпреки това"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Увеличаване на ефективността"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Подобряване на практическата работа с 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s препоръчва да купите план за увеличаване на ефективността. Докоснете, за да купите чрез %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Подобряване на практическата работа в приложението"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Докоснете, за да посетите уебсайта на %s и да научите повече"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не сега"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Управление"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Купете пакет за увеличаване на ефективността."</string>
diff --git a/packages/CarrierDefaultApp/res/values-bn/strings.xml b/packages/CarrierDefaultApp/res/values-bn/strings.xml
index f78449c..890b3c2 100644
--- a/packages/CarrierDefaultApp/res/values-bn/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-bn/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"যেমন, লগ-ইন পৃষ্ঠাটি যে প্রতিষ্ঠানের পৃষ্ঠা বলে দেখানো আছে, আসলে তা নাও হতে পারে৷"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"যাই হোক, ব্রাউজারের মাধ্যমে চালিয়ে যান"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"পারফর্ম্যান্স বুস্ট"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"আপনার 5G অভিজ্ঞতা উন্নত করুন"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s পারফর্ম্যান্স বুস্ট প্ল্যান কেনার সাজেশন দেয়। %2$s-এর মাধ্যমে কিনতে ট্যাপ করুন।"</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"আপনার অ্যাপ ব্যবহারের অভিজ্ঞতা উন্নত করুন"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"%s-এর ওয়েবসাইটে যেতে ট্যাপ করুন এবং আরও জানুন"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"এখন নয়"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ম্যানেজ করুন"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"পারফর্ম্যান্স বুস্ট সংক্রান্ত ফিচার কিনুন।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-bs/strings.xml b/packages/CarrierDefaultApp/res/values-bs/strings.xml
index 7be8e2b..56ec344 100644
--- a/packages/CarrierDefaultApp/res/values-bs/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-bs/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Naprimjer, stranica za prijavljivanje možda ne pripada prikazanoj organizaciji."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Ipak nastavi preko preglednika"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Pojačavanje performansi"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Poboljšajte iskustvo s 5G mrežom"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s preporučuje kupovinu paketa za poboljšanje performansi. Dodirnite da kupite koristeći %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Poboljšajte iskustvo u aplikaciji"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Dodirnite da posjetite web lokaciju %s i saznate više"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne sada"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Upravljajte"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupite pojačavanje performansi."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ca/strings.xml b/packages/CarrierDefaultApp/res/values-ca/strings.xml
index 54c9e6e..9a82acd 100644
--- a/packages/CarrierDefaultApp/res/values-ca/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ca/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Per exemple, la pàgina d\'inici de sessió podria no pertànyer a l\'organització que es mostra."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continua igualment mitjançant el navegador"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Optimització de rendiment"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Millora l\'experiència 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomana comprar un pla d\'optimització de rendiment. Toca per comprar-lo mitjançant %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Millora l\'experiència a l\'aplicació"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Toca per visitar el lloc web de %s i obtenir més informació"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ara no"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gestiona"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Compra una optimització de rendiment."</string>
diff --git a/packages/CarrierDefaultApp/res/values-cs/strings.xml b/packages/CarrierDefaultApp/res/values-cs/strings.xml
index 8a09421..31c84fe 100644
--- a/packages/CarrierDefaultApp/res/values-cs/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-cs/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Přihlašovací stránka například nemusí patřit zobrazované organizaci."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Přesto pokračovat prostřednictvím prohlížeče"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Zvýšení výkonu"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Získejte rychlejší připojení 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s doporučuje zakoupit zvýšení výkonu. Klepnutím ho zakoupíte přes operátora %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Vylepšete si zážitek z aplikace"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Klepnutím přejdete na web %s, kde zjistíte další informace"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Teď ne"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Spravovat"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupte si zvýšení výkonu."</string>
diff --git a/packages/CarrierDefaultApp/res/values-da/strings.xml b/packages/CarrierDefaultApp/res/values-da/strings.xml
index cd411c9..a214db8 100644
--- a/packages/CarrierDefaultApp/res/values-da/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-da/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Det er f.eks. ikke sikkert, at loginsiden tilhører den anførte organisation."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Fortsæt alligevel via browseren"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Ydeevneboost"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Få en bedre 5G-oplevelse"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s anbefaler, at du køber et abonnement med ydeevneboost. Tryk for at købe via %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Få en bedre appoplevelse"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Tryk for at gå til websitet for %s og få flere oplysninger"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ikke nu"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Administrer"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Køb et ydeevneboost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-de/strings.xml b/packages/CarrierDefaultApp/res/values-de/strings.xml
index d20a1e8..7e9191f 100644
--- a/packages/CarrierDefaultApp/res/values-de/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-de/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Beispiel: Die Log-in-Seite gehört eventuell nicht zur angezeigten Organisation."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Trotzdem in einem Browser fortfahren"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Leistungs-Boost"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"5G-Nutzung verbessern"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s empfiehlt den Kauf eines Tarifs mit Leistungs-Boost. Du kannst tippen, um über %2$s einen zu kaufen."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"App-Nutzung verbessern"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Tippe, um die Website von %s zu besuchen und mehr zu erfahren"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Nicht jetzt"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Verwalten"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Leistungs-Boost erwerben."</string>
diff --git a/packages/CarrierDefaultApp/res/values-el/strings.xml b/packages/CarrierDefaultApp/res/values-el/strings.xml
index 0759011..3bc890a 100644
--- a/packages/CarrierDefaultApp/res/values-el/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-el/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Για παράδειγμα, η σελίδα σύνδεσης ενδέχεται να μην ανήκει στον οργανισμό που εμφανίζεται."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Συνέχεια ούτως ή άλλως μέσω του προγράμματος περιήγησης"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Ενίσχυση απόδοσης"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Βελτιώστε την εμπειρία 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"Το %1$s προτείνει την αγορά ενός προγράμματος ενίσχυσης απόδοσης. Πατήστε για αγορά μέσω %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Βελτιώστε την εμπειρία της εφαρμογής"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Πατήστε για να επισκεφτείτε τον ιστότοπο %s και να μάθετε περισσότερα"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Όχι τώρα"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Διαχείριση"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Αγοράστε μια ενίσχυση απόδοσης."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rAU/strings.xml b/packages/CarrierDefaultApp/res/values-en-rAU/strings.xml
index 720dbc7..346a1d1 100644
--- a/packages/CarrierDefaultApp/res/values-en-rAU/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rAU/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"For example, the login page might not belong to the organisation shown."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continue anyway via browser"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performance boost"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Improve your 5G experience"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommends buying a performance boost plan. Tap to buy through %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Improve your app experience"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Tap to visit %s\'s website and learn more"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Not now"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Manage"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Purchase a performance boost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rCA/strings.xml b/packages/CarrierDefaultApp/res/values-en-rCA/strings.xml
index 87978ac..2ae9f16 100644
--- a/packages/CarrierDefaultApp/res/values-en-rCA/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rCA/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"For example, the login page may not belong to the organization shown."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continue anyway via browser"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performance boost"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Improve your 5G experience"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommends buying a performance boost plan. Tap to buy through %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Improve your app experience"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Tap to visit %s\'s website and learn more"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Not now"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Manage"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Purchase a performance boost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rGB/strings.xml b/packages/CarrierDefaultApp/res/values-en-rGB/strings.xml
index 720dbc7..346a1d1 100644
--- a/packages/CarrierDefaultApp/res/values-en-rGB/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rGB/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"For example, the login page might not belong to the organisation shown."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continue anyway via browser"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performance boost"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Improve your 5G experience"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommends buying a performance boost plan. Tap to buy through %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Improve your app experience"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Tap to visit %s\'s website and learn more"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Not now"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Manage"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Purchase a performance boost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rIN/strings.xml b/packages/CarrierDefaultApp/res/values-en-rIN/strings.xml
index 720dbc7..346a1d1 100644
--- a/packages/CarrierDefaultApp/res/values-en-rIN/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rIN/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"For example, the login page might not belong to the organisation shown."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continue anyway via browser"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performance boost"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Improve your 5G experience"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommends buying a performance boost plan. Tap to buy through %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Improve your app experience"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Tap to visit %s\'s website and learn more"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Not now"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Manage"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Purchase a performance boost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rXC/strings.xml b/packages/CarrierDefaultApp/res/values-en-rXC/strings.xml
index 7324a5b..95af4d3 100644
--- a/packages/CarrierDefaultApp/res/values-en-rXC/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rXC/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‎‎‎‏‎‏‎‏‏‏‎‎‎‏‎‏‎‎‎‎‏‏‏‎‏‎‏‏‎‎‎‏‎‏‏‎‏‏‏‎‏‏‏‏‏‎‏‎‎‏‏‎‎‎For example, the login page may not belong to the organization shown.‎‏‎‎‏‎"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‏‏‎‎‏‏‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‏‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‏‏‏‏‏‏‎‎‎‎‎‎Continue anyway via browser‎‏‎‎‏‎"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‏‏‎‏‏‎‎‏‏‏‏‏‏‎‎‎‎‏‎‏‏‎‏‏‎‎‏‏‎‎‎‎‎‏‎‎‏‎‎‏‏‎‎‏‎‏‎‏‎‎‎‎‎‎Performance boost‎‏‎‎‏‎"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‏‎‎‎‏‏‏‏‏‎‏‎‎‏‏‏‎‏‎‎‎‎‎‎‏‏‎‏‏‎‎‎‏‎‏‏‎‎‏‎‏‏‏‎‎‎‏‎‎‎‏‎‎‎‎Improve your 5G experience‎‏‎‎‏‎"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‎‎‎‎‎‏‏‏‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‎‏‎‏‏‎‎‏‎‏‏‎‏‎‎‎‏‏‏‎‎‎‎‏‏‏‏‏‎%1$s recommends buying a performance boost plan. Tap to buy through %2$s.‎‏‎‎‏‎"</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‎‏‎‎‏‏‏‎‏‏‎‎‏‎‏‎‏‎‎‏‏‏‏‎‎‏‏‎‎‎‎‏‎‎‏‏‎‎‎‏‏‏‎‏‎‎‎‏‎‏‎‎‎‎Improve your app experience‎‏‎‎‏‎"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‏‎‎‏‎‏‏‏‏‎‎‏‏‎‏‎‏‎‎‏‏‎‎‎‏‎‎‎‏‎‏‎‏‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‏‎‎‎Tap to visit %s\'s website and learn more‎‏‎‎‏‎"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‎‏‎‏‏‎‏‎‏‎‎‏‎‎‏‏‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‏‏‎‏‎‏‎‎‏‏‏‎‎‏‎‎‏‎Not now‎‏‎‎‏‎"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‎‎‎‏‎‏‎‎‎‏‏‎‎‏‏‎‎‎‎‎‏‎‏‎‎‎‎‎‏‎‎‏‏‏‎‎‎‎‎‏‏‎‎‎‏‎‏‏‎‏‎‏‎Manage‎‏‎‎‏‎"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‎‎‏‏‎‏‎‏‎‎‏‏‎‎‏‎‎‏‎‎‎‎‎‏‎‎‎‎‏‏‏‎‏‎‎‎‎‏‎‎‏‏‏‎‎Purchase a performance boost.‎‏‎‎‏‎"</string>
diff --git a/packages/CarrierDefaultApp/res/values-es-rUS/strings.xml b/packages/CarrierDefaultApp/res/values-es-rUS/strings.xml
index fedf1ac..236a1dc 100644
--- a/packages/CarrierDefaultApp/res/values-es-rUS/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-es-rUS/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Por ejemplo, es posible que la página de acceso no pertenezca a la organización que aparece."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continuar de todos modos desde el navegador"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento de rendimiento"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Mejora tu experiencia de 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomienda que compres un plan de aumento de rendimiento. Presiona para comprar mediante %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Mejora tu experiencia en la app"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Presiona para visitar el sitio web de %s y obtener más información"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ahora no"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Administrar"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Compra un aumento de rendimiento."</string>
diff --git a/packages/CarrierDefaultApp/res/values-es/strings.xml b/packages/CarrierDefaultApp/res/values-es/strings.xml
index 85642b8..2550553 100644
--- a/packages/CarrierDefaultApp/res/values-es/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-es/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Por ejemplo, es posible que la página de inicio de sesión no pertenezca a la organización mostrada."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continuar de todos modos a través del navegador"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Mejora de rendimiento"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Mejora tu experiencia 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomienda comprar un plan de mejora del rendimiento. Toca para comprarlo mediante %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Mejora tu experiencia en la aplicación"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Toca para visitar el sitio web de %s y obtener más información."</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ahora no"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gestionar"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Comprar una mejora de rendimiento."</string>
diff --git a/packages/CarrierDefaultApp/res/values-et/strings.xml b/packages/CarrierDefaultApp/res/values-et/strings.xml
index 769f240..e1e8cc0 100644
--- a/packages/CarrierDefaultApp/res/values-et/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-et/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Näiteks ei pruugi sisselogimisleht kuuluda kuvatavale organisatsioonile."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Jätka siiski brauseris"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Jõudluse võimendus"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Täiustage oma 5G-kogemust"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s soovitab osta jõudluse võimendusega paketi. Puudutage teenuse %2$s kaudu ostmiseks."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Aidake parandada rakenduse kasutuskogemust"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Puudutage, et külastada rakenduse %s veebisaiti ja hankida lisateavet"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Mitte praegu"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Haldamine"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Ostke jõudluse võimendus."</string>
diff --git a/packages/CarrierDefaultApp/res/values-eu/strings.xml b/packages/CarrierDefaultApp/res/values-eu/strings.xml
index 7274bce..ce6603b 100644
--- a/packages/CarrierDefaultApp/res/values-eu/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-eu/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Adibidez, baliteke saioa hasteko orria adierazitako erakundearena ez izatea."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Jarraitu arakatzailearen bidez, halere"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Errendimendu-hobekuntza"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Hobetu 5G bidezko konexioa"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s zerbitzuak errendimendua hobetzeko kidetza bat erostea gomendatzen du. Sakatu hau %2$s bidez erosteko."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Hobetu aplikazioaren erabilera"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Sakatu hau %s aplikazioaren garatzailearen webgunera joateko eta informazio gehiago lortzeko"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Orain ez"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Kudeatu"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Erosi errendimendu-hobekuntza bat."</string>
diff --git a/packages/CarrierDefaultApp/res/values-fa/strings.xml b/packages/CarrierDefaultApp/res/values-fa/strings.xml
index 2cbe297..8ecc5dc 100644
--- a/packages/CarrierDefaultApp/res/values-fa/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-fa/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"به عنوان مثال، صفحه ورود به سیستم ممکن است متعلق به سازمان نشان داده شده نباشد."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"درهر صورت ازطریق مرورگر ادامه یابد"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"تقویت‌کننده عملکرد"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"تجربه نسل پنجم شبکه تلفن همراه را بهبود دهید"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"‏%1$s توصیه می‌کند طرح تقویت عملکرد خریداری شود. برای خرید ازطریق %2$s، ضربه بزنید."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"تجربه برنامه‌تان را بهبود دهید"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"‏برای بازدید از وب‌سایت %s و کسب اطلاعات بیشتر، ضربه بزنید"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"اکنون نه"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"مدیریت"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"تقویت‌کننده عملکرد خریداری کنید."</string>
diff --git a/packages/CarrierDefaultApp/res/values-fi/strings.xml b/packages/CarrierDefaultApp/res/values-fi/strings.xml
index 1a388cd..c283d68 100644
--- a/packages/CarrierDefaultApp/res/values-fi/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-fi/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Kirjautumissivu ei välttämättä kuulu näytetylle organisaatiolle."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Jatka selaimen kautta"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Suorituskykyboosti"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Paranna 5G-kokemusta"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s suosittelee suorituskykyboostipaketin ostamista. Napauta ja tee ostos operaattorilla %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Paranna sovelluskokemustasi"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Avaa sivusto (%s) napauttamalla, niin saat lisätietoja"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ei nyt"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Muuta"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Osta suorituskykyboosti."</string>
diff --git a/packages/CarrierDefaultApp/res/values-fr-rCA/strings.xml b/packages/CarrierDefaultApp/res/values-fr-rCA/strings.xml
index ad6c794..8e5bf62 100644
--- a/packages/CarrierDefaultApp/res/values-fr-rCA/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-fr-rCA/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Par exemple, la page de connexion pourrait ne pas appartenir à l\'organisation représentée."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continuer quand même dans un navigateur"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Optimiseur de performances"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Améliorer votre expérience de la 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommande d\'acheter un forfait d\'amélioration des performances. Touchez pour acheter par l\'intermédiaire de %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Améliorer votre expérience de l\'application"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Touchez pour consulter le site Web de %s et en savoir plus"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Plus tard"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gérer"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Achetez un optimiseur de performances."</string>
diff --git a/packages/CarrierDefaultApp/res/values-fr/strings.xml b/packages/CarrierDefaultApp/res/values-fr/strings.xml
index 92b47be..ce769e3 100644
--- a/packages/CarrierDefaultApp/res/values-fr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-fr/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Par exemple, la page de connexion peut ne pas appartenir à l\'organisation représentée."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continuer quand même dans le navigateur"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Boost de performances"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Améliorer votre expérience 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommande d\'acheter un forfait d\'amélioration des performances. Appuyez pour acheter via %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Améliorer votre expérience dans l\'appli"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Appuyez pour accéder au site Web de %s et en savoir plus"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Pas maintenant"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gérer"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Achetez un boost de performances."</string>
diff --git a/packages/CarrierDefaultApp/res/values-gl/strings.xml b/packages/CarrierDefaultApp/res/values-gl/strings.xml
index 2c1be52..648bca4 100644
--- a/packages/CarrierDefaultApp/res/values-gl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-gl/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Por exemplo, é posible que a páxina de inicio de sesión non pertenza á organización que se mostra."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continuar igualmente co navegador"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Mellora de rendemento"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Mellora a túa experiencia 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomenda comprar un plan de mellora do rendemento. Toca para realizar a compra a través de %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Mellora a túa experiencia ao usar a aplicación"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Toca para consultar máis información no sitio web de %s"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Agora non"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Xestionar"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Comprar unha mellora de rendemento."</string>
diff --git a/packages/CarrierDefaultApp/res/values-gu/strings.xml b/packages/CarrierDefaultApp/res/values-gu/strings.xml
index af09d13..cc4103f 100644
--- a/packages/CarrierDefaultApp/res/values-gu/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-gu/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"ઉદાહરણ તરીકે, લોગિન પૃષ્ઠ બતાવવામાં આવેલી સંસ્થાનું ન પણ હોય."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"તો પણ બ્રાઉઝર મારફતે ચાલુ રાખો"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"પર્ફોર્મન્સ બૂસ્ટ"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"તમારા 5G અનુભવને બહેતર બનાવો"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s પર્ફોર્મન્સ બૂસ્ટ પ્લાન ખરીદવાનો સુઝાવ આપે છે. %2$s મારફતે ખરીદવા માટે ટૅપ કરો."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"ઍપ વિશેનો તમારો અનુભવ બહેતર બનાવો"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"%sની વેબસાઇટની મુલાકાત લેવા માટે ટૅપ કરો અને વધુ જાણો"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"હમણાં નહીં"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"મેનેજ કરો"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"પર્ફોર્મન્સ બૂસ્ટ ખરીદો."</string>
diff --git a/packages/CarrierDefaultApp/res/values-hi/strings.xml b/packages/CarrierDefaultApp/res/values-hi/strings.xml
index e51b1a9..2d832b9 100644
--- a/packages/CarrierDefaultApp/res/values-hi/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-hi/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"उदाहरण के लिए, हो सकता है कि लॉगिन पेज दिखाए गए संगठन का ना हो."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"ब्राउज़र के ज़रिए किसी भी तरह जारी रखें"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"परफ़ॉर्मेंस बूस्ट"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"5G का बेहतर अनुभव पाएं"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s, परफ़ॉर्मेंस को बेहतर बनाने वाले प्लान को खरीदने का सुझाव देता है. %2$s से प्लान खरीदने के लिए टैप करें."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"ऐप्लिकेशन इस्तेमाल करने का अनुभव बेहतर बनाएं"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"%s की वेबसाइट पर जाने और ज़्यादा जानने के लिए टैप करें"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"अभी नहीं"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"मैनेज करें"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"कोई परफ़ॉर्मेंस बूस्ट खरीदें."</string>
diff --git a/packages/CarrierDefaultApp/res/values-hr/strings.xml b/packages/CarrierDefaultApp/res/values-hr/strings.xml
index 5a22ad5..f137d09 100644
--- a/packages/CarrierDefaultApp/res/values-hr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-hr/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Na primjer, stranica za prijavu možda ne pripada prikazanoj organizaciji."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Ipak nastavi putem preglednika"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Poboljšanje izvedbe"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Poboljšajte svoj 5G doživljaj"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s preporučuje kupnju paketa za poboljšanje izvedbe. Dodirnite da biste kupili putem usluge %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Poboljšajte svoj doživljaj aplikacije"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Dodirnite da biste posjetili web-lokaciju %s i saznali više"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne sad"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Upravljajte"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupite poboljšanje izvedbe."</string>
diff --git a/packages/CarrierDefaultApp/res/values-hu/strings.xml b/packages/CarrierDefaultApp/res/values-hu/strings.xml
index a841cb2..45a7e81 100644
--- a/packages/CarrierDefaultApp/res/values-hu/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-hu/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Például lehetséges, hogy a bejelentkezési oldal nem a megjelenített szervezethez tartozik."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Folytatás ennek ellenére böngészőn keresztül"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Teljesítménynövelés"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Az 5G-élmény javítása"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"A(z) %1$s teljesítménynövelő csomag vásárlását javasolja. Koppintson a(z) %2$s szolgáltatón keresztüli vásárláshoz."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Az alkalmazással kapcsolatos élmény javítása"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Koppintson a(z) %s webhelyének megnyitásához és a további információk megtekintéséhez."</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Most nem"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Kezelés"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Vásároljon teljesítménynövelést."</string>
diff --git a/packages/CarrierDefaultApp/res/values-hy/strings.xml b/packages/CarrierDefaultApp/res/values-hy/strings.xml
index 49fbece..23cc557 100644
--- a/packages/CarrierDefaultApp/res/values-hy/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-hy/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Օրինակ՝ մուտքի էջը կարող է ցուցադրված կազմակերպության էջը չլինել:"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Շարունակել դիտարկիչի միջոցով"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Արտադրողականության բարձրացում"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Բարելավեք 5G-ի օգտագործման ձեր փորձառությունը"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s օպերատորը խորհուրդ է տալիս ձեռք բերել արդյունավետությունը բարձրացնող սակագնային պլան։ Հպեք՝ %2$s-ի միջոցով գնելու համար։"</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Բարելավեք հավելվածի օգտագործման ձեր փորձառությունը"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Հպեք՝ %s-ի կայք անցնելու և ավելին իմանալու համար"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ոչ հիմա"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Կառավարել"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Բարձրացրեք ցանցի արտադրողականությունը վճարի դիմաց։"</string>
diff --git a/packages/CarrierDefaultApp/res/values-in/strings.xml b/packages/CarrierDefaultApp/res/values-in/strings.xml
index 170bd76..1a66584 100644
--- a/packages/CarrierDefaultApp/res/values-in/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-in/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Misalnya, halaman login mungkin bukan milik organisasi yang ditampilkan."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Tetap lanjutkan melalui browser"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Penguat sinyal"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Tingkatkan pengalaman 5G Anda"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s merekomendasikan pembelian paket penguat sinyal. Ketuk untuk membeli melalui %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Tingkatkan pengalaman aplikasi Anda"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Ketuk untuk membuka situs %s dan mempelajari lebih lanjut"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Lain kali"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Kelola"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Beli penguat sinyal."</string>
diff --git a/packages/CarrierDefaultApp/res/values-is/strings.xml b/packages/CarrierDefaultApp/res/values-is/strings.xml
index 8684ee6..7e7ecde 100644
--- a/packages/CarrierDefaultApp/res/values-is/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-is/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Til dæmis getur verið að innskráningarsíðan tilheyri ekki fyrirtækinu sem birtist."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Halda samt áfram í vafra"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Afkastaaukning"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Bættu upplifun þína af 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s mælir með að kaupa áskrift sem eykur afköst. Ýttu til að kaupa í gegnum %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Bættu forritsupplifunina"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Ýttu til að opna vefsvæði %s og fá frekari upplýsingar"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ekki núna"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Stjórna"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Kaupa afkastaaukningu."</string>
diff --git a/packages/CarrierDefaultApp/res/values-it/strings.xml b/packages/CarrierDefaultApp/res/values-it/strings.xml
index ea88457..11ef6ba 100644
--- a/packages/CarrierDefaultApp/res/values-it/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-it/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Ad esempio, la pagina di accesso potrebbe non appartenere all\'organizzazione indicata."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continua comunque dal browser"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento di prestazioni"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Migliora la tua esperienza 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s consiglia l\'acquisto di un piano di miglioramento delle prestazioni. Tocca per acquistare tramite %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Migliora l\'esperienza con la tua app"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Tocca per visitare il sito web di %s e scoprire di più"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Non ora"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gestisci"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Acquista un aumento di prestazioni."</string>
diff --git a/packages/CarrierDefaultApp/res/values-iw/strings.xml b/packages/CarrierDefaultApp/res/values-iw/strings.xml
index c7229ba..4e67a42 100644
--- a/packages/CarrierDefaultApp/res/values-iw/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-iw/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"לדוגמה, ייתכן שדף ההתחברות אינו שייך לארגון המוצג."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"המשך בכל זאת באמצעות דפדפן"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"שיפור ביצועים"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"‏שיפור חווית השימוש ב-5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"‏יש המלצה של %1$s לקנות תוכנית לשיפור הביצועים. אפשר להקיש כדי לקנות דרך %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"שיפור חוויית השימוש באפליקציה"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"‏ניתן להקיש כדי להיכנס אל האתר של %s ולקבל מידע נוסף"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"לא עכשיו"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ניהול"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"רכישת שיפור ביצועים."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ja/strings.xml b/packages/CarrierDefaultApp/res/values-ja/strings.xml
index 2fd86c8..3115283 100644
--- a/packages/CarrierDefaultApp/res/values-ja/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ja/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"たとえば、ログインページが表示されている組織に属していない可能性があります。"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"ブラウザから続行"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"パフォーマンス ブースト"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"5G のエクスペリエンスを改善"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s さんがパフォーマンス ブースト プランの購入をおすすめしています。%2$sまでにタップして購入しましょう。"</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"アプリ内エクスペリエンスの改善"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"タップして %s のウェブサイトにアクセスし、詳細をご覧ください"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"後で"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"管理"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"パフォーマンス ブーストを購入してください。"</string>
diff --git a/packages/CarrierDefaultApp/res/values-ka/strings.xml b/packages/CarrierDefaultApp/res/values-ka/strings.xml
index 76f7273..cae7aad 100644
--- a/packages/CarrierDefaultApp/res/values-ka/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ka/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"მაგალითად, სისტემაში შესვლის გვერდი შეიძლება არ ეკუთვნოდეს ნაჩვენებ ორგანიზაციას."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"მაინც ბრაუზერში გაგრძელება"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"ეფექტურობის გაძლიერება"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"გააუმჯობესეთ თქვენი 5G გამოცდილება"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s-ის მიერ რეკომენდებულია ეფექტურობის გაძლიერების გეგმის შეძენა. შეეხეთ %2$s-ის დახმარებით შესაძენად."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"გააუმჯობესეთ თქვენი აპიდან მიღებული გამოცდილება"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"შეეხეთ, რომ ეწვიოთ %s-ის ვებსაიტს და შეიტყოთ მეტი"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ახლა არა"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"მართვა"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"ეფექტურობის გაძლიერების შეძენა."</string>
diff --git a/packages/CarrierDefaultApp/res/values-kk/strings.xml b/packages/CarrierDefaultApp/res/values-kk/strings.xml
index 4a895f4..91a0c83 100644
--- a/packages/CarrierDefaultApp/res/values-kk/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-kk/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Мысалы, кіру беті көрсетілген ұйымға тиесілі болмауы мүмкін."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Бәрібір браузер арқылы жалғастыру"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Өнімділікті арттыру"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"5G желісімен жұмысыңызды жақсартыңыз"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s өнімділікті арттыру жоспарын сатып алуды ұсынады. %2$s операторынан сатып алу үшін түртіңіз."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Қолданба мүмкіндіктерін жақсартыңыз"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"%s веб-сайтына кіру және толық ақпарат алу үшін түртіңіз."</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Қазір емес"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Басқару"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Өнімділікті арттыру құралын сатып алыңыз."</string>
diff --git a/packages/CarrierDefaultApp/res/values-km/strings.xml b/packages/CarrierDefaultApp/res/values-km/strings.xml
index 51a51ff..d15883e 100644
--- a/packages/CarrierDefaultApp/res/values-km/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-km/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"ឧទាហរណ៍៖ ទំព័រចូលនេះអាចនឹងមិនមែនជាកម្មសិទ្ធិរបស់ស្ថាប័នដែលបានបង្ហាញនេះទេ។"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"យ៉ាងណាក៏ដោយនៅតែបន្តតាមរយៈកម្មវិធីរុករកតាមអ៊ីនធឺណិត"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"ការបង្កើនប្រតិបត្តិការ"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"កែលម្អបទពិសោធន៍ប្រើ 5G របស់អ្នក"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s ណែនាំឱ្យទិញផែនការជំរុញប្រតិបត្តិការ។ ចុចដើម្បីទិញតាមរយៈ %2$s។"</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"កែលម្អបទពិសោធន៍ប្រើប្រាស់កម្មវិធីរបស់អ្នក"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"ចុចដើម្បីចូលទៅកាន់គេហទំព័ររបស់ %s និងស្វែងយល់បន្ថែម"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"កុំទាន់"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"គ្រប់គ្រង"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"ទិញការបង្កើនប្រតិបត្តិការ។"</string>
diff --git a/packages/CarrierDefaultApp/res/values-kn/strings.xml b/packages/CarrierDefaultApp/res/values-kn/strings.xml
index c97d6f0..7c7e037 100644
--- a/packages/CarrierDefaultApp/res/values-kn/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-kn/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"ಉದಾಹರಣೆಗೆ, ಲಾಗಿನ್ ಪುಟವು ತೋರಿಸಲಾಗಿರುವ ಸಂಸ್ಥೆಗೆ ಸಂಬಂಧಿಸಿಲ್ಲದಿರಬಹುದು."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"ಪರವಾಗಿಲ್ಲ, ಬ್ರೌಸರ್ ಮೂಲಕ ಮುಂದುವರಿಸಿ"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"ಕಾರ್ಯಕ್ಷಮತೆ ಬೂಸ್ಟ್"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"ನಿಮ್ಮ 5G ಅನುಭವವನ್ನು ಸುಧಾರಿಸಿ"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಹೆಚ್ಚಿಸುವ ಪ್ಲಾನ್ ಅನ್ನು ಖರೀದಿಸಲು %1$s ಶಿಫಾರಸು ಮಾಡುತ್ತದೆ. %2$s ಮೂಲಕ ಖರೀದಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"ನಿಮ್ಮ ಆ್ಯಪ್ ಅನುಭವವನ್ನು ಸುಧಾರಿಸಿ"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"%s ನ ವೆಬ್‌ಸೈಟ್‌ಗೆ ಭೇಟಿ ನೀಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ ಮತ್ತು ಇನ್ನಷ್ಟು ತಿಳಿದುಕೊಳ್ಳಿ"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ಈಗ ಬೇಡ"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ನಿರ್ವಹಿಸಿ"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"ಕಾರ್ಯಕ್ಷಮತೆ ಬೂಸ್ಟ್ ಅನ್ನು ಖರೀದಿಸಿ."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ko/strings.xml b/packages/CarrierDefaultApp/res/values-ko/strings.xml
index 395627d..afc7068 100644
--- a/packages/CarrierDefaultApp/res/values-ko/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ko/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"예를 들어 로그인 페이지가 표시된 조직에 속하지 않을 수 있습니다."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"브라우저를 통해 계속하기"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"성능 향상"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"5G 사용 환경 개선"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s에서 성능 향상 계획 구매를 추천합니다. %2$s을(를) 통해 구매하려면 탭하세요."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"앱 환경 개선"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"%s의 웹사이트를 방문하여 자세히 알아보려면 탭하세요."</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"나중에"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"관리"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"성능 향상 구매"</string>
diff --git a/packages/CarrierDefaultApp/res/values-ky/strings.xml b/packages/CarrierDefaultApp/res/values-ky/strings.xml
index b3970e3..ddb4577 100644
--- a/packages/CarrierDefaultApp/res/values-ky/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ky/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Мисалы, аккаунтка кирүү баракчасы көрсөтүлгөн уюмга таандык эмес болушу мүмкүн."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Баары бир серепчи аркылуу улантуу"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Иштин майнаптуулугун жогорулатуу"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"5G менен оңой иштеңиз"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s майнаптуулугун жогорулата турган тарифтик планды сатып алууну сунуштайт. %2$s аркылуу сатып алуу үчүн таптаңыз."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Колдонмону ыңгайлуу кылыңыз"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"%s вебсайтына баш багуу жана кеңири маалымат алуу үчүн таптаңыз"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Азыр эмес"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Тескөө"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Иштин майнаптуулугун жогорулатууну сатып алыңыз."</string>
diff --git a/packages/CarrierDefaultApp/res/values-lo/strings.xml b/packages/CarrierDefaultApp/res/values-lo/strings.xml
index 70d8888..3e45806 100644
--- a/packages/CarrierDefaultApp/res/values-lo/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-lo/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"ຕົວຢ່າງ, ໜ້າເຂົ້າສູ່ລະບົບອາດຈະບໍ່ແມ່ນຂອງອົງກອນທີ່ປາກົດ."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"ດຳເນີນການຕໍ່ຜ່ານໂປຣແກຣມທ່ອງເວັບ"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"ເລັ່ງປະສິດທິພາບ"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"ປັບປຸງປະສົບການ 5G ຂອງທ່ານ"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s ແນະນຳໃຫ້ຊື້ແຜນການເລັ່ງປະສິດທິພາບ. ແຕະເພື່ອຊື້ຜ່ານ %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"ປັບປຸງປະສົບການແອັບຂອງທ່ານ"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"ແຕະເພື່ອເຂົ້າເບິ່ງເວັບໄຊຂອງ %s ແລະ ສຶກສາເພີ່ມເຕີມ"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ບໍ່ຟ້າວເທື່ອ"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ຈັດການ"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"ຊື້ການເລັ່ງປະສິດທິພາບ."</string>
diff --git a/packages/CarrierDefaultApp/res/values-lt/strings.xml b/packages/CarrierDefaultApp/res/values-lt/strings.xml
index 8068416..689d5f7 100644
--- a/packages/CarrierDefaultApp/res/values-lt/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-lt/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Pavyzdžiui, prisijungimo puslapis gali nepriklausyti rodomai organizacijai."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Vis tiek tęsti naudojant naršyklę"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Našumo pagerinimas"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Pagerinkite 5G ryšį"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"„%1$s“ rekomenduoja įsigyti našumo pagerinimo planą. Palieskite, kad įsigytumėte naudodamiesi „%2$s“ paslaugomis."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Pagerinkite savo programos naudojimo patirtį"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Palieskite, jei norite apsilankyti %s svetainėje ir sužinoti daugiau"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne dabar"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Tvarkyti"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Įsigykite našumo pagerinimo paslaugą."</string>
diff --git a/packages/CarrierDefaultApp/res/values-lv/strings.xml b/packages/CarrierDefaultApp/res/values-lv/strings.xml
index 1fefe92..3485fe1 100644
--- a/packages/CarrierDefaultApp/res/values-lv/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-lv/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Piemēram, pieteikšanās lapa, iespējams, nepieder norādītajai organizācijai."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Tomēr turpināt, izmantojot pārlūkprogrammu"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Veiktspējas uzlabojums"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Uzlabojiet 5G iespējas"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s iesaka iegādāties veiktspējas uzlabošanas plānu. Pieskarieties, lai to iegādātos no %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Uzlabojiet lietotnes darbību"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Pieskarieties, lai apmeklētu %s vietni un uzzinātu vairāk."</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Vēlāk"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Pārvaldīt"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Iegādājieties veiktspējas uzlabojumu."</string>
diff --git a/packages/CarrierDefaultApp/res/values-mk/strings.xml b/packages/CarrierDefaultApp/res/values-mk/strings.xml
index 425edfc..d09bdfe 100644
--- a/packages/CarrierDefaultApp/res/values-mk/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-mk/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"На пример, страницата за најавување може да не припаѓа на прикажаната организација."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Сепак продолжи преку прелистувач"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Засилување на изведбата"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Подобрете го вашето доживување со 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s препорачува да купите пакет за засилување на изведбата. Допрете за да купите преку %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Подобрете го вашето доживување со апликацијата"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Допрете за да го посетите веб-сајтот на %s и да дознаете повеќе"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не сега"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Управувајте"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Купете засилување на изведбата."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ml/strings.xml b/packages/CarrierDefaultApp/res/values-ml/strings.xml
index f258411..77b0f02 100644
--- a/packages/CarrierDefaultApp/res/values-ml/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ml/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"ഉദാഹരണത്തിന്, കാണിച്ചിരിക്കുന്ന ഓർഗനൈസേഷന്റേതായിരിക്കില്ല ലോഗിൻ പേജ്."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"എന്തായാലും ബ്രൗസർ വഴി തുടരുക"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"പ്രകടന ബൂസ്റ്റ്"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"നിങ്ങളുടെ 5G അനുഭവം മെച്ചപ്പെടുത്തുക"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"പ്രകടന ബൂസ്റ്റ് പ്ലാൻ വാങ്ങാൻ %1$s നിർദ്ദേശിക്കുന്നു. %2$s വഴി വാങ്ങാൻ ടാപ്പ് ചെയ്യുക."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"നിങ്ങളുടെ ആപ്പ് അനുഭവം മെച്ചപ്പെടുത്തുക"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"%s എന്നതിന്റെ വെബ്സൈറ്റ് സന്ദർശിക്കാനും കൂടുതലറിയാനും ടാപ്പ് ചെയ്യുക"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ഇപ്പോൾ വേണ്ട"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"മാനേജ് ചെയ്യുക"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"പ്രകടന ബൂസ്റ്റ് വാങ്ങൂ."</string>
diff --git a/packages/CarrierDefaultApp/res/values-mn/strings.xml b/packages/CarrierDefaultApp/res/values-mn/strings.xml
index 12e1719..c101a4e 100644
--- a/packages/CarrierDefaultApp/res/values-mn/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-mn/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Жишээлбэл нэвтрэх хуудас нь харагдаж буй байгууллагынх биш байж болно."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Ямар ч тохиолдолд хөтчөөр үргэлжлүүлэх"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Гүйцэтгэлийн идэвхжүүлэлт"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"5G-н хэрэглээгээ сайжруулах"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s гүйцэтгэл нэмэгдүүлэх багцыг худалдаж авахыг зөвлөж байна. %2$s-р дамжуулан худалдан авах бол товшино уу."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Аппын хэрэглээгээ сайжруулаарай"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"%s-н вебсайтад зочлох болон нэмэлт мэдээлэл авахын тулд товшино уу"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Одоо биш"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Удирдах"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Гүйцэтгэлийн идэвхжүүлэлтийг худалдаж аваарай."</string>
diff --git a/packages/CarrierDefaultApp/res/values-mr/strings.xml b/packages/CarrierDefaultApp/res/values-mr/strings.xml
index a48c605..eba2762 100644
--- a/packages/CarrierDefaultApp/res/values-mr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-mr/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"उदाहरणार्थ, लॉग इन पृष्‍ठ दर्शवलेल्या संस्थेच्या मालकीचे नसू शकते."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"तरीही ब्राउझरद्वारे सुरू ठेवा"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"परफॉर्मन्स बूस्ट"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"तुमच्या 5G अनुभवामध्ये सुधारणा करा"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s हे परफॉर्मन्स बूस्ट प्लॅन खरेदी करण्याची शिफारस करते. %2$s वरून खरेदी करण्यासाठी टॅप करा."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"तुमच्या अ‍ॅपशी संबंधित अनुभवामध्ये सुधारणा करा"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"%s च्या वेबसाइटला भेट देण्यासाठी टॅप करा आणि आणखी जाणून घ्या"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"आता नको"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"व्यवस्थापित करा"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"परफॉर्मन्स बूस्ट खरेदी करा."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ms/strings.xml b/packages/CarrierDefaultApp/res/values-ms/strings.xml
index 85651f4..a6cabe5 100644
--- a/packages/CarrierDefaultApp/res/values-ms/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ms/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Contohnya, halaman log masuk mungkin bukan milik organisasi yang ditunjukkan."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Teruskan juga melalui penyemak imbas"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Peningkatan prestasi"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Tingkatkan pengalaman 5G anda"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s mengesyorkan pembelian pelan peningkatan prestasi. Ketik untuk membeli melalui %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Tingkatkan pengalaman apl anda"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Ketik untuk melawat laman web %s dan ketahui lebih lanjut"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Bukan sekarang"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Urus"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Beli perangsang prestasi."</string>
diff --git a/packages/CarrierDefaultApp/res/values-my/strings.xml b/packages/CarrierDefaultApp/res/values-my/strings.xml
index 34c54b9..f858b00 100644
--- a/packages/CarrierDefaultApp/res/values-my/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-my/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"ဥပမာ− ဝင်ရောက်ရန် စာမျက်နှာသည် ပြသထားသည့် အဖွဲ့အစည်းနှင့် သက်ဆိုင်မှုမရှိခြင်း ဖြစ်နိုင်ပါသည်။"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"မည်သို့ပင်ဖြစ်စေ ဘရောက်ဇာမှတစ်ဆင့် ရှေ့ဆက်ရန်"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"စွမ်းဆောင်ရည် မြှင့်တင်အက်ပ်"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"5G အသုံးပြုမှု ပိုမိုကောင်းမွန်စေခြင်း"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s သည် စွမ်းဆောင်ရည်မြှင့်တင်သော အစီအစဉ်ဝယ်ရန် အကြံပြုပါသည်။ %2$s မှတစ်ဆင့် ဝယ်ရန် တို့ပါ။"</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"အက်ပ်အသုံးပြုမှု ပိုမိုကောင်းမွန်စေခြင်း"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"%s ၏ ဝဘ်ဆိုက်ကို ဝင်ကြည့်ပြီး ပိုမိုလေ့လာရန် တို့ပါ"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ယခုမလုပ်ပါ"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"စီမံရန်"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"စွမ်းဆောင်ရည် မြှင့်တင်အက်ပ် ဝယ်ယူရန်။"</string>
diff --git a/packages/CarrierDefaultApp/res/values-nb/strings.xml b/packages/CarrierDefaultApp/res/values-nb/strings.xml
index b30e3d9..2e9283e 100644
--- a/packages/CarrierDefaultApp/res/values-nb/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-nb/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Det er for eksempel mulig at påloggingssiden ikke tilhører organisasjonen som vises."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Fortsett likevel via nettleseren"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Bedre ytelse"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Få en bedre 5G-opplevelse"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s anbefaler at du kjøper et abonnement for bedre ytelse. Trykk for å kjøpe via %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Få enda mer ut av appen"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Trykk for å gå til nettstedet til %s og finne ut mer"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ikke nå"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Administrer"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Kjøp bedre ytelse."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ne/strings.xml b/packages/CarrierDefaultApp/res/values-ne/strings.xml
index 4dccdb9..5750938 100644
--- a/packages/CarrierDefaultApp/res/values-ne/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ne/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"उदाहरणका लागि, लग इन पृष्ठ देखाइएको संस्थाको नहुन सक्छ।"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"जे भए पनि ब्राउजर मार्फत जारी राख्नुहोस्"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"पर्फर्मेन्स बुस्ट"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"5G प्रयोग गर्दा अझ राम्रो सुविधा पाउनुहोस्"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s ले पर्फर्मेन्स बुस्ट योजना खरिद गर्न सिफारिस गर्छ। %2$s मार्फत खरिद गर्न ट्याप गर्नुहोस्।"</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"एप प्रयोग गर्दा अझ राम्रो सुविधा पाउनुहोस्"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"%s को वेबसाइटमा गई थप जान्न ट्याप गर्नुहोस्"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"अहिले होइन"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"व्यवस्थापन गर्नुहोस्"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"पर्फर्मेन्स बुस्ट किन्नुहोस्।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-nl/strings.xml b/packages/CarrierDefaultApp/res/values-nl/strings.xml
index 6a4642c..061d1b8 100644
--- a/packages/CarrierDefaultApp/res/values-nl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-nl/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Zo hoort de weergegeven inlogpagina misschien niet bij de weergegeven organisatie."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Toch doorgaan via browser"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Prestatieboost"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Verbeter je 5G-functionaliteit"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s beveelt je aan een prestatieboostabonnement te kopen. Tik om er een te kopen via %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Haal meer uit de app"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Tik om naar de website van %s te gaan voor meer informatie"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Niet nu"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Beheren"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Koop een prestatieboost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-or/strings.xml b/packages/CarrierDefaultApp/res/values-or/strings.xml
index f7349f9..5f36024 100644
--- a/packages/CarrierDefaultApp/res/values-or/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-or/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"ଉଦାହରଣସ୍ୱରୂପ, ଲଗଇନ୍‍ ପୃଷ୍ଠା ଦେଖାଯାଇଥିବା ସଂସ୍ଥାର ହୋଇନଥାଇପାରେ।"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"ବ୍ରାଉଜର୍‍ ଜରିଆରେ ଯେମିତିବି ହେଉ ଜାରି ରଖନ୍ତୁ"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"ପରଫରମାନ୍ସ ବୁଷ୍ଟ"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"ଆପଣଙ୍କ 5G ଅନୁଭୂତିକୁ ଉନ୍ନତ କରନ୍ତୁ"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s ଏକ ପରଫରମାନ୍ସ ବୁଷ୍ଟ ପ୍ଲାନ କିଣିବା ପାଇଁ ସୁପାରିଶ କରେ। %2$s ମାଧ୍ୟମରେ କିଣିବା ପାଇଁ ଟାପ କରନ୍ତୁ।"</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"ଆପଣଙ୍କ ଆପ ଅନୁଭୂତିକୁ ଉନ୍ନତ କରନ୍ତୁ"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"%sର ୱେବସାଇଟ ଭିଜିଟ କରି ଅଧିକ ଜାଣିବାକୁ ଟାପ କରନ୍ତୁ"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ବର୍ତ୍ତମାନ ନୁହେଁ"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ପରିଚାଳନା କରନ୍ତୁ"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"ଏକ ପରଫରମାନ୍ସ ବୁଷ୍ଟ କିଣନ୍ତୁ।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-pa/strings.xml b/packages/CarrierDefaultApp/res/values-pa/strings.xml
index 540a54c..f53758e 100644
--- a/packages/CarrierDefaultApp/res/values-pa/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pa/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"ਉਦਾਹਰਣ ਵੱਜੋਂ, ਲੌਗ-ਇਨ ਪੰਨਾ ਦਿਖਾਈ ਗਈ ਸੰਸਥਾ ਨਾਲ ਸੰਬੰਧਿਤ ਨਹੀਂ ਹੋ ਸਕਦਾ ਹੈ।"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"ਬ੍ਰਾਊਜ਼ਰ ਰਾਹੀਂ ਫਿਰ ਵੀ ਜਾਰੀ ਰੱਖੋ"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"ਕਾਰਗੁਜ਼ਾਰੀ ਬੂਸਟ"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"ਆਪਣਾ 5G ਅਨੁਭਵ ਬਿਹਤਰ ਬਣਾਓ"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s ਵੱਲੋਂ ਕਾਰਗੁਜ਼ਾਰੀ ਬੂਸਟ ਪਲਾਨ ਖਰੀਦਣ ਦੀ ਸਿਫ਼ਾਰਸ਼ ਕੀਤੀ ਜਾਂਦੀ ਹੈ। %2$s ਰਾਹੀਂ ਖਰੀਦਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"ਆਪਣੇ ਐਪ ਅਨੁਭਵ ਨੂੰ ਬਿਹਤਰ ਬਣਾਓ"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"%s ਦੀ ਵੈੱਬਸਾਈਟ \'ਤੇ ਜਾਣ ਲਈ ਟੈਪ ਕਰੋ ਅਤੇ ਹੋਰ ਜਾਣੋ"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ਹੁਣੇ ਨਹੀਂ"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"ਕਾਰਗੁਜ਼ਾਰੀ ਬੂਸਟ ਖਰੀਦੋ।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-pl/strings.xml b/packages/CarrierDefaultApp/res/values-pl/strings.xml
index de957a9..cd961b4 100644
--- a/packages/CarrierDefaultApp/res/values-pl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pl/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Na przykład strona logowania może nie należeć do wyświetlanej organizacji."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Kontynuuj mimo to w przeglądarce"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Zwiększenie wydajności"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Lepiej wykorzystaj potencjał 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"Operator %1$s zaleca zakup abonamentu o zwiększonej wydajności. Kliknij, aby kupić u operatora %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Ulepsz działanie aplikacji"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Kliknij, aby odwiedzić witrynę %s i dowiedzieć się więcej"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Nie teraz"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Zarządzaj"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Kup wzmocnienie wydajności"</string>
diff --git a/packages/CarrierDefaultApp/res/values-pt-rBR/strings.xml b/packages/CarrierDefaultApp/res/values-pt-rBR/strings.xml
index 4a144be..1975c6d 100644
--- a/packages/CarrierDefaultApp/res/values-pt-rBR/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pt-rBR/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Por exemplo, a página de login pode não pertencer à organização mostrada."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continuar mesmo assim pelo navegador"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento de performance"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Melhore sua experiência 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomenda a compra de um plano para aumento de desempenho. Toque para comprar em %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Melhore sua experiência no app"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Toque para acessar o site de %s e saber mais"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Agora não"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gerenciar"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Comprar um aumento de performance."</string>
diff --git a/packages/CarrierDefaultApp/res/values-pt-rPT/strings.xml b/packages/CarrierDefaultApp/res/values-pt-rPT/strings.xml
index 56e0c2d..f32fa89 100644
--- a/packages/CarrierDefaultApp/res/values-pt-rPT/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pt-rPT/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Por exemplo, a página de início de sessão pode não pertencer à entidade apresentada."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continuar mesmo assim através do navegador"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento do desempenho"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Melhore a sua experiência 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomenda comprar um plano de melhoria do desempenho. Toque para comprar através do %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Melhore a sua experiência na app"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Toque para visitar o Website de %s e saiba mais"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Agora não"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gerir"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Compre um aumento do desempenho."</string>
diff --git a/packages/CarrierDefaultApp/res/values-pt/strings.xml b/packages/CarrierDefaultApp/res/values-pt/strings.xml
index 4a144be..1975c6d 100644
--- a/packages/CarrierDefaultApp/res/values-pt/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pt/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Por exemplo, a página de login pode não pertencer à organização mostrada."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continuar mesmo assim pelo navegador"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento de performance"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Melhore sua experiência 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomenda a compra de um plano para aumento de desempenho. Toque para comprar em %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Melhore sua experiência no app"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Toque para acessar o site de %s e saber mais"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Agora não"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gerenciar"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Comprar um aumento de performance."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ro/strings.xml b/packages/CarrierDefaultApp/res/values-ro/strings.xml
index f861137..7f0dd4a 100644
--- a/packages/CarrierDefaultApp/res/values-ro/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ro/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"De exemplu, este posibil ca pagina de conectare să nu aparțină organizației afișate."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continuă oricum prin browser"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Boost de performanță"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Îmbunătățește-ți experiența cu tehnologia 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomandă cumpărarea unui plan pentru îmbunătățirea performanței. Atinge pentru a cumpăra de la %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Îmbunătățește-ți experiența în aplicație"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Atinge ca să vizitezi site-ul %s și să afli mai multe"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Nu acum"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gestionează"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Achiziționează un boost de performanță."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ru/strings.xml b/packages/CarrierDefaultApp/res/values-ru/strings.xml
index f0bff17..5bd7444 100644
--- a/packages/CarrierDefaultApp/res/values-ru/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ru/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Например, страница входа в аккаунт может быть фиктивной."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Продолжить в браузере"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Повышение производительности"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Сделайте работу с 5G удобнее"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"\"%1$s\" рекомендует купить тарифный план, повышающий производительность. Чтобы приобрести тариф у оператора \"%2$s\", коснитесь экрана."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Сделайте приложение удобнее"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Нажмите, чтобы перейти на сайт \"%s\" и узнать больше."</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не сейчас"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Настроить"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Повысьте производительность сети за плату."</string>
diff --git a/packages/CarrierDefaultApp/res/values-si/strings.xml b/packages/CarrierDefaultApp/res/values-si/strings.xml
index 166af5a..3694996 100644
--- a/packages/CarrierDefaultApp/res/values-si/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-si/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"උදාහරණයක් ලෙස, පුරනය වන පිටුව පෙන්වා ඇති සංවිධානයට අයිති නැති විය හැක."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"කෙසේ වුවත් බ්‍රවුසරය හරහා ඉදිරියට යන්න"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"කාර්ය සාධනය ඉහළ නැංවීම"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"ඔබේ 5G අත්දැකීම වැඩි දියුණු කරන්න"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s කාර්ය සාධනය වැඩි කිරීමේ සැලසුමක් මිල දී ගැනීම නිර්දේශ කරයි. %2$s හරහා මිල දී ගැනීමට තට්ටු කරන්න."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"ඔබේ යෙදුම් අත්දැකීම වැඩි දියුණු කරන්න"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"%sගේ වෙබ් අඩවියට පිවිසීමට සහ තව දැන ගැනීමට තට්ටු කරන්න"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"දැන් නොවේ"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"කළමනාකරණය කරන්න"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"කාර්ය සාධනය ඉහළ නැංවීමක් මිල දී ගන්න."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sk/strings.xml b/packages/CarrierDefaultApp/res/values-sk/strings.xml
index a58bd06..4eac2a2 100644
--- a/packages/CarrierDefaultApp/res/values-sk/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sk/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Napríklad prihlasovacia stránka nemusí patriť uvedenej organizácii."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Pokračovať pomocou prehliadača"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Zvýšenie výkonu"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Zlepšite svoje prostredie 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s odporúča zakúpiť tarifu na zvýšenie výkonnosti. Klepnutím kúpte cez %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Zlepšite si prostredie v aplikácii"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Ak chcete navštíviť web služby %s a dozvedieť sa viac, klepnite"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Teraz nie"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Spravovať"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Kúpte si zvýšenie výkonu."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sl/strings.xml b/packages/CarrierDefaultApp/res/values-sl/strings.xml
index 3c1fd3e..ae95fed 100644
--- a/packages/CarrierDefaultApp/res/values-sl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sl/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Stran za prijavo na primer morda ne pripada prikazani organizaciji."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Vseeno nadaljuj v brskalniku"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Ojačevalnik zmogljivosti"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Izboljšajte izkušnjo omrežja 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s priporoča nakup paketa ojačevalnika zmogljivosti. Dotaknite se za nakup prek »%2$s«."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Izboljšajte izkušnjo z aplikacijami"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Dotaknite se za ogled več informacij na spletnem mestu operaterja %s."</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne zdaj"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Upravljanje"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupite ojačevalnik zmogljivosti."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sq/strings.xml b/packages/CarrierDefaultApp/res/values-sq/strings.xml
index 618e335..d991599 100644
--- a/packages/CarrierDefaultApp/res/values-sq/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sq/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"për shembull, faqja e identifikimit mund të mos i përkasë organizatës së shfaqur."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Vazhdo gjithsesi nëpërmjet shfletuesit"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Përforcimi i performancës"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Përmirëso përvojën tënde 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s rekomandon blerjen e një plani të përforcimit të performancës. Trokit për të blerë nëpërmjet %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Përmirëso përvojën tënde në aplikacion"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Trokit për të vizituar sajtin e uebit të %s dhe për të mësuar më shumë"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Jo tani"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Menaxho"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Bli një paketë përforcimi të performancës."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sr/strings.xml b/packages/CarrierDefaultApp/res/values-sr/strings.xml
index d28bacc..4b2322e 100644
--- a/packages/CarrierDefaultApp/res/values-sr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sr/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"На пример, страница за пријављивање можда не припада приказаној организацији."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Ипак настави преко прегледача"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Побољшање учинка"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Побољшајте 5G доживљај"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s препоручује куповину пакета за побољшање перформанси. Додирните да бисте купили преко %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Побољшајте доживљај апликације"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Додирните да бисте посетили веб-сајт %s и сазнали више"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не сада"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Управљај"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Купите побољшање учинка."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sv/strings.xml b/packages/CarrierDefaultApp/res/values-sv/strings.xml
index ac044ec..b927cda 100644
--- a/packages/CarrierDefaultApp/res/values-sv/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sv/strings.xml
@@ -15,8 +15,9 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Det kan t.ex. hända att inloggningssidan inte tillhör den organisation som visas."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Fortsätt ändå via webbläsaren"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Prestandahöjning"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Förbättra din 5G-upplevelse"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s rekommenderar att du köper en prenumeration som kan höja prestandan. Tryck för att köpa via %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Tryck för att besöka webbplatsen för %s för att läsa mer"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Inte nu"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Hantera"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Köp en prestandahöjning."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sw/strings.xml b/packages/CarrierDefaultApp/res/values-sw/strings.xml
index 1c72f30..9db9e27 100644
--- a/packages/CarrierDefaultApp/res/values-sw/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sw/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Kwa mfano, ukurasa wa kuingia katika akaunti unaweza usiwe unamilikiwa na shirika lililoonyeshwa."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Endelea hata hivyo kupitia kivinjari"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Kuongeza utendaji"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Boresha hali yako ya utumiaji wa 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s anapendekeza ununue mpango wa kuongeza utendaji. Gusa ili ununue kupitia %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Boresha hali yako ya utumiaji wa programu"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Gusa ili utembelee tovuti ya %s na upate maelezo zaidi"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Si sasa"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Dhibiti"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Nunua programu ya kuongeza utendaji."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ta/strings.xml b/packages/CarrierDefaultApp/res/values-ta/strings.xml
index cfc46e8..0c689bc 100644
--- a/packages/CarrierDefaultApp/res/values-ta/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ta/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"எடுத்துக்காட்டாக, உள்நுழைவுப் பக்கமானது காட்டப்படும் அமைப்பிற்குச் சொந்தமானதாக இல்லாமல் இருக்கலாம்."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"பரவாயில்லை, உலாவி வழியாகத் தொடர்க"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"பெர்ஃபார்மென்ஸ் பூஸ்ட்"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"உங்கள் 5G அனுபவத்தை மேம்படுத்துங்கள்"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"செயல்திறன் மேம்பாட்டுத் திட்டத்தை வாங்க %1$s பரிந்துரைக்கிறது. %2$s மூலம் வாங்க தட்டவும்."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"உங்கள் ஆப்ஸ் அனுபவத்தை மேம்படுத்துங்கள்"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"%s இணையதளத்திற்குச் சென்று மேலும் அறிய தட்டுங்கள்"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"இப்போது வேண்டாம்"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"நிர்வகியுங்கள்"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"ஒரு பெர்ஃபார்மென்ஸ் பூஸ்ட்டைப் பர்ச்சேஸ் செய்யுங்கள்."</string>
diff --git a/packages/CarrierDefaultApp/res/values-te/strings.xml b/packages/CarrierDefaultApp/res/values-te/strings.xml
index f31291e..a413207 100644
--- a/packages/CarrierDefaultApp/res/values-te/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-te/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"ఉదాహరణకు, లాగిన్ పేజీ చూపిన సంస్థకు చెందినది కాకపోవచ్చు."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"ఏదేమైనా బ్రౌజర్ ద్వారా కొనసాగించండి"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"పనితీరు బూస్ట్"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"మీ 5G అనుభవాన్ని మెరుగుపరుచుకోండి"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"పనితీరును బూస్ట్ చేసే ప్లాన్‌ను కొనుగోలు చేయమని %1$s సిఫార్సు చేస్తున్నారు. %2$s ద్వారా కొనుగోలు చేయడానికి ట్యాప్ చేయండి."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"మీ యాప్ అనుభవాన్ని మెరుగుపరచండి"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"%s వెబ్‌సైట్‌కు వెళ్లడానికి ట్యాప్ చేసి, మరింత తెలుసుకోండి"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ఇప్పుడు కాదు"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"మేనేజ్ చేయండి"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"పనితీరు బూస్ట్‌ను కొనుగోలు చేయండి."</string>
diff --git a/packages/CarrierDefaultApp/res/values-th/strings.xml b/packages/CarrierDefaultApp/res/values-th/strings.xml
index f20346e..5b99194 100644
--- a/packages/CarrierDefaultApp/res/values-th/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-th/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"ตัวอย่างเช่น หน้าเข้าสู่ระบบอาจไม่ใช่ขององค์กรที่แสดงไว้"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"ดำเนินการต่อผ่านเบราว์เซอร์"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"การเพิ่มประสิทธิภาพ"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"ปรับปรุงประสบการณ์การใช้งาน 5G ของคุณ"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s แนะนำให้ซื้อแพ็กเกจเพิ่มประสิทธิภาพ แตะเพื่อซื้อผ่าน %2$s"</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"ปรับปรุงประสบการณ์การใช้งานแอป"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"แตะเพื่อไปยังเว็บไซต์ของ %s และดูข้อมูลเพิ่มเติม"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ไว้ทีหลัง"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"จัดการ"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"ซื้อการเพิ่มประสิทธิภาพ"</string>
diff --git a/packages/CarrierDefaultApp/res/values-tl/strings.xml b/packages/CarrierDefaultApp/res/values-tl/strings.xml
index 9e8029a..42dfdeb 100644
--- a/packages/CarrierDefaultApp/res/values-tl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-tl/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Halimbawa, maaaring hindi pag-aari ng ipinapakitang organisasyon ang page ng login."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Magpatuloy pa rin sa pamamagitan ng browser"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Pag-boost ng performance"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Pagandahin ang iyong karanasan sa 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"Inirerekomenda ng %1$s na bumili ng plan sa performance boost. I-tap para bumili sa pamamagitan ng %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Pagandahin ang iyong experience sa app"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"I-tap para pumunta sa website ng %s at matuto pa"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Huwag muna"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Pamahalaan"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Bumili ng pang-boost ng performance."</string>
diff --git a/packages/CarrierDefaultApp/res/values-tr/strings.xml b/packages/CarrierDefaultApp/res/values-tr/strings.xml
index c8fb73b..754c92c 100644
--- a/packages/CarrierDefaultApp/res/values-tr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-tr/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Örneğin, giriş sayfası, gösterilen kuruluşa ait olmayabilir."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Yine de tarayıcıyla devam et"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performans artışı"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"5G deneyiminizi iyileştirin"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s, performans artırma planı satın almanızı öneriyor. %2$s aracılığıyla satın almak için dokunun."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Uygulama deneyiminizi iyileştirin"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"%s web sitesini ziyaret edip daha fazla bilgi edinmek için dokunun"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Şimdi değil"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Yönet"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Performans artışı satın alın."</string>
diff --git a/packages/CarrierDefaultApp/res/values-uk/strings.xml b/packages/CarrierDefaultApp/res/values-uk/strings.xml
index 9927ea0..bbd6a70 100644
--- a/packages/CarrierDefaultApp/res/values-uk/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-uk/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Наприклад, сторінка входу може не належати вказаній організації."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Усе одно продовжити у веб-переглядачі"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Підвищення продуктивності"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Покращте продуктивність свого з’єднання 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s рекомендує придбати тарифний план для підвищення продуктивності. Натисніть, щоб придбати через оператора %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Покращте взаємодію з додатком"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Натисніть, щоб перейти на веб-сайт %s і дізнатися більше"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не зараз"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Керувати"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Придбайте підвищення продуктивності."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ur/strings.xml b/packages/CarrierDefaultApp/res/values-ur/strings.xml
index 681998b..e52f2c9 100644
--- a/packages/CarrierDefaultApp/res/values-ur/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ur/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"مثال کے طور پر ہو سکتا ہے کہ لاگ ان صفحہ دکھائی گئی تنظیم سے تعلق نہ رکھتا ہو۔"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"براؤزر کے ذریعے بہرحال جاری رکھیں"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"پرفارمینس بوسٹ"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"‏اپنے 5G تجربے کو بہتر بنائیں"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"‏%1$s ایک پرفارمنس بوسٹ پلان کی تجویز کرتا ہے۔ %2$s استعمال کر کے خریدنے کے لیے تھپتھپائیں۔"</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"اپنی ایپ کے تجربے کو بہتر بنائیں"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"‏%s کی ویب سائٹ دیکھنے کیلئے تھپتھپائیں اور مزید جانیں"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ابھی نہیں"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"نظم کریں"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"پرفارمینس بوسٹ خریدیں۔"</string>
diff --git a/packages/CarrierDefaultApp/res/values-uz/strings.xml b/packages/CarrierDefaultApp/res/values-uz/strings.xml
index 47006f6..04e1409 100644
--- a/packages/CarrierDefaultApp/res/values-uz/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-uz/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Masalan, tizimga kirish sahifasi ko‘rsatilgan tashkilotga tegishli bo‘lmasligi mumkin."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Brauzerda davom ettirish"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Unumdorlikni kuchaytirish"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"5G bilan ishlashni qulaylashtiring"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s unumdorlikni oshiradigan tarif rejasini xarid qilishni tavsiya etadi. %2$s orqali xarid qilish uchun bosing."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Ilova ishlashini qulaylashtiring"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"%s saytini ochish va batafsil axborot olish uchun bosing"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Hozir emas"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Boshqarish"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Unumdorlikni kuchaytirish xizmatini xarid qiling."</string>
diff --git a/packages/CarrierDefaultApp/res/values-vi/strings.xml b/packages/CarrierDefaultApp/res/values-vi/strings.xml
index 968b6e1..4a4aab7 100644
--- a/packages/CarrierDefaultApp/res/values-vi/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-vi/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Ví dụ: trang đăng nhập có thể không thuộc về tổ chức được hiển thị."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Vẫn tiếp tục qua trình duyệt"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Tăng hiệu suất"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Cải thiện trải nghiệm sử dụng 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s đề xuất bạn mua gói tăng cường hiệu suất. Nhấn để mua thông qua %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Cải thiện trải nghiệm dùng ứng dụng của bạn"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Nhấn để truy cập trang web của %s và tìm hiểu thêm."</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Để sau"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Quản lý"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Mua gói tăng hiệu suất."</string>
diff --git a/packages/CarrierDefaultApp/res/values-zh-rCN/strings.xml b/packages/CarrierDefaultApp/res/values-zh-rCN/strings.xml
index 563117f..f732723 100644
--- a/packages/CarrierDefaultApp/res/values-zh-rCN/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-zh-rCN/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"例如,登录页面可能并不属于页面上显示的单位。"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"仍然通过浏览器继续操作"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"性能提升方案"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"改善 5G 体验"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s建议购买性能提升计划。点按即可通过%2$s进行购买。"</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"提升您的应用体验"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"点按以访问%s的网站并了解详情"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"以后再说"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"管理"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"购买一份性能提升方案。"</string>
diff --git a/packages/CarrierDefaultApp/res/values-zh-rHK/strings.xml b/packages/CarrierDefaultApp/res/values-zh-rHK/strings.xml
index 7ed0c3c..1a223d2 100644
--- a/packages/CarrierDefaultApp/res/values-zh-rHK/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-zh-rHK/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"例如,登入頁面可能並不屬於所顯示的機構。"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"仍要透過瀏覽器繼續操作"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"效能提升服務"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"改善 5G 體驗"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"「%1$s」建議購買效能提升服務計劃。輕按即可透過「%2$s」購買。"</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"改善應用程式體驗"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"輕按即可瀏覽「%s」的網站和瞭解詳情"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"暫時不要"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"管理"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"購買效能提升服務。"</string>
diff --git a/packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml b/packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml
index 332ab9c..a932e20 100644
--- a/packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"例如,登入網頁中顯示的機構可能並非該網頁實際隸屬的機構。"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"仍要透過瀏覽器繼續操作"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"效能提升方案"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"改善 5G 體驗"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"「%1$s」建議購買效能提升方案,輕觸即可透過「%2$s」購買。"</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"改善應用程式體驗"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"輕觸即可造訪「%s」的網站及瞭解詳情"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"暫時不要"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"管理"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"購買效能提升方案。"</string>
diff --git a/packages/CarrierDefaultApp/res/values-zu/strings.xml b/packages/CarrierDefaultApp/res/values-zu/strings.xml
index ae84695..20edb0e 100644
--- a/packages/CarrierDefaultApp/res/values-zu/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-zu/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Isibonelo, ikhasi lokungena ngemvume kungenzeka lingelenhlangano ebonisiwe."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Qhubeka noma kunjalo ngesiphequluli"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"I-boost yokusebenza"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Thuthukisa umuzwa wakho we-5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"I-%1$s incoma ukuthenga uhlelo lokuthuthukisa ukusebenza. Thepha ukuze uthenge nge-%2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Thuthukisa okwenza nge-app"</string>
+    <string name="performance_boost_notification_detail" msgid="907363829888387028">"Thepha ukuze uvakashele iwebhusayithi ye-%s futhi ufunde kabanzi."</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Hhayi manje"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Phatha"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Thenga i-boost yokusebenza."</string>
diff --git a/packages/CarrierDefaultApp/res/values/strings.xml b/packages/CarrierDefaultApp/res/values/strings.xml
index 720e46d..e91d35b 100644
--- a/packages/CarrierDefaultApp/res/values/strings.xml
+++ b/packages/CarrierDefaultApp/res/values/strings.xml
@@ -19,7 +19,7 @@
     <!-- Notification title text for the performance boost notification. -->
     <string name="performance_boost_notification_title">Improve your app experience</string>
     <!-- Notification detail text for the performance boost notification. -->
-    <string name="performance_boost_notification_detail">Tap to visit %s\'s website and learn more.</string>
+    <string name="performance_boost_notification_detail">Tap to visit %s\'s website and learn more</string>
     <!-- Notification button text to cancel the performance boost notification. -->
     <string name="performance_boost_notification_button_not_now">Not now</string>
     <!-- Notification button text to manage the performance boost notification. -->
diff --git a/packages/CompanionDeviceManager/res/values-af/strings.xml b/packages/CompanionDeviceManager/res/values-af/strings.xml
index d621ca2..29caf5f 100644
--- a/packages/CompanionDeviceManager/res/values-af/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-af/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Kies \'n <xliff:g id="PROFILE_NAME">%1$s</xliff:g> om deur &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; bestuur te word"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Hierdie app is nodig om jou <xliff:g id="DEVICE_NAME">%1$s</xliff:g> te bestuur. <xliff:g id="APP_NAME">%2$s</xliff:g> sal toegelaat word om inligting te sinkroniseer, soos die naam van iemand wat bel, interaksie met jou kennisgewings te hê, en sal toegang tot jou Foon-, SMS-, Kontakte-, Mikrofoon-, en Toestelle in die Omtrek-toestemmings hê."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Hierdie app is nodig om jou <xliff:g id="DEVICE_NAME">%1$s</xliff:g> te bestuur. <xliff:g id="APP_NAME">%2$s</xliff:g> sal toegelaat word om inligting te sinkroniseer, soos die naam van iemand wat bel, en toegang tot hierdie toestemmings:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"bril"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Hierdie app is nodig om <xliff:g id="DEVICE_NAME">%1$s</xliff:g> te bestuur. <xliff:g id="APP_NAME">%2$s</xliff:g> sal toegelaat word om interaksie met jou kennisgewings te hê en sal toegang tot jou Foon-, SMS-, Kontakte-, Mikrofoon-, en Toestelle in die Omtrek-toestemmings hê."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Hierdie app is nodig om <xliff:g id="DEVICE_NAME">%1$s</xliff:g> te bestuur. <xliff:g id="APP_NAME">%2$s</xliff:g> sal toegelaat word om interaksie met die volgende toestemmings te hê:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Gee &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; toegang tot hierdie inligting op jou foon"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Oorkruistoestel-dienste"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> versoek tans namens jou <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> toestemming om programme tussen jou toestelle te stroom"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Dienste"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> versoek tans namens jou <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> toegang tot jou foon se foto\'s, media en kennisgewings"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Laat &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; toe om hierdie handeling op jou foon uit te voer"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Oorkruistoesteldienste"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> versoek tans namens jou <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-toestemming om inhoud na toestelle in die omtrek te stroom"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"toestel"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Hierdie app sal inligting kan sinkroniseer, soos die naam van iemand wat bel, tussen jou foon en <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Hierdie app sal inligting kan sinkroniseer, soos die naam van iemand wat bel, tussen jou foon en die gekose toestel."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Foto\'s en media"</string>
     <string name="permission_notification" msgid="693762568127741203">"Kennisgewings"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Toestel in die Omtrek-stroming"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Kan die mikrofoon gebruik om oudio op te neem"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Stroom inhoud na ’n toestel in die omtrek"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-am/strings.xml b/packages/CompanionDeviceManager/res/values-am/strings.xml
index 679dc33..97c1b96 100644
--- a/packages/CompanionDeviceManager/res/values-am/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-am/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"በ&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; የሚተዳደር <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ይምረጡ"</string>
     <string name="summary_watch" msgid="6566922405914995759">"የእርስዎን <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ለማስተዳደር መተግበሪያው ያስፈልጋል። <xliff:g id="APP_NAME">%2$s</xliff:g> እንደ የሚደውል ሰው ስም፣ ከማሳወቂያዎችዎ ጋር መስተጋብር እንዲፈጥር እና የእርስዎን ስልክ፣ ኤስኤምኤስ፣ ዕውቅያዎች፣ የቀን መቁጠሪያ፣ የጥሪ ምዝግብ ማስታወሻዎች እና በአቅራቢያ ያሉ መሣሪያዎችን መድረስ ያሉ መረጃዎችን እንዲያሰምር ይፈቀድለታል።"</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"የእርስዎን <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ለማስተዳደር መተግበሪያው ያስፈልጋል። <xliff:g id="APP_NAME">%2$s</xliff:g> እንደ የሚደውል ሰው ስም እና እነዚህን ፈቃዶች መድረስ ያሉ መረጃዎችን እንዲያሰምር ይፈቀድለታል፦"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"መነጽሮች"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"ይህ መተግበሪያ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ን ለማስተዳደር ያስፈልጋል። <xliff:g id="APP_NAME">%2$s</xliff:g> ከማሳወቂያዎችዎ ጋር መስተጋብር እንዲፈጥር እና የእርስዎን ስልክ፣ ኤስኤምኤስ፣ ዕውቂያዎች፣ ማይክሮፎን እና በአቅራቢያ ያሉ መሣሪያዎች ፈቃዶችን እንዲደርስ ይፈቀድለታል።"</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"ይህ መተግበሪያ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ን ለማስተዳደር ያስፈልጋል። <xliff:g id="APP_NAME">%2$s</xliff:g> ከእነዚህ ፈቃዶች ጋር መስተጋብር እንዲፈጥር ይፈቀድለታል፦"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ይህን መረጃ ከስልክዎ እንዲደርስበት ይፍቀዱለት"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"መሣሪያ ተሻጋሪ አገልግሎቶች"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> በእርስዎ መሣሪያዎች መካከል መተግበሪያዎችን በዥረት ለመልቀቅ የእርስዎን <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ወክሎ ፈቃድ እየጠየቀ ነው"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"የGoogle Play አገልግሎቶች"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> የስልክዎን ፎቶዎች፣ ሚዲያ እና ማሳወቂያዎች ለመድረስ የእርስዎን <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ወክሎ ፈቃድ እየጠየቀ ነው"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ይህን እርምጃ ከስልክዎ እንዲያከናውን ይፍቀዱ"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"መሣሪያ ተሻጋሪ አገልግሎቶች"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> በአቅራቢያ ወዳሉ መሣሪያዎች ይዘትን በዥረት ለመልቀቅ የእርስዎን <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ወክሎ ፈቃድ እየጠየቀ ነው"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"መሣሪያ"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"ይህ መተግበሪያ እንደ የሚደውል ሰው ስም ያለ መረጃን በስልክዎ እና <xliff:g id="DEVICE_NAME">%1$s</xliff:g> መካከል ማስመር ይችላል።"</string>
     <string name="summary_generic" msgid="4988130802522924650">"ይህ መተግበሪያ እንደ የሚደውል ሰው ስም ያለ መረጃን በስልክዎ እና በተመረጠው መሣሪያ መካከል ማስመር ይችላል።"</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"ፎቶዎች እና ሚዲያ"</string>
     <string name="permission_notification" msgid="693762568127741203">"ማሳወቂያዎች"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"መተግበሪያዎች"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"በአቅራቢያ ያለ መሣሪያ በዥረት መልቀቅ"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"ማይክሮፎኑን በመጠቀም ኦዲዮ መቅዳት ይችላል"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"በአቅራቢያ ያሉ መሣሪያዎችን ማግኘት፣ ከእነሱ ጋር መገናኘት እና አንጻራዊ ቦታቸውን መወሰን ይችላል"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"እንደ እውቂያዎች፣ መልዕክቶች እና ፎቶዎች ያሉ መረጃዎችን ጨምሮ ሁሉንም ማሳወቂያዎች ማንበብ ይችላል"</string>
     <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="5776807830582725074">"ይዘትን በአቅራቢያ ወዳለ መሣሪያ በዥረት ይልቀቁ"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ar/strings.xml b/packages/CompanionDeviceManager/res/values-ar/strings.xml
index 154a200..bfb4225 100644
--- a/packages/CompanionDeviceManager/res/values-ar/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ar/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"‏اختَر <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ليديرها تطبيق &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"يجب توفّر التطبيق لإدارة \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". سيتم السماح لتطبيق \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" بمزامنة المعلومات، مثلاً اسم المتصل، والتفاعل مع الإشعارات والوصول إلى هاتفك، والرسائل القصيرة، وجهات الاتصال، والتقويم، وسجلات المكالمات وأذونات الأجهزة المجاورة."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"يجب توفّر التطبيق لإدارة \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". سيتم السماح لتطبيق \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" بمزامنة المعلومات، مثلاً اسم المتصل، والوصول إلى الأذونات التالية:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"النظارة"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"يجب توفّر هذا التطبيق لإدارة \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". سيتم السماح لتطبيق \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" بالتفاعل مع الإشعارات والوصول إلى أذونات الهاتف والرسائل القصيرة وجهات الاتصال والميكروفون والأجهزة المجاورة."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"يجب توفّر التطبيق لإدارة \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". سيتم السماح للتطبيق \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" بالتفاعل مع هذه الأذونات."</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"‏السماح لتطبيق &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; بالوصول إلى هذه المعلومات من هاتفك"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"الخدمات التي تعمل بين الأجهزة"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"يطلب تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> الحصول على إذن نيابةً عن <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> لمشاركة التطبيقات بين أجهزتك."</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"‏خدمات Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"يطلب تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> الحصول على إذن نيابةً عن <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> للوصول إلى الصور والوسائط والإشعارات في هاتفك."</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"‏السماح للتطبيق &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; بتنفيذ هذا الإجراء من هاتفك"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"خدمات تعمل على عدة أجهزة"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"يطلب \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" الحصول على إذن نيابةً عن \"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\" لبثّ محتوى إلى أجهزتك المجاورة."</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"جهاز"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"سيتمكن هذا التطبيق من مزامنة المعلومات، مثلاً اسم المتصل، بين هاتفك و\"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string>
     <string name="summary_generic" msgid="4988130802522924650">"سيتمكن هذا التطبيق من مزامنة المعلومات، مثلاً اسم المتصل، بين هاتفك والجهاز المحدد."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"الصور والوسائط"</string>
     <string name="permission_notification" msgid="693762568127741203">"الإشعارات"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"التطبيقات"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"بثّ محتوى إلى الأجهزة المجاورة"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"يمكن تسجيل الصوت باستخدام الميكروفون."</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"يمكن العثور على الموضع النسبي للأجهزة المجاورة والربط بها وتحديدها."</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"يمكن لهذا الملف الشخصي قراءة جميع الإشعارات، بما في ذلك المعلومات، مثل جهات الاتصال والرسائل والصور."</string>
     <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="5776807830582725074">"بثّ محتوى إلى جهاز مجاور"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-as/strings.xml b/packages/CompanionDeviceManager/res/values-as/strings.xml
index cb2d2e0..b69c1c2 100644
--- a/packages/CompanionDeviceManager/res/values-as/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-as/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;এ পৰিচালনা কৰিব লগা এটা <xliff:g id="PROFILE_NAME">%1$s</xliff:g> বাছনি কৰক"</string>
     <string name="summary_watch" msgid="6566922405914995759">"আপোনাৰ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> পৰিচালনা কৰিবলৈ এপ্‌টোৰ আৱশ্যক। <xliff:g id="APP_NAME">%2$s</xliff:g>ক কল কৰোঁতাৰ নামৰ দৰে তথ্য ছিংক কৰিবলৈ, আপোনাৰ জাননীৰ সৈতে ভাব-বিনিময় কৰিবলৈ আৰু আপোনাৰ ফ’ন, এছএমএছ, সম্পৰ্ক, কেলেণ্ডাৰ, কল লগ আৰু নিকটৱৰ্তী ডিভাইচৰ অনুমতিসমূহ এক্সেছ কৰিবলৈ দিয়া হ’ব।"</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"আপোনাৰ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> পৰিচালনা কৰিবলৈ এপ্‌টোৰ আৱশ্যক। <xliff:g id="APP_NAME">%2$s</xliff:g>ক কল কৰোঁতাৰ নামৰ দৰে তথ্য ছিংক কৰিবলৈ আৰু এই অনুমতিসমূহ এক্সেছ কৰিবলৈ অনুমতি দিয়া হ’ব:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"চছ্‌মা"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> পৰিচালনা কৰিবলৈ এই এপ্‌টোৰ আৱশ্যক। <xliff:g id="APP_NAME">%2$s</xliff:g>ক এই অনুমতিসমূহৰ সৈতে ভাব-বিনিময় কৰিবলৈ আৰু আপোনাৰ ফ’ন, এছএমএছ, সম্পৰ্ক, মাইক্ৰ’ফ’ন আৰু নিকটৱৰ্তী ডিভাইচৰ অনুমতিসমূহ এক্সেছ কৰিবলৈ দিয়া হ’ব।"</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> পৰিচালনা কৰিবলৈ এপ্‌টোৰ আৱশ্যক। <xliff:g id="APP_NAME">%2$s</xliff:g>ক এই অনুমতিসমূহৰ সৈতে ভাব-বিনিময় কৰিবলৈ দিয়া হ’ব:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;ক আপোনাৰ ফ’নৰ পৰা এই তথ্যখিনি এক্সেছ কৰাৰ অনুমতি দিয়ক"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"ক্ৰছ-ডিভাইচ সেৱাসমূহ"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ আপোনাৰ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ৰ হৈ আপোনাৰ ডিভাইচসমূহৰ মাজত এপ্‌ ষ্ট্ৰীম কৰাৰ বাবে অনুৰোধ জনাইছে"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play সেৱা"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ আপোনাৰ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ৰ হৈ আপোনাৰ ফ’নৰ ফট’, মিডিয়া আৰু জাননী এক্সেছ কৰাৰ বাবে অনুৰোধ জনাইছে"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;ক আপোনাৰ ফ’নৰ পৰা এই কাৰ্যটো সম্পাদন কৰিবলৈ দিয়ক"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"ক্ৰছ-ডিভাইচ সেৱাসমূহ"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ আপোনাৰ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ৰ হৈ নিকটৱৰ্তী ডিভাইচত সমল ষ্ট্ৰীম কৰাৰ অনুমতি দিবলৈ অনুৰোধ জনাইছে"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"ডিভাইচ"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"এই এপ্‌টোৱে আপোনাৰ ফ’ন আৰু <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ৰ মাজত তথ্য ছিংক কৰিব পাৰিব, যেনে, কল কৰোঁতাৰ নাম।"</string>
     <string name="summary_generic" msgid="4988130802522924650">"এই এপ্‌টোৱে আপোনাৰ ফ’ন আৰু বাছনি কৰা ডিভাইচটোৰ মাজত তথ্য ছিংক কৰিব পাৰিব, যেনে, কল কৰোঁতাৰ নাম।"</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"ফট’ আৰু মিডিয়া"</string>
     <string name="permission_notification" msgid="693762568127741203">"জাননী"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"এপ্"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"নিকটৱৰ্তী ডিভাইচত ষ্ট্ৰীম কৰা"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"মাইক্ৰ’ফ’ন ব্যৱহাৰ কৰি অডিঅ’ ৰেকৰ্ড কৰিব পাৰে"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"নিকটৱৰ্তী ডিভাইচসমূহ বিচাৰিব, সেইসমূহৰ সৈতে সংযুক্ত হ’ব আৰু সেইসমূহৰ আপেক্ষিক স্থান নিৰ্ধাৰণ কৰিব পাৰে"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"সম্পৰ্কসূচী, বাৰ্তা আৰু ফট’ৰ দৰে তথ্যকে ধৰি আটাইবোৰ জাননী পঢ়িব পাৰে"</string>
     <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="5776807830582725074">"এটা নিকটৱৰ্তী ডিভাইচত সমল ষ্ট্ৰীম কৰক"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-az/strings.xml b/packages/CompanionDeviceManager/res/values-az/strings.xml
index b882203..68acb6b 100644
--- a/packages/CompanionDeviceManager/res/values-az/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-az/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; tərəfindən idarə ediləcək <xliff:g id="PROFILE_NAME">%1$s</xliff:g> seçin"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Tətbiq <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazını idarə etmək üçün lazımdır. <xliff:g id="APP_NAME">%2$s</xliff:g> tətbiqinə zəng edənin adı kimi məlumatları sinxronlaşdırmaq, bildirişlərlə qarşılıqlı əlaqəyə girmək, habelə Telefon, SMS, Kontaktlar, Təqvim, Zəng qeydləri və Yaxınlıqdakı cihazlar üzrə icazələrə daxil olmaq imkanı veriləcək."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Tətbiq <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazını idarə etmək üçün lazımdır. <xliff:g id="APP_NAME">%2$s</xliff:g> tətbiqinə zəng edənin adı kimi məlumatları sinxronlaşdırmaq və bu icazələrə daxil olmaq imkanı veriləcək:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"eynək"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Bu tətbiq <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazını idarə etmək üçün lazımdır. <xliff:g id="APP_NAME">%2$s</xliff:g> üçün bildirişlərlə qarşılıqlı əlaqə, Telefon, SMS, Kontaktlar, Mikrofon və Yaxınlıqdakı cihazlar üzrə icazələrə giriş imkanı veriləcək."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Tətbiq <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazını idarə etmək üçün lazımdır. <xliff:g id="APP_NAME">%2$s</xliff:g> tətbiqinə bu icazələrlə qarşılıqlı əlaqə imkanı veriləcək:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; tətbiqinə telefonunuzdan bu məlumata giriş icazəsi verin"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cihazlararası xidmətlər"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqi <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> adından cihazlarınız arasında tətbiqləri yayımlamaq üçün icazə istəyir"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play xidmətləri"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqi <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> adından telefonunuzun fotoları, mediası və bildirişlərinə giriş üçün icazə istəyir"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; tətbiqinə telefonunuzdan bu əməliyyatı icra etməyə icazə verin"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Cihazlararası xidmətlər"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqi <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> adından yaxınlıqdakı cihazlarda yayımlamaq üçün icazə istəyir"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"cihaz"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Bu tətbiq telefon və <xliff:g id="DEVICE_NAME">%1$s</xliff:g> arasında zəng edənin adı kimi məlumatları sinxronlaşdıra biləcək."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Bu tətbiq telefon və seçilmiş cihaz arasında zəng edənin adı kimi məlumatları sinxronlaşdıra biləcək."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Foto və media"</string>
     <string name="permission_notification" msgid="693762568127741203">"Bildirişlər"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Tətbiqlər"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Yaxınlıqdakı Cihazlarda Yayım"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Mikrofonunuzdan istifadə edərək audio yaza bilər."</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Məzmunu yaxınlıqdakı cihazda yayımlayın"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
index 2add9f7..4812889 100644
--- a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Odaberite <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kojim će upravljati aplikacija &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> će dobiti dozvolu za sinhronizovanje informacija, poput osobe koja upućuje poziv, za interakciju sa obaveštenjima i pristup dozvolama za telefon, SMS, kontakte, kalendar, evidencije poziva i uređaje u blizini."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> će dobiti dozvolu za sinhronizaciju informacija, poput osobe koja upućuje poziv, kao za pristup sledećim dozvolama:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"naočare"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Ova aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> će dobiti dozvolu za interakciju sa obaveštenjima i pristup dozvolama za telefon, SMS, kontakte, mikrofon i uređaje u blizini."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> će dobiti dozvolu za interakciju sa ovim dozvolama:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Dozvolite da &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; pristupa ovim informacijama sa telefona"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Usluge na više uređaja"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> zahteva dozvolu u ime uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> za strimovanje aplikacija između uređaja"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play usluge"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> zahteva dozvolu u ime uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> za pristup slikama, medijskom sadržaju i obaveštenjima sa telefona"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Dozvolite da &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; obavlja ovu radnju sa telefona"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Usluge na više uređaja"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> zahteva dozvolu u ime uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> da strimuje sadržaj na uređaje u blizini"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Ova aplikacija će moći da sinhronizuje podatke, poput imena osobe koja upućuje poziv, između telefona i uređaja <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Ova aplikacija će moći da sinhronizuje podatke, poput imena osobe koja upućuje poziv, između telefona i odabranog uređaja."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Slike i mediji"</string>
     <string name="permission_notification" msgid="693762568127741203">"Obaveštenja"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacije"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Strimovanje, uređaji u blizini"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Može da snima zvuk pomoću mikrofona"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Strimujte sadržaj na uređaj u blizini"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-be/strings.xml b/packages/CompanionDeviceManager/res/values-be/strings.xml
index 605ce33..76de34a 100644
--- a/packages/CompanionDeviceManager/res/values-be/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-be/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Выберыце прыладу (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), якой будзе кіраваць праграма &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Гэта праграма неабходная для кіравання прыладай \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". <xliff:g id="APP_NAME">%2$s</xliff:g> зможа сінхранізаваць інфармацыю (напрыклад, імя таго, хто звоніць), узаемадзейнічаць з вашымі апавяшчэннямі, а таксама атрымае доступ да тэлефона, SMS, кантактаў, календара, журналаў выклікаў і прылад паблізу."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Гэта праграма неабходная для кіравання прыладай \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". <xliff:g id="APP_NAME">%2$s</xliff:g> зможа сінхранізаваць інфармацыю (напрыклад, імя таго, хто звоніць) і атрымае наступныя дазволы:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"акуляры"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Гэта праграма неабходная для кіравання прыладай \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". <xliff:g id="APP_NAME">%2$s</xliff:g> зможа ўзаемадзейнічаць з вашымі апавяшчэннямі і атрымае доступ да тэлефона, SMS, кантактаў, мікрафона і прылад паблізу."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Гэта праграма неабходная для кіравання прыладай \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". <xliff:g id="APP_NAME">%2$s</xliff:g> зможа выкарыстоўваць наступныя дазволы:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Дазвольце праграме &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; мець доступ да гэтай інфармацыі з вашага тэлефона"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Сэрвісы для некалькіх прылад"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Праграма \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запытвае дазвол ад імя вашай прылады \"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\" на трансляцыю праграм паміж вашымі прыладамі"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Сэрвісы Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"Праграма \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запытвае дазвол ад імя вашай прылады \"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\" на доступ да фота, медыяфайлаў і апавяшчэнняў на вашым тэлефоне"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Дазволіць праграме &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; выконваць гэта дзеянне з вашага тэлефона"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Сэрвісы для некалькіх прылад"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Праграма \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запытвае дазвол ад імя вашай прылады \"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\" на перадачу змесціва плынню на прылады паблізу."</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"прылада"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Гэта праграма зможа сінхранізаваць інфармацыю (напрыклад, імя таго, хто звоніць) паміж тэлефонам і прыладай \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Гэта праграма зможа сінхранізаваць інфармацыю (напрыклад, імя таго, хто звоніць) паміж тэлефонам і выбранай прыладай."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Фота і медыяфайлы"</string>
     <string name="permission_notification" msgid="693762568127741203">"Апавяшчэнні"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Праграмы"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Перадача плынню для прылады паблізу"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Можа запісваць аўдыя з выкарыстаннем мікрафона"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Можа знаходзіць прылады паблізу, падключацца да іх і вызначаць іх прыблізнае месцазнаходжанне"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"Можа счытваць усе апавяшчэнні, уключаючы паведамленні, фота і інфармацыю пра кантакты"</string>
     <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="5776807830582725074">"Перадача змесціва плынню на прыладу паблізу"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-bg/strings.xml b/packages/CompanionDeviceManager/res/values-bg/strings.xml
index f1dd8c0..36da32d 100644
--- a/packages/CompanionDeviceManager/res/values-bg/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bg/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Изберете устройство (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), което да се управлява от &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Това приложение е необходимо за управление на <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ще получи право да синхронизира различна информация, като например името на обаждащия се, да взаимодейства с известията ви и достъп до разрешенията за телефона, SMS съобщенията, контактите, календара, списъците с обажданията и устройствата в близост."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Това приложение е необходимо за управление на <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ще получи право да синхронизира различна информация, като например името на обаждащия се, и достъп до следните разрешения:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"очилата"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Това приложение е необходимо за управление на <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ще получи право да взаимодейства с известията ви, както и достъп до разрешенията за телефона, SMS съобщенията, контактите, микрофона и устройствата в близост."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Това приложение е необходимо за управление на <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ще получи разрешение да взаимодейства със следните разрешения:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Разрешете на &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; да осъществява достъп до тази информация от телефона ви"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Услуги за различни устройства"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ иска разрешение от името на <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> да предава поточно приложения между устройствата ви"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Услуги за Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> иска разрешение от името на <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> за достъп до снимките, мултимедията и известията на телефона ви"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Разрешаване на &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; да изпълнява това действие от телефона ви"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Услуги за различни устройства"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> иска разрешение от името на <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> да предава поточно съдържание към устройства в близост"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"устройство"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Това приложение ще може да синхронизира различна информация, като например името на обаждащия се, между телефона ви и <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Това приложение ще може да синхронизира различна информация, като например името на обаждащия се, между телефона ви и избраното устройство."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Снимки и мултимедия"</string>
     <string name="permission_notification" msgid="693762568127741203">"Известия"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Приложения"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Пот. предав. към у-ва наблизо"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Може да записва аудио посредством микрофона"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Може да намира и да се свързва с устройства в близост, както и да определя относителната им позиция"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"Може да чете всички известия, включително различна информация, като например контакти, съобщения и снимки"</string>
     <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="5776807830582725074">"Поточно предаване на съдържание към устройства в близост"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-bn/strings.xml b/packages/CompanionDeviceManager/res/values-bn/strings.xml
index 95ec4a6..20a6e27 100644
--- a/packages/CompanionDeviceManager/res/values-bn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bn/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"<xliff:g id="PROFILE_NAME">%1$s</xliff:g> বেছে নিন যেটি &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ম্যানেজ করবে"</string>
     <string name="summary_watch" msgid="6566922405914995759">"আপনার <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ম্যানেজ করার জন্য অ্যাপটি প্রয়োজন। <xliff:g id="APP_NAME">%2$s</xliff:g>-কে কলারের নামের মতো তথ্য সিঙ্ক করার অনুমতি দেওয়া হবে, এছাড়াও আপনার বিজ্ঞপ্তির সাথে ইন্টার‌্যাক্ট করা এবং আপনার ফোন, এসএমএস, পরিচিতি তালিকা, ক্যালেন্ডার, কল লগ এবং আশেপাশের ডিভাইস ব্যবহার করার অনুমতি অ্যাক্সেস করতে দেওয়া হবে।"</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"আপনার <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ম্যানেজ করার জন্য অ্যাপটি প্রয়োজন। <xliff:g id="APP_NAME">%2$s</xliff:g>-কে কলারের নামের মতো তথ্য় সিঙ্ক করতে এবং এইসব অনুমতি অ্যাক্সেস করতে দেওয়া হবে:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"চশমা"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"আপনার <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ম্যানেজ করতে এই অ্যাপটি প্রয়োজন। <xliff:g id="APP_NAME">%2$s</xliff:g>-কে আপনার বিজ্ঞপ্তির সাথে ইন্টার‌্যাক্ট করার অনুমতি দেওয়া হবে। এছাড়াও আপনার ফোন, এসএমএস, পরিচিতি তালিকা, মাইক্রোফোন এবং আশেপাশের ডিভাইস ব্যবহার করার অনুমতি অ্যাক্সেস করতে দেওয়া হবে।"</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ম্যানেজ করার জন্য অ্যাপটি প্রয়োজন। <xliff:g id="APP_NAME">%2$s</xliff:g> অ্যাপকে এইসব অনুমতির সাথে ইন্টার‌্যাক্ট করার জন্য অনুমোদন দেওয়া হবে:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"আপনার ফোন থেকে &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; অ্যাপকে এই তথ্য অ্যাক্সেস করার অনুমতি দিন"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"ক্রস-ডিভাইস পরিষেবা"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"আপনার ডিভাইসগুলির মধ্যে অ্যাপ স্ট্রিম করার জন্য <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-এর হয়ে অনুমতি চাইছে"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play পরিষেবা"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"আপনার ফোনের ফটো, মিডিয়া এবং তথ্য অ্যাক্সেস করার জন্য <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-এর হয়ে অনুমতি চাইছে"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"আপনার ফোন থেকে এই অ্যাকশন পারফর্ম করার জন্য &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-কে&lt;/strong&gt; অনুমতি দিন"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"ক্রস-ডিভাইস পরিষেবা"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"আশেপাশের ডিভাইসে কন্টেন্ট স্ট্রিম করার জন্য আপনার <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-এর হয়ে <xliff:g id="APP_NAME">%1$s</xliff:g> অনুমতি চাইছে"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"ডিভাইস"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"এই অ্যাপ আপনার ফোন এবং <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ডিভাইসের মধ্যে তথ্য সিঙ্ক করতে পারবে, যেমন কলারের নাম।"</string>
     <string name="summary_generic" msgid="4988130802522924650">"এই অ্যাপ আপনার ফোন এবং বেছে নেওয়া ডিভাইসের মধ্যে তথ্য সিঙ্ক করতে পারবে, যেমন কলারের নাম।"</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"ফটো ও মিডিয়া"</string>
     <string name="permission_notification" msgid="693762568127741203">"বিজ্ঞপ্তি"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"অ্যাপ"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"আশেপাশের ডিভাইসে স্ট্রিম করা"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"মাইক্রোফোন ব্যবহার করে অডিও রেকর্ড করতে পারবেন"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"আশেপাশের ডিভাইস খুঁজে দেখতে, তার সাথে কানেক্ট করতে এবং তার আপেক্ষিক অবস্থান নির্ধারণ করতে পারবে"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"সব বিজ্ঞপ্তি পড়তে পারবে, যার মধ্যে পরিচিতি, মেসেজ ও ফটোর মতো তথ্য অন্তর্ভুক্ত"</string>
     <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="5776807830582725074">"আশেপাশের ডিভাইসে কন্টেন্ট স্ট্রিম করুন"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-bs/strings.xml b/packages/CompanionDeviceManager/res/values-bs/strings.xml
index a4a825c..1df3da5 100644
--- a/packages/CompanionDeviceManager/res/values-bs/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bs/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Odaberite uređaj \"<xliff:g id="PROFILE_NAME">%1$s</xliff:g>\" kojim će upravljati aplikacija &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> će biti dozvoljeni sinhroniziranje informacija, kao što je ime osobe koja upućuje poziv, interakcija s obavještenjima i pristup odobrenjima za Telefon, SMS-ove, Kontakte, Kalendar, Zapisnike poziva i Uređaje u blizini."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> će biti dozvoljeni sinhroniziranje informacija, kao što je ime osobe koja upućuje poziv, i pristup ovim odobrenjima:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"naočale"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Ova aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> će biti dozvoljena interakcija s obavještenjima i pristup odobrenjima za Telefon, SMS-ove, Kontakte, Mikrofon i Uređaje u blizini."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> će biti dozvoljena interakcija s ovim odobrenjima:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Dozvolite da aplikacija &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; pristupa ovim informacijama s telefona"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Usluga na više uređaja"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> u ime uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> zahtijeva odobrenje da prenosi aplikacije između vaših uređaja"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play usluge"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> u ime uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> zahtijeva odobrenje da pristupi fotografijama, medijima i odobrenjima na vašem telefonu"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Dozvolite aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; da obavi ovu radnju s telefona"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Usluga na više uređaja"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> zahtijeva odobrenje u ime uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> da prenosi sadržaj na uređajima u blizini"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Ova aplikacija će moći sinhronizirati informacije, kao što je ime osobe koja upućuje poziv, između vašeg telefona i uređaja <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Ova aplikacija će moći sinhronizirati informacije, kao što je ime osobe koja upućuje poziv, između vašeg telefona i odabranog uređaja."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Fotografije i mediji"</string>
     <string name="permission_notification" msgid="693762568127741203">"Obavještenja"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacije"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Prijenos na uređajima u blizini"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Može snimati zvuk pomoću mikrofona"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Prijenos sadržaja na uređaju u blizini"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ca/strings.xml b/packages/CompanionDeviceManager/res/values-ca/strings.xml
index 9e5aef7..56dd313 100644
--- a/packages/CompanionDeviceManager/res/values-ca/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ca/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Tria un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> perquè el gestioni &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"L\'aplicació és necessària per gestionar el dispositiu (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> tindrà permís per sincronitzar informació, com ara el nom d\'algú que truca, per interaccionar amb les teves notificacions i accedir al telèfon, als SMS, als contactes, al calendari, als registres de trucades i als dispositius propers."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"L\'aplicació és necessària per gestionar el dispositiu (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> tindrà permís per sincronitzar informació, com ara el nom d\'algú que truca, i accedir a aquests permisos:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"ulleres"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Aquesta aplicació es necessita per gestionar el dispositiu (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> tindrà permís per interaccionar amb les teves notificacions i accedir al telèfon, als SMS, als contactes, al micròfon i als dispositius propers."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"L\'aplicació és necessària per gestionar el dispositiu (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> tindrà permís per interaccionar amb aquests permisos:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Permet que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; accedeixi a aquesta informació del telèfon"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serveis multidispositiu"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> demana permís en nom del teu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> per reproduir en continu aplicacions entre els dispositius"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Serveis de Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> demana permís en nom del teu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> per accedir a les fotos, el contingut multimèdia i les notificacions del telèfon"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Permet que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; dugui a terme aquesta acció des del telèfon"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Serveis multidispositiu"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> demana permís en nom del teu dispositiu (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) per reproduir contingut en continu en dispositius propers"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositiu"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Aquesta aplicació podrà sincronitzar informació, com ara el nom d\'algú que truca, entre el teu telèfon i el teu dispositiu (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>)."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Aquesta aplicació podrà sincronitzar informació, com ara el nom d\'algú que truca, entre el teu telèfon i el dispositiu triat."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Fotos i contingut multimèdia"</string>
     <string name="permission_notification" msgid="693762568127741203">"Notificacions"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplicacions"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Reproducció en disp. propers"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Pots gravar àudios amb el micròfon"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Reproduir contingut en continu en dispositius propers"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-cs/strings.xml b/packages/CompanionDeviceManager/res/values-cs/strings.xml
index 7ef6846..edb21d8 100644
--- a/packages/CompanionDeviceManager/res/values-cs/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-cs/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Vyberte zařízení <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, které chcete spravovat pomocí aplikace &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Aplikace je nutná ke správě zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> bude moci synchronizovat údaje, jako je jméno volajícího, interagovat s vašimi oznámeními a získat přístup k vašim oprávněním k telefonu, SMS, kontaktům, kalendáři, seznamům hovorů a zařízením v okolí."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Aplikace je nutná ke správě zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> bude moci synchronizovat údaje, jako je jméno volajícího, a získat přístup k těmto oprávněním:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"brýle"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Tato aplikace je nutná ke správě zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> bude moci interagovat s vašimi oznámeními a získat přístup k vašim oprávněním k telefonu, SMS, kontaktům, mikrofonu a zařízením v okolí."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Aplikace je nutná ke správě zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikace <xliff:g id="APP_NAME">%2$s</xliff:g> bude moci interagovat s těmito oprávněními:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Povolte aplikaci &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; přístup k těmto informacím z vašeho telefonu"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Služby pro více zařízení"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> požaduje za vaše zařízení <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> oprávnění ke streamování aplikací mezi zařízeními"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Služby Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> požaduje za vaše zařízení <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> oprávnění k přístupu k fotkám, médiím a oznámením v telefonu"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Povolte aplikaci &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; provádět tuto akci z vašeho telefonu"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Služby pro více zařízení"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> požaduje za vaše zařízení <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> oprávnění ke streamování obsahu do zařízení v okolí"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"zařízení"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Tato aplikace bude moci synchronizovat údaje, jako je jméno volajícího, mezi vaším telefonem a zařízením <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Tato aplikace bude moci synchronizovat údaje, jako je jméno volajícího, mezi vaším telefonem a vybraným zařízením."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Fotky a média"</string>
     <string name="permission_notification" msgid="693762568127741203">"Oznámení"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikace"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streamování do zařízení v okolí"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Může nahrávat zvuk pomocí mikrofonu"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Streamování obsahu do zařízení v okolí"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-da/strings.xml b/packages/CompanionDeviceManager/res/values-da/strings.xml
index 99913da..181c4aa 100644
--- a/packages/CompanionDeviceManager/res/values-da/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-da/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Vælg det <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, som skal administreres af &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Du skal bruge denne app for at administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tilladelse til at interagere med dine notifikationer og synkronisere oplysninger som f.eks. navnet på en person, der ringer, og appen får adgang til dine tilladelser for Opkald, Sms, Kalender, Opkaldshistorik og Enheder i nærheden."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Du skal bruge denne app for at administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tilladelse til at synkronisere oplysninger som f.eks. navnet på en person, der ringer, og appen får adgang til følgende tilladelser:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"briller"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Du skal bruge denne app for at administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tilladelse til at interagere med dine notifikationer og tilgå tilladelserne Telefon, Sms, Kontakter, Mikrofon og Enheder i nærheden."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Du skal bruge denne app for at administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får mulighed for at interagere med følgende tilladelser:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Giv &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; adgang til disse oplysninger fra din telefon"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjenester, som kan tilsluttes en anden enhed"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> anmoder om tilladelse på vegne af din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> til at streame apps mellem dine enheder"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play-tjenester"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> anmoder om tilladelse på vegne af din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> til at få adgang til din telefons billeder, medier og notifikationer"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Giv &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; tilladelse til at udføre denne handling på din telefon"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Tjenester til flere enheder"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> anmoder om tilladelse på vegne af din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> til at streame indhold til enheder i nærheden"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"enhed"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Denne app vil kunne synkronisere oplysninger som f.eks. navnet på en person, der ringer, mellem din telefon og <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Denne app vil kunne synkronisere oplysninger som f.eks. navnet på en person, der ringer, mellem din telefon og den valgte enhed."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Billeder og medier"</string>
     <string name="permission_notification" msgid="693762568127741203">"Notifikationer"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streaming til enhed i nærheden"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Kan optage lyd via mikrofonen"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Stream indhold til en enhed i nærheden"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-de/strings.xml b/packages/CompanionDeviceManager/res/values-de/strings.xml
index ce22c34..5063e7e 100644
--- a/packages/CompanionDeviceManager/res/values-de/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-de/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Gerät „<xliff:g id="PROFILE_NAME">%1$s</xliff:g>“ auswählen, das von &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; verwaltet werden soll"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Die App wird zur Verwaltung deines Geräts (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) benötigt. <xliff:g id="APP_NAME">%2$s</xliff:g> darf dann Daten wie den Namen eines Anrufers synchronisieren, mit deinen Benachrichtigungen interagieren und auf die Berechtigungen „Telefon“, „SMS“, „Kontakte“, „Kalender“, „Anruflisten“ und „Geräte in der Nähe“ zugreifen."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Die App wird zur Verwaltung deines Geräts (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) benötigt. <xliff:g id="APP_NAME">%2$s</xliff:g> darf dann Daten wie den Namen eines Anrufers synchronisieren und auf folgende Berechtigungen zugreifen:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"Glass-Geräte"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Diese App wird zur Verwaltung deines Geräts (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) benötigt. <xliff:g id="APP_NAME">%2$s</xliff:g> darf dann mit deinen Benachrichtigungen interagieren und auf die Berechtigungen „Telefon“, „SMS“, „Kontakte“, „Mikrofon“ und „Geräte in der Nähe“ zugreifen."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Die App wird zur Verwaltung deines Geräts (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) benötigt. <xliff:g id="APP_NAME">%2$s</xliff:g> darf dann mit diesen Berechtigungen interagieren:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; Zugriff auf diese Informationen von deinem Smartphone gewähren"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Geräteübergreifende Dienste"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> bittet für dein <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> um die Berechtigung zum Streamen von Apps zwischen deinen Geräten"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play-Dienste"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> bittet im Namen deines <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> um die Berechtigung zum Zugriff auf die Fotos, Medien und Benachrichtigungen deines Smartphones"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; darf diese Aktion von deinem Smartphone ausführen"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Geräteübergreifende Dienste"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> bittet für dein Gerät (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) um die Berechtigung zum Streamen von Inhalten auf Geräte in der Nähe"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"Gerät"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Diese App kann dann Daten wie den Namen eines Anrufers zwischen deinem Smartphone und deinem Gerät (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) synchronisieren."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Diese App kann dann Daten wie den Namen eines Anrufers zwischen deinem Smartphone und dem ausgewählten Gerät synchronisieren."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Fotos und Medien"</string>
     <string name="permission_notification" msgid="693762568127741203">"Benachrichtigungen"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streamen an Geräte in der Nähe"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Mit dem Mikrofon dürfen Audioaufnahmen gemacht werden"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Inhalte dürfen auf ein Gerät in der Nähe gestreamt werden"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-el/strings.xml b/packages/CompanionDeviceManager/res/values-el/strings.xml
index f817de0..992d7cf 100644
--- a/packages/CompanionDeviceManager/res/values-el/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-el/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Επιλέξτε ένα προφίλ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> για διαχείριση από την εφαρμογή &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Η εφαρμογή είναι απαραίτητη για τη διαχείριση της συσκευής <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Η εφαρμογή <xliff:g id="APP_NAME">%2$s</xliff:g> θα μπορεί να συγχρονίζει πληροφορίες, όπως το όνομα ενός ατόμου που σας καλεί, να αλληλεπιδρά με τις ειδοποιήσεις σας και να αποκτά πρόσβαση στις άδειες Τηλέφωνο, SMS, Επαφές, Ημερολόγιο, Αρχεία καταγρ. κλήσ. και Συσκευές σε κοντινή απόσταση."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Η εφαρμογή είναι απαραίτητη για τη διαχείριση της συσκευής <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Η εφαρμογή <xliff:g id="APP_NAME">%2$s</xliff:g> θα μπορεί να συγχρονίζει πληροφορίες, όπως το όνομα ενός ατόμου που σας καλεί, και να αποκτά πρόσβαση σε αυτές τις άδειες:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"γυαλιά"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Αυτή η εφαρμογή είναι απαραίτητη για τη διαχείριση της συσκευής <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Θα επιτρέπεται στην εφαρμογή <xliff:g id="APP_NAME">%2$s</xliff:g> να αλληλεπιδρά με τις ειδοποιήσεις σας και να αποκτά πρόσβαση στις άδειες για το Τηλέφωνο, τα SMS, τις Επαφές, το Μικρόφωνο και τις Συσκευές σε κοντινή απόσταση."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Η εφαρμογή είναι απαραίτητη για τη διαχείριση της συσκευής <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Η εφαρμογή <xliff:g id="APP_NAME">%2$s</xliff:g> θα επιτρέπεται να αλληλεπιδρά με τις εξής άδειες:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Να επιτρέπεται στο &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; η πρόσβαση σε αυτές τις πληροφορίες από το τηλέφωνό σας."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Υπηρεσίες πολλών συσκευών"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> ζητά εκ μέρους της συσκευής σας <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> άδεια για ροή εφαρμογών μεταξύ των συσκευών σας"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Υπηρεσίες Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> ζητά εκ μέρους της συσκευής σας <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> άδεια για πρόσβαση στις φωτογραφίες, τα αρχεία μέσων και τις ειδοποιήσεις του τηλεφώνου σας"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Να επιτρέπεται στην εφαρμογή &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; να εκτελεί αυτήν την ενέργεια στο τηλέφωνό σας"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Υπηρεσίες πολλών συσκευών"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> ζητά άδεια εκ μέρους της συσκευής <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> για ροή περιεχομένου σε συσκευές σε κοντινή απόσταση."</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"συσκευή"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Αυτή η εφαρμογή θα μπορεί να συγχρονίζει πληροφορίες μεταξύ του τηλεφώνου και της συσκευής <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, όπως το όνομα ενός ατόμου που σας καλεί."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Αυτή η εφαρμογή θα μπορεί να συγχρονίζει πληροφορίες μεταξύ του τηλεφώνου και της επιλεγμένης συσκευής σας, όπως το όνομα ενός ατόμου που σας καλεί."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Φωτογραφίες και μέσα"</string>
     <string name="permission_notification" msgid="693762568127741203">"Ειδοποιήσεις"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Εφαρμογές"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Ροή σε κοντινή συσκευή"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Μπορεί να εγγράφει ήχο χρησιμοποιώντας το μικρόφωνο"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Δεν μπορεί να βρει, να συνδεθεί και να προσδιορίσει τη σχετική τοποθεσία των κοντινών συσκευών"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"Μπορεί να διαβάσει όλες τις ειδοποιήσεις, συμπεριλαμβανομένων πληροφοριών όπως επαφές, μηνύματα και φωτογραφίες"</string>
     <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="5776807830582725074">"Ροή περιεχομένου σε συσκευή σε κοντινή απόσταση"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
index 5708fdc..21b8434 100644
--- a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to sync info, like the name of someone calling, interact with your notifications and access your Phone, SMS, Contacts, Calendar, Call logs and Nearby devices permissions."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to sync info, like the name of someone calling, and access these permissions:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"glasses"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"This app is needed to manage <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with your notifications and access your phone, SMS, contacts, microphone and Nearby devices permissions."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"The app is needed to manage <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with these permissions:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to access this information from your phone"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream apps between your devices"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play services"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to access your phone’s photos, media and notifications"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to perform this action from your phone"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Cross-device services"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream content to nearby devices"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"This app will be able to sync info, like the name of someone calling, between your phone and <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"This app will be able to sync info, like the name of someone calling, between your phone and the chosen device."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Photos and media"</string>
     <string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Nearby device streaming"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Can record audio using the microphone"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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_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="5776807830582725074">"Stream content to a nearby device"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
index ea0ceb2..873c602 100644
--- a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
@@ -22,9 +22,10 @@
     <string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to sync info, like the name of someone calling, interact with your notifications and access your Phone, SMS, Contacts, Calendar, Call logs and Nearby devices permissions."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to sync info, like the name of someone calling, and access these permissions:"</string>
+    <string name="confirmation_title_glasses" msgid="8288346850537727333">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to manage &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="profile_name_glasses" msgid="8488394059007275998">"glasses"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"This app is needed to manage <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts, Microphone and Nearby devices permissions."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"The app is needed to manage <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with these permissions:"</string>
+    <string name="summary_glasses_multi_device" msgid="615259525961937348">"This app is needed to manage <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts, Microphone and Nearby devices permissions."</string>
+    <string name="summary_glasses_single_device" msgid="5783761806783565716">"This app will be allowed to access these permissions on your phone:"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to access this information from your phone"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream apps between your devices"</string>
@@ -34,9 +35,8 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play services"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to access your phone’s photos, media, and notifications"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to perform this action from your phone"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Cross-device services"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream content to nearby devices"</string>
+    <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Allow &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; to take this action?"</string>
+    <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to stream apps and other system features to nearby devices"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"This app will be able to sync info, like the name of someone calling, between your phone and <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"This app will be able to sync info, like the name of someone calling, between your phone and the chosen device."</string>
@@ -57,16 +57,16 @@
     <string name="permission_storage" msgid="6831099350839392343">"Photos and media"</string>
     <string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Nearby Device Streaming"</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="4241354865859396558">"Can record audio using the microphone"</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_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="5776807830582725074">"Stream content to a nearby device"</string>
+    <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"Stream apps and other system features from your phone"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
index 5708fdc..21b8434 100644
--- a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to sync info, like the name of someone calling, interact with your notifications and access your Phone, SMS, Contacts, Calendar, Call logs and Nearby devices permissions."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to sync info, like the name of someone calling, and access these permissions:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"glasses"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"This app is needed to manage <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with your notifications and access your phone, SMS, contacts, microphone and Nearby devices permissions."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"The app is needed to manage <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with these permissions:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to access this information from your phone"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream apps between your devices"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play services"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to access your phone’s photos, media and notifications"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to perform this action from your phone"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Cross-device services"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream content to nearby devices"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"This app will be able to sync info, like the name of someone calling, between your phone and <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"This app will be able to sync info, like the name of someone calling, between your phone and the chosen device."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Photos and media"</string>
     <string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Nearby device streaming"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Can record audio using the microphone"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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_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="5776807830582725074">"Stream content to a nearby device"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
index 5708fdc..21b8434 100644
--- a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to sync info, like the name of someone calling, interact with your notifications and access your Phone, SMS, Contacts, Calendar, Call logs and Nearby devices permissions."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to sync info, like the name of someone calling, and access these permissions:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"glasses"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"This app is needed to manage <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with your notifications and access your phone, SMS, contacts, microphone and Nearby devices permissions."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"The app is needed to manage <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with these permissions:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to access this information from your phone"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream apps between your devices"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play services"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to access your phone’s photos, media and notifications"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to perform this action from your phone"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Cross-device services"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream content to nearby devices"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"This app will be able to sync info, like the name of someone calling, between your phone and <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"This app will be able to sync info, like the name of someone calling, between your phone and the chosen device."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Photos and media"</string>
     <string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Nearby device streaming"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Can record audio using the microphone"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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_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="5776807830582725074">"Stream content to a nearby device"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
index ffad25b..0d12e98 100644
--- a/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
@@ -22,9 +22,10 @@
     <string name="chooser_title" msgid="2262294130493605839">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‎‎‏‎‎‎‏‎‎‎‎‏‏‎‏‎‎‎‏‎‎‏‏‎‎‎‎‏‎‏‏‏‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎Choose a ‎‏‎‎‏‏‎<xliff:g id="PROFILE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to be managed by &lt;strong&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/strong&gt;‎‏‎‎‏‎"</string>
     <string name="summary_watch" msgid="6566922405914995759">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‎‎‏‎‎‏‏‎‎‏‎‏‎‎‏‎‎‎‏‎‏‎‎‏‏‎‎‎‎‎‎‏‏‏‎‏‏‏‏‎‏‏‎‎‎‎‏‎‏‏‏‏‎The app is needed to manage your ‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎. ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ will be allowed to sync info, like the name of someone calling, interact with your notifications and access your Phone, SMS, Contacts, Calendar, Call logs and Nearby devices permissions.‎‏‎‎‏‎"</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‏‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‎‏‎‎‏‎‏‏‏‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‏‏‎The app is needed to manage your ‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎. ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ will be allowed to sync info, like the name of someone calling, and access these permissions:‎‏‎‎‏‎"</string>
+    <string name="confirmation_title_glasses" msgid="8288346850537727333">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‎‎‏‏‎‎‎‎‏‏‏‏‏‏‎‎‎‏‏‎‎‎‎‎‎‏‎‎‏‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‏‎‏‏‎‎‏‎‏‎Allow &lt;strong&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/strong&gt; to manage &lt;strong&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/strong&gt;?‎‏‎‎‏‎"</string>
     <string name="profile_name_glasses" msgid="8488394059007275998">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‏‏‎‎‏‏‎‏‎‏‎‏‎‏‏‎‏‏‎‎‎‏‎‏‏‎‎‎‏‎‏‎‏‎‏‎‎‎‏‏‎‎‏‏‏‏‎‏‏‏‏‎‎glasses‎‏‎‎‏‎"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‏‏‎‎‏‏‎‏‎‏‏‏‏‎‏‎‏‏‏‏‎‏‎‎‎‏‏‏‎‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‏‏‏‏‏‏‎‎‏‎This app is needed to manage ‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎. ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ will be allowed to interact with your notifications and access your Phone, SMS, Contacts, Microphone and Nearby devices permissions.‎‏‎‎‏‎"</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‏‏‎‏‏‏‎‎‏‎‏‎‎‎‏‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‏‏‎‎‏‎‎‎‏‏‎‎‎‏‏‏‏‏‏‎‎‎‎The app is needed to manage ‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎. ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ will be allowed to interact with these permissions:‎‏‎‎‏‎"</string>
+    <string name="summary_glasses_multi_device" msgid="615259525961937348">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‎‎‎‏‎‎‏‏‏‎‏‎‏‏‏‎‏‎‎‎‏‏‏‎‏‏‏‎‎‎‏‏‎‏‎‎‎‏‎‏‏‏‏‎‎‎‏‏‏‎‎‎‏‎‎‎This app is needed to manage ‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎. ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ will be allowed to interact with your notifications and access your Phone, SMS, Contacts, Microphone and Nearby devices permissions.‎‏‎‎‏‎"</string>
+    <string name="summary_glasses_single_device" msgid="5783761806783565716">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‏‎‎‎‎‎‎‏‏‎‎‏‎‏‏‏‎‎‎‎‎‏‏‎‏‏‎‏‏‎‎‏‏‏‎‎‏‎‎‏‏‏‏‏‎‎‏‎‏‎‎‎This app will be allowed to access these permissions on your phone:‎‏‎‎‏‎"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‎‏‎‏‏‎‎‎‎‎‏‎‎‏‏‏‎‎‎‏‎‏‎‏‏‎‏‎‎‎‎‏‏‏‎‎‏‎‎‏‏‎‎‏‏‎‎Allow &lt;strong&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/strong&gt; to access this information from your phone‎‏‎‎‏‎"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‏‏‏‎‏‏‏‎‎‎‎‎‏‎‏‎‏‎‏‎‏‎‏‎‎‎‎‏‎‏‎‏‎‎‏‎‏‎‎‏‏‎‏‎‏‏‏‏‎‎‏‎‏‎Cross-device services‎‏‎‎‏‎"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‎‏‎‏‏‎‏‎‏‎‎‏‏‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‎‎‎‏‎‎‏‏‎‎‎‎‏‏‏‏‎‏‎‎‏‏‎‏‏‎‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is requesting permission on behalf of your ‎‏‎‎‏‏‎<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>‎‏‎‎‏‏‏‎ to stream apps between your devices‎‏‎‎‏‎"</string>
@@ -34,9 +35,8 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‎‏‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‏‏‎‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‏‏‏‎‎‏‎‏‏‏‎‏‎‏‎‎‏‎‏‎Google Play services‎‏‎‎‏‎"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‏‎‏‎‎‎‏‎‎‎‏‎‎‏‏‎‏‎‎‏‎‎‎‎‏‏‏‎‏‎‏‎‎‎‏‏‎‏‎‎‎‎‎‏‏‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is requesting permission on behalf of your ‎‏‎‎‏‏‎<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>‎‏‎‎‏‏‏‎ to access your phone’s photos, media, and notifications‎‏‎‎‏‎"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‎‎‏‎‏‎‎‏‎‏‏‏‏‎‏‎‏‏‎‎‏‏‎‎‏‎‏‏‏‎‏‏‎‎‎‎‏‎‎‎‎‎‎Allow &lt;strong&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/strong&gt; to perform this action from your phone‎‏‎‎‏‎"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‏‏‏‏‎‎‏‏‎‎‎‎‎‎‎‎‏‏‏‎‎‎‎‏‏‏‎‏‎‎‎‎‏‏‎‏‎‎‎‎‏‏‏‎‎‎‎‎‎‎‏‎‏‎Cross-device services‎‏‎‎‏‎"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‏‎‏‏‏‎‎‎‎‎‏‏‎‎‏‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‏‏‎‎‏‏‏‏‏‎‎‏‎‏‏‏‏‏‎‏‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is requesting permission on behalf of your ‎‏‎‎‏‏‎<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>‎‏‎‎‏‏‏‎ to stream content to nearby devices‎‏‎‎‏‎"</string>
+    <string name="title_nearby_device_streaming" msgid="7269956847378799794">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‎‎‏‎‎‎‎‎‏‎‎‏‏‎‎‏‏‏‏‎‎‎‎‎‏‏‏‎‎‎‏‏‎‏‏‏‎‏‎‎‏‏‏‎‎‏‎‏‏‎‎‏‎‎Allow &lt;strong&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/strong&gt; to take this action?‎‏‎‎‏‎"</string>
+    <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‎‎‏‎‎‏‎‏‎‏‏‎‏‎‏‎‎‏‎‏‏‏‏‏‏‎‎‏‎‎‎‎‎‎‎‎‏‎‎‏‎‏‎‏‎‎‏‎‎‏‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is requesting permission on behalf of your ‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ to stream apps and other system features to nearby devices‎‏‎‎‏‎"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‏‏‏‏‏‎‎‏‎‎‏‎‎‏‏‏‏‎‎‎‏‏‏‎‏‏‏‎‎‎‎‎‎‎‎‏‏‏‎‏‏‎‏‏‎‎‎device‎‏‎‎‏‎"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‏‏‎‏‏‎‎‏‎‏‏‎‏‏‎‎‎‏‎‏‎‎‏‎‏‎‎‏‏‎‎‏‎‏‏‎‎‎‎‏‏‎‎‎‏‎‏‏‏‎‎‏‏‏‎This app will be able to sync info, like the name of someone calling, between your phone and ‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
     <string name="summary_generic" msgid="4988130802522924650">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‏‏‏‎‎‏‎‏‏‎‎‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎‎‎‎‏‏‎‎‏‎‎‎‎‎‎‏‎‎‏‏‎‎‏‏‎‏‎‏‎‎This app will be able to sync info, like the name of someone calling, between your phone and the chosen device.‎‏‎‎‏‎"</string>
@@ -57,16 +57,16 @@
     <string name="permission_storage" msgid="6831099350839392343">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‏‏‎‎‎‎‏‎‏‎‏‎‏‎‏‎‏‏‏‎‎‎‎‎‏‎‏‏‏‎‏‏‏‏‏‎‎‎‎‏‎‏‎‏‏‏‎Photos and media‎‏‎‎‏‎"</string>
     <string name="permission_notification" msgid="693762568127741203">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‏‎‏‎‎‎‎‎‏‎‏‏‏‏‎‏‎‏‏‎‎‎‎‏‎‏‎‎‎‏‏‏‏‎‏‏‎‏‏‏‎‏‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎Notifications‎‏‎‎‏‎"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‎‎‏‏‎‏‎‏‏‏‎‎‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎‏‎‏‎‎‎‎‎‏‎‏‎‎‏‏‎‎‎‏‎‏‏‎‎Apps‎‏‎‎‏‎"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‎‏‏‏‏‏‎‏‏‎‏‎‏‎‏‎‎‎‏‎‏‎‎‏‎‎‏‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‎‏‎‏‏‏‎‎‏‎Nearby Device Streaming‎‏‎‎‏‎"</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="4241354865859396558">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‎‏‏‏‎‎‎‏‎‏‎‎‎‏‏‏‎‎‎‏‏‏‎‏‏‎‎‎‎‏‏‏‏‎‏‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‎‎Can record audio using the microphone‎‏‎‎‏‎"</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_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="5776807830582725074">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‏‎‏‎‏‏‎‏‎‏‏‎‎‎‎‎‎‏‏‏‎‏‎‏‏‏‎‏‎‏‏‎‎‏‎‏‎‎‎‎‎‎‏‎‎‏‏‏‎‏‎‎‏‎‎Stream content to a nearby device‎‏‎‎‏‎"</string>
+    <string name="permission_nearby_device_streaming_summary" msgid="8280824871197081246">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‎‏‏‎‏‏‎‎‏‏‎‎‏‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‎Stream apps and other system features from your phone‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
index debfcd9..df5562e 100644
--- a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Elige un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para que la app &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; lo administre"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Esta app es necesaria para administrar tu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá sincronizar información, como el nombre de la persona que llama, interactuar con tus notificaciones y acceder a los permisos de Teléfono, SMS, Contactos, Calendario, Llamadas y Dispositivos cercanos."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Esta app es necesaria para administrar tu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá sincronizar información, como el nombre de la persona que llama, y acceder a los siguientes permisos:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"Gafas"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Esta app es necesaria para administrar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá interactuar con tus notificaciones y acceder a los permisos de Teléfono, SMS, Contactos, Micrófono y Dispositivos cercanos."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Esta app es necesaria para administrar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá interactuar con estos permisos:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Permite que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acceda a esta información de tu teléfono"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servicios multidispositivo"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicita tu permiso en nombre de <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para transmitir apps entre dispositivos"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Servicios de Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicita tu permiso en nombre de <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para acceder a las fotos, el contenido multimedia y las notificaciones de tu teléfono"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Permite que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; realice esta acción desde tu teléfono"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Servicios multidispositivo"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicita tu permiso en nombre de <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para transmitir contenido a dispositivos cercanos"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Esta app podrá sincronizar información, como el nombre de la persona que llama, entre el teléfono y <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Esta app podrá sincronizar información, como el nombre de la persona que llama, entre el teléfono y el dispositivo elegido."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Fotos y contenido multimedia"</string>
     <string name="permission_notification" msgid="693762568127741203">"Notificaciones"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Transmisión a disp. cercanos"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Puede grabar audio con el micrófono"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Transmitir contenido a un dispositivo cercano"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-es/strings.xml b/packages/CompanionDeviceManager/res/values-es/strings.xml
index acdb957..ba8fd5d 100644
--- a/packages/CompanionDeviceManager/res/values-es/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-es/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Elige un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para gestionarlo con &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Se necesita la aplicación para gestionar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá sincronizar información (por ejemplo, el nombre de la persona que te llama), interactuar con tus notificaciones y acceder a tus permisos de teléfono, SMS, contactos, calendario, registros de llamadas y dispositivos cercanos."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Se necesita la aplicación para gestionar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá sincronizar información (por ejemplo, el nombre de la persona que te llama) y acceder a los permisos siguientes:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"gafas"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Se necesita esta aplicación para gestionar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá interactuar con tus notificaciones y acceder a tus permisos de teléfono, SMS, contactos, micrófono y dispositivos cercanos."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Se necesita la aplicación para gestionar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Se permitirá que <xliff:g id="APP_NAME">%2$s</xliff:g> interaccione con los siguientes permisos:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Permitir que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acceda a esta información de tu teléfono"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servicios multidispositivo"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pidiendo permiso en nombre de tu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para emitir aplicaciones en otros dispositivos tuyos"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Servicios de Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pidiendo permiso en nombre de tu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para acceder a las fotos, los archivos multimedia y las notificaciones de tu teléfono"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Permite que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; realice esta acción desde tu teléfono"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Servicios multidispositivo"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pidiendo permiso en nombre de tu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para reproducir contenido en dispositivos cercanos"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Esta aplicación podrá sincronizar información (por ejemplo, el nombre de la persona que te llama) entre tu teléfono y <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Esta aplicación podrá sincronizar información (por ejemplo, el nombre de la persona que te llama) entre tu teléfono y el dispositivo que elijas."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Fotos y elementos multimedia"</string>
     <string name="permission_notification" msgid="693762568127741203">"Notificaciones"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplicaciones"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streaming en dispositivos cercanos"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Puede grabar audio usando el micrófono"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Reproduce contenido en un dispositivo cercano"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-et/strings.xml b/packages/CompanionDeviceManager/res/values-et/strings.xml
index 0e029bd..fadb56a 100644
--- a/packages/CompanionDeviceManager/res/values-et/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-et/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Valige <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, mida haldab rakendus &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Seda rakendust on vaja teie seadme <xliff:g id="DEVICE_NAME">%1$s</xliff:g> haldamiseks. Rakendusel <xliff:g id="APP_NAME">%2$s</xliff:g> lubatakse sünkroonida teavet, näiteks helistaja nime, kasutada teie märguandeid ning pääseda juurde teie telefoni, SMS-ide, kontaktide, kalendri, kõnelogide ja läheduses olevate seadmete lubadele."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Seda rakendust on vaja teie seadme <xliff:g id="DEVICE_NAME">%1$s</xliff:g> haldamiseks. <xliff:g id="APP_NAME">%2$s</xliff:g> lubatakse sünkroonida teavet, näiteks helistaja nime, ja pääseda juurde järgmistele lubadele."</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"prillid"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Seda rakendust on vaja seadme <xliff:g id="DEVICE_NAME">%1$s</xliff:g> haldamiseks. Rakendusel <xliff:g id="APP_NAME">%2$s</xliff:g> lubatakse kasutada teie märguandeid ning pääseda juurde teie telefoni, SMS-ide, kontaktide, mikrofoni ja läheduses olevate seadmete lubadele."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Seda rakendust on vaja seadme <xliff:g id="DEVICE_NAME">%1$s</xliff:g> haldamiseks. Rakendusel <xliff:g id="APP_NAME">%2$s</xliff:g> lubatakse kasutada järgmisi lube."</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Lubage rakendusel &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; pääseda teie telefonis juurde sellele teabele"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Seadmeülesed teenused"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nimel luba teie seadmete vahel rakendusi voogesitada"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play teenused"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nimel luba pääseda juurde telefoni fotodele, meediale ja märguannetele"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Lubage rakendusel &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; teha teie telefonis seda toimingut"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Seadmeülesed teenused"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nimel luba voogesitada sisu läheduses olevates seadmetes"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"seade"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"See rakendus saab sünkroonida teavet, näiteks helistaja nime, teie telefoni ja seadme <xliff:g id="DEVICE_NAME">%1$s</xliff:g> vahel."</string>
     <string name="summary_generic" msgid="4988130802522924650">"See rakendus saab sünkroonida teavet, näiteks helistaja nime, teie telefoni ja valitud seadme vahel."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Fotod ja meedia"</string>
     <string name="permission_notification" msgid="693762568127741203">"Märguanded"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Rakendused"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Läheduses olevas seadmes esit."</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Saab mikrofoni abil heli salvestada"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Sisu voogesitamine läheduses olevas seadmes"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-eu/strings.xml b/packages/CompanionDeviceManager/res/values-eu/strings.xml
index 8d58f88..4d2b67c 100644
--- a/packages/CompanionDeviceManager/res/values-eu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-eu/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Aukeratu &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; aplikazioak kudeatu beharreko <xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_watch" msgid="6566922405914995759">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> kudeatzeko behar da aplikazioa. Informazioa sinkronizatzeko (esate baterako, deitzaileen izenak), jakinarazpenekin interakzioan aritzeko, eta telefonoa, SMSak, kontaktuak, egutegia, deien erregistroa eta inguruko gailuak erabiltzeko baimena izango du <xliff:g id="APP_NAME">%2$s</xliff:g> aplikazioak."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> kudeatzeko behar da aplikazioa. Informazioa sinkronizatzeko (esate baterako, deitzaileen izenak) eta ekintza hauek gauzatzeko baimena izango du <xliff:g id="APP_NAME">%2$s</xliff:g> aplikazioak:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"betaurrekoak"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> kudeatzeko behar da aplikazioa. Jakinarazpenekin interakzioan aritzeko, eta telefonoa, SMSak, kontaktuak, mikrofonoa eta inguruko gailuak erabiltzeko baimena izango du <xliff:g id="APP_NAME">%2$s</xliff:g> aplikazioak."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> kudeatzeko behar da aplikazioa. Baimen hauek izango ditu <xliff:g id="APP_NAME">%2$s</xliff:g> aplikazioak:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Eman informazioa telefonotik hartzeko baimena &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; aplikazioari"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Gailu baterako baino gehiagotarako zerbitzuak"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Gailu batetik bestera aplikazioak igortzeko baimena eskatzen ari da <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> gailuaren izenean"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Services"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"Telefonoko argazkiak, multimedia-edukia eta jakinarazpenak erabiltzeko baimena eskatzen ari da <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> gailuaren izenean"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Eman telefonotik ekintza hau gauzatzeko baimena &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; aplikazioari"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Gailu baterako baino gehiagotarako zerbitzuak"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Inguruko gailuetara edukia igortzeko baimena eskatzen ari da <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> gailuaren izenean"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"gailua"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Telefonoaren eta <xliff:g id="DEVICE_NAME">%1$s</xliff:g> gailuaren artean informazioa sinkronizatzeko gai izango da aplikazioa (esate baterako, deitzaileen izenak)."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Telefonoaren eta hautatutako gailuaren artean informazioa sinkronizatzeko gai izango da aplikazioa (esate baterako, deitzaileen izenak)."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Argazkiak eta multimedia-edukia"</string>
     <string name="permission_notification" msgid="693762568127741203">"Jakinarazpenak"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikazioak"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Inguruko gailuetara igortzeko baimena"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Audioa graba dezake mikrofonoa erabilita"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Inguruko gailu batera edukia igor dezake"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-fa/strings.xml b/packages/CompanionDeviceManager/res/values-fa/strings.xml
index 701cdb3..5d638e0 100644
--- a/packages/CompanionDeviceManager/res/values-fa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fa/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"‏انتخاب <xliff:g id="PROFILE_NAME">%1$s</xliff:g> برای مدیریت کردن با &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>‏&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"این برنامه برای مدیریت <xliff:g id="DEVICE_NAME">%1$s</xliff:g> شما لازم است. به <xliff:g id="APP_NAME">%2$s</xliff:g> اجازه داده می‌شود اطلاعاتی مثل نام شخصی که تماس می‌گیرد را همگام‌سازی کند، با اعلان‌های شما تعامل داشته باشد، و به اجازه‌های «تلفن»، «پیامک»، «مخاطبین»، «تقویم»، «گزارش‌های تماس»، و «دستگاه‌های اطراف» دسترسی داشته باشد."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"این برنامه برای مدیریت <xliff:g id="DEVICE_NAME">%1$s</xliff:g> شما لازم است. به <xliff:g id="APP_NAME">%2$s</xliff:g> اجازه داده می‌شود اطلاعاتی مثل نام شخصی که تماس می‌گیرد را همگام‌سازی کند و به این اجازه‌ها دسترسی داشته باشد:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"عینک"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"این برنامه برای مدیریت <xliff:g id="DEVICE_NAME">%1$s</xliff:g> لازم است. به <xliff:g id="APP_NAME">%2$s</xliff:g> اجازه داده می‌شود با اعلان‌های شما تعامل داشته باشد و به اجازه‌های «تلفن»، «پیامک»، «مخاطبین»، «میکروفون»، و «دستگاه‌های اطراف» دسترسی داشته باشد."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"این برنامه برای مدیریت <xliff:g id="DEVICE_NAME">%1$s</xliff:g> لازم است. <xliff:g id="APP_NAME">%2$s</xliff:g> مجاز می‌شود با این اجازه‌ها تعامل داشته باشد:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"‏اجازه دادن به &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; برای دسترسی به اطلاعات تلفن"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"سرویس‌های بین‌دستگاهی"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> اجازه می‌خواهد ازطرف <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> برنامه‌ها را بین دستگاه‌های شما جاری‌سازی کند"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"‏خدمات Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> اجازه می‌خواهد ازطرف <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> به عکس‌ها، رسانه‌ها، و اعلان‌های تلفن شما دسترسی پیدا کند"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"‏به &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; اجازه داده می‌شود این کنش را در تلفنتان اجرا کند"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"سرویس‌های بین‌دستگاهی"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> ازطرف <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> اجازه می‌خواهد تا در دستگاه‌های اطراف محتوا جاری‌سازی کند."</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"دستگاه"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"این برنامه مجاز می‌شود اطلاعتی مثل نام شخصی که تماس می‌گیرد را بین تلفن شما و <xliff:g id="DEVICE_NAME">%1$s</xliff:g> همگام‌سازی کند."</string>
     <string name="summary_generic" msgid="4988130802522924650">"این برنامه مجاز می‌شود اطلاعتی مثل نام شخصی که تماس می‌گیرد را بین تلفن شما و دستگاه انتخاب‌شده همگام‌سازی کند."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"عکس‌ها و رسانه‌ها"</string>
     <string name="permission_notification" msgid="693762568127741203">"اعلان‌ها"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"برنامه‌ها"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"جاری‌سازی دستگاه‌های اطراف"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"می‌تواند بااستفاده از میکروفون صدا ضبط کند"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"می‌تواند دستگاه‌های اطراف را پیدا کند، به آن‌ها متصل شود، و موقعیت نسبی آن‌ها را تعیین کند"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"می‌تواند همه اعلان‌ها، ازجمله اطلاعاتی مثل مخاطبین، پیام‌ها، و عکس‌ها را بخواند"</string>
     <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="5776807830582725074">"جاری‌سازی کردن محتوا در دستگاه‌های اطراف"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-fi/strings.xml b/packages/CompanionDeviceManager/res/values-fi/strings.xml
index 9f5c57f..2f0e266 100644
--- a/packages/CompanionDeviceManager/res/values-fi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fi/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Valitse <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, jota &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; hallinnoi"</string>
     <string name="summary_watch" msgid="6566922405914995759">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> edellyttää ylläpitoon tätä sovellusta. <xliff:g id="APP_NAME">%2$s</xliff:g> saa luvan synkronoida tietoja (esimerkiksi soittajan nimen), hallinnoida ilmoituksiasi sekä pääsyn puhelimeen, tekstiviesteihin, yhteystietoihin, kalenteriin, puhelulokeihin ja lähellä olevat laitteet ‑lupiin."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> edellyttää ylläpitoon tätä sovellusta. <xliff:g id="APP_NAME">%2$s</xliff:g> saa luvan synkronoida tietoja (esimerkiksi soittajan nimen) ja pääsyn näihin lupiin:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"lasit"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> edellyttää ylläpitoon tätä sovellusta. <xliff:g id="APP_NAME">%2$s</xliff:g> saa luvan hallinnoida ilmoituksiasi sekä pääsyn puhelimeen, tekstiviesteihin, yhteystietoihin, mikrofoniin ja lähellä olevat laitteet ‑lupiin."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> edellyttää ylläpitoon tätä sovellusta. <xliff:g id="APP_NAME">%2$s</xliff:g> saa käyttää näitä lupia:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Salli, että &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; saa pääsyn näihin puhelimesi tietoihin"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Laitteidenväliset palvelut"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> pyytää laitteesi (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) puolesta lupaa striimata sovelluksia laitteidesi välillä"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Palvelut"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> pyytää laitteesi (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) puolesta lupaa päästä puhelimesi kuviin, mediaan ja ilmoituksiin"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Myönnä lupa suorittaa tämä toiminto puhelimeltasi: &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Laitteidenväliset palvelut"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> pyytää laitteesi (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) puolesta lupaa striimata sisältöä lähellä oleviin laitteisiin"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"laite"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Sovellus voi synkronoida tietoja (esimerkiksi soittajan nimen) puhelimesi ja laitteen (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) välillä."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Sovellus voi synkronoida tietoja (esimerkiksi soittajan nimen) puhelimesi ja valitun laitteen välillä."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Kuvat ja media"</string>
     <string name="permission_notification" msgid="693762568127741203">"Ilmoitukset"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Sovellukset"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Striimaus muille laitteille"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Voi tallentaa audiota mikrofonilla"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Striimaa sisältöä lähellä olevalle laitteelle"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
index 1c6daef..97aaa76 100644
--- a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Choisissez un(e) <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qui sera géré(e) par &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"L\'application est nécessaire pour gérer votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation de synchroniser des informations, comme le nom de l\'appelant, d\'interagir avec vos notifications et d\'accéder à vos autorisations pour le téléphone, les messages texte, les contacts, l\'agenda, les journaux d\'appels et les appareils à proximité."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"L\'application est nécessaire pour gérer votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation de synchroniser des informations, comme le nom de l\'appelant, et d\'accéder à ces autorisations :"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"lunettes"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Cette application est nécessaire pour gérer <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> sera autorisée à interagir avec vos notifications et à accéder à vos autorisations pour le téléphone, les messages texte, les contacts, le microphone et les appareils à proximité."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"L\'application est nécessaire pour gérer <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation d\'interagir avec ces autorisations :"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Autorisez &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; à accéder à ces informations à partir de votre téléphone"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Services multiappareils"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> pour diffuser des applications entre vos appareils"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Services Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> pour accéder aux photos, aux fichiers multimédias et aux notifications de votre téléphone"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Permettre à &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; d\'accomplir cette action à partir de votre téléphone"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Services multiappareils"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> de diffuser du contenu aux appareils à proximité"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"appareil"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Cette application pourra synchroniser des informations, comme le nom de l\'appelant, entre votre téléphone et <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Cette application pourra synchroniser des informations, comme le nom de l\'appelant, entre votre téléphone et l\'appareil sélectionné."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Photos et fichiers multimédias"</string>
     <string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Applications"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Diffusion en cours à proximité"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Il est possible d\'enregistrer du contenu audio en utilisant le microphone"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Diffuser du contenu à un appareil à proximité"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-fr/strings.xml b/packages/CompanionDeviceManager/res/values-fr/strings.xml
index bbdb5ce..65e4a36 100644
--- a/packages/CompanionDeviceManager/res/values-fr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fr/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Sélectionnez le/la <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qui sera géré(e) par &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Cette appli est nécessaire pour gérer votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation de synchroniser des informations (comme le nom de la personne à l\'origine d\'un appel entrant), d\'interagir avec vos notifications et d\'accéder aux autorisations du téléphone, des SMS, des contacts, de l\'agenda, des journaux d\'appels et des appareils à proximité."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Cette appli est nécessaire pour gérer votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation de synchroniser vos informations, comme le nom de la personne à l\'origine d\'un appel entrant, et d\'accéder à ces autorisations :"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"lunettes"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Cette appli est nécessaire pour gérer <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation d\'interagir avec vos notifications et d\'accéder aux autorisations du téléphone, des SMS, des contacts, du micro et des appareils à proximité."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Cette appli est nécessaire pour gérer <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> pourra interagir avec ces autorisations :"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Autoriser &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; à accéder à ces informations depuis votre téléphone"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Services inter-appareils"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> pour caster des applis d\'un appareil à l\'autre"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Services Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> pour accéder aux photos, contenus multimédias et notifications de votre téléphone"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Autorisez &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; à effectuer cette action sur votre téléphone"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Services inter-appareils"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> de diffuser du contenu en streaming sur les appareils à proximité"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"appareil"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Cette appli pourra synchroniser des informations entre votre téléphone et <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, comme le nom de la personne à l\'origine d\'un appel entrant."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Cette appli pourra synchroniser des informations entre votre téléphone et l\'appareil choisi, comme le nom de la personne à l\'origine d\'un appel entrant."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Photos et contenus multimédias"</string>
     <string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Applis"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streaming appareil à proximité"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Peut enregistrer de l\'audio à l\'aide du micro"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Diffuse du contenu sur un appareil à proximité"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-gl/strings.xml b/packages/CompanionDeviceManager/res/values-gl/strings.xml
index 0a6db74..59d6226 100644
--- a/packages/CompanionDeviceManager/res/values-gl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-gl/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Escolle un dispositivo (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) para que o xestione a aplicación &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"A aplicación é necesaria para xestionar o teu dispositivo (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> poderá sincronizar información (por exemplo, o nome de quen chama), interactuar coas túas notificacións e acceder aos permisos do teu teléfono, das SMS, dos contactos, do calendario, dos rexistros de chamadas e dos dispositivos próximos."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"A aplicación é necesaria para xestionar o teu dispositivo (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> poderá sincronizar información (por exemplo, o nome de quen chama) e acceder a estes permisos:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"lentes"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Esta aplicación é necesaria para xestionar o dispositivo (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> poderá interactuar coas túas notificacións e acceder aos permisos do teu teléfono, das SMS, dos contactos, do micrófono e dos dispositivos próximos."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"A aplicación é necesaria para xestionar o dispositivo (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> poderá interactuar con estes permisos:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Permitir que a aplicación &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acceda a esta información desde o teu teléfono"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servizos multidispositivo"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> está solicitando permiso en nome do teu dispositivo (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) para emitir contido de aplicacións entre os teus aparellos"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Servizos de Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> está solicitando permiso en nome do teu dispositivo (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) para acceder ás fotos, ao contido multimedia e ás notificacións do teléfono"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Permitir que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; realice esta acción no teléfono"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Servizos multidispositivo"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> está solicitando permiso en nome do teu dispositivo (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) para emitir contido aos dispositivos próximos"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Esta aplicación poderá sincronizar información (por exemplo, o nome de quen chama) entre o teléfono e o dispositivo (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>)."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Esta aplicación poderá sincronizar información (por exemplo, o nome de quen chama) entre o teléfono e o dispositivo escollido."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Fotos e contido multimedia"</string>
     <string name="permission_notification" msgid="693762568127741203">"Notificacións"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplicacións"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Emitir a dispositivos próximos"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Pode gravar audio usando o micrófono"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Emite contido a un dispositivo próximo"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-gu/strings.xml b/packages/CompanionDeviceManager/res/values-gu/strings.xml
index 1a6107e..85be70a 100644
--- a/packages/CompanionDeviceManager/res/values-gu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-gu/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; દ્વારા મેનેજ કરવા માટે કોઈ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> પસંદ કરો"</string>
     <string name="summary_watch" msgid="6566922405914995759">"તમારા <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ને મેનેજ કરવા માટે ઍપ જરૂરી છે. <xliff:g id="APP_NAME">%2$s</xliff:g>ને કૉલ કરનાર વ્યક્તિનું નામ જેવી માહિતી સિંક કરવાની, તમારા નોટિફિકેશન સાથે ક્રિયાપ્રતિક્રિયા કરવાની અને તમારો ફોન, SMS, સંપર્કો, Calendar, કૉલ લૉગ તથા નજીકના ડિવાઇસની પરવાનગીઓ ઍક્સેસ કરવાની મંજૂરી આપવામાં આવશે."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"તમારા <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ને મેનેજ કરવા માટે ઍપ જરૂરી છે. <xliff:g id="APP_NAME">%2$s</xliff:g>ને કૉલ કરનાર વ્યક્તિનું નામ જેવી માહિતી સિંક કરવાની અને આ પરવાનગીઓ ઍક્સેસ કરવાની મંજૂરી આપવામાં આવશે:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"ચશ્માં"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>ને મેનેજ કરવા માટે આ ઍપ જરૂરી છે. <xliff:g id="APP_NAME">%2$s</xliff:g>ને તમારા નોટિફિકેશન સાથે ક્રિયાપ્રતિક્રિયા કરવાની અને તમારો ફોન, SMS, સંપર્કો, માઇક્રોફોન તથા નજીકના ડિવાઇસની પરવાનગીઓ ઍક્સેસ કરવાની મંજૂરી આપવામાં આવશે."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>ને મેનેજ કરવા માટે ઍપ જરૂરી છે. <xliff:g id="APP_NAME">%2$s</xliff:g>ને આ પરવાનગીઓ સાથે ક્રિયાપ્રતિક્રિયા કરવાની મંજૂરી આપવામાં આવશે:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"તમારા ફોનમાંથી આ માહિતી ઍક્સેસ કરવા માટે, &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;ને મંજૂરી આપો"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"ક્રોસ-ડિવાઇસ સેવાઓ"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> તમારા <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> વતી તમારા ડિવાઇસ વચ્ચે ઍપ સ્ટ્રીમ કરવાની પરવાનગીની વિનંતી કરી રહી છે"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play સેવાઓ"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> તમારા <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> વતી તમારા ફોનના ફોટા, મીડિયા અને નોટિફિકેશન ઍક્સેસ કરવાની પરવાનગીની વિનંતી કરી રહી છે"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;ને તમારા ફોન પરથી આ ક્રિયા કરવાની મંજૂરી આપો"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"ક્રૉસ-ડિવાઇસ સેવાઓ"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> નજીકના ડિવાઇસ પર કન્ટેન્ટ સ્ટ્રીમ કરવા માટે તમારા <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> વતી પરવાનગીની વિનંતી કરી રહી છે"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"ડિવાઇસ"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"આ ઍપ તમારા ફોન અને <xliff:g id="DEVICE_NAME">%1$s</xliff:g> વચ્ચે, કૉલ કરનાર કોઈ વ્યક્તિનું નામ જેવી માહિતી સિંક કરી શકશે."</string>
     <string name="summary_generic" msgid="4988130802522924650">"આ ઍપ તમારા ફોન અને પસંદ કરેલા ડિવાઇસ વચ્ચે, કૉલ કરનાર કોઈ વ્યક્તિનું નામ જેવી માહિતી સિંક કરી શકશે."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"ફોટા અને મીડિયા"</string>
     <string name="permission_notification" msgid="693762568127741203">"નોટિફિકેશન"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"ઍપ"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"નજીકના ડિવાઇસ પર સ્ટ્રીમિંગ"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"માઇક્રોફોનનો ઉપયોગ કરીને ઑડિયો રેકોર્ડ કરી શકાય છે"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"નજીકના ડિવાઇસ શોધી શકે છે, તેમની સાથે કનેક્ટ કરી શકે છે અને તેમની સંબંધિત સ્થિતિ નિર્ધારિત કરી શકે છે"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"સંપર્કો, મેસેજ અને ફોટા જેવી માહિતી સહિતના બધા નોટિફિકેશન વાંચી શકે છે"</string>
     <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="5776807830582725074">"નજીકના ડિવાઇસ પર કન્ટેન્ટ સ્ટ્રીમ કરો"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-hi/strings.xml b/packages/CompanionDeviceManager/res/values-hi/strings.xml
index 4ceb30c..a3e8bce 100644
--- a/packages/CompanionDeviceManager/res/values-hi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hi/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"कोई <xliff:g id="PROFILE_NAME">%1$s</xliff:g> चुनें, ताकि उसे &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; की मदद से मैनेज किया जा सके"</string>
     <string name="summary_watch" msgid="6566922405914995759">"यह ऐप्लिकेशन, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> को मैनेज करने के लिए ज़रूरी है. <xliff:g id="APP_NAME">%2$s</xliff:g> को डिवाइस की जानकारी सिंक करने की अनुमति होगी. जैसे, कॉल करने वाले व्यक्ति का नाम. इसे आपकी सूचनाओं पर कार्रवाई करने के साथ-साथ आपके फ़ोन, एसएमएस, संपर्कों, कैलेंडर, कॉल लॉग, और आस-पास मौजूद डिवाइसों को ऐक्सेस करने की अनुमति भी होगी."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"यह ऐप्लिकेशन, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> को मैनेज करने के लिए ज़रूरी है. <xliff:g id="APP_NAME">%2$s</xliff:g> को डिवाइस की जानकारी सिंक करने की अनुमति होगी. जैसे, कॉल करने वाले व्यक्ति का नाम. ऐप्लिकेशन इन अनुमतियों का भी इस्तेमाल कर पाएगा:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"चश्मा"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"यह ऐप्लिकेशन, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> को मैनेज करने के लिए ज़रूरी है. <xliff:g id="APP_NAME">%2$s</xliff:g> को डिवाइस की सूचनाओं पर कार्रवाई करने की अनुमति होगी. इसे आपके फ़ोन, मैसेज, संपर्कों, माइक्रोफ़ोन, और आस-पास मौजूद डिवाइसों को ऐक्सेस करने की अनुमति भी होगी."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"यह ऐप्लिकेशन, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> को मैनेज करने के लिए ज़रूरी है. <xliff:g id="APP_NAME">%2$s</xliff:g>, इन अनुमतियों का इस्तेमाल कर पाएगा:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; को अपने फ़ोन से यह जानकारी ऐक्सेस करने की अनुमति दें"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"क्रॉस-डिवाइस से जुड़ी सेवाएं"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपके <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> की ओर से, आपके डिवाइसों के बीच ऐप्लिकेशन को स्ट्रीम करने की अनुमति मांग रहा है"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play services"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपके <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> की ओर से, फ़ोन में मौजूद फ़ोटो, मीडिया, और सूचनाओं को ऐक्सेस करने की अनुमति मांग रहा है"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; को अपने फ़ोन से यह कार्रवाई करने की अनुमति दें"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"क्रॉस-डिवाइस से जुड़ी सेवाएं"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपके <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> की ओर से, कॉन्टेंट को आस-पास मौजूद डिवाइसों पर स्ट्रीम करने की अनुमति मांग रहा है"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"डिवाइस"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"यह ऐप्लिकेशन, आपके फ़ोन और <xliff:g id="DEVICE_NAME">%1$s</xliff:g> के बीच जानकारी सिंक कर सकता है. जैसे, कॉल करने वाले व्यक्ति का नाम."</string>
     <string name="summary_generic" msgid="4988130802522924650">"यह ऐप्लिकेशन, आपके फ़ोन और चुने हुए डिवाइस के बीच जानकारी सिंक कर सकता है. जैसे, कॉल करने वाले व्यक्ति का नाम."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"फ़ोटो और मीडिया"</string>
     <string name="permission_notification" msgid="693762568127741203">"सूचनाएं"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"ऐप्लिकेशन"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"आस-पास के डिवाइस पर स्ट्रीमिंग"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"माइक्रोफ़ोन का इस्तेमाल करके ऑडियो रिकॉर्ड किया जा सकता है"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"आपको आस-पास मौजूद डिवाइसों को खोजने, उनसे कनेक्ट करने, और उनकी जगह की जानकारी का पता लगाने की अनुमति है"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"इससे सभी सूचनाएं देखी जा सकती हैं. इनमें संपर्क, मैसेज, और फ़ोटो जैसी जानकारी शामिल होती है"</string>
     <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="5776807830582725074">"कॉन्टेंट को आस-पास मौजूद डिवाइस पर स्ट्रीम करने की अनुमति"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-hr/strings.xml b/packages/CompanionDeviceManager/res/values-hr/strings.xml
index c901d70..f1672b9 100644
--- a/packages/CompanionDeviceManager/res/values-hr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hr/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Odaberite <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kojim će upravljati aplikacija &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Aplikacija je potrebna za upravljanje vašim uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacija <xliff:g id="APP_NAME">%2$s</xliff:g> moći će sinkronizirati podatke, primjerice ime pozivatelja, stupati u interakciju s vašim obavijestima i pristupati vašim dopuštenjima za telefon, SMS-ove, kontakte, kalendar, zapisnike poziva i uređaje u blizini."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Aplikacija je potrebna za upravljanje vašim uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacija <xliff:g id="APP_NAME">%2$s</xliff:g> moći će sinkronizirati podatke, primjerice ime pozivatelja i pristupati sljedećim dopuštenjima:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"naočale"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Ta je aplikacija potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacija <xliff:g id="APP_NAME">%2$s</xliff:g> moći će stupati u interakciju s vašim obavijestima i pristupati vašim dopuštenjima za telefon, SMS-ove, kontakte, mikrofon i uređaje u blizini."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacija <xliff:g id="APP_NAME">%2$s</xliff:g> moći će stupati u interakciju s ovim dopuštenjima:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Omogućite aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; da pristupa informacijama s vašeg telefona"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Usluge na različitim uređajima"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> zahtijeva dopuštenje u ime vašeg uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> za emitiranje aplikacija između vaših uređaja"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Usluge za Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> zahtijeva dopuštenje u ime vašeg uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> za pristup fotografijama, medijskim sadržajima i obavijestima na telefonu"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Omogućite aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; da izvede tu radnju na vašem telefonu"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Usluge na različitim uređajima"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> zahtijeva dopuštenje u ime vašeg uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> za streamanje sadržaja na uređaje u blizini"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Ta će aplikacija moći sinkronizirati podatke između vašeg telefona i uređaja <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, primjerice ime pozivatelja."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Ta će aplikacija moći sinkronizirati podatke između vašeg telefona i odabranog uređaja, primjerice ime pozivatelja."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Fotografije i mediji"</string>
     <string name="permission_notification" msgid="693762568127741203">"Obavijesti"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacije"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streamanje uređaja u blizini"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Može snimiti zvuk pomoću mikrofona"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Streamanje sadržaja na uređaj u blizini"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-hu/strings.xml b/packages/CompanionDeviceManager/res/values-hu/strings.xml
index 8151038..74757f9 100644
--- a/packages/CompanionDeviceManager/res/values-hu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hu/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"A(z) &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; alkalmazással kezelni kívánt <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kiválasztása"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Az alkalmazásra szükség van a következő eszköz kezeléséhez: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A(z) <xliff:g id="APP_NAME">%2$s</xliff:g> képes lesz szinkronizálni információkat (például a hívó fél nevét), műveleteket végezhet majd az értesítésekkel, és hozzáférhet majd a Telefon, az SMS, a Névjegyek, a Naptár, a Hívásnaplók és a Közeli eszközök engedélyekhez."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Az alkalmazásra szükség van a következő eszköz kezeléséhez: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A(z) <xliff:g id="APP_NAME">%2$s</xliff:g> képes lesz szinkronizálni információkat (például a hívó fél nevét), és hozzáférhet majd ezekhez az engedélyekhez:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"szemüveg"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Erre az alkalmazásra szükség van a következő eszköz kezeléséhez: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A(z) <xliff:g id="APP_NAME">%2$s</xliff:g> műveleteket végezhet majd az értesítésekkel, és hozzáférhet majd a Telefon, az SMS, a Névjegyek, a Mikrofon és a Közeli eszközök engedélyekhez."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Az alkalmazásra szükség van a következő eszköz kezeléséhez: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A(z) <xliff:g id="APP_NAME">%2$s</xliff:g> műveleteket végezhet majd ezekkel az engedélyekkel:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Engedélyezi a(z) „<xliff:g id="APP_NAME">%1$s</xliff:g>” alkalmazás számára az információhoz való hozzáférést a telefonról"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Többeszközös szolgáltatások"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> engedélyt kér a(z) <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nevében az alkalmazások eszközök közötti streameléséhez"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play-szolgáltatások"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> engedélyt kér a(z) <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nevében a telefonon tárolt fotókhoz, médiatartalmakhoz és értesítésekhez való hozzáféréshez"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Engedélyezi a(z) &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; alkalmazás számára ennek a műveletnek az elvégzését a telefonjáról."</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Többeszközös szolgáltatások"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> engedélyt kér a(z) <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nevében a közeli eszközökre való streameléséhez."</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"eszköz"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Ez az alkalmazás képes lesz szinkronizálni az olyan információkat a telefon és a(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> eszköz között, mint például a hívó fél neve."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Ez az alkalmazás képes lesz szinkronizálni az olyan információkat a telefon és a kiválasztott eszköz között, mint például a hívó fél neve."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Fotók és médiatartalmak"</string>
     <string name="permission_notification" msgid="693762568127741203">"Értesítések"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Alkalmazások"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streamelés közeli eszközökre"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Hangfelvételt készíthet a mikrofon használatával."</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Tartalmat streamelhet közeli eszközökre."</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-hy/strings.xml b/packages/CompanionDeviceManager/res/values-hy/strings.xml
index 719496c..cedc6fc 100644
--- a/packages/CompanionDeviceManager/res/values-hy/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hy/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Ընտրեք <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ը, որը պետք է կառավարվի &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; հավելվածի կողմից"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Հավելվածն անհրաժեշտ է ձեր <xliff:g id="DEVICE_NAME">%1$s</xliff:g> սարքը կառավարելու համար։ <xliff:g id="APP_NAME">%2$s</xliff:g> հավելվածը կկարողանա համաժամացնել տվյալները, օր․՝ զանգողի անունը, փոխազդել ձեր ծանուցումների հետ և կստանա «Հեռախոս», «SMS», «Կոնտակտներ», «Օրացույց», «Կանչերի ցուցակ» և «Մոտակա սարքեր» թույլտվությունները։"</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Հավելվածն անհրաժեշտ է ձեր <xliff:g id="DEVICE_NAME">%1$s</xliff:g> սարքը կառավարելու համար։ <xliff:g id="APP_NAME">%2$s</xliff:g> հավելվածը կկարողանա համաժամացնել տվյալները, օր․՝ զանգողի անունը, և կստանա հետևյալ թույլտվությունները․"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"ակնոց"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Այս հավելվածն անհրաժեշտ է <xliff:g id="DEVICE_NAME">%1$s</xliff:g> սարքը կառավարելու համար։ <xliff:g id="APP_NAME">%2$s</xliff:g> հավելվածը կկարողանա փոխազդել ձեր ծանուցումների հետ և կստանա «Հեռախոս», «SMS», «Կոնտակտներ», «Խոսափող» և «Մոտակա սարքեր» թույլտվությունները։"</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Հավելվածն անհրաժեշտ է <xliff:g id="DEVICE_NAME">%1$s</xliff:g> սարքը կառավարելու համար։ <xliff:g id="APP_NAME">%2$s</xliff:g> հավելվածին կթույլատրվի օգտվել այս թույլտվություններից․"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Թույլատրեք &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; հավելվածին օգտագործել այս տեղեկությունները ձեր հեռախոսից"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Միջսարքային ծառայություններ"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը ձեր <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> սարքի անունից թույլտվություն է խնդրում՝ ձեր սարքերի միջև հավելվածներ հեռարձակելու համար"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play ծառայություններ"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը ձեր <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> սարքի անունից թույլտվություն է խնդրում՝ ձեր հեռախոսի լուսանկարները, մեդիաֆայլերն ու ծանուցումները տեսնելու համար"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Թույլատրել &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; հավելվածին կատարել այս գործողությունը ձեր հեռախոսում"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Միջսարքային ծառայություններ"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը ձեր <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> սարքի անունից թույլտվություն է խնդրում՝ մոտակա սարքերին բովանդակություն հեռարձակելու համար"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"սարք"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Այս հավելվածը կկարողանա համաժամացնել ձեր հեռախոսի և <xliff:g id="DEVICE_NAME">%1$s</xliff:g> սարքի տվյալները, օր․՝ զանգողի անունը։"</string>
     <string name="summary_generic" msgid="4988130802522924650">"Այս հավելվածը կկարողանա համաժամացնել ձեր հեռախոսի և ընտրված սարքի տվյալները, օր․՝ զանգողի անունը։"</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Լուսանկարներ և մուլտիմեդիա"</string>
     <string name="permission_notification" msgid="693762568127741203">"Ծանուցումներ"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Հավելվածներ"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Հեռարձակում մոտակա սարքերին"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Կարող է օգտագործել խոսափողը՝ ձայնագրություններ անելու համար"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Կարող է գտնել և որոշել մոտակա սարքերի մոտավոր դիրքը և միանալ դրանց"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"Կարող է կարդալ բոլոր ծանուցումները, ներառյալ տեղեկությունները, օրինակ՝ կոնտակտները, հաղորդագրությունները և լուսանկարները"</string>
     <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="5776807830582725074">"Հեռարձակել բովանդակություն մոտակա սարքերին"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-in/strings.xml b/packages/CompanionDeviceManager/res/values-in/strings.xml
index 598a0be..5f07125 100644
--- a/packages/CompanionDeviceManager/res/values-in/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-in/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Pilih <xliff:g id="PROFILE_NAME">%1$s</xliff:g> untuk dikelola oleh &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Aplikasi diperlukan untuk mengelola <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> akan diizinkan menyinkronkan informasi, seperti nama pemanggil, berinteraksi dengan notifikasi, dan mengakses izin Telepon, SMS, Kontak, Kalender, Log panggilan, dan Perangkat di sekitar."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Aplikasi diperlukan untuk mengelola <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> akan diizinkan menyinkronkan informasi, seperti nama pemanggil, dan mengakses izin berikut:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"glasses"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Aplikasi ini diperlukan untuk mengelola <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> akan diizinkan berinteraksi dengan notifikasi dan mengakses izin Telepon, SMS, Kontak, Mikrofon, dan Perangkat di sekitar."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Aplikasi diperlukan untuk mengelola <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> akan diizinkan berinteraksi dengan izin ini:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Izinkan &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; untuk mengakses informasi ini dari ponsel Anda"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Layanan lintas perangkat"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta izin atas nama <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> untuk menstreaming aplikasi di antara perangkat Anda"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Layanan Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta izin atas nama <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> untuk mengakses foto, media, dan notifikasi ponsel Anda"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Izinkan &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; melakukan tindakan ini dari ponsel"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Layanan lintas perangkat"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta izin atas nama <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> untuk menstreaming konten ke perangkat di sekitar"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"perangkat"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Aplikasi ini akan dapat menyinkronkan info, seperti nama penelepon, antara ponsel dan <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Aplikasi ini akan dapat menyinkronkan info, seperti nama penelepon, antara ponsel dan perangkat yang dipilih."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Foto dan media"</string>
     <string name="permission_notification" msgid="693762568127741203">"Notifikasi"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikasi"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streaming Perangkat di Sekitar"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Dapat merekam audio menggunakan mikrofon"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Dapat menemukan, menghubungkan, dan menentukan posisi relatif dari perangkat di sekitar"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"Dapat membaca semua notifikasi, termasuk informasi seperti kontak, pesan, dan foto"</string>
     <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="5776807830582725074">"Menstreaming konten ke perangkat di sekitar"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-is/strings.xml b/packages/CompanionDeviceManager/res/values-is/strings.xml
index 6f0b0c3..507abc6 100644
--- a/packages/CompanionDeviceManager/res/values-is/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-is/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Velja <xliff:g id="PROFILE_NAME">%1$s</xliff:g> sem &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; á að stjórna"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Forritið er nauðsynlegt til að stjórna <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> fær heimild til að samstilla upplýsingar, t.d. nafn þess sem hringir, og bregðast við tilkynningum og fær aðgang að heimildum fyrir síma, SMS, tengiliði, dagatal, símtalaskrár og nálæg tæki."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Forritið er nauðsynlegt til að stjórna <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> fær heimild til að samstilla upplýsingar, t.d. nafn þess sem hringir, og fær aðgang að eftirfarandi heimildum:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"gleraugu"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Þetta forrit er nauðsynlegt til að hafa umsjón með <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> fær heimild til að bregðast við tilkynningum og fær aðgang að heimildum fyrir síma, SMS, tengiliði, hljóðnema og nálæg tæki."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Forritið er nauðsynlegt til að stjórna <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> fær aðgang að eftirfarandi heimildum:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Veita &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; aðgang að þessum upplýsingum úr símanum þínum"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Þjónustur á milli tækja"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> sendir beiðni um heimild til straumspilunar forrita á milli tækjanna þinna fyrir hönd <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Þjónusta Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> sendir beiðni um aðgang að myndum, margmiðlunarefni og tilkynningum símans þíns fyrir hönd <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Leyfa &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; að framkvæma þessa aðgerð í símanum"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Þjónustur á milli tækja"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> biður um heimild fyrir <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> til að streyma efni í nálægum tækjum"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"tæki"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Þetta forrit mun geta samstillt upplýsingar, t.d. nafn þess sem hringir, á milli símans og <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Þetta forrit mun geta samstillt upplýsingar, t.d. nafn þess sem hringir, á milli símans og valins tækis."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Myndir og efni"</string>
     <string name="permission_notification" msgid="693762568127741203">"Tilkynningar"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Forrit"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streymi í nálægum tækjum"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Getur tekið upp hljóð með hljóðnemanum"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Streyma efni í nálægum tækjum"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-it/strings.xml b/packages/CompanionDeviceManager/res/values-it/strings.xml
index 0d2d9ad..4612893 100644
--- a/packages/CompanionDeviceManager/res/values-it/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-it/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Scegli un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> da gestire con &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Questa app è necessaria per gestire <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> potrà sincronizzare informazioni, ad esempio il nome di un chiamante, interagire con le tue notifiche e accedere alle autorizzazioni Telefono, SMS, Contatti, Calendario, Registri chiamate e Dispositivi nelle vicinanze."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Questa app è necessaria per gestire <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> potrà sincronizzare informazioni, ad esempio il nome di un chiamante, e accedere alle seguenti autorizzazioni:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"occhiali"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Questa app è necessaria per gestire <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> potrà interagire con le tue notifiche e accedere alle autorizzazioni Telefono, SMS, Contatti, Microfono e Dispositivi nelle vicinanze."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Questa app è necessaria per gestire <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> potrà interagire con le seguenti autorizzazioni:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Consenti a &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; di accedere a queste informazioni dal tuo telefono"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servizi cross-device"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> richiede per conto del tuo <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> l\'autorizzazione a trasmettere app in streaming tra i dispositivi"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Services"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> richiede per conto del tuo <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> l\'autorizzazione ad accedere a foto, contenuti multimediali e notifiche del telefono"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Consenti all\'app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; di compiere questa azione dal tuo telefono"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Servizi cross-device"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> richiede per conto di <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> l\'autorizzazione a trasmettere contenuti in streaming ai dispositivi nelle vicinanze"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Questa app potrà sincronizzare informazioni, ad esempio il nome di un chiamante, tra il telefono e <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Questa app potrà sincronizzare informazioni, ad esempio il nome di un chiamante, tra il telefono e il dispositivo scelto."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Foto e contenuti multimediali"</string>
     <string name="permission_notification" msgid="693762568127741203">"Notifiche"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"App"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streaming dispos. in vicinanze"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Consente di registrare audio usando il microfono"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Consente di trasmettere contenuti in streaming a un dispositivo nelle vicinanze"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-iw/strings.xml b/packages/CompanionDeviceManager/res/values-iw/strings.xml
index df7ab6d..f080652 100644
--- a/packages/CompanionDeviceManager/res/values-iw/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-iw/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"‏בחירת <xliff:g id="PROFILE_NAME">%1$s</xliff:g> לניהול באמצעות &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"‏האפליקציה הזו נחוצה כדי לנהל את <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. האפליקציה <xliff:g id="APP_NAME">%2$s</xliff:g> תוכל לסנכרן מידע, כמו השם של מישהו שמתקשר, לבצע פעולות בהתראות ולקבל הרשאות גישה לטלפון, ל-SMS לאנשי הקשר, למיקרופון ולמכשירים בקרבת מקום."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"האפליקציה הזו נחוצה כדי לנהל את <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. האפליקציה <xliff:g id="APP_NAME">%2$s</xliff:g> תוכל לסנכרן מידע, כמו השם של מישהו שמתקשר, ולקיים אינטראקציה עם ההרשאות הבאות:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"משקפיים"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"‏האפליקציה הזו נחוצה כדי לנהל את <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. האפליקציה <xliff:g id="APP_NAME">%2$s</xliff:g> תוכל לבצע פעולות בהתראות ותקבל הרשאות גישה לטלפון, ל-SMS לאנשי הקשר, למיקרופון ולמכשירים בקרבת מקום."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"האפליקציה הזו נחוצה כדי לנהל את <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. האפליקציה <xliff:g id="APP_NAME">%2$s</xliff:g> תוכל לקיים אינטראקציה עם ההרשאות הבאות:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"‏מתן אישור לאפליקציה &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; לגשת למידע הזה מהטלפון שלך"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"שירותים למספר מכשירים"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> מבקשת הרשאה עבור מכשיר <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> כדי לשדר אפליקציות בין המכשירים שלך"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Services"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> מבקשת הרשאה עבור מכשיר <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> כדי לגשת לתמונות, למדיה ולהתראות בטלפון שלך"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"‏הרשאה לאפליקציה &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; לבצע את הפעולה הזו מהטלפון"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"שירותים למספר מכשירים"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> מבקשת הרשאה עבור מכשיר <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> כדי להעביר תוכן בסטרימינג למכשירים בקרבת מקום."</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"מכשיר"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"האפליקציה הזו תוכל לסנכרן מידע, כמו השם של מישהו שמתקשר, מהטלפון שלך ל-<xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"האפליקציה הזו תוכל לסנכרן מידע, כמו השם של מישהו שמתקשר, מהטלפון שלך למכשיר שבחרת."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"תמונות ומדיה"</string>
     <string name="permission_notification" msgid="693762568127741203">"התראות"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"אפליקציות"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"סטרימינג למכשירים בקרבת מקום"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"הרשאה להשתמש במיקרופון כדי להקליט אודיו"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"אפשרות למצוא מכשירים בקרבת מקום, להתחבר אליהם ולהעריך את המיקום היחסי שלהם"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"גישת קריאה לכל ההתראות, כולל מידע כמו אנשי קשר, הודעות ותמונות."</string>
     <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="5776807830582725074">"העברת תוכן בסטרימינג למכשירים בקרבת מקום"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ja/strings.xml b/packages/CompanionDeviceManager/res/values-ja/strings.xml
index 606712b..6275e59 100644
--- a/packages/CompanionDeviceManager/res/values-ja/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ja/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; の管理対象となる<xliff:g id="PROFILE_NAME">%1$s</xliff:g>の選択"</string>
     <string name="summary_watch" msgid="6566922405914995759">"このアプリは <xliff:g id="DEVICE_NAME">%1$s</xliff:g> の管理に必要です。<xliff:g id="APP_NAME">%2$s</xliff:g> は通話相手の名前などの情報を同期したり、デバイスの通知を使用したり、電話、SMS、連絡先、カレンダー、通話履歴、付近のデバイスの権限にアクセスしたりできるようになります。"</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"このアプリは <xliff:g id="DEVICE_NAME">%1$s</xliff:g> の管理に必要です。<xliff:g id="APP_NAME">%2$s</xliff:g> は通話相手の名前などの情報を同期したり、次の権限にアクセスしたりできるようになります。"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"眼鏡"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"このアプリは <xliff:g id="DEVICE_NAME">%1$s</xliff:g> の管理に必要です。<xliff:g id="APP_NAME">%2$s</xliff:g> はデバイスの通知を使用したり、電話、SMS、連絡先、マイク、付近のデバイスの権限にアクセスしたりできるようになります。"</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"このアプリは <xliff:g id="DEVICE_NAME">%1$s</xliff:g> の管理に必要です。<xliff:g id="APP_NAME">%2$s</xliff:g> は次の権限を使用できるようになります。"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"スマートフォンのこの情報へのアクセスを &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; に許可"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"クロスデバイス サービス"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> が <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> に代わってデバイス間でアプリをストリーミングする権限をリクエストしています"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play 開発者サービス"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> が <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> に代わってスマートフォンの写真、メディア、通知にアクセスする権限をリクエストしています"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; に、スマートフォンからこの操作を実行することを許可します"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"クロスデバイス サービス"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> が <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> に代わって付近のデバイスにコンテンツをストリーミングする権限をリクエストしています"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"デバイス"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"このアプリは、あなたのスマートフォンと <xliff:g id="DEVICE_NAME">%1$s</xliff:g> との間で、通話相手の名前などの情報を同期できるようになります。"</string>
     <string name="summary_generic" msgid="4988130802522924650">"このアプリは、あなたのスマートフォンと選択したデバイスとの間で、通話相手の名前などの情報を同期できるようになります。"</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"写真とメディア"</string>
     <string name="permission_notification" msgid="693762568127741203">"通知"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"アプリ"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"付近のデバイスへのストリーミング"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"マイクを使って録音できます"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"付近のデバイスの検出、接続、相対位置の特定を行えます"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"連絡先、メッセージ、写真に関する情報を含め、すべての通知を読み取ることができます"</string>
     <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="5776807830582725074">"付近のデバイスへのコンテンツのストリーミング"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ka/strings.xml b/packages/CompanionDeviceManager/res/values-ka/strings.xml
index 21b703d..0e0d08d 100644
--- a/packages/CompanionDeviceManager/res/values-ka/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ka/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"აირჩიეთ <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, რომელიც უნდა მართოს &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;-მა"</string>
     <string name="summary_watch" msgid="6566922405914995759">"ეს აპი საჭიროა თქვენი <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-ის სამართავად. <xliff:g id="APP_NAME">%2$s</xliff:g>-ს ექნება უფლება, მოახდინოს ისეთი ინფორმაციის სინქრონიზაცია, როგორიც იმ ადამიანის სახელია, რომელიც რეკავს, მოახდინოს ინტერაქცია თქვენს შეტყობინებებთან და ჰქონდეს წვდომა თქვენს ტელეფონზე, SMS-ებზე, კონტაქტებზე, კალენდარზე, ზარების ჟურნალებზე და ახლომახლო მოწყობილობების ნებართვებზე."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"ეს აპი საჭიროა თქვენი <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-ის სამართავად. <xliff:g id="APP_NAME">%2$s</xliff:g>-ს ექნება უფლება, მოახდინოს ისეთი ინფორმციის სინქრონიზაცია, როგორიც იმ ადამიანის სახელია, რომელიც რეკავს, და ჰქონდეს წვდომა შემდეგ ნებართვებზე:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"სათვალე"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"ეს აპი საჭიროა თქვენი <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-ის სამართავად. <xliff:g id="APP_NAME">%2$s</xliff:g> შეძლებს თქვენს შეტყობინებებთან ინტერაქციას და თქვენს ტელეფონზე, SMS-ებზე, კონტაქტებზე, მიკროფონსა და ახლომახლო მოწყობილობების ნებართვებზე წვდომას."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"ეს აპი საჭიროა <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-ის სამართავად. <xliff:g id="APP_NAME">%2$s</xliff:g> შეძლებს ინტერაქციას შემდეგი ნებართვებით:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"ნება დართეთ, რომ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; აპს ჰქონდეს ამ ინფორმაციაზე წვდომა თქვენი ტელეფონიდან"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"მოწყობილობათშორისი სერვისები"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> ითხოვს უფლებას თქვენი <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-ის სახელით, რომ მოწყობილობებს შორის აპების სტრიმინგი შეძლოს"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play services"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> ითხოვს უფლებას თქვენი <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-ის სახელით, რომ წვდომა ჰქონდეს თქვენი ტელეფონის ფოტოებზე, მედიასა და შეტყობინებებზე"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"ნება მიეცით <xliff:g id="APP_NAME">%1$s</xliff:g> თქვენი ტელეფონიდან ამ მოქმედების შესასრულებლად"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"მოწყობილობათშორისი სერვისები"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> ითხოვს ნებართვას თქვენი სახელით<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> კონტენტის სტრიმინგისთვის ახლომდებარე მოწყობილობებზე"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"მოწყობილობა"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"ეს აპი შეძლებს, მოახდინოს ისეთი ინფორმაციის სინქრონიზაცია, როგორიც იმ ადამიანის სახელია, რომელიც რეკავს, თქვენს ტელეფონსა და <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-ს შორის."</string>
     <string name="summary_generic" msgid="4988130802522924650">"ეს აპი შეძლებს, მოახდინოს ისეთი ინფორმაციის სინქრონიზაცია, როგორიც იმ ადამიანის სახელია, რომელიც რეკავს, თქვენს ტელეფონსა და არჩეულ მოწყობილობას შორის."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"ფოტოები და მედია"</string>
     <string name="permission_notification" msgid="693762568127741203">"შეტყობინებები"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"აპები"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"ახლომდებარე მოწყობილობის სტრიმინგი"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"შეუძლია აუდიოს ჩაწერა მიკროფონის გამოყენებით"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"შეძლოს ახლომახლო მოწყობილობების აღმოჩენა, მათთან დაკავშირება და მათი შედარებითი პოზიციის დადგენა"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"შეუძლია წაიკითხოს ყველა შეტყობინება, მათ შორის ისეთი ინფორმაცია, როგორიცაა კონტაქტები, ტექსტური შეტყობინებები და ფოტოები"</string>
     <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="5776807830582725074">"კონტენტის სტრიმინგი ახლომდებარე მოწყობილობაზე"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-kk/strings.xml b/packages/CompanionDeviceManager/res/values-kk/strings.xml
index c6016cb..e857852 100644
--- a/packages/CompanionDeviceManager/res/values-kk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-kk/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; арқылы басқарылатын <xliff:g id="PROFILE_NAME">%1$s</xliff:g> құрылғысын таңдаңыз"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Қолданба <xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысын басқару үшін қажет. <xliff:g id="APP_NAME">%2$s</xliff:g> қолданбасына қоңырау шалушының аты сияқты деректі синхрондау, хабарландыруларды оқу, телефон, SMS, контактілер, күнтізбе, қоңырау журналдары қолданбаларын және маңайдағы құрылғыларды пайдалану рұқсаттары беріледі."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Қолданба <xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысын басқару үшін қажет. <xliff:g id="APP_NAME">%2$s</xliff:g> қолданбасына деректі (мысалы, қоңырау шалушының аты) синхрондауға және мына рұқсаттарды пайдалануға рұқсат беріледі:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"көзілдірік"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Бұл қолданба <xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысын басқару үшін қажет. <xliff:g id="APP_NAME">%2$s</xliff:g> қолданбасына хабарландыруларды оқуға, телефонды, хабарларды, контактілерді, микрофон мен маңайдағы құрылғыларды пайдалануға рұқсат беріледі."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Қолданба <xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысын басқару үшін қажет. <xliff:g id="APP_NAME">%2$s</xliff:g> қолданбасына осы рұқсаттар беріледі:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; қолданбасына телефоныңыздағы осы ақпаратты пайдалануға рұқсат беріңіз."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Аралық құрылғы қызметтері"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> атынан құрылғылар арасында қолданбалар трансляциялау үшін рұқсат сұрайды."</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play қызметтері"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> атынан телефондағы фотосуреттерді, медиафайлдар мен хабарландыруларды пайдалану үшін рұқсат сұрайды."</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; қолданбасына осы әрекетті телефоныңыздан орындауға рұқсат беріңіз."</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Аралық құрылғы қызметтері"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы маңайдағы құрылғыларға <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> атынан контент трансляциялау үшін рұқсат сұрайды."</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"құрылғы"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Бұл қолданба телефон мен <xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысы арасында деректі (мысалы, қоңырау шалушының атын) синхрондайды."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Бұл қолданба телефон мен таңдалған құрылғы арасында деректі (мысалы, қоңырау шалушының атын) синхрондайды."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Фотосуреттер мен медиафайлдар"</string>
     <string name="permission_notification" msgid="693762568127741203">"Хабарландырулар"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Қолданбалар"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Маңайдағы құрылғыға трансляция"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Микрофон пайдалану арқылы аудио жаза алады."</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Маңайдағы құрылғыларды тауып, олармен байланысып, бір-біріне қатысты локациясын анықтайды."</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"Барлық хабарландыруды, соның ішінде контактілер, хабарлар және фотосуреттер сияқты ақпаратты оқи алады."</string>
     <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="5776807830582725074">"Маңайдағы құрылғыға контент трансляциялайды."</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-km/strings.xml b/packages/CompanionDeviceManager/res/values-km/strings.xml
index 9619d70..c4901d7 100644
--- a/packages/CompanionDeviceManager/res/values-km/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-km/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"ជ្រើសរើស <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ដើម្បីឱ្យស្ថិតក្រោម​ការគ្រប់គ្រងរបស់ &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"ត្រូវការកម្មវិធីនេះ ដើម្បីគ្រប់គ្រង <xliff:g id="DEVICE_NAME">%1$s</xliff:g> របស់អ្នក។ <xliff:g id="APP_NAME">%2$s</xliff:g> នឹងត្រូវបានអនុញ្ញាតឱ្យ​ធ្វើសមកាលកម្មព័ត៌មានដូចជា ឈ្មោះមនុស្សដែលហៅទូរសព្ទ ធ្វើអន្តរកម្មជាមួយ​ការជូនដំណឹងរបស់អ្នក និងចូលប្រើការអនុញ្ញាតទូរសព្ទ, SMS, ទំនាក់ទំនង, ប្រតិទិន, កំណត់ហេតុហៅទូរសព្ទ និងឧបករណ៍នៅជិតរបស់អ្នក។"</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"ត្រូវការកម្មវិធីនេះ ដើម្បីគ្រប់គ្រង <xliff:g id="DEVICE_NAME">%1$s</xliff:g> របស់អ្នក។ <xliff:g id="APP_NAME">%2$s</xliff:g> នឹងត្រូវបានអនុញ្ញាតឱ្យ​ធ្វើសមកាលកម្មព័ត៌មានដូចជា ឈ្មោះមនុស្សដែលហៅទូរសព្ទ និងចូលប្រើការអនុញ្ញាតទាំងនេះ៖"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"វ៉ែនតា"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"ត្រូវការកម្មវិធីនេះ ដើម្បីគ្រប់គ្រង <xliff:g id="DEVICE_NAME">%1$s</xliff:g>។ <xliff:g id="APP_NAME">%2$s</xliff:g> នឹងត្រូវបានអនុញ្ញាតឱ្យ​ធ្វើអន្តរកម្មជាមួយ​ការជូនដំណឹងរបស់អ្នក និងចូលប្រើការអនុញ្ញាត​របស់ទូរសព្ទ, SMS, ទំនាក់ទំនង, មីក្រូហ្វូន និងឧបករណ៍នៅជិត​របស់អ្នក។"</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"ត្រូវការកម្មវិធីនេះ ដើម្បីគ្រប់គ្រង <xliff:g id="DEVICE_NAME">%1$s</xliff:g>។ <xliff:g id="APP_NAME">%2$s</xliff:g> នឹងត្រូវបានអនុញ្ញាតឱ្យធ្វើអន្តរកម្មជាមួយការអនុញ្ញាតទាំងនេះ៖"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"អនុញ្ញាតឱ្យ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ចូលប្រើព័ត៌មាននេះពីទូរសព្ទរបស់អ្នក"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"សេវាកម្មឆ្លងកាត់ឧបករណ៍"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងស្នើសុំការអនុញ្ញាតជំនួសឱ្យ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> របស់អ្នក ដើម្បីបញ្ចាំងកម្មវិធីរវាងឧបករណ៍របស់អ្នក"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"សេវាកម្ម Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងស្នើសុំការអនុញ្ញាតជំនួសឱ្យ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> របស់អ្នក ដើម្បីចូលប្រើរូបថត មេឌៀ និងការជូនដំណឹងរបស់ទូរសព្ទអ្នក"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"អនុញ្ញាតឱ្យ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ធ្វើសកម្មភាពនេះពីទូរសព្ទរបស់អ្នក"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"សេវាកម្មឆ្លងកាត់ឧបករណ៍"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងស្នើសុំការអនុញ្ញាតជំនួសឱ្យ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> របស់អ្នក ដើម្បីផ្សាយខ្លឹមសារទៅឧបករណ៍នៅជិត"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"ឧបករណ៍"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"កម្មវិធីនឹងអាច​ធ្វើសមកាលកម្មព័ត៌មាន​ដូចជា ឈ្មោះមនុស្សដែលហៅទូរសព្ទ​រវាងទូរសព្ទ និង <xliff:g id="DEVICE_NAME">%1$s</xliff:g> របស់អ្នក។"</string>
     <string name="summary_generic" msgid="4988130802522924650">"កម្មវិធីនេះនឹងអាច​ធ្វើសមកាលកម្មព័ត៌មាន​ដូចជា ឈ្មោះមនុស្សដែលហៅទូរសព្ទ​រវាងឧបករណ៍ដែលបានជ្រើសរើស និងទូរសព្ទរបស់អ្នក។"</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"រូបថត និងមេឌៀ"</string>
     <string name="permission_notification" msgid="693762568127741203">"ការ​ជូនដំណឹង"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"កម្មវិធី"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"ការផ្សាយទៅឧបករណ៍នៅជិត"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"អាចថតសំឡេងដោយប្រើមីក្រូហ្វូន"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"អាចស្វែងរក ភ្ជាប់ទៅ និងកំណត់​ចម្ងាយពាក់ព័ន្ធ​រវាងឧបករណ៍​ដែលនៅជិត"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"អាចអាន​ការជូនដំណឹង​ទាំងអស់ រួមទាំង​ព័ត៌មាន​ដូចជាទំនាក់ទំនង សារ និងរូបថត"</string>
     <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="5776807830582725074">"ផ្សាយខ្លឹមសារទៅឧបករណ៍នៅជិត"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-kn/strings.xml b/packages/CompanionDeviceManager/res/values-kn/strings.xml
index 0bc7175..6f93275 100644
--- a/packages/CompanionDeviceManager/res/values-kn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-kn/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ಮೂಲಕ ನಿರ್ವಹಿಸಬೇಕಾದ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
     <string name="summary_watch" msgid="6566922405914995759">"ನಿಮ್ಮ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಅನ್ನು ನಿರ್ವಹಿಸಲು ಆ್ಯಪ್‌ನ ಅಗತ್ಯವಿದೆ. ಕರೆ ಮಾಡುವವರ ಹೆಸರು, ನಿಮ್ಮ ಅಧಿಸೂಚನೆಗಳೊಂದಿಗೆ ಸಂವಹನ ನಡೆಸಲು ಮತ್ತು ಫೋನ್, SMS, ಸಂಪರ್ಕಗಳು, ಕ್ಯಾಲೆಂಡರ್, ಕರೆ ಲಾಗ್‌ಗಳು ಮತ್ತು ಸಮೀಪದಲ್ಲಿರುವ ಸಾಧನಗಳ ದೃಢೀಕರಣಗಳಂತಹ ಮಾಹಿತಿಯನ್ನು ಸಿಂಕ್ ಮಾಡಲು <xliff:g id="APP_NAME">%2$s</xliff:g> ಗೆ ಸಾಧ್ಯವಾಗುತ್ತದೆ."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"ನಿಮ್ಮ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಅನ್ನು ನಿರ್ವಹಿಸಲು ಆ್ಯಪ್‌ನ ಅಗತ್ಯವಿದೆ. ಕರೆ ಮಾಡುವವರ ಹೆಸರಿನಂತಹ ಮಾಹಿತಿಯನ್ನು ಸಿಂಕ್ ಮಾಡಲು ಮತ್ತು ಈ ಅನುಮತಿಗಳನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು <xliff:g id="APP_NAME">%2$s</xliff:g> ಗೆ ಅನುಮತಿಸಲಾಗುತ್ತದೆ:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"ಗ್ಲಾಸ್‌ಗಳು"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಅನ್ನು ನಿರ್ವಹಿಸಲು ಈ ಆ್ಯಪ್‌ನ ಅಗತ್ಯವಿದೆ. ನಿಮ್ಮ ಫೋನ್, SMS, ಸಂಪರ್ಕಗಳು, ಮೈಕ್ರೊಫೋನ್ ಮತ್ತು ಸಮೀಪದಲ್ಲಿರುವ ಸಾಧನಗಳ ಅನುಮತಿಗಳನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು ಹಾಗೂ ನಿಮ್ಮ ಅಧಿಸೂಚನೆಗಳೊಂದಿಗೆ ಸಂವಹನ ನಡೆಸಲು <xliff:g id="APP_NAME">%2$s</xliff:g> ಗೆ ಅನುಮತಿಸಲಾಗುತ್ತದೆ."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಅನ್ನು ನಿರ್ವಹಿಸಲು ಆ್ಯಪ್‌ನ ಅಗತ್ಯವಿದೆ. <xliff:g id="APP_NAME">%2$s</xliff:g> ಗೆ ಈ ಅನುಮತಿಗಳ ಜೊತೆಗೆ ಸಂವಹನ ನಡೆಸಲು ಅನುಮತಿಸಲಾಗುತ್ತದೆ:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"ನಿಮ್ಮ ಫೋನ್ ಮೂಲಕ ಈ ಮಾಹಿತಿಯನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ಗೆ ಅನುಮತಿಸಿ"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"ಕ್ರಾಸ್-ಡಿವೈಸ್ ಸೇವೆಗಳು"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"ನಿಮ್ಮ ಸಾಧನಗಳ ನಡುವೆ ಆ್ಯಪ್‌ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು ನಿಮ್ಮ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ನ ಪರವಾಗಿ <xliff:g id="APP_NAME">%1$s</xliff:g> ಅನುಮತಿಯನ್ನು ವಿನಂತಿಸಿಕೊಳ್ಳುತ್ತಿದೆ"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play ಸೇವೆಗಳು"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"ನಿಮ್ಮ ಫೋನ್‌ನ ಫೋಟೋಗಳು, ಮೀಡಿಯಾ ಮತ್ತು ಅಧಿಸೂಚನೆಗಳನ್ನು ಪ್ರವೇಶಿಸಲು ನಿಮ್ಮ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ನ ಪರವಾಗಿ <xliff:g id="APP_NAME">%1$s</xliff:g> ಅನುಮತಿಯನ್ನು ವಿನಂತಿಸಿಕೊಳ್ಳುತ್ತಿದೆ"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"ಈ ಕ್ರಿಯೆಯನ್ನು ನಿಮ್ಮ ಫೋನ್‌ನಿಂದ ನಿರ್ವಹಿಸಲು &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ಗೆ ಅನುಮತಿಸಿ"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"ಕ್ರಾಸ್-ಡಿವೈಸ್ ಸೇವೆಗಳು"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"ಕಂಟೆಂಟ್ ಅನ್ನು ಸಮೀಪದಲ್ಲಿರುವ ಸಾಧನಗಳಿಗೆ ಸ್ಟ್ರೀಮ್ ಮಾಡಲು ನಿಮ್ಮ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ನ ಪರವಾಗಿ <xliff:g id="APP_NAME">%1$s</xliff:g> ಅನುಮತಿಗಾಗಿ ವಿನಂತಿಸುತ್ತಿದೆ"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"ಸಾಧನ"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"ಈ ಆ್ಯಪ್, ಮೊಬೈಲ್ ಫೋನ್ ಮತ್ತು <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಸಾಧನದ ನಡುವೆ ಕರೆ ಮಾಡುವವರ ಹೆಸರಿನಂತಹ ಮಾಹಿತಿಯನ್ನು ಸಿಂಕ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗುತ್ತದೆ."</string>
     <string name="summary_generic" msgid="4988130802522924650">"ಈ ಆ್ಯಪ್, ಮೊಬೈಲ್ ಫೋನ್ ಮತ್ತು ಆಯ್ಕೆಮಾಡಿದ ಸಾಧನದ ನಡುವೆ ಕರೆ ಮಾಡುವವರ ಹೆಸರಿನಂತಹ ಮಾಹಿತಿಯನ್ನು ಸಿಂಕ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗುತ್ತದೆ."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"ಫೋಟೋಗಳು ಮತ್ತು ಮಾಧ್ಯಮ"</string>
     <string name="permission_notification" msgid="693762568127741203">"ಅಧಿಸೂಚನೆಗಳು"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"ಆ್ಯಪ್‌ಗಳು"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"ಸಮೀಪದಲ್ಲಿರುವ ಸಾಧನದ ಸ್ಟ್ರೀಮಿಂಗ್"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"ಮೈಕ್ರೊಫೋನ್ ಅನ್ನು ಬಳಸಿಕೊಂಡು ಆಡಿಯೋವನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಬಹುದು"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"ಸಮೀಪದಲ್ಲಿರುವ ಸಾಧನಗಳನ್ನು ಹುಡುಕಬಹುದು, ಅವುಗಳಿಗೆ ಕನೆಕ್ಟ್ ಆಗಬಹುದು ಮತ್ತು ಅವುಗಳ ಸಂಬಂಧಿತ ಸ್ಥಾನವನ್ನು ನಿರ್ಧರಿಸಬಹುದು"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"ಸಂಪರ್ಕಗಳು, ಸಂದೇಶಗಳು ಮತ್ತು ಫೋಟೋಗಳಂತಹ ಮಾಹಿತಿಯನ್ನು ಒಳಗೊಂಡಂತೆ ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳನ್ನು ಓದಬಹುದು"</string>
     <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="5776807830582725074">"ಕಂಟೆಂಟ್ ಅನ್ನು ಸಮೀಪದಲ್ಲಿರುವ ಸಾಧನಕ್ಕೆ ಸ್ಟ್ರೀಮ್ ಮಾಡಿ"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ko/strings.xml b/packages/CompanionDeviceManager/res/values-ko/strings.xml
index 91e9637..38b3df1 100644
--- a/packages/CompanionDeviceManager/res/values-ko/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ko/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;에서 관리할 <xliff:g id="PROFILE_NAME">%1$s</xliff:g>을(를) 선택"</string>
     <string name="summary_watch" msgid="6566922405914995759">"이 앱은 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 기기를 관리하는 데 필요합니다. <xliff:g id="APP_NAME">%2$s</xliff:g>에서 전화를 건 사람 이름과 같은 정보를 동기화하며 알림과 상호작용하고 내 전화, SMS, 연락처, Calendar, 통화 기록, 근처 기기에 액세스할 수 있게 됩니다."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"이 앱은 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 기기를 관리하는 데 필요합니다. <xliff:g id="APP_NAME">%2$s</xliff:g>에서 전화를 건 사람 이름과 같은 정보를 동기화하며 이러한 권한에 액세스할 수 있게 됩니다."</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"안경"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"이 앱은 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 기기를 관리하는 데 필요합니다. <xliff:g id="APP_NAME">%2$s</xliff:g>에서 알림과 상호작용하고 내 전화, SMS, 연락처, 마이크, 근처 기기에 대한 권한을 갖게 됩니다."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"이 앱은 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 기기를 관리하는 데 필요합니다. <xliff:g id="APP_NAME">%2$s</xliff:g>에서 다음 권한과 상호작용할 수 있습니다."</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;이 휴대전화의 이 정보에 액세스하도록 허용합니다."</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"교차 기기 서비스"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> 대신 기기 간에 앱을 스트리밍할 수 있는 권한을 요청하고 있습니다."</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play 서비스"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> 대신 휴대전화의 사진, 미디어, 알림에 액세스할 수 있는 권한을 요청하고 있습니다."</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; 앱이 휴대전화에서 이 작업을 수행하도록 허용합니다."</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"교차 기기 서비스"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> 대신 근처 기기로 콘텐츠를 스트리밍할 수 있는 권한을 요청하고 있습니다."</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"기기"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"이 앱이 전화를 건 사람 이름과 같은 정보를 휴대전화와 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 간에 동기화할 수 있습니다."</string>
     <string name="summary_generic" msgid="4988130802522924650">"이 앱이 전화를 건 사람 이름과 같은 정보를 휴대전화와 선택한 기기 간에 동기화할 수 있습니다."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"사진 및 미디어"</string>
     <string name="permission_notification" msgid="693762568127741203">"알림"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"앱"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"근처 기기 스트리밍"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"마이크를 사용하여 오디오를 녹음할 수 있습니다."</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"근처 기기를 찾아 연결하고 기기 간 상대적 위치를 파악할 수 있습니다."</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"연락처, 메시지, 사진 등의 정보를 포함한 모든 알림을 읽을 수 있습니다."</string>
     <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="5776807830582725074">"근처 기기로 콘텐츠를 스트리밍합니다."</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ky/strings.xml b/packages/CompanionDeviceManager/res/values-ky/strings.xml
index 5a30ae1..c40e080 100644
--- a/packages/CompanionDeviceManager/res/values-ky/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ky/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"<xliff:g id="PROFILE_NAME">%1$s</xliff:g> &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; тарабынан башкарылсын"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Бул колдонмо <xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүңүздү тескөө үчүн керек. <xliff:g id="APP_NAME">%2$s</xliff:g> маалыматты шайкештирип, мисалы, билдирмелериңизди көрүп, телефонуңуз, SMS билдирүүлөр, байланыштар, жылнаама, чалуулар тизмеси жана жакын жердеги түзмөктөргө болгон уруксаттарды пайдалана алат."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Бул колдонмо <xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүңүздү тескөө үчүн керек. <xliff:g id="APP_NAME">%2$s</xliff:g> маалыматты шайкештире алат, мисалы, чалып жаткан кишинин атын шайкештирет жана анын төмөнкү уруксаттары болот:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"көз айнектер"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Бул колдонмо <xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүн башкаруу үчүн керек. <xliff:g id="APP_NAME">%2$s</xliff:g> билдирмелериңизди көрүп, телефонуңуз, SMS билдирүүлөр, Байланыштар, Микрофон жана Жакын жердеги түзмөктөргө болгон уруксаттарды пайдалана алат."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Бул колдонмо <xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүн тескөө үчүн керек. <xliff:g id="APP_NAME">%2$s</xliff:g> төмөнкү уруксаттарды пайдалана алат:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; колдонмосуна телефонуңуздагы ушул маалыматты көрүүгө уруксат бериңиз"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Түзмөктөр аралык кызматтар"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> түзмөгүңүздүн атынан түзмөктөрүңүздүн ортосунда колдонмолорду өткөрүүгө уруксат сурап жатат"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play кызматтары"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> түзмөгүңүздүн атынан телефондогу сүрөттөрдү, медиа файлдарды жана билдирмелерди колдонууга уруксат сурап жатат"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; колдонмосуна бул аракетти телефонуңуздан аткарууга уруксат бериңиз"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Түзмөктөр аралык кызматтар"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> түзмөгүңүздүн атынан жакын жердеги түзмөктөрдө контентти алып ойнотууга уруксат сурап жатат"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"түзмөк"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Бул колдонмо маалыматты шайкештире алат, мисалы, чалып жаткан кишинин атын телефон жана <xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгү менен шайкештирет."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Бул колдонмо маалыматты шайкештире алат, мисалы, чалып жаткан кишинин атын телефон жана тандалган түзмөк менен шайкештирет."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Сүрөттөр жана медиафайлдар"</string>
     <string name="permission_notification" msgid="693762568127741203">"Билдирмелер"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Колдонмолор"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Жакын жердеги түзмөктөрдө алып ойнотуу"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Микрофон аркылуу аудио жаздыра алат"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Жакын жердеги түзмөктөрдү таап, аларга туташып, абалын аныктай алат"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"Бардык билдирмелерди, анын ичинде байланыштар, билдирүүлөр жана сүрөттөр сыяктуу маалыматты окуй алат"</string>
     <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="5776807830582725074">"Контентти жакын жердеги түзмөктө алып ойнотуу"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-lo/strings.xml b/packages/CompanionDeviceManager/res/values-lo/strings.xml
index 5787bb1..a7b0cac 100644
--- a/packages/CompanionDeviceManager/res/values-lo/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lo/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"ເລືອກ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ເພື່ອໃຫ້ຖືກຈັດການໂດຍ &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"ຕ້ອງໃຊ້ແອັບດັ່ງກ່າວເພື່ອຈັດການ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ຂອງທ່ານ. <xliff:g id="APP_NAME">%2$s</xliff:g> ຈະໄດ້ຮັບອະນຸຍາດໃຫ້ຊິງ​ຂໍ້​ມູນ​ເຊັ່ນ: ຊື່​ຂອງ​ບາງ​ຄົນ​ທີ່​ກຳ​ລັງ​ໂທ, ໂຕ້​ຕອບ​ກັບການແຈ້ງເຕືອນຂອງທ່ານ ແລະ ເຂົ້າເຖິງການ​ອະ​ນຸ​ຍາດໂທລະສັບ, SMS, ລາຍຊື່ຜູ້ຕິດຕໍ່, ປະ​ຕິ​ທິນ, ບັນ​ທຶກ​ການ​ໂທ ແລະ ອຸປະກອນທີ່ຢູ່ໃກ້ຄຽງຂອງທ່ານ."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"ຕ້ອງໃຊ້ແອັບດັ່ງກ່າວເພື່ອຈັດການ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ຂອງທ່ານ. <xliff:g id="APP_NAME">%2$s</xliff:g> ຈະໄດ້ຮັບອະນຸຍາດໃຫ້ຊິງ​ຂໍ້​ມູນ​ເຊັ່ນ: ຊື່​ຂອງ​ບາງ​ຄົນ​ທີ່​ກຳ​ລັງ​ໂທ ແລະ ເຂົ້າ​ເຖິງ​ການ​ອະ​ນຸ​ຍາດ​ເຫຼົ່າ​ນີ້:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"ແວ່ນຕາ"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"ຕ້ອງໃຊ້ແອັບນີ້ເພື່ອຈັດການ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ຈະໄດ້ຮັບອະນຸຍາດໃຫ້ໂຕ້ຕອບກັບການແຈ້ງເຕືອນຂອງທ່ານ ແລະ ການອະນຸຍາດສິດເຂົ້າເຖິງໂທລະສັບ, SMS, ລາຍຊື່ຜູ້ຕິດຕໍ່, ໄມໂຄຣໂຟນ ແລະ ອຸປະກອນທີ່ຢູ່ໃກ້ຄຽງຂອງທ່ານ."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"ຕ້ອງໃຊ້ແອັບດັ່ງກ່າວເພື່ອຈັດການ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ຈະໄດ້ຮັບອະນຸຍາດໃຫ້ໂຕ້ຕອບກັບການອະນຸຍາດເຫຼົ່ານີ້:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"ອະນຸຍາດ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ໃຫ້ເຂົ້າເຖິງຂໍ້ມູນນີ້ຈາກໂທລະສັບຂອງທ່ານໄດ້"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"ບໍລິການຂ້າມອຸປະກອນ"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງຮ້ອງຂໍການອະນຸຍາດໃນນາມຂອງ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ເພື່ອສະຕຣີມແອັບລະຫວ່າງອຸປະກອນຂອງທ່ານ"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"ບໍລິການ Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງຮ້ອງຂໍການອະນຸຍາດໃນນາມຂອງ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ເພື່ອເຂົ້າເຖິງຮູບພາບ, ມີເດຍ ແລະ ການແຈ້ງເຕືອນຂອງໂທລະສັບທ່ານ"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"ອະນຸຍາດ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ໃຫ້ດຳເນີນການນີ້ຈາກໂທລະສັບຂອງທ່ານ"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"ບໍລິການຂ້າມອຸປະກອນ"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງຮ້ອງຂໍການອະນຸຍາດໃນນາມຂອງ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ຂອງທ່ານເພື່ອສະຕຣີມເນື້ອຫາໄປຫາອຸປະກອນທີ່ຢູ່ໃກ້ຄຽງ"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"ອຸປະກອນ"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"ແອັບ​ນີ້​ຈະ​ສາ​ມາດ​ຊິງ​ຂໍ້​ມູນ​ເຊັ່ນ: ຊື່​ຂອງ​ບາງ​ຄົນ​ທີ່​ກຳ​ລັງ​ໂທ​ຢູ່​ລະ​ຫວ່າງ​ໂທ​ລະ​ສັບ​ຂອງ​ທ່ານ ແລະ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ໄດ້."</string>
     <string name="summary_generic" msgid="4988130802522924650">"ແອັບ​ນີ້​ຈະ​ສາ​ມາດ​ຊິງ​ຂໍ້​ມູນ​ເຊັ່ນ: ຊື່​ຂອງ​ບາງ​ຄົນ​ທີ່​ກຳ​ລັງ​ໂທ​ຢູ່​ລະ​ຫວ່າງ​ໂທ​ລະ​ສັບ​ຂອງ​ທ່ານ ແລະ ອຸ​ປະ​ກອນ​ທີ່​ເລືອກ​ໄດ້."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"ຮູບພາບ ແລະ ມີເດຍ"</string>
     <string name="permission_notification" msgid="693762568127741203">"ການແຈ້ງເຕືອນ"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"ແອັບ"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"ການສະຕຣີມອຸປະກອນທີ່ຢູ່ໃກ້ຄຽງ"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"ສາມາດບັນທຶກສຽງໂດຍນຳໃຊ້ໄມໂຄຣໂຟນໄດ້"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"ສາມາດຊອກຫາ, ເຊື່ອມຕໍ່ ແລະ ລະບຸສະຖານທີ່ທີ່ກ່ຽວຂ້ອງກັນຂອງອຸປະກອນທີ່ຢູ່ໃກ້ຄຽງ"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"ສາມາດອ່ານການແຈ້ງເຕືອນທັງໝົດ, ຮວມທັງຂໍ້ມູນ ເຊັ່ນ: ລາຍຊື່ຜູ້ຕິດຕໍ່, ຂໍ້ຄວາມ ແລະ ຮູບພາບ"</string>
     <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="5776807830582725074">"ສະຕຣີມເນື້ອຫາໄປຫາອຸປະກອນທີ່ຢູ່ໃກ້ຄຽງ"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-lt/strings.xml b/packages/CompanionDeviceManager/res/values-lt/strings.xml
index 77f89ad..d3d8ca9 100644
--- a/packages/CompanionDeviceManager/res/values-lt/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lt/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Jūsų <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, kurį valdys &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; (pasirinkite)"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Programa reikalinga norint tvarkyti jūsų įrenginį „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“. Programai „<xliff:g id="APP_NAME">%2$s</xliff:g>“ bus leidžiama sinchronizuoti tam tikrą informaciją, pvz., skambinančio asmens vardą, sąveikauti su jūsų pranešimais ir pasiekti jūsų leidimus „Telefonas“, „SMS“, „Kontaktai“, „Kalendorius“, „Skambučių žurnalai“ ir „Įrenginiai netoliese“."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Programa reikalinga norint tvarkyti jūsų įrenginį „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“. Programai „<xliff:g id="APP_NAME">%2$s</xliff:g>“ bus leidžiama sinchronizuoti tam tikrą informaciją, pvz., skambinančio asmens vardą, ir pasiekti toliau nurodytus leidimus."</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"akiniai"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Ši programa reikalinga norint tvarkyti įrenginį „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“. Programai „<xliff:g id="APP_NAME">%2$s</xliff:g>“ bus leidžiama sąveikauti su jūsų pranešimais ir pasiekti jūsų leidimus „Telefonas“, „SMS“, „Kontaktai“, „Mikrofonas“ ir „Įrenginiai netoliese“."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Programa reikalinga norint tvarkyti įrenginį „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“. „<xliff:g id="APP_NAME">%2$s</xliff:g>“ bus leidžiama sąveikauti su toliau nurodytais leidimais."</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Leisti &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; pasiekti šią informaciją iš jūsų telefono"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Pasl. keliuose įrenginiuose"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Programa „<xliff:g id="APP_NAME">%1$s</xliff:g>“ prašo leidimo jūsų „<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>“ vardu, kad galėtų srautu perduoti programas iš vieno įrenginio į kitą"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"„Google Play“ paslaugos"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"Programa „<xliff:g id="APP_NAME">%1$s</xliff:g>“ prašo leidimo jūsų „<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>“ vardu, kad galėtų pasiekti telefono nuotraukas, mediją ir pranešimus"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Leisti programai &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; atlikti šį veiksmą iš jūsų telefono"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Keliais įreng. naud. paslaugos"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ prašo leidimo jūsų „<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>“ vardu, kad galėtų srautu perduoti turinį įrenginiams netoliese"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"įrenginys"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Ši programa galės sinchronizuoti tam tikrą informaciją, pvz., skambinančio asmens vardą, su jūsų telefonu ir įrenginiu „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Ši programa galės sinchronizuoti tam tikrą informaciją, pvz., skambinančio asmens vardą, su jūsų telefonu ir pasirinktu įrenginiu."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Nuotraukos ir medija"</string>
     <string name="permission_notification" msgid="693762568127741203">"Pranešimai"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Programos"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Perdav. įrenginiams netoliese"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Naudojant šį mikrofoną negalima įrašyti garso"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Perduokite turinį įrenginiams netoliese"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-lv/strings.xml b/packages/CompanionDeviceManager/res/values-lv/strings.xml
index 7441c0d..8fe14bd4 100644
--- a/packages/CompanionDeviceManager/res/values-lv/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lv/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Profila (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) izvēle, ko pārvaldīt lietotnē &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Šī lietotne ir nepieciešama jūsu ierīces (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) pārvaldībai. <xliff:g id="APP_NAME">%2$s</xliff:g> drīkstēs sinhronizēt informāciju, piemēram, zvanītāja vārdu, mijiedarboties ar jūsu paziņojumiem un piekļūt atļaujām Tālrunis, Īsziņas, Kontaktpersonas, Kalendārs, Zvanu žurnāli un Tuvumā esošas ierīces."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Šī lietotne ir nepieciešama jūsu ierīces (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) pārvaldībai. <xliff:g id="APP_NAME">%2$s</xliff:g> drīkstēs sinhronizēt informāciju, piemēram, zvanītāja vārdu, un piekļūt šīm atļaujām:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"brilles"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Šī lietotne ir nepieciešama šādas ierīces pārvaldībai: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> drīkstēs mijiedarboties ar jūsu paziņojumiem un piekļūt atļaujām Tālrunis, Īsziņas, Kontaktpersonas, Mikrofons un Tuvumā esošas ierīces."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Lietotne ir nepieciešama šādas ierīces pārvaldībai: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Lietotnei <xliff:g id="APP_NAME">%2$s</xliff:g> tiks atļauts mijiedarboties ar šīm atļaujām:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Atļaut lietotnei &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; piekļūt šai informācijai no jūsu tālruņa"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Vairāku ierīču pakalpojumi"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> pieprasa atļauju straumēt lietotnes starp jūsu ierīcēm šīs ierīces vārdā: <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play pakalpojumi"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> pieprasa atļauju piekļūt jūsu tālruņa fotoattēliem, multivides saturam un paziņojumiem šīs ierīces vārdā: <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Atļaut lietotnei &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; veikt šo darbību no jūsu tālruņa"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Vairāku ierīču pakalpojumi"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> pieprasa atļauju straumēt saturu tuvumā esošās ierīcēs šīs ierīces vārdā: <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"ierīce"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Šī lietotne varēs sinhronizēt informāciju, piemēram, zvanītāja vārdu, starp jūsu tālruni un šo ierīci: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Šī lietotne varēs sinhronizēt informāciju, piemēram, zvanītāja vārdu, starp jūsu tālruni un izvēlēto ierīci."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Fotoattēli un multivides faili"</string>
     <string name="permission_notification" msgid="693762568127741203">"Paziņojumi"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Lietotnes"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Straumēšana ierīcēs tuvumā"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Var ierakstīt audio, izmantojot mikrofonu"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Satura straumēšana tuvumā esošā ierīcē"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-mk/strings.xml b/packages/CompanionDeviceManager/res/values-mk/strings.xml
index 455b559..0fc9061 100644
--- a/packages/CompanionDeviceManager/res/values-mk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mk/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Изберете <xliff:g id="PROFILE_NAME">%1$s</xliff:g> со којшто ќе управува &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Апликацијата е потребна за управување со вашиот <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ќе може да ги синхронизира податоците како што се имињата на јавувачите, да остварува интеракција со известувањата и да пристапува до дозволите за „Телефон“, SMS, „Контакти“, „Календар“, „Евиденција на повици“ и „Уреди во близина“."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Апликацијата е потребна за управување со вашиот <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ќе има дозвола да ги синхронизира податоците како што се имињата на јавувачите и да пристапува до следниве дозволи:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"очила"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Апликацијава е потребна за управување со <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ќе може да остварува интеракција со известувањата и да пристапува до дозволите за „Телефон“, SMS, „Контакти“, „Микрофон“ и „Уреди во близина“."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Апликацијата е потребна за управување со <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ќе може да остварува интеракција со следниве дозволи:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Овозможете &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; да пристапува до овие податоци на телефонот"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Повеќенаменски услуги"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> бара дозвола во име на вашиот <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> за да стримува апликации помеѓу вашите уреди"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Услуги на Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> бара дозвола во име на вашиот <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> за да пристапува до фотографиите, аудиовизуелните содржини и известувањата на телефонот"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Дозволете &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; да го извршува ова дејство од телефонот"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Услуги на повеќе уреди"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> бара дозвола во име на вашиот <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> за да стримува содржини на уредите во близина"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"уред"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Оваа апликација ќе може да ги синхронизира податоците како што се имињата на јавувачите помеѓу вашиот телефон и <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Оваа апликација ќе може да ги синхронизира податоците како што се имињата на јавувачите помеѓу вашиот телефон и избраниот уред."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Аудиовизуелни содржини"</string>
     <string name="permission_notification" msgid="693762568127741203">"Известувања"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Апликации"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Стриминг на уреди во близина"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Може да снима аудио со микрофонот"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Може да наоѓа и да се поврзува со уреди во близина и да ја утврдува нивната релативна положба"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"може да ги чита сите известувања, вклучително и податоци како контакти, пораки и фотографии"</string>
     <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="5776807830582725074">"Стримување содржини на уреди во близина"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ml/strings.xml b/packages/CompanionDeviceManager/res/values-ml/strings.xml
index 920cf83..ee8b25b 100644
--- a/packages/CompanionDeviceManager/res/values-ml/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ml/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ഉപയോഗിച്ച് മാനേജ് ചെയ്യുന്നതിന് ഒരു <xliff:g id="PROFILE_NAME">%1$s</xliff:g> തിരഞ്ഞെടുക്കുക"</string>
     <string name="summary_watch" msgid="6566922405914995759">"നിങ്ങളുടെ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> മാനേജ് ചെയ്യാൻ ആപ്പ് ആവശ്യമാണ്. വിളിക്കുന്നയാളുടെ പേര് പോലുള്ള വിവരങ്ങൾ സമന്വയിപ്പിക്കുന്നതിനും നിങ്ങളുടെ അറിയിപ്പുകളുമായി സംവദിക്കാനും നിങ്ങളുടെ ഫോൺ, SMS, Contacts, Calendar, കോൾ ചരിത്രം, സമീപമുള്ള ഉപകരണങ്ങളുടെ അനുമതികൾ എന്നിവ ആക്‌സസ് ചെയ്യാനും <xliff:g id="APP_NAME">%2$s</xliff:g> ആപ്പിനെ അനുവദിക്കും."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"നിങ്ങളുടെ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> മാനേജ് ചെയ്യാൻ ആപ്പ് ആവശ്യമാണ്. വിളിക്കുന്നയാളുടെ പേര് പോലുള്ള വിവരങ്ങൾ സമന്വയിപ്പിക്കുന്നതിനും ഈ അനുമതികൾ ആക്സസ് ചെയ്യുന്നതിനും <xliff:g id="APP_NAME">%2$s</xliff:g> എന്നതിനെ അനുവദിക്കും:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"ഗ്ലാസുകൾ"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> മാനേജ് ചെയ്യാൻ ഈ ആപ്പ് ആവശ്യമാണ്. നിങ്ങളുടെ അറിയിപ്പുകളുമായി സംവദിക്കാനും ഫോൺ, SMS, കോൺടാക്റ്റുകൾ, മൈക്രോഫോൺ, സമീപമുള്ള ഉപകരണങ്ങളുടെ അനുമതികൾ എന്നിവ ആക്‌സസ് ചെയ്യാനും <xliff:g id="APP_NAME">%2$s</xliff:g> എന്നതിനെ അനുവദിക്കും."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> മാനേജ് ചെയ്യാൻ ആപ്പ് ആവശ്യമാണ്. ഇനിപ്പറയുന്ന അനുമതികളുമായി സംവദിക്കാൻ <xliff:g id="APP_NAME">%2$s</xliff:g> ആപ്പിനെ അനുവദിക്കും:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"നിങ്ങളുടെ ഫോണിൽ നിന്ന് ഈ വിവരങ്ങൾ ആക്‌സസ് ചെയ്യാൻ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ആപ്പിനെ അനുവദിക്കുക"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"ക്രോസ്-ഉപകരണ സേവനങ്ങൾ"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"നിങ്ങളുടെ ഉപകരണങ്ങളിൽ ഒന്നിൽ നിന്ന് അടുത്തതിലേക്ക് ആപ്പുകൾ സ്ട്രീം ചെയ്യാൻ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ഉപകരണത്തിന് വേണ്ടി <xliff:g id="APP_NAME">%1$s</xliff:g> അനുമതി അഭ്യർത്ഥിക്കുന്നു"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play സേവനങ്ങൾ"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"നിങ്ങളുടെ ഫോണിലെ ഫോട്ടോകൾ, മീഡിയ, അറിയിപ്പുകൾ എന്നിവ ആക്സസ് ചെയ്യാൻ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ഉപകരണത്തിന് വേണ്ടി <xliff:g id="APP_NAME">%1$s</xliff:g> അനുമതി അഭ്യർത്ഥിക്കുന്നു"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"നിങ്ങളുടെ ഫോണിൽ നിന്ന് ഈ പ്രവർത്തനം നടത്താൻ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ആപ്പിനെ അനുവദിക്കുക"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"ക്രോസ്-ഉപകരണ സേവനങ്ങൾ"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"സമീപമുള്ള ഉപകരണങ്ങളിൽ ഉള്ളടക്കം സ്ട്രീം ചെയ്യാൻ നിങ്ങളുടെ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> എന്നതിന് വേണ്ടി <xliff:g id="APP_NAME">%1$s</xliff:g> അനുമതി അഭ്യർത്ഥിക്കുന്നു"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"ഉപകരണം"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"വിളിക്കുന്നയാളുടെ പേര് പോലുള്ള വിവരങ്ങൾ നിങ്ങളുടെ ഫോണിനും <xliff:g id="DEVICE_NAME">%1$s</xliff:g> എന്നതിനും ഇടയിൽ സമന്വയിപ്പിക്കുന്നതിന് ഈ ആപ്പിന് കഴിയും."</string>
     <string name="summary_generic" msgid="4988130802522924650">"വിളിക്കുന്നയാളുടെ പേര് പോലുള്ള വിവരങ്ങൾ നിങ്ങളുടെ ഫോണിനും തിരഞ്ഞെടുത്ത ഉപകരണത്തിനും ഇടയിൽ സമന്വയിപ്പിക്കുന്നതിന് ഈ ആപ്പിന് കഴിയും."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"ഫോട്ടോകളും മീഡിയയും"</string>
     <string name="permission_notification" msgid="693762568127741203">"അറിയിപ്പുകൾ"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"ആപ്പുകൾ"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"സമീപമുള്ള ഉപകരണ സ്ട്രീമിംഗ്"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"മൈക്രോഫോൺ ഉപയോഗിച്ച് ഓഡിയോ റെക്കോർഡ് ചെയ്യാം"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"സമീപമുള്ള ഉപകരണങ്ങൾ കണ്ടെത്താനും അവയിലേക്ക് കണക്റ്റ് ചെയ്യാനും അവയുടെ ആപേക്ഷിക സ്ഥാനം നിർണ്ണയിക്കാനും കഴിയും"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"കോൺടാക്‌റ്റുകൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ മുതലായ വിവരങ്ങൾ ഉൾപ്പെടെയുള്ള എല്ലാ അറിയിപ്പുകളും വായിക്കാനാകും"</string>
     <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="5776807830582725074">"സമീപമുള്ള ഉപകരണത്തിൽ ഉള്ളടക്കം സ്ട്രീം ചെയ്യുക"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-mn/strings.xml b/packages/CompanionDeviceManager/res/values-mn/strings.xml
index 02266f2..e005b48 100644
--- a/packages/CompanionDeviceManager/res/values-mn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mn/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;-н удирдах<xliff:g id="PROFILE_NAME">%1$s</xliff:g>-г сонгоно уу"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Энэ апп таны <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-г удирдахад шаардлагатай. <xliff:g id="APP_NAME">%2$s</xliff:g>-д залгаж буй хүний нэр зэрэг мэдээллийг синк хийх, таны мэдэгдэлтэй харилцан үйлдэл хийх, Утас, SMS, Харилцагчид, Календарь, Дуудлагын жагсаалт болон Ойролцоох төхөөрөмжүүдийн зөвшөөрөлд хандахыг зөвшөөрнө."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Энэ апп таны <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-г удирдахад шаардлагатай. <xliff:g id="APP_NAME">%2$s</xliff:g>-д залгаж буй хүний нэр зэрэг мэдээллийг синк хийх болон эдгээр зөвшөөрөлд хандахыг зөвшөөрнө:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"нүдний шил"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Энэ апп <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-г удирдахад шаардлагатай. <xliff:g id="APP_NAME">%2$s</xliff:g>-д таны мэдэгдэлтэй харилцан үйлдэл хийх, Утас, SMS, Харилцагчид, Микрофон болон Ойролцоох төхөөрөмжүүдийн зөвшөөрөлд хандахыг зөвшөөрнө."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Энэ апп <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-г удирдахад шаардлагатай. <xliff:g id="APP_NAME">%2$s</xliff:g>-д эдгээр зөвшөөрөлтэй харилцан үйлдэл хийхийг зөвшөөрнө:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;-д таны утаснаас энэ мэдээлэлд хандахыг зөвшөөрнө үү"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Төхөөрөмж хоорондын үйлчилгээ"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Таны төхөөрөмжүүд хооронд апп дамжуулахын тулд <xliff:g id="APP_NAME">%1$s</xliff:g> таны <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-н өмнөөс зөвшөөрөл хүсэж байна"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play үйлчилгээ"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"Таны утасны зураг, медиа болон мэдэгдэлд хандахын тулд <xliff:g id="APP_NAME">%1$s</xliff:g> таны <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-н өмнөөс зөвшөөрөл хүсэж байна"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;-д энэ үйлдлийг таны утаснаас гүйцэтгэхийг зөвшөөрнө үү"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Төхөөрөмж хоорондын үйлчилгээ"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> таны <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-н өмнөөс ойролцоох төхөөрөмжүүд рүү контент дамжуулах зөвшөөрөл хүсэж байна"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"төхөөрөмж"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Энэ апп залгаж буй хүний нэр зэрэг мэдээллийг таны утас болон <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-н хооронд синк хийх боломжтой болно."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Энэ апп залгаж буй хүний нэр зэрэг мэдээллийг таны утас болон сонгосон төхөөрөмжийн хооронд синк хийх боломжтой болно."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Зураг болон медиа"</string>
     <string name="permission_notification" msgid="693762568127741203">"Мэдэгдэл"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Аппууд"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Ойролцоох төхөөрөмжид дамжуул"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Микрофоныг ашиглан аудио бичих боломжтой"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Ойролцоох төхөөрөмжүүдийн харьцангуй байршлыг тодорхойлох, холбох, олох боломжтой"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"Харилцагчид, мессеж болон зураг зэрэг мэдээллийг оруулаад бүх мэдэгдлийг унших боломжтой"</string>
     <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="5776807830582725074">"Ойролцоох төхөөрөмжид контент дамжуулах"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-mr/strings.xml b/packages/CompanionDeviceManager/res/values-mr/strings.xml
index 8a22595..b693748 100644
--- a/packages/CompanionDeviceManager/res/values-mr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mr/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; द्वारे व्यवस्थापित करण्यासाठी <xliff:g id="PROFILE_NAME">%1$s</xliff:g> निवडा"</string>
     <string name="summary_watch" msgid="6566922405914995759">"तुमचे <xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापित करण्यासाठी हे ॲप आवश्यक आहे. <xliff:g id="APP_NAME">%2$s</xliff:g> ला कॉल करत असलेल्या एखाद्या व्यक्तीचे नाव यासारखी माहिती सिंक करण्याची, तुमच्या सूचनांसोबत संवाद साधण्याची आणि तुमचा फोन, एसएमएस, संपर्क, कॅलेंडर, कॉल लॉग व जवळपासच्या डिव्हाइसच्या परवानग्या अ‍ॅक्सेस करण्याची अनुमती मिळेल."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"तुमचे <xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापित करण्यासाठी हे ॲप आवश्यक आहे. <xliff:g id="APP_NAME">%2$s</xliff:g> ला कॉल करत असलेल्या एखाद्या व्यक्तीचे नाव यासारखी माहिती सिंक करण्याची आणि पुढील परवानग्या अ‍ॅक्सेस करण्याची अनुमती मिळेल:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"Glasses"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापित करण्यासाठी हे ॲप आवश्यक आहे. <xliff:g id="APP_NAME">%2$s</xliff:g> ला तुमच्या सूचनांसोबत संवाद साधण्याची आणि तुमचा फोन, एसएमएस, संपर्क, मायक्रोफोन व जवळपासच्या डिव्हाइसच्या परवानग्या अ‍ॅक्सेस करण्याची अनुमती मिळेल."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापित करण्यासाठी ॲप आवश्यक आहे. <xliff:g id="APP_NAME">%2$s</xliff:g> ला पुढील परवानग्यांशी संवाद साधण्याची अनुमती मिळेल:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ला ही माहिती तुमच्या फोनवरून अ‍ॅक्सेस करण्यासाठी अनुमती द्या"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"क्रॉस-डिव्हाइस सेवा"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"तुमच्या डिव्हाइसदरम्यान ॲप्स स्ट्रीम करण्यासाठी <xliff:g id="APP_NAME">%1$s</xliff:g> हे तुमच्या <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> च्या वतीने परवानगीची विनंती करत आहे"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play सेवा"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"तुमच्या फोनमधील फोटो, मीडिया आणि सूचना ॲक्सेस करण्यासाठी <xliff:g id="APP_NAME">%1$s</xliff:g> हे तुमच्या <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> च्या वतीने परवानगीची विनंती करत आहे"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ला तुमच्या फोनवरून ही कृती करण्याची अनुमती द्या"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"क्रॉस-डिव्हाइस सेवा"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> हे जवळपासच्या डिव्हाइसवर आशय स्ट्रीम करण्यासाठी तुमच्या <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> च्या वतीने परवानगीची विनंती करत आहे"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"डिव्हाइस"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"हे ॲप तुमचा फोन आणि <xliff:g id="DEVICE_NAME">%1$s</xliff:g> दरम्यान कॉल करत असलेल्‍या एखाद्या व्यक्तीचे नाव यासारखी माहिती सिंक करू शकेल."</string>
     <string name="summary_generic" msgid="4988130802522924650">"हे ॲप तुमचा फोन आणि निवडलेल्या डिव्‍हाइसदरम्यान कॉल करत असलेल्‍या एखाद्या व्यक्तीचे नाव यासारखी माहिती सिंक करू शकेल."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"फोटो आणि मीडिया"</string>
     <string name="permission_notification" msgid="693762568127741203">"सूचना"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"ॲप्स"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"जवळपासच्या डिव्हाइसवरील स्ट्रीमिंग"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"मायक्रोफोन वापरून ऑडिओ रेकॉर्ड करता येईल"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"जवळील डिव्हाइस शोधू शकते, त्यांच्याशी कनेक्ट करू शकते आणि त्यांचे संबंधित स्थान निर्धारित करू शकते"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"संपर्क, मेसेज आणि फोटो यांसारख्या माहितीचा समावेश असलेल्या सर्व सूचना वाचू शकते"</string>
     <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="5776807830582725074">"जवळपासच्या डिव्हाइसवर आशय स्ट्रीम करा"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ms/strings.xml b/packages/CompanionDeviceManager/res/values-ms/strings.xml
index 9fdedff..78d272d 100644
--- a/packages/CompanionDeviceManager/res/values-ms/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ms/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Pilih <xliff:g id="PROFILE_NAME">%1$s</xliff:g> untuk diurus oleh &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Apl ini diperlukan untuk mengurus <xliff:g id="DEVICE_NAME">%1$s</xliff:g> anda. <xliff:g id="APP_NAME">%2$s</xliff:g> akan dibenarkan untuk menyegerakkan maklumat seperti nama individu yang memanggil, berinteraksi dengan pemberitahuan anda dan mengakses kebenaran Telefon, SMS, Kenalan, Kalendar, Log panggilan dan Peranti berdekatan anda."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Apl ini diperlukan untuk mengurus <xliff:g id="DEVICE_NAME">%1$s</xliff:g> anda. <xliff:g id="APP_NAME">%2$s</xliff:g> akan dibenarkan untuk menyegerakkan maklumat seperti nama individu yang memanggil dan mengakses kebenaran ini:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"cermin mata"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Apl ini diperlukan untuk mengurus <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> akan dibenarkan untuk berinteraksi dengan pemberitahuan anda dan mengakses kebenaran Telefon, SMS, Kenalan, Mikrofon dan Peranti berdekatan anda."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Apl ini diperlukan untuk mengurus <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> akan dibenarkan untuk berinteraksi dengan kebenaran ini:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Benarkan &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; mengakses maklumat ini daripada telefon anda"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Perkhidmatan silang peranti"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang meminta kebenaran bagi pihak <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> anda untuk menstrim apl antara peranti anda"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Perkhidmatan Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang meminta kebenaran bagi pihak <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> anda untuk mengakses foto, media dan pemberitahuan telefon anda"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Benarkan &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; melakukan tindakan ini daripada telefon anda"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Perkhidmatan silang peranti"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang meminta kebenaran bagi pihak <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> anda untuk menstrim kandungan kepada peranti berdekatan"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"peranti"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Apl ini akan dapat menyegerakkan maklumat seperti nama individu yang memanggil, antara telefon anda dengan <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Apl ini akan dapat menyegerakkan maklumat seperti nama individu yang memanggil, antara telefon anda dengan peranti yang dipilih."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Foto dan media"</string>
     <string name="permission_notification" msgid="693762568127741203">"Pemberitahuan"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apl"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Penstriman Peranti Berdekatan"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Boleh merakam audio menggunakan mikrofon"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Strim kandungan kepada peranti berdekatan"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-my/strings.xml b/packages/CompanionDeviceManager/res/values-my/strings.xml
index 406e91c..d63e4f2 100644
--- a/packages/CompanionDeviceManager/res/values-my/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-my/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; က စီမံခန့်ခွဲရန် <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ကို ရွေးချယ်ပါ"</string>
     <string name="summary_watch" msgid="6566922405914995759">"သင်၏ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ကို စီမံခန့်ခွဲရန် ဤအက်ပ်လိုအပ်သည်။ ခေါ်ဆိုသူ၏အမည်ကဲ့သို့ အချက်အလက်ကို စင့်ခ်လုပ်ရန်၊ သင်၏ဖုန်း၊ SMS စာတိုစနစ်၊ အဆက်အသွယ်များ၊ ပြက္ခဒိန်၊ ခေါ်ဆိုမှတ်တမ်းနှင့် အနီးတစ်ဝိုက်ရှိ စက်များဆိုင်ရာ ခွင့်ပြုချက်များသုံးရန်၊ အကြောင်းကြားချက်များနှင့် ပြန်လှန်တုံ့ပြန်ရန် <xliff:g id="APP_NAME">%2$s</xliff:g> ကို ခွင့်ပြုမည်။"</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"သင်၏ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ကို စီမံခန့်ခွဲရန် ဤအက်ပ်လိုအပ်သည်။ ခေါ်ဆိုသူ၏အမည်ကဲ့သို့ အချက်အလက်ကို စင့်ခ်လုပ်ရန်နှင့် ဤခွင့်ပြုချက်များသုံးရန် <xliff:g id="APP_NAME">%2$s</xliff:g> ကို ခွင့်ပြုမည်-"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"မျက်မှန်"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ကို စီမံခန့်ခွဲရန် ဤအက်ပ်လိုအပ်သည်။ သင်၏ဖုန်း၊ SMS စာတိုစနစ်၊ အဆက်အသွယ်များ၊ မိုက်ခရိုဖုန်းနှင့် အနီးတစ်ဝိုက်ရှိ စက်များဆိုင်ရာ ခွင့်ပြုချက်များသုံးရန်၊ အကြောင်းကြားချက်များနှင့် ပြန်လှန်တုံ့ပြန်ရန် <xliff:g id="APP_NAME">%2$s</xliff:g> ကို ခွင့်ပြုမည်။"</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ကို စီမံခန့်ခွဲရန် ဤအက်ပ်လိုအပ်သည်။ ဤခွင့်ပြုချက်များနှင့် ပြန်လှန်တုံ့ပြန်ရန် <xliff:g id="APP_NAME">%2$s</xliff:g> ကို ခွင့်ပြုမည်-"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ကို သင့်ဖုန်းမှ ဤအချက်အလက် သုံးခွင့်ပြုမည်"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"စက်များကြားသုံး ဝန်ဆောင်မှုများ"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် သင်၏စက်များအကြား အက်ပ်များတိုက်ရိုက်လွှင့်ရန် <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ကိုယ်စား ခွင့်ပြုချက်တောင်းနေသည်"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play ဝန်ဆောင်မှုများ"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် သင့်ဖုန်း၏ ဓာတ်ပုံ၊ မီဒီယာနှင့် အကြောင်းကြားချက်များသုံးရန် <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ကိုယ်စား ခွင့်ပြုချက်တောင်းနေသည်"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"သင့်ဖုန်းမှ ဤလုပ်ဆောင်ချက်ပြုလုပ်ရန် &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ကို ခွင့်ပြုနိုင်သည်"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"စက်များကြားသုံး ဝန်ဆောင်မှု"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် အနီးတစ်ဝိုက်ရှိ စက်များတွင် အကြောင်းအရာတိုက်ရိုက်ဖွင့်ရန် သင့် <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ကိုယ်စား ခွင့်ပြုချက်တောင်းနေသည်"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"စက်"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"ဤအက်ပ်သည် သင့်ဖုန်းနှင့် <xliff:g id="DEVICE_NAME">%1$s</xliff:g> အကြား ခေါ်ဆိုသူ၏အမည်ကဲ့သို့ အချက်အလက်ကို စင့်ခ်လုပ်နိုင်ပါမည်။"</string>
     <string name="summary_generic" msgid="4988130802522924650">"ဤအက်ပ်သည် သင့်ဖုန်းနှင့် ရွေးထားသောစက်အကြား ခေါ်ဆိုသူ၏အမည်ကဲ့သို့ အချက်အလက်ကို စင့်ခ်လုပ်နိုင်ပါမည်။"</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"ဓာတ်ပုံနှင့် မီဒီယာများ"</string>
     <string name="permission_notification" msgid="693762568127741203">"အကြောင်းကြားချက်များ"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"အက်ပ်များ"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"အနီးရှိစက်တိုက်ရိုက်ဖွင့်ခြင်း"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"မိုက်ခရိုဖုန်းသုံးပြီး အသံဖမ်းနိုင်သည်"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"အနီးတစ်ဝိုက်ရှိ စက်များ၏ ဆက်စပ်နေရာကို ရှာခြင်း၊ ချိတ်ဆက်ခြင်းနှင့် သတ်မှတ်ခြင်းတို့ လုပ်နိုင်သည်"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"အဆက်အသွယ်၊ မက်ဆေ့ဂျ်နှင့် ဓာတ်ပုံကဲ့သို့ အချက်အလက်များအပါအဝင် အကြောင်းကြားချက်အားလုံးကို ဖတ်နိုင်သည်"</string>
     <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="5776807830582725074">"အနီးတစ်ဝိုက်ရှိစက်တွင် အကြောင်းအရာ တိုက်ရိုက်ဖွင့်နိုင်သည်"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-nb/strings.xml b/packages/CompanionDeviceManager/res/values-nb/strings.xml
index ee7091f..6c76f2b 100644
--- a/packages/CompanionDeviceManager/res/values-nb/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-nb/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Velg <xliff:g id="PROFILE_NAME">%1$s</xliff:g> som skal administreres av &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Appen kreves for å administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillatelse til å synkronisere informasjon som navnet til noen som ringer, og samhandle med varslene dine, og får tilgang til tillatelsene for telefon, SMS, kontakter, kalender, samtalelogger og enheter i nærheten."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Appen kreves for å administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillatelse til å synkronisere informasjon som navnet til noen som ringer, og kan bruke disse tillatelsene:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"briller"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Denne appen kreves for å administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillatelse til å samhandle med varslene dine og har tilgang til tillatelsene for telefon, SMS, kontakter, mikrofon og enheter i nærheten."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Appen kreves for å administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillatelse til å samhandle med disse tillatelsene:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Gi &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; tilgang til denne informasjonen fra telefonen din"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjenester på flere enheter"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> ber om tillatelse til å strømme apper mellom enhetene dine, på vegne av <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play-tjenester"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> ber om tillatelse til å få tilgang til bilder, medier og varsler på telefonen din, på vegne av <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Gi &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; tillatelse til å utføre denne handlingen fra telefonen din"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Tjenester på flere enheter"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> ber om tillatelse på vegne av <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> til å strømme innhold til enheter i nærheten"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"enhet"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Denne appen kan synkronisere informasjon som navnet til noen som ringer, mellom telefonen og <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Denne appen kan synkronisere informasjon som navnet til noen som ringer, mellom telefonen og den valgte enheten."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Bilder og medier"</string>
     <string name="permission_notification" msgid="693762568127741203">"Varsler"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apper"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Strøm til enheter i nærheten"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Kan ta opp lyd med mikrofonen"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Strøm innhold til en enhet i nærheten"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ne/strings.xml b/packages/CompanionDeviceManager/res/values-ne/strings.xml
index f494e79..6e0a66d 100644
--- a/packages/CompanionDeviceManager/res/values-ne/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ne/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"आफूले &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; प्रयोग गरी व्यवस्थापन गर्न चाहेको <xliff:g id="PROFILE_NAME">%1$s</xliff:g> चयन गर्नुहोस्"</string>
     <string name="summary_watch" msgid="6566922405914995759">"तपाईंको <xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापन गर्न यो एप चाहिन्छ। <xliff:g id="APP_NAME">%2$s</xliff:g> लाई कल गर्ने व्यक्तिको नाम जस्ता जानकारी सिंक गर्ने, तपाईंका सूचना हेर्ने र फोन, SMS, कन्ट्याक्ट, पात्रो, कल लग तथा नजिकैका डिभाइससम्बन्धी अनुमतिहरू हेर्ने तथा प्रयोग गर्ने अनुमति दिइने छ।"</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"तपाईंको <xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापन गर्न यो एप चाहिन्छ। <xliff:g id="APP_NAME">%2$s</xliff:g> लाई कल गर्ने व्यक्तिको नाम जस्ता जानकारी सिंक गर्ने र यी अनुमतिहरू हेर्ने तथा प्रयोग गर्ने अनुमति दिइने छ:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"चस्मा"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापन गर्न यो एप चाहिन्छ। <xliff:g id="APP_NAME">%2$s</xliff:g> लाई तपाईंका सूचना हेर्ने र फोन, SMS, कन्ट्याक्ट, माइक्रोफोन तथा नजिकैका डिभाइससम्बन्धी अनुमतिहरू हेर्ने तथा प्रयोग गर्ने अनुमति दिइने छ।"</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापन गर्न यो एप चाहिन्छ। <xliff:g id="APP_NAME">%2$s</xliff:g> लाई निम्न अनुमतिहरू फेरबदल गर्न दिइने छः"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; लाई तपाईंको फोनमा भएको यो जानकारी हेर्ने तथा प्रयोग गर्ने अनुमति दिनुहोस्"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"क्रस-डिभाइस सेवाहरू"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> तपाईंको डिभाइस <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> को तर्फबाट तपाईंका कुनै एउटा डिभाइसबाट अर्को डिभाइसमा एप स्ट्रिम गर्ने अनुमति माग्दै छ"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play services"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> तपाईंको डिभाइस <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> को तर्फबाट तपाईंको फोनमा भएका फोटो, मिडिया र सूचनाहरू हेर्ने तथा प्रयोग गर्ने अनुमति माग्दै छ"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; लाई तपाईंको फोनबाट यो कार्य गर्ने अनुमति दिनुहोस्"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"क्रस-डिभाइस सेवाहरू"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> तपाईंको <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> को तर्फबाट नजिकैका डिभाइसहरूमा सामग्री स्ट्रिम गर्ने अनुमति माग्दै छ"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"यन्त्र"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"यो एपले तपाईंको फोन र तपाईंले छनौट गर्ने <xliff:g id="DEVICE_NAME">%1$s</xliff:g> का बिचमा कल गर्ने व्यक्तिको नाम जस्ता जानकारी सिंक गर्न सक्ने छ।"</string>
     <string name="summary_generic" msgid="4988130802522924650">"यो एपले तपाईंको फोन र तपाईंले छनौट गर्ने डिभाइसका बिचमा कल गर्ने व्यक्तिको नाम जस्ता जानकारी सिंक गर्न सक्ने छ।"</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"फोटो र मिडिया"</string>
     <string name="permission_notification" msgid="693762568127741203">"सूचनाहरू"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"एपहरू"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"नजिकैको डिभाइसमा स्ट्रिम गरिँदै छ"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"यसका सहायताले माइक्रोफोन प्रयोग गरी अडियो रेकर्ड गर्न सकिन्छ"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"नजिकैका डिभाइसहरू भेट्टाउन, ती डिभाइससँग कनेक्ट गर्न र तिनको सापेक्ष स्थिति निर्धारण गर्न सक्छ"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"कन्ट्याक्ट, म्यासेज र फोटोलगायतका जानकारीसहित सबै सूचनाहरू पढ्न सक्छ"</string>
     <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="5776807830582725074">"नजिकैको डिभाइसमा सामग्री स्ट्रिम गर्नुहोस्"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-nl/strings.xml b/packages/CompanionDeviceManager/res/values-nl/strings.xml
index bec7e405..aadf83d 100644
--- a/packages/CompanionDeviceManager/res/values-nl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-nl/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Een <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kiezen om te beheren met &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"De app is nodig om je <xliff:g id="DEVICE_NAME">%1$s</xliff:g> te beheren. <xliff:g id="APP_NAME">%2$s</xliff:g> mag informatie (zoals de naam van iemand die belt) synchroniseren, interactie hebben met je meldingen en krijgt toegang tot de rechten Telefoon, Sms, Contacten, Agenda, Gesprekslijsten en Apparaten in de buurt."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"De app is nodig om je <xliff:g id="DEVICE_NAME">%1$s</xliff:g> te beheren. <xliff:g id="APP_NAME">%2$s</xliff:g> mag informatie (zoals de naam van iemand die belt) synchroniseren en krijgt toegang tot deze rechten:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"brillen"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Deze app is nodig om <xliff:g id="DEVICE_NAME">%1$s</xliff:g> te beheren. <xliff:g id="APP_NAME">%2$s</xliff:g> mag interactie hebben met je meldingen en krijgt toegang tot de rechten Telefoon, Sms, Contacten, Microfoon en Apparaten in de buurt."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"De app is nodig om <xliff:g id="DEVICE_NAME">%1$s</xliff:g> te beheren. <xliff:g id="APP_NAME">%2$s</xliff:g> mag interactie hebben met deze rechten:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; toegang geven tot deze informatie op je telefoon"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device-services"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> vraagt namens jouw <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> toestemming om apps te streamen tussen je apparaten"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play-services"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> vraagt namens jouw <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> toegang tot de foto\'s, media en meldingen van je telefoon"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Sta &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; toe om deze actie uit te voeren via je telefoon"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Cross-device-services"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> vraagt namens je <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> toestemming om content te streamen naar apparaten in de buurt"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"apparaat"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Deze app kan informatie, zoals de naam van iemand die belt, synchroniseren tussen je telefoon en <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Deze app kan informatie (zoals de naam van iemand die belt) synchroniseren tussen je telefoon en het gekozen apparaat."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Foto\'s en media"</string>
     <string name="permission_notification" msgid="693762568127741203">"Meldingen"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streaming op apparaten in de buurt"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Kan audio opnemen met de microfoon"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Stream content naar een apparaat in de buurt"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-or/strings.xml b/packages/CompanionDeviceManager/res/values-or/strings.xml
index cd742f1..2fbeea3 100644
--- a/packages/CompanionDeviceManager/res/values-or/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-or/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ଦ୍ୱାରା ପରିଚାଳିତ ହେବା ପାଇଁ ଏକ <xliff:g id="PROFILE_NAME">%1$s</xliff:g>କୁ ବାଛନ୍ତୁ"</string>
     <string name="summary_watch" msgid="6566922405914995759">"ଆପଣଙ୍କ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>କୁ ପରିଚାଳନା କରିବା ପାଇଁ ଆପ ଆବଶ୍ୟକ। କଲ କରୁଥିବା ଯେ କୌଣସି ବ୍ୟକ୍ତିଙ୍କ ନାମ ପରି ସୂଚନା ସିଙ୍କ କରିବା, ଆପଣଙ୍କ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ସହ ଇଣ୍ଟରାକ୍ଟ କରିବା ଏବଂ ଆପଣଙ୍କର ଫୋନ, SMS, କଣ୍ଟାକ୍ଟ, କେଲେଣ୍ଡର, କଲ ଲଗ ଓ ଆଖପାଖର ଡିଭାଇସ ଅନୁମତିଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%2$s</xliff:g>କୁ ଅନୁମତି ଦିଆଯିବ।"</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"ଆପଣଙ୍କ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>କୁ ପରିଚାଳନା କରିବା ପାଇଁ ଆପ ଆବଶ୍ୟକ। କଲ କରୁଥିବା ଯେ କୌଣସି ବ୍ୟକ୍ତିଙ୍କ ନାମ ପରି ସୂଚନା ସିଙ୍କ କରିବା ଏବଂ ଏହି ଅନୁମତିଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%2$s</xliff:g>କୁ ଅନୁମତି ଦିଆଯିବ:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"ଚଷମା"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>କୁ ପରିଚାଳନା କରିବା ପାଇଁ ଏହି ଆପ ଆବଶ୍ୟକ। ଆପଣଙ୍କ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ସହ ଇଣ୍ଟରାକ୍ଟ କରିବା ଏବଂ ଆପଣଙ୍କର ଫୋନ, SMS, କଣ୍ଟାକ୍ଟ, ମାଇକ୍ରୋଫୋନ ଓ ଆଖପାଖର ଡିଭାଇସ ଅନୁମତିଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%2$s</xliff:g>କୁ ଅନୁମତି ଦିଆଯିବ।"</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>କୁ ପରିଚାଳନା କରିବା ପାଇଁ ଆପ ଆବଶ୍ୟକ। ଏହି ଅନୁମତିଗୁଡ଼ିକ ସହ ଇଣ୍ଟରାକ୍ଟ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%2$s</xliff:g>କୁ ଅନୁମତି ଦିଆଯିବ:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"ଆପଣଙ୍କ ଫୋନରୁ ଏହି ସୂଚନାକୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;କୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"କ୍ରସ-ଡିଭାଇସ ସେବାଗୁଡ଼ିକ"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"ଆପଣଙ୍କ ଡିଭାଇସଗୁଡ଼ିକ ମଧ୍ୟରେ ଆପ୍ସକୁ ଷ୍ଟ୍ରିମ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%1$s</xliff:g> ଆପଣଙ୍କର <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ତରଫରୁ ଅନୁମତି ପାଇଁ ଅନୁରୋଧ କରୁଛି"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play ସେବାଗୁଡ଼ିକ"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"ଆପଣଙ୍କ ଫୋନର ଫଟୋ, ମିଡିଆ ଏବଂ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%1$s</xliff:g> ଆପଣଙ୍କର <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ତରଫରୁ ଅନୁମତି ପାଇଁ ଅନୁରୋଧ କରୁଛି"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"ଆପଣଙ୍କ ଫୋନରେ ଏହି କାର୍ଯ୍ୟ କରିବା ପାଇଁ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;କୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"କ୍ରସ-ଡିଭାଇସ ସେବାଗୁଡ଼ିକ"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"ଆଖପାଖର ଡିଭାଇସଗୁଡ଼ିକରେ ବିଷୟବସ୍ତୁକୁ ଷ୍ଟ୍ରିମ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%1$s</xliff:g> ଆପଣଙ୍କର <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ତରଫରୁ ଅନୁମତି ପାଇଁ ଅନୁରୋଧ କରୁଛି"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"ଡିଭାଇସ୍"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"ଆପଣଙ୍କ ଫୋନ ଏବଂ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ମଧ୍ୟରେ, କଲ କରୁଥିବା ଯେ କୌଣସି ବ୍ୟକ୍ତିଙ୍କ ନାମ ପରି ସୂଚନା ସିଙ୍କ କରିବାକୁ ଏହି ଆପ ସକ୍ଷମ ହେବ।"</string>
     <string name="summary_generic" msgid="4988130802522924650">"ଆପଣଙ୍କ ଫୋନ ଏବଂ ବଛାଯାଇଥିବା ଡିଭାଇସ ମଧ୍ୟରେ, କଲ କରୁଥିବା ଯେ କୌଣସି ବ୍ୟକ୍ତିଙ୍କ ନାମ ପରି ସୂଚନା ସିଙ୍କ କରିବାକୁ ଏହି ଆପ ସକ୍ଷମ ହେବ।"</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"ଫଟୋ ଏବଂ ମିଡିଆ"</string>
     <string name="permission_notification" msgid="693762568127741203">"ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"ଆପ୍ସ"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"ଆଖପାଖର ଡିଭାଇସରେ ଷ୍ଟ୍ରିମିଂ"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"ମାଇକ୍ରୋଫୋନକୁ ବ୍ୟବହାର କରି ଅଡିଓ ରେକର୍ଡ କରାଯାଇପାରିବ"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"ଆଖପାଖର ଡିଭାଇସଗୁଡ଼ିକୁ ଖୋଜିପାରିବ, କନେକ୍ଟ କରିପାରିବ ଏବଂ ସେଗୁଡ଼ିକର ଆପେକ୍ଷିକ ଅବସ୍ଥିତିକୁ ନିର୍ଦ୍ଧାରଣ କରିପାରିବ"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"ଯୋଗାଯୋଗ, ମେସେଜ ଏବଂ ଫଟୋଗୁଡ଼ିକ ପରି ସୂଚନା ସମେତ ସମସ୍ତ ବିଜ୍ଞପ୍ତିକୁ ପଢ଼ିପାରିବ"</string>
     <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="5776807830582725074">"ଆଖପାଖର ଏକ ଡିଭାଇସରେ ବିଷୟବସ୍ତୁକୁ ଷ୍ଟ୍ରିମ କରନ୍ତୁ"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-pa/strings.xml b/packages/CompanionDeviceManager/res/values-pa/strings.xml
index 1e03ee0..869f54c 100644
--- a/packages/CompanionDeviceManager/res/values-pa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pa/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ਵੱਲੋਂ ਪ੍ਰਬੰਧਿਤ ਕੀਤੇ ਜਾਣ ਲਈ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ਚੁਣੋ"</string>
     <string name="summary_watch" msgid="6566922405914995759">"ਇਹ ਐਪ ਤੁਹਾਡੇ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਲਈ ਲੋੜੀਂਦੀ ਹੈ। <xliff:g id="APP_NAME">%2$s</xliff:g> ਨੂੰ ਕਾਲਰ ਦੇ ਨਾਮ ਵਰਗੀ ਜਾਣਕਾਰੀ ਨੂੰ ਸਿੰਕ ਕਰਨ, ਤੁਹਾਡੀਆਂ ਸੂਚਨਾਵਾਂ ਨਾਲ ਅੰਤਰਕਿਰਿਆ ਕਰਨ ਅਤੇ ਤੁਹਾਡੇ ਫ਼ੋਨ, SMS, ਸੰਪਰਕਾਂ, ਕੈਲੰਡਰ, ਕਾਲ ਲੌਗਾਂ ਅਤੇ ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸਾਂ ਸੰਬੰਧੀ ਇਜਾਜ਼ਤਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਹੋਵੇਗੀ।"</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"ਇਹ ਐਪ ਤੁਹਾਡੇ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਲਈ ਲੋੜੀਂਦੀ ਹੈ। <xliff:g id="APP_NAME">%2$s</xliff:g> ਨੂੰ ਕਾਲਰ ਦੇ ਨਾਮ ਵਰਗੀ ਜਾਣਕਾਰੀ ਨੂੰ ਸਿੰਕ ਕਰਨ ਅਤੇ ਇਨ੍ਹਾਂ ਇਜਾਜ਼ਤਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਹੋਵੇਗੀ:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"ਐਨਕਾਂ"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"ਇਹ ਐਪ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਲਈ ਲੋੜੀਂਦੀ ਹੈ। <xliff:g id="APP_NAME">%2$s</xliff:g> ਨੂੰ ਤੁਹਾਡੀਆਂ ਸੂਚਨਾਵਾਂ ਨਾਲ ਅੰਤਰਕਿਰਿਆ ਕਰਨ ਅਤੇ ਤੁਹਾਡੇ ਫ਼ੋਨ, SMS, ਸੰਪਰਕਾਂ, ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਅਤੇ ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸਾਂ ਸੰਬੰਧੀ ਇਜਾਜ਼ਤਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਹੋਵੇਗੀ।"</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"ਇਹ ਐਪ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਲਈ ਲੋੜੀਂਦੀ ਹੈ। <xliff:g id="APP_NAME">%2$s</xliff:g> ਨੂੰ ਇਨ੍ਹਾਂ ਇਜਾਜ਼ਤਾਂ ਨਾਲ ਅੰਤਰਕਿਰਿਆ ਕਰਨ ਦੀ ਆਗਿਆ ਹੋਵੇਗੀ:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ ਤੋਂ ਇਸ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"ਕ੍ਰਾਸ-ਡੀਵਾਈਸ ਸੇਵਾਵਾਂ"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ਦੀ ਤਰਫ਼ੋਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸਾਂ ਵਿਚਕਾਰ ਐਪਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਰਹੀ ਹੈ"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play ਸੇਵਾਵਾਂ"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ਦੀ ਤਰਫ਼ੋਂ ਤੁਹਾਡੇ ਫ਼ੋਨ ਦੀਆਂ ਫ਼ੋਟੋਆਂ, ਮੀਡੀਆ ਅਤੇ ਸੂਚਨਾਵਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਰਹੀ ਹੈ"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ਨੂੰ ਆਪਣੇ ਫ਼ੋਨ ਤੋਂ ਇਹ ਕਾਰਵਾਈ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿਓ"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"ਕ੍ਰਾਸ-ਡੀਵਾਈਸ ਸੇਵਾਵਾਂ"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ਦੀ ਤਰਫ਼ੋਂ ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸਾਂ ਲਈ ਸਮੱਗਰੀ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਰਹੀ ਹੈ"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"ਡੀਵਾਈਸ"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਫ਼ੋਨ ਅਤੇ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਵਿਚਕਾਰ ਕਾਲਰ ਦੇ ਨਾਮ ਵਰਗੀ ਜਾਣਕਾਰੀ ਨੂੰ ਸਿੰਕ ਕਰ ਸਕੇਗੀ।"</string>
     <string name="summary_generic" msgid="4988130802522924650">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਫ਼ੋਨ ਅਤੇ ਚੁਣੇ ਗਏ ਡੀਵਾਈਸ ਵਿਚਕਾਰ ਕਾਲਰ ਦੇ ਨਾਮ ਵਰਗੀ ਜਾਣਕਾਰੀ ਨੂੰ ਸਿੰਕ ਕਰ ਸਕੇਗੀ।"</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"ਫ਼ੋਟੋਆਂ ਅਤੇ ਮੀਡੀਆ"</string>
     <string name="permission_notification" msgid="693762568127741203">"ਸੂਚਨਾਵਾਂ"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"ਐਪਾਂ"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸਾਂ \'ਤੇ ਸਟ੍ਰੀਮਿੰਗ"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਆਡੀਓ ਰਿਕਾਰਡ ਕਰ ਸਕਦੇ ਹੋ"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸਾਂ ਨੂੰ ਲੱਭਣ, ਉਨ੍ਹਾਂ ਨਾਲ ਕਨੈਕਟ ਕਰਨ ਅਤੇ ਸੰਬੰਧਿਤ ਸਥਿਤੀ ਨਿਰਧਾਰਿਤ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਹੈ"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"ਤੁਸੀਂ ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ ਪੜ੍ਹ ਸਕਦੇ ਹੋ, ਜਿਨ੍ਹਾਂ ਵਿੱਚ ਸੰਪਰਕਾਂ, ਸੁਨੇਹਿਆਂ ਅਤੇ ਫ਼ੋਟੋਆਂ ਵਰਗੀ ਜਾਣਕਾਰੀ ਸ਼ਾਮਲ ਹੁੰਦੀ ਹੈ"</string>
     <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="5776807830582725074">"ਸਮੱਗਰੀ ਨੂੰ ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸ \'ਤੇ ਸਟ੍ਰੀਮ ਕਰੋ"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-pl/strings.xml b/packages/CompanionDeviceManager/res/values-pl/strings.xml
index c591594..38e4bc0 100644
--- a/packages/CompanionDeviceManager/res/values-pl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pl/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Wybierz profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, którym ma zarządzać aplikacja &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Ta aplikacja jest niezbędna do zarządzania urządzeniem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacja <xliff:g id="APP_NAME">%2$s</xliff:g> będzie mogła synchronizować informacje takie jak nazwa osoby dzwoniącej, korzystać z powiadomień oraz uprawnień dotyczących Telefonu, SMS-ów, Kontaktów, Kalendarza, rejestrów połączeń i Urządzeń w pobliżu."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Ta aplikacja jest niezbędna do zarządzania urządzeniem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacja <xliff:g id="APP_NAME">%2$s</xliff:g> będzie mogła synchronizować informacje takie jak nazwa osoby dzwoniącej i korzystać z tych uprawnień:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"Okulary"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Ta aplikacja jest niezbędna do zarządzania urządzeniem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacja <xliff:g id="APP_NAME">%2$s</xliff:g> będzie mogła wchodzić w interakcję z powiadomieniami i korzystać z uprawnień dotyczących telefonu, SMS-ów, kontaktów, mikrofonu oraz urządzeń w pobliżu."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Ta aplikacja jest niezbędna do zarządzania urządzeniem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacja <xliff:g id="APP_NAME">%2$s</xliff:g> będzie mogła korzystać z tych uprawnień:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Zezwól urządzeniu &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; na dostęp do tych informacji na Twoim telefonie"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Usługi na innym urządzeniu"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> prosi w imieniu urządzenia <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> o uprawnienia dotyczące strumieniowego odtwarzania treści z aplikacji na innym urządzeniu"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Usługi Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> prosi w imieniu urządzenia <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> o uprawnienia dotyczące dostępu do zdjęć, multimediów i powiadomień na telefonie"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Zezwól na wykonywanie tych działań z Twojego telefonu przez aplikację &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Usługi na innym urządzeniu"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> prosi w imieniu urządzenia <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> o uprawnienia dotyczące strumieniowego odtwarzania treści na urządzeniach w pobliżu"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"urządzenie"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Ta aplikacja może synchronizować informacje takie jak nazwa osoby dzwoniącej między Twoim telefonem i urządzeniem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Ta aplikacja może synchronizować informacje takie jak nazwa osoby dzwoniącej między Twoim telefonem i wybranym urządzeniem."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Zdjęcia i multimedia"</string>
     <string name="permission_notification" msgid="693762568127741203">"Powiadomienia"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacje"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Strumieniowanie danych na urządzenia w pobliżu"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Może nagrywać dźwięk przy użyciu mikrofonu"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Strumieniowe odtwarzanie treści na urządzeniach w pobliżu"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
index 29f00ca..6c620df 100644
--- a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Escolha um <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para ser gerenciado pelo app &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"O app <xliff:g id="APP_NAME">%2$s</xliff:g> é necessário para gerenciar o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Ele poderá sincronizar informações, como o nome de quem está ligando, interagir com suas notificações e acessar as permissões de telefone, SMS, contatos, agenda, registro de chamadas e dispositivos por perto."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"O app <xliff:g id="APP_NAME">%2$s</xliff:g> é necessário para gerenciar seu dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Ele poderá sincronizar informações, como o nome de quem está ligando, e acessar estas permissões:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"óculos"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"O app <xliff:g id="APP_NAME">%2$s</xliff:g> é necessário para gerenciar o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Ele poderá interagir com suas notificações e acessar suas permissões de telefone, SMS, contatos, microfone e dispositivos por perto."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"O app <xliff:g id="APP_NAME">%2$s</xliff:g> é necessário para gerenciar o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Ele poderá interagir com estas permissões:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Permitir que o app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acesse estas informações do smartphone"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serviços entre dispositivos"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para fazer streaming de apps entre seus dispositivos"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Services"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para acessar fotos, mídia e notificações do smartphone."</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Permitir que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; realize esta ação pelo smartphone"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Serviços entre dispositivos"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome de <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para fazer streaming de conteúdo para dispositivos por perto"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"O app poderá sincronizar informações, como o nome de quem está ligando, entre seu smartphone e o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"O app poderá sincronizar informações, como o nome de quem está ligando, entre seu smartphone e o dispositivo escolhido."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Fotos e mídia"</string>
     <string name="permission_notification" msgid="693762568127741203">"Notificações"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streaming em disp. por perto"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Pode gravar áudio usando o microfone"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Fazer streaming de conteúdo para dispositivos por perto"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
index d5978e2..89fcdfe 100644
--- a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
@@ -22,9 +22,10 @@
     <string name="chooser_title" msgid="2262294130493605839">"Escolha um <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para ser gerido pela app &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"A app é necessária para gerir o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A app <xliff:g id="APP_NAME">%2$s</xliff:g> vai poder sincronizar informações, como o nome do autor de uma chamada, interagir com as suas notificações e aceder às autorizações do Telefone, SMS, Contactos, Calendário, Registos de chamadas e Dispositivos próximos."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"A app é necessária para gerir o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A app <xliff:g id="APP_NAME">%2$s</xliff:g> vai poder sincronizar informações, como o nome do autor de uma chamada, e aceder às seguintes autorizações:"</string>
+    <string name="confirmation_title_glasses" msgid="8288346850537727333">"Permita que a app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; faça a gestão do dispositivo &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="profile_name_glasses" msgid="8488394059007275998">"óculos"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Esta app é necessária para gerir o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A app <xliff:g id="APP_NAME">%2$s</xliff:g> vai poder interagir com as suas notificações e aceder às autorizações do Telemóvel, SMS, Contactos, Microfone e Dispositivos próximos."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"A app é necessária para gerir o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A app <xliff:g id="APP_NAME">%2$s</xliff:g> vai poder interagir com estas autorizações:"</string>
+    <string name="summary_glasses_multi_device" msgid="615259525961937348">"Esta app é necessária para gerir o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A app <xliff:g id="APP_NAME">%2$s</xliff:g> vai poder interagir com as suas notificações e aceder às autorizações do Telemóvel, SMS, Contactos, Microfone e Dispositivos próximos."</string>
+    <string name="summary_glasses_single_device" msgid="5783761806783565716">"Esta app fica autorizada a aceder a estas autorizações no seu telemóvel:"</string>
     <string name="title_app_streaming" msgid="2270331024626446950">"Permita que a app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; aceda a estas informações do seu telemóvel"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serviços entre dispositivos"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a pedir autorização em nome do seu dispositivo <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para fazer stream de apps entre os seus dispositivos"</string>
@@ -34,9 +35,8 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Serviços do Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a pedir autorização em nome do seu dispositivo <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para aceder às fotos, ao conteúdo multimédia e às notificações do seu telemóvel"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Permita que a app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; realize esta ação a partir do seu telemóvel"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Serviços entre dispositivos"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a pedir autorização em nome do dispositivo <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para fazer stream de conteúdo para dispositivos próximos"</string>
+    <string name="title_nearby_device_streaming" msgid="7269956847378799794">"Permitir que o dispositivo &lt;strong&gt;<xliff:g id="DEVICE_NAME">%1$s</xliff:g>&lt;/strong&gt; realize esta ação?"</string>
+    <string name="helper_summary_nearby_device_streaming" msgid="2063965070936844876">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a pedir autorização em nome do dispositivo <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para fazer stream de apps e outras funcionalidades do sistema para dispositivos próximos"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Esta app vai poder sincronizar informações, como o nome do autor de uma chamada, entre o telemóvel e o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Esta app vai poder sincronizar informações, como o nome do autor de uma chamada, entre o telemóvel e o dispositivo escolhido."</string>
@@ -57,16 +57,16 @@
     <string name="permission_storage" msgid="6831099350839392343">"Fotos e multimédia"</string>
     <string name="permission_notification" msgid="693762568127741203">"Notificações"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Stream de dispositivo próximo"</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="4241354865859396558">"Não é possível gravar áudio através do microfone"</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_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="5776807830582725074">"Faça stream de conteúdo para um dispositivo próximo"</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>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-pt/strings.xml b/packages/CompanionDeviceManager/res/values-pt/strings.xml
index 29f00ca..6c620df 100644
--- a/packages/CompanionDeviceManager/res/values-pt/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Escolha um <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para ser gerenciado pelo app &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"O app <xliff:g id="APP_NAME">%2$s</xliff:g> é necessário para gerenciar o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Ele poderá sincronizar informações, como o nome de quem está ligando, interagir com suas notificações e acessar as permissões de telefone, SMS, contatos, agenda, registro de chamadas e dispositivos por perto."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"O app <xliff:g id="APP_NAME">%2$s</xliff:g> é necessário para gerenciar seu dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Ele poderá sincronizar informações, como o nome de quem está ligando, e acessar estas permissões:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"óculos"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"O app <xliff:g id="APP_NAME">%2$s</xliff:g> é necessário para gerenciar o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Ele poderá interagir com suas notificações e acessar suas permissões de telefone, SMS, contatos, microfone e dispositivos por perto."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"O app <xliff:g id="APP_NAME">%2$s</xliff:g> é necessário para gerenciar o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Ele poderá interagir com estas permissões:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Permitir que o app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acesse estas informações do smartphone"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Serviços entre dispositivos"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para fazer streaming de apps entre seus dispositivos"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play Services"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do seu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para acessar fotos, mídia e notificações do smartphone."</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Permitir que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; realize esta ação pelo smartphone"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Serviços entre dispositivos"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome de <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para fazer streaming de conteúdo para dispositivos por perto"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"O app poderá sincronizar informações, como o nome de quem está ligando, entre seu smartphone e o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"O app poderá sincronizar informações, como o nome de quem está ligando, entre seu smartphone e o dispositivo escolhido."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Fotos e mídia"</string>
     <string name="permission_notification" msgid="693762568127741203">"Notificações"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streaming em disp. por perto"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Pode gravar áudio usando o microfone"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Fazer streaming de conteúdo para dispositivos por perto"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ro/strings.xml b/packages/CompanionDeviceManager/res/values-ro/strings.xml
index 072a131..240e7da 100644
--- a/packages/CompanionDeviceManager/res/values-ro/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ro/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Alege un profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> pe care să îl gestioneze &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Aplicația este necesară pentru a gestiona <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> va putea să sincronizeze informații, cum ar fi numele unui apelant, să interacționeze cu notificările tale și să îți acceseze permisiunile pentru Telefon, SMS, Agendă, Calendar, Jurnale de apeluri și Dispozitive din apropiere."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Aplicația este necesară pentru a gestiona <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> va putea să sincronizeze informații, cum ar fi numele unui apelant, și să acceseze următoarele permisiuni:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"ochelari"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Această aplicație este necesară pentru a gestiona <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> va putea să interacționeze cu notificările tale și să-ți acceseze permisiunile pentru Telefon, SMS, Agendă, Microfon și Dispozitive din apropiere."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Aplicația este necesară pentru a gestiona <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> va putea să interacționeze cu următoarele permisiuni:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Permite ca &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; să acceseze aceste informații de pe telefon"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Servicii pe mai multe dispozitive"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicită permisiunea pentru <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> de a reda în stream aplicații între dispozitivele tale"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Servicii Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicită permisiunea pentru <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> de a accesa fotografiile, conținutul media și notificările de pe telefon"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Permite ca &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; să realizeze această acțiune de pe telefon"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Servicii pe mai multe dispozitive"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicită permisiunea pentru <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> de a reda în stream conținut pe dispozitivele din apropiere"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"dispozitiv"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Aplicația va putea să sincronizeze informații, cum ar fi numele unui apelant, între telefonul tău și <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Aplicația va putea să sincronizeze informații, cum ar fi numele unui apelant, între telefonul tău și dispozitivul ales."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Fotografii și media"</string>
     <string name="permission_notification" msgid="693762568127741203">"Notificări"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplicații"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streaming pe dispozitivele din apropiere"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <string name="permission_phone_summary" msgid="6684396967861278044">"Poate să facă ș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="4241354865859396558">"Poate înregistra conținut audio folosind microfonul"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Redă în stream conținut pe un dispozitiv din apropiere"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ru/strings.xml b/packages/CompanionDeviceManager/res/values-ru/strings.xml
index 832bfe9..f888ff9 100644
--- a/packages/CompanionDeviceManager/res/values-ru/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ru/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Выберите устройство (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), которым будет управлять приложение &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Это приложение необходимо для управления устройством \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Приложение \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" сможет синхронизировать данные, например журнала звонков, а также получит доступ к уведомлениям и разрешения \"Телефон\", \"SMS\", \"Контакты\", \"Микрофон\" и \"Устройства поблизости\"."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Это приложение необходимо для управления устройством \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Приложение \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" сможет синхронизировать данные, например журнала звонков, и получит следующие разрешения:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"Очки"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Это приложение необходимо для управления устройством \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Приложение \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" получит доступ к уведомлениям, а также разрешения \"Телефон\", SMS, \"Контакты\", \"Микрофон\" и \"Устройства поблизости\"."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Это приложение необходимо для управления устройством \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Приложение \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" получит следующие разрешения:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Разрешите приложению &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; получать эту информацию с вашего телефона"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Сервисы стриминга приложений"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запрашивает разрешение от имени вашего устройства <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, чтобы транслировать приложения между вашими устройствами."</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Сервисы Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запрашивает разрешение от имени вашего устройства <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, чтобы получить доступ к фотографиям, медиаконтенту и уведомлениям на телефоне."</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Разрешить приложению &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; выполнять это действие с вашего телефона"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Сервисы взаимодействия устр-в"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запрашивает разрешение на трансляцию контента на устройства поблизости от имени вашего устройства \"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\"."</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"устройство"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Приложение сможет синхронизировать информацию между телефоном и устройством \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\", например данные из журнала звонков."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Приложение сможет синхронизировать информацию между телефоном и выбранным устройством, например данные из журнала звонков."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Фотографии и медиафайлы"</string>
     <string name="permission_notification" msgid="693762568127741203">"Уведомления"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Приложения"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Трансляция на устройства рядом"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Можно записывать аудио с помощью микрофона"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Приложение сможет находить устройства поблизости, подключаться к ним и определять их относительное местоположение."</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"Чтение всех уведомлений, в том числе сведений о контактах, сообщениях и фотографиях."</string>
     <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="5776807830582725074">"Можно транслировать контент на устройства поблизости"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-si/strings.xml b/packages/CompanionDeviceManager/res/values-si/strings.xml
index 21ed787..8da88cf 100644
--- a/packages/CompanionDeviceManager/res/values-si/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-si/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; මගින් කළමනාකරණය කරනු ලැබීමට <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ක් තෝරන්න"</string>
     <string name="summary_watch" msgid="6566922405914995759">"ඔබේ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> කළමනාකරණය කිරීමට මෙම යෙදුම අවශ්‍යයි. <xliff:g id="APP_NAME">%2$s</xliff:g> හට අමතන කෙනෙකුගේ නම වැනි, තතු සමමුහුර්ත කිරීමට, ඔබේ දැනුම්දීම් සමග අන්තර්ක්‍රියා කිරීමට සහ ඔබේ දුරකථනය, SMS, සම්බන්ධතා, දින දර්ශනය, ඇමතුම් ලොග සහ අවට උපාංග අවසර වෙත ප්‍රවේශ වීමට ඉඩ දෙනු ඇත."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"ඔබේ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> කළමනාකරණය කිරීමට මෙම යෙදුම අවශ්‍යයි. <xliff:g id="APP_NAME">%2$s</xliff:g> හට අමතන කෙනෙකුගේ නම වැනි, තතු සමමුහුර්ත කිරීමට සහ මෙම අවසරවලට ප්‍රවේශ වීමට ඉඩ දෙනු ඇත:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"කණ්ණාඩි"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> කළමනාකරණය කිරීමට මෙම යෙදුම අවශ්‍යයි. <xliff:g id="APP_NAME">%2$s</xliff:g> හට ඔබේ දැනුම්දීම් සමග අන්තර් ක්‍රියා කිරීමට සහ ඔබේ දුරකථනය, SMS, සම්බන්ධතා, මයික්‍රෆෝනය සහ අවට උපාංග අවසර වෙත ප්‍රවේශ වීමට ඉඩ දෙනු ඇත."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> කළමනාකරණය කිරීමට මෙම යෙදුම අවශ්‍යයි. <xliff:g id="APP_NAME">%2$s</xliff:g> හට මෙම අවසර සමග අන්තර්ක්‍රියා කිරීමට අවසර දෙනු ලැබේ:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; හට ඔබගේ දුරකථනයෙන් මෙම තොරතුරුවලට ප්‍රවේශ වීමට ඉඩ දෙන්න"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"හරස්-උපාංග සේවා"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> ඔබගේ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> වෙනුවෙන් ඔබගේ උපාංග අතර යෙදුම් ප්‍රවාහ කිරීමට අවසරය ඉල්ලමින් සිටියි"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play සේවා"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> ඔබගේ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> වෙනුවෙන් ඔබගේ දුරකථනයෙහි ඡායාරූප, මාධ්‍ය සහ දැනුම්දීම් වෙත ප්‍රවේශ වීමට අවසරය ඉල්ලමින් සිටියි"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; හට ඔබේ දුරකථනයෙන් මෙම ක්‍රියාව සිදු කිරීමට ඉඩ දෙන්න"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"හරස්-උපාංග සේවා"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> අවට උපාංග වෙත අන්තර්ගතය ප්‍රවාහ කිරීමට ඔබේ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> වෙනුවෙන් අවසර ඉල්ලයි"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"උපාංගය"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"මෙම යෙදුමට ඔබේ දුරකථනය සහ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> අතර, අමතන කෙනෙකුගේ නම වැනි, තතු සමමුහුර්ත කිරීමට හැකි වනු ඇත."</string>
     <string name="summary_generic" msgid="4988130802522924650">"මෙම යෙදුමට ඔබේ දුරකථනය සහ තෝරා ගත් උපාංගය අතර, අමතන කෙනෙකුගේ නම වැනි, තතු සමමුහුර්ත කිරීමට හැකි වනු ඇත."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"ඡායාරූප සහ මාධ්‍ය"</string>
     <string name="permission_notification" msgid="693762568127741203">"දැනුම්දීම්"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"යෙදුම්"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"ආසන්න උපාංග ප්‍රවාහය"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"මයික්‍රෆෝනය භාවිතයෙන් ශ්‍රව්‍ය පටිගත කළ හැක"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"අවට උපාංගවල සාපේක්ෂ පිහිටීම සොයා ගැනීමට, සම්බන්ධ කිරීමට, සහ තීරණය කිරීමට හැක"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"සම්බන්ධතා, පණිවිඩ සහ ඡායාරූප වැනි තොරතුරු ඇතුළුව සියලු දැනුම්දීම් කියවිය හැකිය"</string>
     <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="5776807830582725074">"අවට උපාංගයකට අන්තර්ගතය ප්‍රවාහ කරන්න"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-sk/strings.xml b/packages/CompanionDeviceManager/res/values-sk/strings.xml
index 805c2c8..d73f0c6 100644
--- a/packages/CompanionDeviceManager/res/values-sk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sk/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Vyberte profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, ktorý bude spravovať aplikácia &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Daná aplikácia sa vyžaduje na správu zariadenia <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> bude môcť synchronizovať informácie, napríklad meno volajúceho, interagovať s vašimi upozorneniami a získavať prístup k povoleniam telefónu, SMS, kontaktov, kalendára, zoznamu hovorov a zariadení v okolí."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Daná aplikácia sa vyžaduje na správu zariadenia <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> bude môcť synchronizovať informácie, napríklad meno volajúceho, a získavať prístup k týmto povoleniam:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"okuliare"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Táto aplikácia sa vyžaduje na správu zariadenia <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> bude môcť interagovať s vašimi upozorneniami a získa prístup k povoleniam pre telefón, SMS, kontakty, mikrofón a zariadenia v okolí."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Daná aplikácia sa vyžaduje na správu zariadenia <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> bude môcť interagovať s týmito povoleniami:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Povoľte aplikácii &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; prístup k týmto informáciám z vášho telefónu"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Služby pre viacero zariadení"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g> vyžaduje povolenie na streamovanie aplikácií medzi vašimi zariadeniami v mene tohto zariadenia (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>)"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Služby Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"Aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g> vyžaduje povolenie na prístup k fotkám, médiám a upozorneniam vášho telefónu v mene tohto zariadenia (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>)"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Povoľte aplikácii &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; vykonať túto akciu z vášho telefónu"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Služby pre viacero zariadení"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> vyžaduje pre zariadenie <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> povolenie streamovať obsah do zariadení v okolí"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"zariadenie"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Táto aplikácia bude môcť synchronizovať informácie, napríklad meno volajúceho, medzi telefónom a zariadením <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Táto aplikácia bude môcť synchronizovať informácie, napríklad meno volajúceho, medzi telefónom a vybraným zariadením."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Fotky a médiá"</string>
     <string name="permission_notification" msgid="693762568127741203">"Upozornenia"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikácie"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streamovať do zariad. v okolí"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Môže nahrávať zvuk pomocou mikrofónu"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Streamovanie obsahu do zariadení v okolí"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-sl/strings.xml b/packages/CompanionDeviceManager/res/values-sl/strings.xml
index f804e69..118e85a 100644
--- a/packages/CompanionDeviceManager/res/values-sl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sl/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Izbira naprave »<xliff:g id="PROFILE_NAME">%1$s</xliff:g>«, ki jo bo upravljala aplikacija &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Ta aplikacija je potrebna za upravljanje naprave »<xliff:g id="DEVICE_NAME">%1$s</xliff:g>«. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> bodo omogočene sinhronizacija podatkov, na primer imena klicatelja, interakcija z obvestili in uporaba dovoljenj Telefon, SMS, Stiki, Koledar, Dnevniki klicev in Naprave v bližini."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Ta aplikacija je potrebna za upravljanje naprave »<xliff:g id="DEVICE_NAME">%1$s</xliff:g>«. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> bosta omogočena sinhronizacija podatkov, na primer imena klicatelja, in dostop do teh dovoljenj:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"očala"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Ta aplikacija je potrebna za upravljanje naprave »<xliff:g id="DEVICE_NAME">%1$s</xliff:g>«. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> bosta omogočeni interakcija z obvestili in uporaba dovoljenj Telefon, SMS, Stiki, Mikrofon in Naprave v bližini."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Ta aplikacija je potrebna za upravljanje naprave »<xliff:g id="DEVICE_NAME">%1$s</xliff:g>«. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> bo omogočena interakcija s temi dovoljenji:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Dovolite, da &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; dostopa do teh podatkov v vašem telefonu"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Storitve za zunanje naprave"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> v imenu naprave »<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>« zahteva dovoljenje za pretočno predvajanje aplikacij v vaših napravah."</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Storitve Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> v imenu naprave »<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>« zahteva dovoljenje za dostop do fotografij, predstavnosti in obvestil v telefonu."</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; omogočite izvajanje tega dejanja iz telefona."</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Storitve za zunanje naprave"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> v imenu naprave »<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>« zahteva dovoljenje za pretočno predvajanje vsebine v napravah v bližini."</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"naprava"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Ta aplikacija bo lahko sinhronizirala podatke, na primer ime klicatelja, v telefonu in napravi »<xliff:g id="DEVICE_NAME">%1$s</xliff:g>«."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Ta aplikacija bo lahko sinhronizirala podatke, na primer ime klicatelja, v telefonu in izbrani napravi."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Fotografije in predstavnost"</string>
     <string name="permission_notification" msgid="693762568127741203">"Obvestila"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacije"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Predvajanje v napravi v bližini"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Lahko uporablja mikrofon za snemanje zvoka."</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Pretočno predvajanje vsebine v napravi v bližini"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-sq/strings.xml b/packages/CompanionDeviceManager/res/values-sq/strings.xml
index 0ca0173..472fcf3 100644
--- a/packages/CompanionDeviceManager/res/values-sq/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sq/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Zgjidh \"<xliff:g id="PROFILE_NAME">%1$s</xliff:g>\" që do të menaxhohet nga &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Aplikacioni nevojitet për të menaxhuar profilin tënd të <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> do të lejohet të sinkronizojë informacione, si p.sh. emri i dikujt që po telefonon, të ndërveprojë me njoftimet e tua dhe të ketë qasje te lejet e \"Telefonit\", \"SMS-ve\", \"Kontakteve\", \"Kalendarit\", \"Evidencave të telefonatave\" dhe \"Pajisjeve në afërsi\"."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Aplikacioni nevojitet për të menaxhuar profilin tënd të <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> do të lejohet të sinkronizojë informacione, si p.sh. emri i dikujt që po telefonon dhe të ketë qasje te këto leje:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"syzet"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Ky aplikacion nevojitet për të menaxhuar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> do të lejohet të ndërveprojë me njoftimet e tua dhe të ketë qasje te lejet e \"Telefonit\", \"SMS-ve\", \"Kontakteve\", \"Mikrofonit\" dhe të \"Pajisjeve në afërsi\"."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Aplikacioni nevojitet për të menaxhuar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> do të lejohet të ndërveprojë me këto leje:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Lejo që &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; të ketë qasje në këtë informacion nga telefoni yt"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Shërbimet mes pajisjeve"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> po kërkon leje në emër të <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> për të transmetuar aplikacione ndërmjet pajisjeve të tua"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Shërbimet e Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> po kërkon leje në emër të <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> për të marrë qasje te fotografitë, media dhe njoftimet e telefonit tënd"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Lejo &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; të kryejë këtë veprim nga telefoni yt"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Shërbimet mes pajisjeve"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> po kërkon leje në emër të <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> për të transmetuar përmbajtje te pajisjet në afërsi"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"pajisja"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Ky aplikacion do të mund të sinkronizojë informacione, si p.sh emri i dikujt që po telefonon, mes telefonit tënd dhe <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Ky aplikacion do të mund të sinkronizojë informacione, si p.sh emri i dikujt që po telefonon, mes telefonit tënd dhe pajisjes së zgjedhur."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Fotografitë dhe media"</string>
     <string name="permission_notification" msgid="693762568127741203">"Njoftimet"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacionet"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Transmetim: Pajisjet në afërsi"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Mund të regjistrojë audio duke përdorur mikrofonin"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Transmeto përmbajtje te një pajisje në afërsi"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-sr/strings.xml b/packages/CompanionDeviceManager/res/values-sr/strings.xml
index 8d13c89..8dbcd2a 100644
--- a/packages/CompanionDeviceManager/res/values-sr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sr/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Одаберите <xliff:g id="PROFILE_NAME">%1$s</xliff:g> којим ће управљати апликација &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Апликација је потребна за управљање уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ће добити дозволу за синхронизовање информација, попут особе која упућује позив, за интеракцију са обавештењима и приступ дозволама за телефон, SMS, контакте, календар, евиденције позива и уређаје у близини."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Апликација је потребна за управљање уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ће добити дозволу за синхронизацију информација, попут особе која упућује позив, као за приступ следећим дозволама:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"наочаре"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Ова апликација је потребна за управљање уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ће добити дозволу за интеракцију са обавештењима и приступ дозволама за телефон, SMS, контакте, микрофон и уређаје у близини."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Апликација је потребна за управљање уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ће добити дозволу за интеракцију са овим дозволама:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Дозволите да &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; приступа овим информацијама са телефона"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Услуге на више уређаја"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> захтева дозволу у име уређаја <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> за стримовање апликација између уређаја"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play услуге"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"Апликација <xliff:g id="APP_NAME">%1$s</xliff:g> захтева дозволу у име уређаја <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> за приступ сликама, медијском садржају и обавештењима са телефона"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Дозволите да &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; обавља ову радњу са телефона"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Услуге на више уређаја"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Апликација <xliff:g id="APP_NAME">%1$s</xliff:g> захтева дозволу у име уређаја <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> да стримује садржај на уређаје у близини"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"уређај"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Ова апликација ће моћи да синхронизује податке, попут имена особе која упућује позив, између телефона и уређаја <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Ова апликација ће моћи да синхронизује податке, попут имена особе која упућује позив, између телефона и одабраног уређаја."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Слике и медији"</string>
     <string name="permission_notification" msgid="693762568127741203">"Обавештења"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Апликације"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Стримовање, уређаји у близини"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Може да снима звук помоћу микрофона"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Може да проналази и утврђује релативну позицију уређаја у близини, као и да се повезује са њима"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"Може да чита сва обавештења, укључујући информације попут контаката, порука и слика"</string>
     <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="5776807830582725074">"Стримујте садржај на уређај у близини"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-sv/strings.xml b/packages/CompanionDeviceManager/res/values-sv/strings.xml
index 82c7e41..3545c00 100644
--- a/packages/CompanionDeviceManager/res/values-sv/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sv/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Välj en <xliff:g id="PROFILE_NAME">%1$s</xliff:g> för hantering av &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Appen behövs för att hantera <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillåtelse att synkronisera information, till exempel namnet på någon som ringer, interagera med dina aviseringar och får åtkomst till behörigheterna Telefon, Sms, Kontakter, Kalender, Samtalsloggar och Enheter i närheten."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Appen behövs för att hantera <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillåtelse att synkronisera information, till exempel namnet på någon som ringer, och får åtkomst till följande behörigheter:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"glasögon"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Appen behövs för att hantera <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillåtelse att interagera med dina aviseringar och får åtkomst till behörigheterna Telefon, Sms, Kontakter, Mikrofon och Enheter i närheten."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Appen behövs för att hantera <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillåtelse att interagera med följande behörigheter:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Ge &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; åtkomstbehörighet till denna information på telefonen"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjänster för flera enheter"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> begär behörighet att låta <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> streama appar mellan enheter"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play-tjänster"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> begär behörighet att ge <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> åtkomst till foton, mediefiler och aviseringar på telefonen"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Tillåt att &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; utför denna åtgärd på din telefon"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Tjänster för flera enheter"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> begär behörighet för att streama innehåll till enheter i närheten för din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"enhet"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Den här appen kommer att kunna synkronisera information mellan telefonen och <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, till exempel namnet på någon som ringer."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Den här appen kommer att kunna synkronisera information mellan telefonen och den valda enheten, till exempel namnet på någon som ringer."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Foton och media"</string>
     <string name="permission_notification" msgid="693762568127741203">"Aviseringar"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Appar"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"En enhet i närheten streamar"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Kan spela in ljud med mikrofonen"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Streamar innehåll till en enhet i närheten"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-sw/strings.xml b/packages/CompanionDeviceManager/res/values-sw/strings.xml
index 37354bb..3e3ee8f 100644
--- a/packages/CompanionDeviceManager/res/values-sw/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sw/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Chagua <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ili idhibitiwe na &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Programu hii inahitajika ili udhibiti <xliff:g id="DEVICE_NAME">%1$s</xliff:g> yako. <xliff:g id="APP_NAME">%2$s</xliff:g> itaruhusiwa kusawazisha maelezo, kama vile jina la mtu anayepiga simu, kutumia arifa zako na ruhusa zako za Simu, SMS, Anwani, Maikrofoni na vifaa vilivyo Karibu."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Programu hii inahitajika ili udhibiti <xliff:g id="DEVICE_NAME">%1$s</xliff:g> yako. <xliff:g id="APP_NAME">%2$s</xliff:g> itaruhusiwa kusawazisha maelezo, kama vile jina la mtu anayepiga simu na kufikia ruhusa hizi:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"miwani"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Programu hii inahitajika ili udhibiti <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> itaruhusiwa kutumia arifa zako na kufikia ruhusa zako za Simu, SMS, Anwani, Maikrofoni na Vifaa vilivyo Karibu."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Programu inahitajika ili udhibiti <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> itaruhusiwa kufikia ruhusa hizi:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Ruhusu &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ifikie maelezo haya kutoka kwenye simu yako"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Huduma za kifaa kilichounganishwa kwingine"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Programu ya <xliff:g id="APP_NAME">%1$s</xliff:g> inaomba ruhusa kwa niaba ya <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yako ili itiririshe programu kati ya vifaa vyako"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Huduma za Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"Programu ya <xliff:g id="APP_NAME">%1$s</xliff:g> inaomba ruhusa kwa niaba ya <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yako ili ifikie picha, maudhui na arifa za simu yako"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Ruhusu &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; itekeleze kitendo hiki kwenye simu yako"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Huduma za kifaa kilichounganishwa kwingine"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> inaomba ruhusa kwa niaba ya <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ili itiririshe maudhui kwenye vifaa vilivyo karibu"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"kifaa"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Programu hii itaweza kusawazisha maelezo, kama vile jina la mtu anayepiga simu, kati ya simu na <xliff:g id="DEVICE_NAME">%1$s</xliff:g> yako."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Programu hii itaweza kusawazisha maelezo, kama vile jina la mtu anayepiga simu, kati ya simu yako na kifaa ulichochagua."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Picha na maudhui"</string>
     <string name="permission_notification" msgid="693762568127741203">"Arifa"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Programu"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Kutiririsha kwenye Kifaa kilicho Karibu"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Inaweza kurekodi sauti ikitumia maikrofoni"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Kutiririsha maudhui kwenye kifaa kilicho karibu"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ta/strings.xml b/packages/CompanionDeviceManager/res/values-ta/strings.xml
index 2e1c872..ab05c26 100644
--- a/packages/CompanionDeviceManager/res/values-ta/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ta/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ஆப்ஸ் நிர்வகிக்கக்கூடிய <xliff:g id="PROFILE_NAME">%1$s</xliff:g> தேர்ந்தெடுக்கப்பட வேண்டும்"</string>
     <string name="summary_watch" msgid="6566922405914995759">"உங்கள் <xliff:g id="DEVICE_NAME">%1$s</xliff:g> சாதனத்தை நிர்வகிக்க இந்த ஆப்ஸ் தேவை. தகவலை (அழைப்பவரின் பெயர் போன்றவை) ஒத்திசைத்தல், உங்கள் அறிவிப்புகளைப் பார்த்தல் போன்றவற்றுக்கான அனுமதியையும் உங்கள் மொபைல், மெசேஜ், தொடர்புகள், கேலெண்டர், அழைப்புப் பதிவுகள், அருகிலுள்ள சாதனங்கள் ஆகியவற்றுக்கான அணுகலையும் <xliff:g id="APP_NAME">%2$s</xliff:g> ஆப்ஸ் பெறும்."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"உங்கள் <xliff:g id="DEVICE_NAME">%1$s</xliff:g> சாதனத்தை நிர்வகிக்க இந்த ஆப்ஸ் தேவை. தகவலை (அழைப்பவரின் பெயர் போன்றவை) ஒத்திசைப்பதற்கும் இந்த அனுமதிகளைப் பயன்படுத்துவதற்கும் <xliff:g id="APP_NAME">%2$s</xliff:g> ஆப்ஸுக்கு அனுமதி வழங்கப்படும்:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"கிளாஸஸ்"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> சாதனத்தை நிர்வகிக்க இந்த ஆப்ஸ் தேவை. உங்கள் மொபைல், மெசேஜ், தொடர்புகள், மைக்ரோஃபோன், அருகிலுள்ள சாதனங்கள் ஆகியவற்றுக்கான அணுகலையும் உங்கள் அறிவிப்புகளைப் பார்ப்பதற்கான அனுமதியையும் <xliff:g id="APP_NAME">%2$s</xliff:g> பெறும்."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> சாதனத்தை நிர்வகிக்க இந்த ஆப்ஸ் தேவை. இந்த அனுமதிகளைப் பயன்படுத்த <xliff:g id="APP_NAME">%2$s</xliff:g> ஆப்ஸ் அனுமதிக்கப்படும்:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"மொபைலில் உள்ள இந்தத் தகவல்களை அணுக, &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ஆப்ஸை அனுமதிக்கவும்"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"பன்முக சாதன சேவைகள்"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"உங்கள் சாதனங்களுக்கு இடையே ஆப்ஸை ஸ்ட்ரீம் செய்ய உங்கள் <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> சார்பாக <xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸ் அனுமதியைக் கோருகிறது"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play சேவைகள்"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"உங்கள் மொபைலில் உள்ள படங்கள், மீடியா, அறிவிப்புகள் ஆகியவற்றை அணுக உங்கள் <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> சார்பாக <xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸ் அனுமதியைக் கோருகிறது"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"உங்கள் மொபைலில் இந்தச் செயலைச் செய்ய &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ஆப்ஸை அனுமதியுங்கள்"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"பன்முக சாதன சேவைகள்"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"அருகிலுள்ள சாதனங்களுடன் உள்ளடக்கத்தை ஸ்ட்ரீம் செய்ய உங்கள் <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> சார்பாக <xliff:g id="APP_NAME">%1$s</xliff:g> அனுமதி கோருகிறது"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"சாதனம்"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"இந்த ஆப்ஸால் தகவலை (அழைப்பவரின் பெயர் போன்றவை) உங்கள் மொபைலிலும் <xliff:g id="DEVICE_NAME">%1$s</xliff:g> சாதனத்திலும் ஒத்திசைக்க முடியும்."</string>
     <string name="summary_generic" msgid="4988130802522924650">"இந்த ஆப்ஸால் தகவலை (அழைப்பவரின் பெயர் போன்றவை) உங்கள் மொபைலிலும் தேர்ந்தெடுக்கப்பட்ட சாதனத்திலும் ஒத்திசைக்க முடியும்."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"படங்கள் மற்றும் மீடியா"</string>
     <string name="permission_notification" msgid="693762568127741203">"அறிவிப்புகள்"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"ஆப்ஸ்"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"அருகிலுள்ள சாதன ஸ்ட்ரீமிங்"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"மைக்ரோஃபோனைப் பயன்படுத்தி ஆடியோவை ரெக்கார்டு செய்யலாம்"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"அருகிலுள்ள சாதனங்களைக் கண்டறியலாம் அவற்றுடன் இணையலாம் அவற்றின் தூரத்தைத் தீர்மானிக்கலாம்"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"தொடர்புகள், மெசேஜ்கள், படங்கள் போன்ற தகவல்கள் உட்பட அனைத்து அறிவிப்புகளையும் படிக்க முடியும்"</string>
     <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="5776807830582725074">"அருகிலுள்ள சாதனத்தில் உள்ளடக்கத்தை ஸ்ட்ரீம் செய்யலாம்"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-te/strings.xml b/packages/CompanionDeviceManager/res/values-te/strings.xml
index 4c193c5..3b1e75e 100644
--- a/packages/CompanionDeviceManager/res/values-te/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-te/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ద్వారా మేనేజ్ చేయబడటానికి ఒక <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ను ఎంచుకోండి"</string>
     <string name="summary_watch" msgid="6566922405914995759">"మీ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>‌ను మేనేజ్ చేయడానికి ఈ యాప్ అవసరం. కాల్ చేస్తున్న వారి పేరు వంటి సమాచారాన్ని సింక్ చేయడానికి, మీ నోటిఫికేషన్‌లతో ఇంటరాక్ట్ అవ్వడానికి, అలాగే మీ ఫోన్, SMS, కాంటాక్ట్‌లు, క్యాలెండర్, కాల్ లాగ్‌లు, సమీపంలోని పరికరాల అనుమతులను యాక్సెస్ చేయడానికి <xliff:g id="APP_NAME">%2$s</xliff:g> అనుమతించబడుతుంది."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"మీ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>‌ను మేనేజ్ చేయడానికి ఈ యాప్ అవసరం. కాల్ చేస్తున్న వారి పేరు వంటి సమాచారాన్ని సింక్ చేయడానికి, ఈ అనుమతులను యాక్సెస్ చేయడానికి <xliff:g id="APP_NAME">%2$s</xliff:g> అనుమతించబడుతుంది:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"గ్లాసెస్"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‌ను మేనేజ్ చేయడానికి ఈ యాప్ అవసరం. మీ నోటిఫికేషన్‌లతో ఇంటరాక్ట్ అవ్వడానికి, అలాగే మీ ఫోన్, SMS, కాంటాక్ట్‌లు, మైక్రోఫోన్, సమీపంలోని పరికరాల అనుమతులను యాక్సెస్ చేయడానికి <xliff:g id="APP_NAME">%2$s</xliff:g> అనుమతించబడుతుంది."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‌ను మేనేజ్ చేయడానికి ఈ యాప్ అవసరం. ఈ అనుమతులతో ఇంటరాక్ట్ అవ్వడానికి <xliff:g id="APP_NAME">%2$s</xliff:g> అనుమతించబడుతుంది:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"మీ ఫోన్ నుండి ఈ సమాచారాన్ని యాక్సెస్ చేయడానికి &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; యాప్‌ను అనుమతించండి"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"మీ పరికరాల మధ్య యాప్‌లను స్ట్రీమ్ చేయడానికి <xliff:g id="APP_NAME">%1$s</xliff:g> మీ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> తరఫున అనుమతిని రిక్వెస్ట్ చేస్తోంది"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play సర్వీసులు"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> మీ ఫోన్‌లోని ఫోటోలను, మీడియాను, ఇంకా నోటిఫికేషన్‌లను యాక్సెస్ చేయడానికి మీ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> తరఫున అనుమతిని రిక్వెస్ట్ చేస్తోంది"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"మీ ఫోన్ నుండి ఈ చర్యను అమలు చేయడానికి &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;‌ను అనుమతించండి"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"క్రాస్-డివైజ్ సర్వీస్‌లు"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"సమీపంలోని పరికరాలకు కంటెంట్‌ను స్ట్రీమ్ చేయడానికి <xliff:g id="APP_NAME">%1$s</xliff:g> మీ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> తరఫున అనుమతిని రిక్వెస్ట్ చేస్తోంది"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"పరికరం"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"కాల్ చేస్తున్న వారి పేరు వంటి సమాచారాన్ని ఈ యాప్ మీ ఫోన్, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> మధ్య సింక్ చేయగలుగుతుంది."</string>
     <string name="summary_generic" msgid="4988130802522924650">"కాల్ చేస్తున్న వారి పేరు వంటి సమాచారాన్ని ఈ యాప్ మీ ఫోన్, ఎంచుకున్న పరికరం మధ్య సింక్ చేయగలుగుతుంది."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"ఫోటోలు, మీడియా"</string>
     <string name="permission_notification" msgid="693762568127741203">"నోటిఫికేషన్‌లు"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"యాప్‌లు"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"సమీపంలోని పరికర స్ట్రీమింగ్"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"మైక్రోఫోన్‌ను ఉపయోగించి ఆడియోను రికార్డ్ చేయవచ్చు"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"సమీపంలోని పరికరాలను కనుగొనగలదు, వాటికి కనెక్ట్ అవ్వగలదు, అవి ఎంత దూరంలో ఉన్నాయో తెలుసుకొనగలదు"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"కాంటాక్ట్‌లు, మెసేజ్‌లు, ఫోటోల వంటి సమాచారంతో సహా అన్ని నోటిఫికేషన్‌లను చదవగలదు"</string>
     <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="5776807830582725074">"సమీపంలోని పరికరానికి కంటెంట్‌ను స్ట్రీమ్ చేయండి"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-th/strings.xml b/packages/CompanionDeviceManager/res/values-th/strings.xml
index 7438ab32..abf7ac8 100644
--- a/packages/CompanionDeviceManager/res/values-th/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-th/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"เลือก<xliff:g id="PROFILE_NAME">%1$s</xliff:g>ที่จะให้มีการจัดการโดย &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"ต้องใช้แอปนี้ในการจัดการ<xliff:g id="DEVICE_NAME">%1$s</xliff:g> <xliff:g id="APP_NAME">%2$s</xliff:g> จะได้รับอนุญาตให้ซิงค์ข้อมูล เช่น ชื่อของบุคคลที่โทรเข้ามา โต้ตอบกับการแจ้งเตือน รวมถึงมีสิทธิ์เข้าถึงโทรศัพท์, SMS, รายชื่อติดต่อ, ปฏิทิน, บันทึกการโทร และอุปกรณ์ที่อยู่ใกล้เคียง"</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"ต้องใช้แอปนี้ในการจัดการ<xliff:g id="DEVICE_NAME">%1$s</xliff:g> <xliff:g id="APP_NAME">%2$s</xliff:g> จะได้รับอนุญาตให้ซิงค์ข้อมูล เช่น ชื่อของบุคคลที่โทรเข้ามา และมีสิทธิ์เข้าถึงสิ่งต่างๆ ต่อไปนี้"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"แว่นตา"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"ต้องใช้แอปนี้ในการจัดการ<xliff:g id="DEVICE_NAME">%1$s</xliff:g> <xliff:g id="APP_NAME">%2$s</xliff:g> จะได้รับอนุญาตให้โต้ตอบกับการแจ้งเตือนและมีสิทธิ์เข้าถึงโทรศัพท์, SMS, รายชื่อติดต่อ, ไมโครโฟน และอุปกรณ์ที่อยู่ใกล้เคียง"</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"ต้องใช้แอปนี้ในการจัดการ<xliff:g id="DEVICE_NAME">%1$s</xliff:g> <xliff:g id="APP_NAME">%2$s</xliff:g> จะได้รับอนุญาตให้โต้ตอบกับสิทธิ์เหล่านี้"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"อนุญาตให้ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; เข้าถึงข้อมูลนี้จากโทรศัพท์ของคุณ"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"บริการหลายอุปกรณ์"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังขอสิทธิ์ในนามของ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> เพื่อสตรีมแอประหว่างอุปกรณ์ต่างๆ ของคุณ"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"บริการ Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังขอสิทธิ์ในนามของ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> เพื่อเข้าถึงรูปภาพ สื่อ และการแจ้งเตือนในโทรศัพท์ของคุณ"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"อนุญาตให้ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ทำงานนี้จากโทรศัพท์"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"บริการหลายอุปกรณ์"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังขอสิทธิ์ในนามของ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> เพื่อสตรีมเนื้อหาไปยังอุปกรณ์ที่อยู่ใกล้เคียง"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"อุปกรณ์"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"แอปนี้จะสามารถซิงค์ข้อมูล เช่น ชื่อของบุคคลที่โทรเข้ามา ระหว่างโทรศัพท์ของคุณและ<xliff:g id="DEVICE_NAME">%1$s</xliff:g>ได้"</string>
     <string name="summary_generic" msgid="4988130802522924650">"แอปนี้จะสามารถซิงค์ข้อมูล เช่น ชื่อของบุคคลที่โทรเข้ามา ระหว่างโทรศัพท์ของคุณและอุปกรณ์ที่เลือกไว้ได้"</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"รูปภาพและสื่อ"</string>
     <string name="permission_notification" msgid="693762568127741203">"การแจ้งเตือน"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"แอป"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"การสตรีมไปยังอุปกรณ์ที่อยู่ใกล้เคียง"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"บันทึกเสียงโดยใช้ไมโครโฟนได้"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"สามารถค้นหา เชื่อมต่อ และระบุตำแหน่งซึ่งสัมพันธ์กับอุปกรณ์ที่อยู่ใกล้เคียง"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"สามารถอ่านการแจ้งเตือนทั้งหมด รวมถึงข้อมูลอย่างรายชื่อติดต่อ ข้อความ และรูปภาพ"</string>
     <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="5776807830582725074">"สตรีมเนื้อหาไปยังอุปกรณ์ที่อยู่ใกล้เคียง"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-tl/strings.xml b/packages/CompanionDeviceManager/res/values-tl/strings.xml
index dd9a0f6..717ce38 100644
--- a/packages/CompanionDeviceManager/res/values-tl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tl/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Pumili ng <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para pamahalaan ng &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Kailangan ang app para mapamahalaan ang iyong <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Papayagan ang <xliff:g id="APP_NAME">%2$s</xliff:g> na mag-sync ng impormasyon, tulad ng pangalan ng isang taong tumatawag, makipag-ugnayan sa mga notification mo, at ma-access ang iyong mga pahintulot sa Telepono, SMS, Mga Contact, Kalendaryo, Mga log ng tawag, at Mga kalapit na device."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Kailangan ang app para mapamahalaan ang iyong <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Papayagan ang <xliff:g id="APP_NAME">%2$s</xliff:g> na mag-sync ng impormasyon, tulad ng pangalan ng isang taong tumatawag, at na ma-access ang mga pahintulot na ito:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"salamin"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Kailangan ang app na ito para mapamahalaan ang <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Papayagan ang <xliff:g id="APP_NAME">%2$s</xliff:g> na makipag-ugnayan sa mga notification mo at i-access ang iyong mga pahintulot sa Telepono, SMS, Mga Contact, Mikropono, at Mga kalapit na device."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Kailangan ang app para mapamahalaan ang <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Papayagan ang <xliff:g id="APP_NAME">%2$s</xliff:g> na makipag-ugnayan sa mga pahintulot na ito:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Payagan ang &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; na i-access ang impormasyong ito sa iyong telepono"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Mga cross-device na serbisyo"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Ang <xliff:g id="APP_NAME">%1$s</xliff:g> ay humihiling ng pahintulot sa ngalan ng iyong <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para mag-stream ng mga app sa pagitan ng mga device mo"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Mga serbisyo ng Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"Ang <xliff:g id="APP_NAME">%1$s</xliff:g> ay humihiling ng pahintulot sa ngalan ng iyong <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para i-access ang mga larawan, media, at notification ng telepono mo"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Payagan ang &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; na gawin ang pagkilos na ito mula sa iyong telepono"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Mga cross-device na serbisyo"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Humihiling ng pahintulot ang <xliff:g id="APP_NAME">%1$s</xliff:g> sa ngalan ng iyong <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para mag-stream ng content sa mga kalapit na device"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Magagawa ng app na ito na mag-sync ng impormasyon, tulad ng pangalan ng isang taong tumatawag, sa pagitan ng iyong telepono at ng <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Magagawa ng app na ito na mag-sync ng impormasyon, tulad ng pangalan ng isang taong tumatawag, sa pagitan ng iyong telepono at ng napiling device."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Mga larawan at media"</string>
     <string name="permission_notification" msgid="693762568127741203">"Mga Notification"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Mga App"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streaming sa Kalapit na Device"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Puwedeng mag-record ng audio gamit ang mikropono"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Mag-stream ng content sa kalapit na device"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-tr/strings.xml b/packages/CompanionDeviceManager/res/values-tr/strings.xml
index 0bf5c1f..533e1f9 100644
--- a/packages/CompanionDeviceManager/res/values-tr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tr/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; tarafından yönetilecek bir <xliff:g id="PROFILE_NAME">%1$s</xliff:g> seçin"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Bu uygulama, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazınızın yönetilmesi için gereklidir. <xliff:g id="APP_NAME">%2$s</xliff:g> adlı uygulamanın arayan kişinin adı gibi bilgileri senkronize etmesine, bildirimlerinizle etkileşimde bulunup Telefon, SMS, Kişiler, Takvim, Arama kayıtları ve Yakındaki cihazlar izinlerine erişmesine izin verilir."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Bu uygulama, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazınızın yönetilmesi için gereklidir. <xliff:g id="APP_NAME">%2$s</xliff:g> adlı uygulamanın arayan kişinin adı gibi bilgileri senkronize etmesine ve aşağıdaki izinlere erişmesine izin verilir:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"glasses"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Bu uygulama, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazının yönetilmesi için gereklidir. <xliff:g id="APP_NAME">%2$s</xliff:g> adlı uygulamanın bildirimlerinizle etkileşimde bulunup Telefon, SMS, Kişiler, Mikrofon ve Yakındaki cihazlar izinlerine erişmesine izin verilir."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Uygulama, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazının yönetilmesi için gereklidir. <xliff:g id="APP_NAME">%2$s</xliff:g> uygulamasının şu izinlerle etkileşime girmesine izin verilir:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; uygulamasının, telefonunuzdaki bu bilgilere erişmesine izin verin"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Cihazlar arası hizmetler"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g>, cihazlarınız arasında uygulama akışı gerçekleştirmek için <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> cihazınız adına izin istiyor"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play hizmetleri"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g>, telefonunuzdaki fotoğraf, medya ve bildirimlere erişmek için <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> cihazınız adına izin istiyor"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; uygulamasının bu işlemi telefonunuzda gerçekleştirmesine izin verin"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Cihazlar arası hizmetler"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g>, yakındaki cihazlarda içerikleri canlı oynatmak için <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> cihazınız adına izin istiyor"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"cihaz"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Bu uygulama, arayan kişinin adı gibi bilgileri telefonunuz ve <xliff:g id="DEVICE_NAME">%1$s</xliff:g> adlı cihaz arasında senkronize edebilir."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Bu uygulama, arayan kişinin adı gibi bilgileri telefonunuz ve seçili cihaz arasında senkronize edebilir."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Fotoğraflar ve medya"</string>
     <string name="permission_notification" msgid="693762568127741203">"Bildirimler"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Uygulamalar"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Yakındaki Cihazda Oynatma"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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ı okuma ve yazma"</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="4241354865859396558">"Mikrofonu kullanarak ses kaydedebilir"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <string name="permission_app_streaming_summary" msgid="606923325679670624">"Telefonunuzun uygulamalarını yayınlama"</string>
     <string name="permission_storage_summary" msgid="3918240895519506417"></string>
-    <string name="permission_nearby_device_streaming_summary" msgid="5776807830582725074">"Yakındaki bir cihazda içerikleri canlı oynatın"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-uk/strings.xml b/packages/CompanionDeviceManager/res/values-uk/strings.xml
index 29a55da..01029ae 100644
--- a/packages/CompanionDeviceManager/res/values-uk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-uk/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Виберіть <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, яким керуватиме додаток &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Цей додаток потрібен, щоб керувати пристроєм \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Додаток <xliff:g id="APP_NAME">%2$s</xliff:g> зможе синхронізувати інформацію (наприклад, ім’я абонента, який викликає), взаємодіяти з вашими сповіщеннями й отримає дозволи \"Телефон\", \"SMS\", \"Контакти\", \"Календар\", \"Журнали викликів\" і \"Пристрої поблизу\"."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Цей додаток потрібен, щоб керувати пристроєм \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Додаток <xliff:g id="APP_NAME">%2$s</xliff:g> зможе синхронізувати інформацію (наприклад, ім’я абонента, який викликає) і отримає такі дозволи:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"окуляри"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Цей додаток потрібен, щоб керувати пристроєм \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Додаток <xliff:g id="APP_NAME">%2$s</xliff:g> зможе взаємодіяти з вашими сповіщеннями й отримає дозволи \"Телефон\", \"SMS\", \"Контакти\", \"Мікрофон\" і \"Пристрої поблизу\"."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Цей додаток потрібен, щоб керувати пристроєм \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Додаток <xliff:g id="APP_NAME">%2$s</xliff:g> зможе взаємодіяти з такими дозволами:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Надайте додатку &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; доступ до цієї інформації з телефона"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Сервіси для кількох пристроїв"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> від імені вашого пристрою <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> запитує дозвіл на трансляцію додатків між вашими пристроями"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Сервіси Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> від імені вашого пристрою <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> запитує дозвіл на доступ до фотографій, медіафайлів і сповіщень вашого телефона"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Дозволити додатку &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; виконувати цю дію на вашому телефоні"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Сервіси для кількох пристроїв"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> від імені вашого пристрою (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) запитує дозвіл на трансляцію контенту на пристрої поблизу"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"пристрій"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Цей додаток зможе синхронізувати інформацію (наприклад, ім’я абонента, який викликає) між телефоном і пристроєм \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Цей додаток зможе синхронізувати інформацію (наприклад, ім’я абонента, який викликає) між телефоном і вибраним пристроєм."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Фотографії та медіафайли"</string>
     <string name="permission_notification" msgid="693762568127741203">"Сповіщення"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Додатки"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Трансляція на пристрої поблизу"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Може записувати звук за допомогою мікрофона"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Може знаходити пристрої поблизу, підключатися до них і визначати їх відносне розташування"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"Може читати всі сповіщення, зокрема таку інформацію, як контакти, повідомлення та фотографії"</string>
     <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="5776807830582725074">"Транслювати контент на пристрої поблизу"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ur/strings.xml b/packages/CompanionDeviceManager/res/values-ur/strings.xml
index c38217a..a65cb66 100644
--- a/packages/CompanionDeviceManager/res/values-ur/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ur/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"‏&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; کے ذریعے نظم کئے جانے کیلئے <xliff:g id="PROFILE_NAME">%1$s</xliff:g> کو منتخب کریں"</string>
     <string name="summary_watch" msgid="6566922405914995759">"‏آپ کے <xliff:g id="DEVICE_NAME">%1$s</xliff:g> کا نظم کرنے کے لیے، ایپ کی ضرورت ہے۔ <xliff:g id="APP_NAME">%2$s</xliff:g> کو کسی کے کال کرنے والے کے نام، آپ کی اطلاعات کے ساتھ تعامل، آپ کے فون، SMS، رابطے، کیلنڈر، کال لاگز اور قریبی آلات کی اجازتوں جیسی معلومات کی مطابقت پذیری کی اجازت ہوگی۔"</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"آپ کے <xliff:g id="DEVICE_NAME">%1$s</xliff:g> کا نظم کرنے کے لیے، ایپ کی ضرورت ہے۔ <xliff:g id="APP_NAME">%2$s</xliff:g> کو کسی کال کرنے والے کے نام اور ان اجازتوں تک رسائی جیسی معلومات کی مطابقت پذیری کی اجازت ہوگی:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"گلاسز"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"‏<xliff:g id="DEVICE_NAME">%1$s</xliff:g> کا نظم کرنے کے لیے، اس ایپ کی ضرورت ہے۔ <xliff:g id="APP_NAME">%2$s</xliff:g> کو آپ کی اطلاعات کے ساتھ تعامل کرنے اور آپ کے فون، SMS، رابطوں، مائیکروفون اور قریبی آلات کی اجازتوں تک رسائی کی اجازت ہوگی۔"</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> کا نظم کرنے کے لیے، ایپ کی ضرورت ہے۔ <xliff:g id="APP_NAME">%2$s</xliff:g> کو ان اجازتوں کے ساتھ تعامل کرنے کی اجازت ہوگی:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"‏اپنے فون سے ان معلومات تک رسائی حاصل کرنے کی &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; کو اجازت دیں"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"کراس ڈیوائس سروسز"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> ایپ آپ کے <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> کی جانب سے آپ کے آلات کے درمیان ایپس کی سلسلہ بندی کرنے کی اجازت کی درخواست کر رہی ہے"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"‏Google Play سروسز"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> ایپ آپ کے <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> کی جانب سے آپ کے فون کی تصاویر، میڈیا اور اطلاعات تک رسائی کی اجازت طلب کر رہی ہے"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"‏اپنے فون سے اس کارروائی کو انجام دینے کے لیے ‎&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;‎ کو اجازت دیں"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"کراس آلے کی سروسز"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> ایپ آپ کے <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> کی جانب سے مواد کے قریبی آلات کی سلسلہ بندی کرنے کی اجازت کی درخواست کر رہی ہے"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"آلہ"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"یہ ایپ آپ کے فون اور <xliff:g id="DEVICE_NAME">%1$s</xliff:g> کے درمیان معلومات، جیسے کسی کال کرنے والے کے نام، کی مطابقت پذیری کر سکے گی۔"</string>
     <string name="summary_generic" msgid="4988130802522924650">"یہ ایپ آپ کے فون اور منتخب کردہ آلے کے درمیان معلومات، جیسے کسی کال کرنے والے کے نام، کی مطابقت پذیری کر سکے گی۔"</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"تصاویر اور میڈیا"</string>
     <string name="permission_notification" msgid="693762568127741203">"اطلاعات"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"ایپس"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"قریبی آلات کی سلسلہ بندی"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"مائیکروفون کا استعمال کر کے آڈیو ریکارڈ کر سکتے ہیں"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"قریبی آلات کی متعلقہ پوزیشن تلاش کر سکتا ہے، ان سے منسلک ہو سکتا ہے اور اس کا تعین کر سکتا ہے"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"رابطوں، پیغامات اور تصاویر جیسی معلومات سمیت تمام اطلاعات پڑھ سکتے ہیں"</string>
     <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="5776807830582725074">"مواد کی قریبی آلے سے سلسلہ بندی کریں"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-uz/strings.xml b/packages/CompanionDeviceManager/res/values-uz/strings.xml
index 4748e14..76f8e18 100644
--- a/packages/CompanionDeviceManager/res/values-uz/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-uz/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; boshqaradigan <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qurilmasini tanlang"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Ilova <xliff:g id="DEVICE_NAME">%1$s</xliff:g> qurilmangizni boshqarish uchun kerak. <xliff:g id="APP_NAME">%2$s</xliff:g> ilovasiga chaqiruvchining ismi, bildirishnomalar bilan ishlash va telefon, SMS, kontaktlar, taqvim, chaqiruvlar jurnali va yaqin-atrofdagi qurilmalarni aniqlash kabi maʼlumotlarni sinxronlashga ruxsat beriladi."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Ilova <xliff:g id="DEVICE_NAME">%1$s</xliff:g> qurilmangizni boshqarish uchun kerak. <xliff:g id="APP_NAME">%2$s</xliff:g> ilovasiga chaqiruvchining ismi kabi maʼlumotlarni sinxronlash va quyidagi amallarni bajarishga ruxsat beriladi:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"koʻzoynak"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Bu ilova <xliff:g id="DEVICE_NAME">%1$s</xliff:g> qurilmasini boshqarish uchun kerak. <xliff:g id="APP_NAME">%2$s</xliff:g> ilovasiga bildirishnomalar bilan ishlash va telefon, SMS, kontaktlar, mikrofon va yaqin-atrofdagi qurilmalarga kirishga ruxsat beriladi."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Ilova <xliff:g id="DEVICE_NAME">%1$s</xliff:g> qurilmasini boshqarish uchun kerak. <xliff:g id="APP_NAME">%2$s</xliff:g> ilovasiga quyidagi ruxsatlar bilan ishlashga ruxsat beriladi:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ilovasiga telefondagi ushbu maʼlumot uchun ruxsat bering"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Qurilmalararo xizmatlar"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"Qurilamalararo ilovalar strimingi uchun <xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nomidan ruxsat soʻramoqda"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play xizmatlari"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"Telefoningizdagi rasm, media va bildirishnomalarga kirish uchun <xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nomidan ruxsat soʻramoqda"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ilovasi telefonda amallar bajarishiga ruxsat bering"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Qurilmalararo xizmatlar"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> qurilmangizdan nomidan atrofdagi qurilmalarga kontent uzatish uchun ruxsat olmoqchi"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"qurilma"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Bu ilova telefoningiz va <xliff:g id="DEVICE_NAME">%1$s</xliff:g> qurilmasida chaqiruvchining ismi kabi maʼlumotlarni sinxronlay oladi."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Bu ilova telefoningiz va tanlangan qurilmada chaqiruvchining ismi kabi maʼlumotlarni sinxronlay oladi."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Suratlar va media"</string>
     <string name="permission_notification" msgid="693762568127741203">"Bildirishnomalar"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Ilovalar"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Atrofdagi qurilmalarga uzatish"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Mikrofon orqali audio yozib olishi mumkin"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Atrofdagi qurilmalarga kontent uzatish"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-vi/strings.xml b/packages/CompanionDeviceManager/res/values-vi/strings.xml
index a71d647..4abe51e 100644
--- a/packages/CompanionDeviceManager/res/values-vi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-vi/strings.xml
@@ -16,15 +16,19 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
+    <string name="app_label" msgid="4470785958457506021">"Trình quản lý thiết bị đồng hành"</string>
     <string name="confirmation_title" msgid="8024993972587946678">"Cho phép &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; truy cập &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="profile_name_watch" msgid="576290739483672360">"đồng hồ"</string>
     <string name="chooser_title" msgid="2262294130493605839">"Chọn một <xliff:g id="PROFILE_NAME">%1$s</xliff:g> sẽ do &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; quản lý"</string>
     <string name="summary_watch" msgid="6566922405914995759">"Cần có ứng dụng này để quản lý <xliff:g id="DEVICE_NAME">%1$s</xliff:g> của bạn. <xliff:g id="APP_NAME">%2$s</xliff:g> sẽ được phép đồng bộ hoá thông tin (ví dụ: tên người gọi), tương tác với thông báo của bạn cũng như truy cập vào dữ liệu Điện thoại, SMS, Danh bạ, Lịch, Nhật ký cuộc gọi và Thiết bị ở gần."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"Cần có ứng dụng này để quản lý <xliff:g id="DEVICE_NAME">%1$s</xliff:g> của bạn. <xliff:g id="APP_NAME">%2$s</xliff:g> sẽ được phép đồng bộ hoá thông tin (ví dụ: tên người gọi) và có các quyền sau:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"kính"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Bạn cần có ứng dụng này để quản lý <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> sẽ được phép tương tác với thông báo của bạn cũng như truy cập vào dữ liệu Điện thoại, SMS, Danh bạ, Micrô và Thiết bị ở gần."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"Bạn cần có ứng dụng này để quản lý <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> sẽ được phép tương tác bằng những quyền sau:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Cho phép &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; truy cập vào thông tin này trên điện thoại của bạn"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Dịch vụ trên nhiều thiết bị"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang yêu cầu quyền thay cho <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> để truyền trực tuyến ứng dụng giữa các thiết bị của bạn"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Dịch vụ Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang yêu cầu quyền thay cho <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> để truy cập vào ảnh, nội dung nghe nhìn và thông báo trên điện thoại của bạn."</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Cho phép &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; thực hiện thao tác này qua điện thoại của bạn"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Dịch vụ trên nhiều thiết bị"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang thay mặt <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yêu cầu quyền để truyền nội dung đến các thiết bị ở gần"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"thiết bị"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Ứng dụng này sẽ đồng bộ hoá được thông tin (ví dụ: tên người gọi) giữa điện thoại của bạn và <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Ứng dụng này sẽ đồng bộ hoá được thông tin (ví dụ: tên người gọi) giữa điện thoại của bạn và thiết bị bạn chọn."</string>
@@ -57,16 +62,19 @@
     <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>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Ứng dụng"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Truyền đến thiết bị ở gần"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Có thể ghi âm bằng micrô"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Truyền nội dung đến thiết bị ở gần"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
index c863fa8..30b89e8 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"选择要由&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_watch" msgid="6566922405914995759">"需要使用此应用才能管理您的“<xliff:g id="DEVICE_NAME">%1$s</xliff:g>”。<xliff:g id="APP_NAME">%2$s</xliff:g>将能同步信息(例如来电者的姓名),与通知交互,并可获得电话、短信、通讯录、日历、通话记录和附近设备的访问权限。"</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"需要使用此应用才能管理您的“<xliff:g id="DEVICE_NAME">%1$s</xliff:g>”。<xliff:g id="APP_NAME">%2$s</xliff:g>将能同步信息(例如来电者的姓名),并可使用以下权限:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"眼镜"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"需要使用此应用才能管理“<xliff:g id="DEVICE_NAME">%1$s</xliff:g>”。<xliff:g id="APP_NAME">%2$s</xliff:g>将能与通知交互,并可获得电话、短信、通讯录、麦克风和附近设备的访问权限。"</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"需要使用此应用才能管理“<xliff:g id="DEVICE_NAME">%1$s</xliff:g>”。<xliff:g id="APP_NAME">%2$s</xliff:g>将可使用以下权限:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"允许“<xliff:g id="APP_NAME">%1$s</xliff:g>”&lt;strong&gt;&lt;/strong&gt;访问您手机中的这项信息"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"跨设备服务"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正代表您的<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>请求在您的设备之间流式传输应用内容"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play 服务"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正代表您的<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>请求访问您手机上的照片、媒体内容和通知"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"允许&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;从您的手机执行此操作"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"跨设备服务"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正代表您的<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>请求向您附近的设备流式传输内容"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"设备"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"此应用将能够在您的手机和“<xliff:g id="DEVICE_NAME">%1$s</xliff:g>”之间同步信息,例如来电者的姓名。"</string>
     <string name="summary_generic" msgid="4988130802522924650">"此应用将能够在您的手机和所选设备之间同步信息,例如来电者的姓名。"</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"照片和媒体内容"</string>
     <string name="permission_notification" msgid="693762568127741203">"通知"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"应用"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"附近的设备流式传输"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"可使用麦克风录音"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"可以查找、连接附近的设备以及确定附近设备的相对位置"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"可以读取所有通知,包括合同、消息和照片等信息"</string>
     <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="5776807830582725074">"向附近的设备流式传输内容"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
index b582d94..23301b5 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"選擇由 &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; 管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_watch" msgid="6566922405914995759">"必須使用此應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可同步資訊 (例如來電者的名稱)、透過通知與您互動,並存取電話、短訊、通訊錄、日曆、通話記錄和附近的裝置權限。"</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"必須使用此應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可同步資訊 (例如來電者的名稱),並存取以下權限:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"眼鏡"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"必須使用此應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可透過通知與您互動,並存取電話、短訊、通訊錄、麥克風和附近的裝置權限。"</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"必須使用此應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可存取以下權限:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;存取您手機中的這項資料"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"跨裝置服務"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在為 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> 要求權限,以在裝置之間串流應用程式內容"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play 服務"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> 要求權限,以便存取手機上的相片、媒體和通知"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;透過您的手機執行此操作"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"跨裝置服務"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表「<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>」將內容串流至附近的裝置"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"裝置"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"此應用程式將可同步手機和「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」的資訊,例如來電者的名稱。"</string>
     <string name="summary_generic" msgid="4988130802522924650">"此應用程式將可同步手機和所選裝置的資訊,例如來電者的名稱。"</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"相片和媒體"</string>
     <string name="permission_notification" msgid="693762568127741203">"通知"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"應用程式"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"附近的裝置串流"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"可使用麥克風錄音"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"可尋找、連接及判斷附近裝置的相對位置"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"可以讀取所有通知,包括聯絡人、訊息和電話等資訊"</string>
     <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="5776807830582725074">"將內容串流至附近的裝置"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
index 401368d..ccc50d9 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"選擇要讓「<xliff:g id="APP_NAME">%2$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
     <string name="summary_watch" msgid="6566922405914995759">"你必須使用這個應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可同步資訊 (例如來電者名稱)、存取通知及在通知上執行操作,並取得電話、簡訊、聯絡人、日曆、通話記錄、麥克風和鄰近裝置權限。"</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"你必須使用這個應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可同步資訊 (例如來電者名稱),並取得以下權限:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"眼鏡"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"你必須使用這個應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可存取通知及在通知上執行操作,並取得電話、簡訊、聯絡人、麥克風和鄰近裝置權限。"</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"你必須使用這個應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將取得以下權限:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;存取手機中的這項資訊"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"跨裝置服務"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表你的「<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>」要求必要權限,以便在裝置之間串流傳輸應用程式內容"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Google Play 服務"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表你的「<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>」要求必要權限,以便存取手機上的相片、媒體和通知"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;透過你的手機執行這項操作"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"跨裝置服務"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表你的「<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>」將內容串流傳輸到鄰近裝置"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"裝置"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"這個應用程式將可在手機和「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」之間同步資訊,例如來電者名稱。"</string>
     <string name="summary_generic" msgid="4988130802522924650">"這個應用程式將可在手機和指定裝置之間同步資訊,例如來電者名稱。"</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"相片和媒體"</string>
     <string name="permission_notification" msgid="693762568127741203">"通知"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"應用程式"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"鄰近裝置串流"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"可使用麥克風錄音"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <string name="permission_nearby_devices_summary" msgid="931940524460876655">"可尋找、連線及判斷鄰近裝置的相對位置"</string>
     <string name="permission_notification_summary" msgid="884075314530071011">"可讀取所有通知,包括聯絡人、訊息和電話等資訊"</string>
     <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="5776807830582725074">"將內容串流傳輸到鄰近裝置"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-zu/strings.xml b/packages/CompanionDeviceManager/res/values-zu/strings.xml
index 7af3531..6ccfd97 100644
--- a/packages/CompanionDeviceManager/res/values-zu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zu/strings.xml
@@ -22,9 +22,13 @@
     <string name="chooser_title" msgid="2262294130493605839">"Khetha i-<xliff:g id="PROFILE_NAME">%1$s</xliff:g> ezophathwa yi-&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="summary_watch" msgid="6566922405914995759">"I-app iyadingeka ukuphatha i-<xliff:g id="DEVICE_NAME">%1$s</xliff:g> yakho. I-<xliff:g id="APP_NAME">%2$s</xliff:g> izovunyelwa ukuvumelanisa ulwazi, njengegama lomuntu othile ofonayo, ukusebenzisana nezaziso zakho futhi ufinyelele Ifoni yakho, i-SMS, Oxhumana Nabo, Ikhalenda, Amarekhodi Amakholi nezimvume zamadivayisi aseduze."</string>
     <string name="summary_watch_single_device" msgid="7443464525873186735">"I-app iyadingeka ukuphatha i-<xliff:g id="DEVICE_NAME">%1$s</xliff:g> yakho. I-<xliff:g id="APP_NAME">%2$s</xliff:g> izovunyelwa ukuvumelanisa ulwazi, njengegama lomuntu othile ofonayo, futhi ufinyelele lezi zimvume:"</string>
+    <!-- no translation found for confirmation_title_glasses (8288346850537727333) -->
+    <skip />
     <string name="profile_name_glasses" msgid="8488394059007275998">"Izingilazi"</string>
-    <string name="summary_glasses" msgid="3808267780579061241">"Le app iyadingeka ukuphatha i-<xliff:g id="DEVICE_NAME">%1$s</xliff:g>. I-<xliff:g id="APP_NAME">%2$s</xliff:g> izovunyelwa ukuthi ihlanganyele nezaziso zakho futhi ifinyelele kufoni yakho, i-SMS, Oxhumana nabo, Imakrofoni nezimvume zamadivayisi aseduze."</string>
-    <string name="summary_glasses_single_device" msgid="7051392780285915640">"I-app iyadingeka ukuphatha i-<xliff:g id="DEVICE_NAME">%1$s</xliff:g>. I-<xliff:g id="APP_NAME">%2$s</xliff:g> izovunyelwa ukusebenzisana nalezi zimvume:"</string>
+    <!-- no translation found for summary_glasses_multi_device (615259525961937348) -->
+    <skip />
+    <!-- no translation found for summary_glasses_single_device (5783761806783565716) -->
+    <skip />
     <string name="title_app_streaming" msgid="2270331024626446950">"Vumela i-&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ifinyelele lolu lwazi kusukela efonini yakho"</string>
     <string name="helper_title_app_streaming" msgid="4151687003439969765">"Amasevisi amadivayisi amaningi"</string>
     <string name="helper_summary_app_streaming" msgid="5977509499890099">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> icela imvume esikhundleni se-<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yakho ukuze isakaze-bukhoma ama-app phakathi kwamadivayisi akho"</string>
@@ -34,9 +38,10 @@
     <string name="summary_computer" msgid="3798467601598297062"></string>
     <string name="helper_title_computer" msgid="4671071173916176037">"Amasevisi we-Google Play"</string>
     <string name="helper_summary_computer" msgid="9050724687678157852">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> icela imvume esikhundleni se-<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yakho ukuze ifinyelele izithombe zefoni yakho, imidiya nezaziso"</string>
-    <string name="title_nearby_device_streaming" msgid="179278282547719200">"Vumela i-<xliff:g id="APP_NAME">%1$s</xliff:g> ukwenza lesi senzo ngocingo lwakho"</string>
-    <string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Amasevisi amadivayisi amaningi"</string>
-    <string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> icela imvume esikhundleni se-<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yakho ukuze isakaze okuqukethwe kumadivayisi aseduze"</string>
+    <!-- no translation found for title_nearby_device_streaming (7269956847378799794) -->
+    <skip />
+    <!-- no translation found for helper_summary_nearby_device_streaming (2063965070936844876) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"idivayisi"</string>
     <string name="summary_generic_single_device" msgid="4735072202474939111">"Le app izokwazi ukuvumelanisa ulwazi, njengegama lomuntu othile ofonayo, phakathi kwefoni yakho ne-<xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
     <string name="summary_generic" msgid="4988130802522924650">"Le app izokwazi ukuvumelanisa ulwazi, njengegama lomuntu othile ofonayo, phakathi kwefoni yakho nedivayisi ekhethiwe."</string>
@@ -57,16 +62,19 @@
     <string name="permission_storage" msgid="6831099350839392343">"Izithombe nemidiya"</string>
     <string name="permission_notification" msgid="693762568127741203">"Izaziso"</string>
     <string name="permission_app_streaming" msgid="6009695219091526422">"Ama-app"</string>
-    <string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Ukusakazwa Kwedivayisi Eseduze"</string>
+    <!-- no translation found for permission_nearby_device_streaming (1023325519477349499) -->
+    <skip />
     <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="4241354865859396558">"Ingakwazi ukurekhoda umsindo isebenzisa imakrofoni"</string>
+    <!-- no translation found for permission_microphone_summary (3692091540613093394) -->
+    <skip />
     <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>
     <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="5776807830582725074">"Sakaza okuqukethwe kudivayisi eseduze"</string>
+    <!-- no translation found for permission_nearby_device_streaming_summary (8280824871197081246) -->
+    <skip />
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values/strings.xml b/packages/CompanionDeviceManager/res/values/strings.xml
index b842761..82e5a7f 100644
--- a/packages/CompanionDeviceManager/res/values/strings.xml
+++ b/packages/CompanionDeviceManager/res/values/strings.xml
@@ -36,17 +36,19 @@
     <!-- Description of the privileges the application will get if associated with the companion device of WATCH profile for singleDevice(type) [CHAR LIMIT=NONE] -->
     <string name="summary_watch_single_device">The app is needed to manage your <xliff:g id="device_name" example="My Watch">%1$s</xliff:g>. <xliff:g id="app_name" example="Android Wear">%2$s</xliff:g> will be allowed to sync info, like the name of someone calling, and access these permissions:</string>
 
-    <!-- TODO(b/256140614) To replace all glasses related strings with final versions -->
     <!-- ================= DEVICE_PROFILE_GLASSES ================= -->
 
+    <!-- Title of the device association confirmation dialog for glasses. -->
+    <string name="confirmation_title_glasses">Allow &lt;strong&gt;<xliff:g id="app_name" example="Android Wear">%1$s</xliff:g>&lt;/strong&gt; to manage &lt;strong&gt;<xliff:g id="device_name" example="Glasses">%2$s</xliff:g>&lt;/strong&gt;?</string>
+
     <!-- The name of the "glasses" device type [CHAR LIMIT=30] -->
     <string name="profile_name_glasses">glasses</string>
 
     <!-- Description of the privileges the application will get if associated with the companion device of GLASSES profile (type) [CHAR LIMIT=NONE] -->
-    <string name="summary_glasses">This app is needed to manage <xliff:g id="device_name" example="My Glasses">%1$s</xliff:g>. <xliff:g id="app_name" example="Glasses">%2$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts, Microphone and Nearby devices permissions.</string>
+    <string name="summary_glasses_multi_device">This app is needed to manage <xliff:g id="device_name" example="My Glasses">%1$s</xliff:g>. <xliff:g id="app_name" example="Glasses">%2$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts, Microphone and Nearby devices permissions.</string>
 
     <!-- Description of the privileges the application will get if associated with the companion device of GLASSES profile for singleDevice(type) [CHAR LIMIT=NONE] -->
-    <string name="summary_glasses_single_device">The app is needed to manage <xliff:g id="device_name" example="My Glasses">%1$s</xliff:g>. <xliff:g id="app_name" example="Glasses">%2$s</xliff:g> will be allowed to interact with these permissions:</string>
+    <string name="summary_glasses_single_device">This app will be allowed to access these permissions on your phone:</string>
 
     <!-- ================= DEVICE_PROFILE_APP_STREAMING ================= -->
 
@@ -81,17 +83,13 @@
     <!-- Description of the helper dialog for COMPUTER profile. [CHAR LIMIT=NONE] -->
     <string name="helper_summary_computer"><xliff:g id="app_name" example="GMS">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="device_type" example="Chromebook">%2$s</xliff:g> to access your phone\u2019s photos, media, and notifications</string>
 
-    <!-- TODO(b/256140614) To replace all nearby_device_streaming related strings with final versions -->
     <!-- ================= DEVICE_PROFILE_NEARBY_DEVICE_STREAMING ================= -->
 
     <!-- Confirmation for associating an application with a companion device of NEARBY_DEVICE_STREAMING profile (type) [CHAR LIMIT=NONE] -->
-    <string name="title_nearby_device_streaming">Allow &lt;strong&gt;<xliff:g id="app_name" example="NearbyStreamer">%1$s</xliff:g>&lt;/strong&gt; to perform this action from your phone</string>
-
-    <!-- Title of the helper dialog for NEARBY_DEVICE_STREAMING profile [CHAR LIMIT=30]. -->
-    <string name="helper_title_nearby_device_streaming">Cross-device services</string>
+    <string name="title_nearby_device_streaming">Allow &lt;strong&gt;<xliff:g id="device_name" example="NearbyStreamer">%1$s</xliff:g>&lt;/strong&gt; to take this action?</string>
 
     <!-- Description of the helper dialog for NEARBY_DEVICE_STREAMING profile. [CHAR LIMIT=NONE] -->
-    <string name="helper_summary_nearby_device_streaming"><xliff:g id="app_name" example="NearbyStreamerApp">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="device_type" example="NearbyDevice">%2$s</xliff:g> to stream content to nearby devices</string>
+    <string name="helper_summary_nearby_device_streaming"><xliff:g id="app_name" example="NearbyStreamerApp">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="device_name" example="NearbyDevice">%2$s</xliff:g> to stream apps and other system features to nearby devices</string>
 
     <!-- ================= null profile ================= -->
 
@@ -161,7 +159,7 @@
     <string name="permission_app_streaming">Apps</string>
 
     <!-- Nearby_device_streaming permission will be granted to the corresponding profile [CHAR LIMIT=45] -->
-    <string name="permission_nearby_device_streaming">Nearby Device Streaming</string>
+    <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>
@@ -179,8 +177,7 @@
     <string name="permission_calendar_summary">Can access your calendar</string>
 
     <!-- Description of microphone permission of corresponding profile [CHAR LIMIT=NONE] -->
-    <!-- TODO(b/256140614) Need the description for microphone permission  -->
-    <string name="permission_microphone_summary">Can record audio using the microphone</string>
+    <string name="permission_microphone_summary">Can 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>
@@ -195,7 +192,6 @@
     <string name="permission_storage_summary"></string>
 
     <!-- Description of nearby_device_streaming permission of corresponding profile [CHAR LIMIT=NONE] -->
-    <!-- TODO(b/256140614) Need the description for nearby devices' permission  -->
-    <string name="permission_nearby_device_streaming_summary">Stream content to a nearby device</string>
+    <string name="permission_nearby_device_streaming_summary">Stream apps and other system features from your phone</string>
 
 </resources>
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
index 918f9c6..8316f9d 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
@@ -30,6 +30,7 @@
 import static com.android.companiondevicemanager.CompanionDeviceResources.MULTI_DEVICES_SUMMARIES;
 import static com.android.companiondevicemanager.CompanionDeviceResources.PERMISSION_TYPES;
 import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILES_NAME;
+import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILES_NAME_MULTI;
 import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILE_ICON;
 import static com.android.companiondevicemanager.CompanionDeviceResources.SUMMARIES;
 import static com.android.companiondevicemanager.CompanionDeviceResources.SUPPORTED_PROFILES;
@@ -571,6 +572,7 @@
         final String deviceProfile = mRequest.getDeviceProfile();
 
         final String profileName;
+        final String profileNameMulti;
         final Spanned summary;
         final Drawable profileIcon;
         final int summaryResourceId;
@@ -580,6 +582,7 @@
         }
 
         profileName = getString(PROFILES_NAME.get(deviceProfile));
+        profileNameMulti = getString(PROFILES_NAME_MULTI.get(deviceProfile));
         profileIcon = getIcon(this, PROFILE_ICON.get(deviceProfile));
         summaryResourceId = MULTI_DEVICES_SUMMARIES.get(deviceProfile);
 
@@ -590,7 +593,7 @@
         }
 
         final Spanned title = getHtmlFromResources(
-                this, R.string.chooser_title, profileName, appLabel);
+                this, R.string.chooser_title, profileNameMulti, appLabel);
 
         mTitle.setText(title);
         mSummary.setText(summary);
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceResources.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceResources.java
index e3fd354..7aed139 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceResources.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceResources.java
@@ -59,7 +59,7 @@
         map.put(DEVICE_PROFILE_COMPUTER, R.string.title_computer);
         map.put(DEVICE_PROFILE_NEARBY_DEVICE_STREAMING, R.string.title_nearby_device_streaming);
         map.put(DEVICE_PROFILE_WATCH, R.string.confirmation_title);
-        map.put(DEVICE_PROFILE_GLASSES, R.string.confirmation_title);
+        map.put(DEVICE_PROFILE_GLASSES, R.string.confirmation_title_glasses);
         map.put(null, R.string.confirmation_title);
 
         TITLES = unmodifiableMap(map);
@@ -97,7 +97,7 @@
     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(DEVICE_PROFILE_GLASSES, R.string.summary_glasses_multi_device);
         map.put(null, R.string.summary_generic);
 
         MULTI_DEVICES_SUMMARIES = unmodifiableMap(map);
@@ -113,6 +113,16 @@
         PROFILES_NAME = 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> map = new ArrayMap<>();
@@ -133,7 +143,6 @@
         SUPPORTED_PROFILES = unmodifiableSet(set);
     }
 
-
     static final Set<String> SUPPORTED_SELF_MANAGED_PROFILES;
     static {
         final Set<String> set = new ArraySet<>();
@@ -145,6 +154,4 @@
 
         SUPPORTED_SELF_MANAGED_PROFILES = unmodifiableSet(set);
     }
-
-
 }
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionVendorHelperDialogFragment.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionVendorHelperDialogFragment.java
index eae14a6..8f32dbb 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionVendorHelperDialogFragment.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionVendorHelperDialogFragment.java
@@ -21,6 +21,7 @@
 import static android.companion.AssociationRequest.DEVICE_PROFILE_NEARBY_DEVICE_STREAMING;
 
 import static com.android.companiondevicemanager.Utils.getApplicationIcon;
+import static com.android.companiondevicemanager.Utils.getApplicationLabel;
 import static com.android.companiondevicemanager.Utils.getHtmlFromResources;
 
 import android.annotation.Nullable;
@@ -105,9 +106,11 @@
         final String packageName = request.getPackageName();
         final CharSequence displayName = request.getDisplayName();
         final int userId = request.getUserId();
+        final CharSequence appLabel;
 
         try {
             applicationIcon = getApplicationIcon(getContext(), packageName);
+            appLabel = getApplicationLabel(getContext(), packageName, userId);
         } catch (PackageManager.NameNotFoundException e) {
             Log.e(TAG, "Package u" + userId + "/" + packageName + " not found.");
             mListener.onShowHelperDialogFailed();
@@ -119,7 +122,7 @@
         mAppIcon = view.findViewById(R.id.app_icon);
         mButton = view.findViewById(R.id.btn_back);
 
-        final Spanned title;
+        final CharSequence title;
         final Spanned summary;
 
         switch (deviceProfile) {
@@ -136,8 +139,7 @@
                 break;
 
             case DEVICE_PROFILE_NEARBY_DEVICE_STREAMING:
-                title = getHtmlFromResources(getContext(),
-                        R.string.helper_title_nearby_device_streaming);
+                title = appLabel;
                 summary = getHtmlFromResources(
                         getContext(), R.string.helper_summary_nearby_device_streaming, title,
                         displayName);
diff --git a/packages/CredentialManager/Android.bp b/packages/CredentialManager/Android.bp
index 00d42bd..28b9bc0 100644
--- a/packages/CredentialManager/Android.bp
+++ b/packages/CredentialManager/Android.bp
@@ -20,6 +20,7 @@
     },
 
     static_libs: [
+        "PlatformComposeCore",
         "androidx.activity_activity-compose",
         "androidx.appcompat_appcompat",
         "androidx.compose.animation_animation-core",
diff --git a/packages/CredentialManager/res/drawable/ic_other_devices.xml b/packages/CredentialManager/res/drawable/ic_other_devices.xml
deleted file mode 100644
index 754648c..0000000
--- a/packages/CredentialManager/res/drawable/ic_other_devices.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<vector
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    tools:ignore="VectorPath"
-    android:name="vector"
-    android:width="20dp"
-    android:height="20dp"
-    android:viewportWidth="20"
-    android:viewportHeight="20">
-    <path
-        android:name="path"
-        android:pathData="M 7.6 4.72 L 7.6 7.6 L 4.72 7.6 L 4.72 4.72 L 7.6 4.72 Z M 9.04 3.28 L 3.28 3.28 L 3.28 9.04 L 9.04 9.04 L 9.04 3.28 Z M 7.6 12.4 L 7.6 15.28 L 4.72 15.28 L 4.72 12.4 L 7.6 12.4 Z M 9.04 10.96 L 3.28 10.96 L 3.28 16.72 L 9.04 16.72 L 9.04 10.96 Z M 15.28 4.72 L 15.28 7.6 L 12.4 7.6 L 12.4 4.72 L 15.28 4.72 Z M 16.72 3.28 L 10.96 3.28 L 10.96 9.04 L 16.72 9.04 L 16.72 3.28 Z M 10.96 10.96 L 12.4 10.96 L 12.4 12.4 L 10.96 12.4 L 10.96 10.96 Z M 12.4 12.4 L 13.84 12.4 L 13.84 13.84 L 12.4 13.84 L 12.4 12.4 Z M 13.84 10.96 L 15.28 10.96 L 15.28 12.4 L 13.84 12.4 L 13.84 10.96 Z M 10.96 13.84 L 12.4 13.84 L 12.4 15.28 L 10.96 15.28 L 10.96 13.84 Z M 12.4 15.28 L 13.84 15.28 L 13.84 16.72 L 12.4 16.72 L 12.4 15.28 Z M 13.84 13.84 L 15.28 13.84 L 15.28 15.28 L 13.84 15.28 L 13.84 13.84 Z M 15.28 12.4 L 16.72 12.4 L 16.72 13.84 L 15.28 13.84 L 15.28 12.4 Z M 15.28 15.28 L 16.72 15.28 L 16.72 16.72 L 15.28 16.72 L 15.28 15.28 Z M 19.6 5.2 L 17.68 5.2 L 17.68 2.32 L 14.8 2.32 L 14.8 0.4 L 19.6 0.4 L 19.6 5.2 Z M 19.6 19.6 L 19.6 14.8 L 17.68 14.8 L 17.68 17.68 L 14.8 17.68 L 14.8 19.6 L 19.6 19.6 Z M 0.4 19.6 L 5.2 19.6 L 5.2 17.68 L 2.32 17.68 L 2.32 14.8 L 0.4 14.8 L 0.4 19.6 Z M 0.4 0.4 L 0.4 5.2 L 2.32 5.2 L 2.32 2.32 L 5.2 2.32 L 5.2 0.4 L 0.4 0.4 Z"
-        android:fillColor="#000000"
-        android:strokeWidth="1"/>
-</vector>
\ No newline at end of file
diff --git a/packages/CredentialManager/res/drawable/ic_other_sign_in.xml b/packages/CredentialManager/res/drawable/ic_other_sign_in.xml
deleted file mode 100644
index 8150197..0000000
--- a/packages/CredentialManager/res/drawable/ic_other_sign_in.xml
+++ /dev/null
@@ -1,36 +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.
-  -->
-
-<vector
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    tools:ignore="VectorPath"
-    android:name="vector"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-    <path
-        android:name="path"
-        android:pathData="M 20 19 L 12 19 L 12 21 L 20 21 C 21.1 21 22 20.1 22 19 L 22 5 C 22 3.9 21.1 3 20 3 L 12 3 L 12 5 L 20 5 L 20 19 Z"
-        android:fillColor="#000"
-        android:strokeWidth="1"/>
-    <path
-        android:name="path_1"
-        android:pathData="M 12 7 L 10.6 8.4 L 13.2 11 L 8.85 11 C 8.42 9.55 7.09 8.5 5.5 8.5 C 3.57 8.5 2 10.07 2 12 C 2 13.93 3.57 15.5 5.5 15.5 C 7.09 15.5 8.42 14.45 8.85 13 L 13.2 13 L 10.6 15.6 L 12 17 L 17 12 L 12 7 Z M 5.5 13.5 C 4.67 13.5 4 12.83 4 12 C 4 11.17 4.67 10.5 5.5 10.5 C 6.33 10.5 7 11.17 7 12 C 7 12.83 6.33 13.5 5.5 13.5 Z"
-        android:fillColor="#000"
-        android:strokeWidth="1"/>
-</vector>
\ No newline at end of file
diff --git a/packages/CredentialManager/res/drawable/ic_other_sign_in_24.xml b/packages/CredentialManager/res/drawable/ic_other_sign_in_24.xml
new file mode 100644
index 0000000..ce2aeb2
--- /dev/null
+++ b/packages/CredentialManager/res/drawable/ic_other_sign_in_24.xml
@@ -0,0 +1,30 @@
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<vector
+    android:alpha="0.8"
+    android:height="24dp"
+    android:viewportHeight="24"
+    android:viewportWidth="24"
+    android:width="24dp"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+>
+<group>
+    <clip-path android:pathData="M0,0h24v24h-24z"/>
+    <path android:fillColor="#444746" android:pathData="M20,19H12V21H20C21.1,21 22,20.1 22,19V5C22,3.9 21.1,3 20,3H12V5H20V19Z"/>
+    <path android:fillColor="#444746" android:pathData="M12,7L10.6,8.4L13.2,11H8.85C8.42,9.55 7.09,8.5 5.5,8.5C3.57,8.5 2,10.07 2,12C2,13.93 3.57,15.5 5.5,15.5C7.09,15.5 8.42,14.45 8.85,13H13.2L10.6,15.6L12,17L17,12L12,7ZM5.5,13.5C4.67,13.5 4,12.83 4,12C4,11.17 4.67,10.5 5.5,10.5C6.33,10.5 7,11.17 7,12C7,12.83 6.33,13.5 5.5,13.5Z"/>
+</group>
+</vector>
\ No newline at end of file
diff --git a/packages/CredentialManager/res/drawable/ic_passkey.xml b/packages/CredentialManager/res/drawable/ic_passkey.xml
deleted file mode 100644
index 041a321..0000000
--- a/packages/CredentialManager/res/drawable/ic_passkey.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="28dp"
-    android:height="24dp"
-    android:viewportWidth="28"
-    android:viewportHeight="24">
-  <path
-      android:pathData="M27.453,13.253C27.453,14.952 26.424,16.411 24.955,17.041L26.21,18.295L24.839,19.666L26.21,21.037L23.305,23.942L22.012,22.65L22.012,17.156C20.385,16.605 19.213,15.066 19.213,13.253C19.213,10.977 21.058,9.133 23.333,9.133C25.609,9.133 27.453,10.977 27.453,13.253ZM25.47,13.254C25.47,14.434 24.514,15.39 23.334,15.39C22.154,15.39 21.197,14.434 21.197,13.254C21.197,12.074 22.154,11.118 23.334,11.118C24.514,11.118 25.47,12.074 25.47,13.254Z"
-      android:fillColor="#00639B"
-      android:fillType="evenOdd"/>
-  <path
-      android:pathData="M17.85,5.768C17.85,8.953 15.268,11.536 12.083,11.536C8.897,11.536 6.315,8.953 6.315,5.768C6.315,2.582 8.897,0 12.083,0C15.268,0 17.85,2.582 17.85,5.768Z"
-      android:fillColor="#00639B"/>
-  <path
-      android:pathData="M0.547,20.15C0.547,16.32 8.23,14.382 12.083,14.382C13.59,14.382 15.684,14.679 17.674,15.269C18.116,16.454 18.952,17.447 20.022,18.089V23.071H0.547V20.15Z"
-      android:fillColor="#00639B"/>
-</vector>
diff --git a/packages/CredentialManager/res/drawable/ic_passkey_24.xml b/packages/CredentialManager/res/drawable/ic_passkey_24.xml
new file mode 100644
index 0000000..a2c4f37
--- /dev/null
+++ b/packages/CredentialManager/res/drawable/ic_passkey_24.xml
@@ -0,0 +1,28 @@
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<vector
+    android:alpha="0.8"
+    android:height="24dp"
+    android:viewportHeight="24"
+    android:viewportWidth="24"
+    android:width="24dp"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools">
+  <path android:fillColor="#4C463C" android:fillType="evenOdd" android:pathData="M22.18,14.09C22.18,15.364 21.408,16.459 20.306,16.931L21.247,17.872L20.219,18.9L21.247,19.928L19.068,22.107L18.099,21.138L18.099,17.017C16.878,16.604 16,15.45 16,14.09C16,12.383 17.383,11 19.09,11C20.796,11 22.18,12.383 22.18,14.09ZM20.692,14.091C20.692,14.976 19.975,15.693 19.09,15.693C18.205,15.693 17.488,14.976 17.488,14.091C17.488,13.206 18.205,12.488 19.09,12.488C19.975,12.488 20.692,13.206 20.692,14.091Z"/>
+  <path android:fillColor="#4C463C" android:pathData="M14.978,8.476C14.978,10.865 13.041,12.802 10.652,12.802C8.263,12.802 6.326,10.865 6.326,8.476C6.326,6.087 8.263,4.15 10.652,4.15C13.041,4.15 14.978,6.087 14.978,8.476Z"/>
+  <path android:fillColor="#4C463C" android:pathData="M2,19.263C2,16.39 7.762,14.937 10.652,14.937C11.782,14.937 13.353,15.16 14.845,15.602C15.177,16.491 15.804,17.236 16.607,17.717V21.454H2V19.263Z"/>
+</vector>
diff --git a/packages/CredentialManager/res/drawable/ic_password.xml b/packages/CredentialManager/res/drawable/ic_password.xml
deleted file mode 100644
index bf3056a..0000000
--- a/packages/CredentialManager/res/drawable/ic_password.xml
+++ /dev/null
@@ -1,31 +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.
-  -->
-
-<vector
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    tools:ignore="VectorPath"
-    android:name="vector"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-    <path
-        android:name="path"
-        android:pathData="M 8.71 10.29 C 8.52 10.1 8.28 10 8 10 L 7.75 10 L 7.75 8.75 C 7.75 7.98 7.48 7.33 6.95 6.8 C 6.42 6.27 5.77 6 5 6 C 4.23 6 3.58 6.27 3.05 6.8 C 2.52 7.33 2.25 7.98 2.25 8.75 L 2.25 10 L 2 10 C 1.72 10 1.48 10.1 1.29 10.29 C 1.1 10.48 1 10.72 1 11 L 1 16 C 1 16.28 1.1 16.52 1.29 16.71 C 1.48 16.9 1.72 17 2 17 L 8 17 C 8.28 17 8.52 16.9 8.71 16.71 C 8.9 16.52 9 16.28 9 16 L 9 11 C 9 10.72 8.9 10.48 8.71 10.29 Z M 6.25 10 L 3.75 10 L 3.75 8.75 C 3.75 8.4 3.87 8.1 4.11 7.86 C 4.35 7.62 4.65 7.5 5 7.5 C 5.35 7.5 5.65 7.62 5.89 7.86 C 6.13 8.1 6.25 8.4 6.25 8.75 L 6.25 10 Z M 10 14 L 23 14 L 23 16 L 10 16 Z M 21.5 9 C 21.102 9 20.721 9.158 20.439 9.439 C 20.158 9.721 20 10.102 20 10.5 C 20 10.898 20.158 11.279 20.439 11.561 C 20.721 11.842 21.102 12 21.5 12 C 21.898 12 22.279 11.842 22.561 11.561 C 22.842 11.279 23 10.898 23 10.5 C 23 10.102 22.842 9.721 22.561 9.439 C 22.279 9.158 21.898 9 21.5 9 Z M 16.5 9 C 16.102 9 15.721 9.158 15.439 9.439 C 15.158 9.721 15 10.102 15 10.5 C 15 10.898 15.158 11.279 15.439 11.561 C 15.721 11.842 16.102 12 16.5 12 C 16.898 12 17.279 11.842 17.561 11.561 C 17.842 11.279 18 10.898 18 10.5 C 18 10.102 17.842 9.721 17.561 9.439 C 17.279 9.158 16.898 9 16.5 9 Z M 11.5 9 C 11.102 9 10.721 9.158 10.439 9.439 C 10.158 9.721 10 10.102 10 10.5 C 10 10.898 10.158 11.279 10.439 11.561 C 10.721 11.842 11.102 12 11.5 12 C 11.898 12 12.279 11.842 12.561 11.561 C 12.842 11.279 13 10.898 13 10.5 C 13 10.102 12.842 9.721 12.561 9.439 C 12.279 9.158 11.898 9 11.5 9 Z"
-        android:fillColor="#000"
-        android:strokeWidth="1"/>
-</vector>
\ No newline at end of file
diff --git a/packages/CredentialManager/res/drawable/ic_password_24.xml b/packages/CredentialManager/res/drawable/ic_password_24.xml
new file mode 100644
index 0000000..8b24e88
--- /dev/null
+++ b/packages/CredentialManager/res/drawable/ic_password_24.xml
@@ -0,0 +1,34 @@
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:ignore="VectorPath"
+    android:name="vector"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <group>
+        <clip-path android:pathData="M0,0h24v24h-24z"/>
+        <path android:fillColor="#4C463C" android:pathData="M8.46,10.29C8.27,10.1 8.03,10 7.75,10H7.5V8.75C7.5,7.98 7.23,7.33 6.7,6.8C6.17,6.27 5.52,6 4.75,6C3.98,6 3.33,6.27 2.8,6.8C2.27,7.33 2,7.98 2,8.75V10H1.75C1.47,10 1.23,10.1 1.04,10.29C0.85,10.48 0.75,10.72 0.75,11V16C0.75,16.28 0.85,16.52 1.04,16.71C1.23,16.9 1.47,17 1.75,17H7.75C8.03,17 8.27,16.9 8.46,16.71C8.65,16.52 8.75,16.28 8.75,16V11C8.75,10.72 8.65,10.48 8.46,10.29ZM6,10H3.5V8.75C3.5,8.4 3.62,8.1 3.86,7.86C4.1,7.62 4.4,7.5 4.75,7.5C5.1,7.5 5.4,7.62 5.64,7.86C5.88,8.1 6,8.4 6,8.75V10Z"/>
+        <path android:fillColor="#4C463C" android:pathData="M23.5,14H10.5V16H23.5V14Z"/>
+        <path android:fillColor="#4C463C" android:pathData="M22,12C22.828,12 23.5,11.328 23.5,10.5C23.5,9.672 22.828,9 22,9C21.172,9 20.5,9.672 20.5,10.5C20.5,11.328 21.172,12 22,12Z"/>
+        <path android:fillColor="#4C463C" android:pathData="M17,12C17.828,12 18.5,11.328 18.5,10.5C18.5,9.672 17.828,9 17,9C16.172,9 15.5,9.672 15.5,10.5C15.5,11.328 16.172,12 17,12Z"/>
+        <path android:fillColor="#4C463C" android:pathData="M12,12C12.828,12 13.5,11.328 13.5,10.5C13.5,9.672 12.828,9 12,9C11.172,9 10.5,9.672 10.5,10.5C10.5,11.328 11.172,12 12,12Z"/>
+    </group>
+</vector>
\ No newline at end of file
diff --git a/packages/CredentialManager/res/values-af/strings.xml b/packages/CredentialManager/res/values-af/strings.xml
index 3d32642..e60cc98 100644
--- a/packages/CredentialManager/res/values-af/strings.xml
+++ b/packages/CredentialManager/res/values-af/strings.xml
@@ -20,7 +20,8 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Verbeterde rekeningsekuriteit"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Elke sleutel is uitsluitlik gekoppel aan die app of webwerf waarvoor dit geskep is, en daarom kan jy nooit per ongeluk by ’n bedrieglike app of webwerf aanmeld nie. En omdat bedieners net publieke sleutels hou, is kuberkrakery baie moeiliker."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Moeitevrye oorgang"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Wagwoorde sal steeds saam met wagwoordsleutels beskikbaar wees terwyl ons na ’n wagwoordlose toekoms beweeg."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Kies waar om jou <xliff:g id="CREATETYPES">%1$s</xliff:g> te stoor"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Kies ’n wagwoordbestuurder om jou inligting te stoor en volgende keer vinniger aan te meld"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Skep wagwoordsleutel vir <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Stoor <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> in"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Skep wagwoordsleutel op ’n ander toestel?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Gebruik <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> vir al jou aanmeldings?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Hierdie wagwoordbestuurder sal jou wagwoorde en wagwoordsleutels berg om jou te help om maklik aan te meld"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Stel as verstek"</string>
     <string name="use_once" msgid="9027366575315399714">"Gebruik een keer"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> wagwoorde • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> wagwoordsleutels"</string>
@@ -48,6 +50,7 @@
     <string name="close_sheet" msgid="1393792015338908262">"Maak sigblad toe"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Gaan terug na die vorige bladsy"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Maak toe"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Maak toe"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Gebruik jou gestoorde wagwoordsleutel vir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Gebruik jou gestoorde aanmelding vir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Kies ’n gestoorde aanmelding vir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-am/strings.xml b/packages/CredentialManager/res/values-am/strings.xml
index 76533e5..e34bbcc 100644
--- a/packages/CredentialManager/res/values-am/strings.xml
+++ b/packages/CredentialManager/res/values-am/strings.xml
@@ -20,7 +20,8 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"የእርስዎን <xliff:g id="CREATETYPES">%1$s</xliff:g> የት እንደሚያስቀምጡ ይምረጡ"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"መረጃዎን ለማስቀመጥ እና በቀጣይ ጊዜ በፍጥነት በመለያ ለመግባት የሚስጥር ቁልፍ አስተዳዳሪን ይምረጡ"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"ለ<xliff:g id="APPNAME">%1$s</xliff:g> የይለፍ ቁልፍ ይፈጠር?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>ን አስቀምጥ ወደ"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"በሌላ መሣሪያ ውስጥ የይለፍ ቁልፍ ይፈጠር?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"ለሁሉም መግቢያዎችዎ <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>ን ይጠቀሙ?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"ይህ የሚስጥር ቁልፍ አስተዳዳሪ እርስዎን በቀላሉ በመለያ እንዲገቡ ለማገዝ የእርስዎን የይለፍ ቃላት እና የይለፍ ቁልፎችን ያከማቻል"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"እንደ ነባሪ ያዋቅሩ"</string>
     <string name="use_once" msgid="9027366575315399714">"አንዴ ይጠቀሙ"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> የይለፍ ቃሎች • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> የይለፍ ቁልፎች"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"ሌሎች የይለፍ ቃል አስተዳዳሪዎች"</string>
     <string name="close_sheet" msgid="1393792015338908262">"ሉህን ዝጋ"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ወደ ቀዳሚው ገፅ ይመለሱ"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"ዝጋ"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"አሰናብት"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"የተቀመጠ የይለፍ ቁልፍዎን ለ<xliff:g id="APP_NAME">%1$s</xliff:g> ይጠቀሙ?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"የተቀመጠ መግቢያዎን ለ<xliff:g id="APP_NAME">%1$s</xliff:g> ይጠቀሙ?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"ለ<xliff:g id="APP_NAME">%1$s</xliff:g> የተቀመጠ መግቢያ ይጠቀሙ"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"የተቆለፉ የሚስጥር ቁልፍ አስተዳዳሪዎች"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"ለመክፈት መታ ያድርጉ"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"ምንም የመግቢያ ማስረጃ የለም"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> ውስጥ ምንም የመግቢያ መረጃ የለም"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"መግቢያዎችን ያስተዳድሩ"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"ከሌላ መሣሪያ"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"የተለየ መሣሪያ ይጠቀሙ"</string>
diff --git a/packages/CredentialManager/res/values-ar/strings.xml b/packages/CredentialManager/res/values-ar/strings.xml
index c5de5c8..c55fd0b 100644
--- a/packages/CredentialManager/res/values-ar/strings.xml
+++ b/packages/CredentialManager/res/values-ar/strings.xml
@@ -20,10 +20,11 @@
     <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>
-    <string name="choose_provider_title" msgid="8870795677024868108">"اختَر الموقع الذي تريد حفظ <xliff:g id="CREATETYPES">%1$s</xliff:g> فيه"</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
+    <string name="choose_provider_title" msgid="8870795677024868108">"اختيار المكان الذي تريد حفظ <xliff:g id="CREATETYPES">%1$s</xliff:g> فيه"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"اختَر مدير كلمات مرور لحفظ معلوماتك وتسجيل الدخول بشكل أسرع في المرة القادمة."</string>
-    <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"إنشاء مفتاح مرور لتطبيق \"<xliff:g id="APPNAME">%1$s</xliff:g>\""</string>
+    <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"هل تريد إنشاء مفتاح مرور لتطبيق \"<xliff:g id="APPNAME">%1$s</xliff:g>\"؟"</string>
     <string name="choose_create_option_password_title" msgid="7097275038523578687">"هل تريد حفظ كلمة المرور لتطبيق \"<xliff:g id="APPNAME">%1$s</xliff:g>\"؟"</string>
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"هل تريد حفظ معلومات تسجيل الدخول لتطبيق \"<xliff:g id="APPNAME">%1$s</xliff:g>\"؟"</string>
     <string name="passkey" msgid="632353688396759522">"مفتاح مرور"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"حفظ <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> في"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"هل تريد إنشاء مفتاح المرور في خدمة أخرى؟"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"هل تريد استخدام \"<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>\" لكل عمليات تسجيل الدخول؟"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"سيخزِّن مدير كلمات المرور هذا كلمات المرور ومفاتيح المرور لمساعدتك في تسجيل الدخول بسهولة."</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"ضبط الخيار كتلقائي"</string>
     <string name="use_once" msgid="9027366575315399714">"الاستخدام مرة واحدة"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> كلمة مرور • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> مفتاح مرور"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"خدمات مدراء كلمات المرور الأخرى"</string>
     <string name="close_sheet" msgid="1393792015338908262">"إغلاق ورقة البيانات"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"العودة إلى الصفحة السابقة"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"إغلاق"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"إغلاق"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"هل تريد استخدام مفتاح المرور المحفوظ لتطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"؟"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"هل تريد استخدام بيانات اعتماد تسجيل الدخول المحفوظة لتطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"؟"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"اختيار بيانات اعتماد تسجيل دخول محفوظة لـ \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"خدمات إدارة كلمات المرور المقفولة"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"انقر لفتح القفل."</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"ما مِن معلومات تسجيل دخول."</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"ليس هناك معلومات تسجيل دخول في <xliff:g id="SOURCE">%1$s</xliff:g>."</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"إداراة عمليات تسجيل الدخول"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"من جهاز آخر"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"استخدام جهاز مختلف"</string>
diff --git a/packages/CredentialManager/res/values-as/strings.xml b/packages/CredentialManager/res/values-as/strings.xml
index 1ee0a46..c719081 100644
--- a/packages/CredentialManager/res/values-as/strings.xml
+++ b/packages/CredentialManager/res/values-as/strings.xml
@@ -20,7 +20,8 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"আপোনাৰ <xliff:g id="CREATETYPES">%1$s</xliff:g> ক’ত ছেভ কৰিব লাগে সেয়া বাছনি কৰক"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"আপোনাৰ তথ্য ছেভ কৰি পৰৱৰ্তী সময়ত দ্ৰুতভাৱে ছাইন ইন কৰিবলৈ এটা পাছৱৰ্ড পৰিচালক বাছনি কৰক"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g>ৰ বাবে পাছকী সৃষ্টি কৰিবনে?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> ইয়াত ছেভ কৰক"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"অন্য এটা ডিভাইচত পাছকী সৃষ্টি কৰিবনে?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"আপোনাৰ আটাইবোৰ ছাইন ইনৰ বাবে <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> ব্যৱহাৰ কৰিবনে?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"আপোনাক সহজে ছাইন ইন কৰাত সহায় কৰিবলৈ এই পাছৱৰ্ড পৰিচালকটোৱে আপোনাৰ পাছৱৰ্ড আৰু পাছকী ষ্ট’ৰ কৰিব"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"ডিফ’ল্ট হিচাপে ছেট কৰক"</string>
     <string name="use_once" msgid="9027366575315399714">"এবাৰ ব্যৱহাৰ কৰক"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> টা পাছৱৰ্ড • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> টা পাছকী"</string>
@@ -48,6 +50,7 @@
     <string name="close_sheet" msgid="1393792015338908262">"শ্বীট বন্ধ কৰক"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"পূৰ্বৱৰ্তী পৃষ্ঠালৈ ঘূৰি যাওক"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"বন্ধ কৰক"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"অগ্ৰাহ্য কৰক"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে আপোনাৰ ছেভ হৈ থকা পাছকী ব্যৱহাৰ কৰিবনে?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে আপোনাৰ ছেভ হৈ থকা ছাইন ইন তথ্য ব্যৱহাৰ কৰিবনে?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে ছেভ হৈ থকা এটা ছাইন ইন বাছনি কৰক"</string>
diff --git a/packages/CredentialManager/res/values-az/strings.xml b/packages/CredentialManager/res/values-az/strings.xml
index 778b78f..d0afaa5 100644
--- a/packages/CredentialManager/res/values-az/strings.xml
+++ b/packages/CredentialManager/res/values-az/strings.xml
@@ -20,7 +20,8 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Təkmilləşdirilmiş hesab təhlükəsizliyi"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Hər bir açar eksklüziv olaraq onların yaradıldığı tətbiq və ya vebsaytla əlaqələndirilib, ona görə də heç vaxt səhvən saxta tətbiqə və ya vebsayta daxil ola bilməzsiniz. Üstəlik, yalnız ictimai açarları saxlayan serverlərlə hekinq daha çətindir."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Rahat keçid"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Parolsuz gələcəyə doğru irəlilədikcə parollar hələ də giriş açarları ilə yanaşı əlçatan olacaq."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"<xliff:g id="CREATETYPES">%1$s</xliff:g> elementinin saxlanacağı yeri seçin"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Məlumatlarınızı yadda saxlamaq və növbəti dəfə daha sürətli daxil olmaq üçün parol meneceri seçin"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> üçün giriş açarı yaradılsın?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> burada yadda saxlansın:"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Başqa cihazda giriş açarı yaradılsın?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Bütün girişlər üçün <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> istifadə edilsin?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Bu parol meneceri asanlıqla daxil olmanıza kömək etmək üçün parollarınızı və giriş açarlarınızı saxlayacaq"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Defolt olaraq seçin"</string>
     <string name="use_once" msgid="9027366575315399714">"Bir dəfə istifadə edin"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> parol • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> giriş açarı"</string>
@@ -48,6 +50,7 @@
     <string name="close_sheet" msgid="1393792015338908262">"Səhifəni bağlayın"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Əvvəlki səhifəyə qayıdın"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Bağlayın"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"İmtina edin"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün yadda saxlanmış giriş açarı istifadə edilsin?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün yadda saxlanmış girişdən istifadə edilsin?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün yadda saxlanmış girişi seçin"</string>
diff --git a/packages/CredentialManager/res/values-b+sr+Latn/strings.xml b/packages/CredentialManager/res/values-b+sr+Latn/strings.xml
index e18aed5..5716aa6 100644
--- a/packages/CredentialManager/res/values-b+sr+Latn/strings.xml
+++ b/packages/CredentialManager/res/values-b+sr+Latn/strings.xml
@@ -20,7 +20,8 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Poboljšana bezbednost naloga"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Svaki ključ je isključivo povezan sa aplikacijom ili veb-sajtom za koje je napravljen, pa nikad ne možete greškom da se prijavite u aplikaciju ili na veb-sajt koji služe za prevaru. Osim toga, sa serverima koji čuvaju samo javne ključeve hakovanje je mnogo teže."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Besprekoran prelaz"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Kako se krećemo ka budućnosti bez lozinki, lozinke će i dalje biti dostupne uz pristupne kodove."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Odaberite gde ćete sačuvati stavke <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Izaberite menadžera lozinki da biste sačuvali podatke i brže se prijavili sledeći put"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Želite da napravite pristupni kôd za: <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -32,10 +33,11 @@
     <string name="passwords" msgid="5419394230391253816">"lozinke"</string>
     <string name="sign_ins" msgid="4710739369149469208">"prijavljivanja"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"podaci za prijavljivanje"</string>
-    <string name="save_credential_to_title" msgid="3172811692275634301">"Sačuvajte stavku<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> u"</string>
+    <string name="save_credential_to_title" msgid="3172811692275634301">"Sačuvaj stavku <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> u"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Želite da napravite pristupni kôd na drugom uređaju?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Želite da za sva prijavljivanja koristite: <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Ovaj menadžer lozinki će čuvati lozinke i pristupne kodove da biste se lako prijavljivali"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Podesi kao podrazumevano"</string>
     <string name="use_once" msgid="9027366575315399714">"Koristi jednom"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Lozinki: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • Pristupnih kodova:<xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Drugi menadžeri lozinki"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Zatvorite tabelu"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Vratite se na prethodnu stranicu"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Zatvorite"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Odbaci"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Želite da koristite sačuvani pristupni kôd za: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Želite da koristite sačuvane podatke za prijavljivanje za: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Odaberite sačuvano prijavljivanje za: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Menadžeri zaključanih lozinki"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Dodirnite da biste otključali"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nema podataka za prijavljivanje"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nema podataka za prijavljivanje u: <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Upravljajte prijavljivanjima"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Sa drugog uređaja"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Koristi drugi uređaj"</string>
diff --git a/packages/CredentialManager/res/values-be/strings.xml b/packages/CredentialManager/res/values-be/strings.xml
index d3512ba..ad82b23 100644
--- a/packages/CredentialManager/res/values-be/strings.xml
+++ b/packages/CredentialManager/res/values-be/strings.xml
@@ -20,7 +20,8 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Выберыце, куды захаваць <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Выберыце менеджар пароляў, каб захаваць свае даныя і забяспечыць хуткі ўваход у наступныя разы"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Стварыце ключ доступу да праграмы \"<xliff:g id="APPNAME">%1$s</xliff:g>\""</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Захаваць <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> сюды:"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Стварыць ключ доступу на іншай прыладзе?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Выкарыстоўваць папку \"<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>\" для ўсіх спосабаў уваходу?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Каб вам было прасцей уваходзіць у сістэму, вашы паролі і ключы доступу будуць захоўвацца ў менеджары пароляў"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Выкарыстоўваць стандартна"</string>
     <string name="use_once" msgid="9027366575315399714">"Скарыстаць адзін раз"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Пароляў: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • Ключоў доступу: <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Іншыя спосабы ўваходу"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Закрыць аркуш"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Вярнуцца да папярэдняй старонкі"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Закрыць"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Закрыць"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Скарыстаць захаваны ключ доступу для праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Скарыстаць захаваныя спосабы ўваходу для праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Выберыце захаваны спосаб уваходу для праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Заблакіраваныя спосабы ўваходу"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Націсніце, каб разблакіраваць"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Няма даных для ўваходу"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Ва ўліковым запісе <xliff:g id="SOURCE">%1$s</xliff:g> адсутнічае інфармацыя для ўваходу"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Кіраваць спосабамі ўваходу"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"З іншай прылады"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Скарыстаць іншую прыладу"</string>
diff --git a/packages/CredentialManager/res/values-bg/strings.xml b/packages/CredentialManager/res/values-bg/strings.xml
index 35926ca..f5015b0 100644
--- a/packages/CredentialManager/res/values-bg/strings.xml
+++ b/packages/CredentialManager/res/values-bg/strings.xml
@@ -20,7 +20,8 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Изберете къде да запазите своите <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Изберете мениджър на пароли, в който да се запазят данните ви, така че следващия път да влезете по-бързо в профила си"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Да се създаде ли код за достъп за <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Запазване на <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> във:"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Искате ли да създадете код за достъп на друго устройство?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Да се използва ли <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> за всичките ви данни за вход?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Този мениджър на пароли ще съхранява вашите пароли и кодове за достъп, за да влизате лесно в профила си"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Задаване като основно"</string>
     <string name="use_once" msgid="9027366575315399714">"Еднократно използване"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> пароли • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> кода за достъп"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Други мениджъри на пароли"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Затваряне на таблицата"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Назад към предишната страница"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Затваряне"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Отхвърляне"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Да се използва ли запазеният ви код за достъп за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Да се използват ли запазените ви данни за вход за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Изберете запазени данни за вход за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Заключени мениджъри на пароли"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Докоснете, за да отключите"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Няма данни за вход"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> не съдържа данни за вход"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Управление на данните за вход"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"От друго устройство"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Използване на друго устройство"</string>
diff --git a/packages/CredentialManager/res/values-bn/strings.xml b/packages/CredentialManager/res/values-bn/strings.xml
index 3273aa4..ec7e154 100644
--- a/packages/CredentialManager/res/values-bn/strings.xml
+++ b/packages/CredentialManager/res/values-bn/strings.xml
@@ -20,7 +20,8 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"আপনার <xliff:g id="CREATETYPES">%1$s</xliff:g> কোথায় সেভ করবেন তা বেছে নিন"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"আপনার তথ্য সেভ করতে একটি Password Manager বেছে নিন এবং পরের বার আরও দ্রুত সাইন-ইন করুন"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g>-এর জন্য \'পাসকী\' তৈরি করবেন?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> এখানে সেভ করুন"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"অন্য ডিভাইসে পাসকী তৈরি করবেন?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"আপনার সব সাইন-ইনের জন্য <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> ব্যবহার করবেন?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"এই Password Manager আপনার পাসওয়ার্ড ও পাসকী সেভ করবে যাতে সহজেই সাইন-ইন করতে পারেন"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"ডিফল্ট হিসেবে সেট করুন"</string>
     <string name="use_once" msgid="9027366575315399714">"একবার ব্যবহার করুন"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g>টি পাসওয়ার্ড • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>টি \'পাসকী\'"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"অন্যান্য Password Manager"</string>
     <string name="close_sheet" msgid="1393792015338908262">"শিট বন্ধ করুন"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"আগের পৃষ্ঠায় ফিরে যান"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"বন্ধ করুন"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"বাতিল করুন"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর জন্য আপনার সেভ করা পাসকী ব্যবহার করবেন?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর জন্য আপনার সেভ করা সাইন-ইন সম্পর্কিত ক্রেডেনশিয়াল ব্যবহার করবেন?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর জন্য সাইন-ইন করা সম্পর্কিত ক্রেডেনশিয়াল বেছে নিন"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"লক করা Password Manager"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"আনলক করতে ট্যাপ করুন"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"সাইন-ইন সম্পর্কিত তথ্য নেই"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>-এ সাইন-ইন সম্পর্কিত কোনও তথ্য নেই"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"সাইন-ইন করার ক্রেডেনশিয়াল ম্যানেজ করুন"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"অন্য ডিভাইস থেকে"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"আলাদা ডিভাইস ব্যবহার করুন"</string>
diff --git a/packages/CredentialManager/res/values-bs/strings.xml b/packages/CredentialManager/res/values-bs/strings.xml
index 2751651..7d888ec 100644
--- a/packages/CredentialManager/res/values-bs/strings.xml
+++ b/packages/CredentialManager/res/values-bs/strings.xml
@@ -9,7 +9,7 @@
     <string name="content_description_show_password" msgid="3283502010388521607">"Prikaži lozinku"</string>
     <string name="content_description_hide_password" msgid="6841375971631767996">"Sakrij lozinku"</string>
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Sigurniji ste uz pristupne ključeve"</string>
-    <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Uz pristupne ključeve ne morate kreirati ili pamtiti složene lozinke"</string>
+    <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Uz pristupne ključeve ne morate kreirati niti pamtiti složene lozinke"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Pristupni ključevi su šifrirani digitalni ključevi koje kreirate pomoću otiska prsta, lica ili zaključavanja ekrana"</string>
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Pristupni ključevi se pohranjuju u upravitelju lozinki da se možete prijaviti na drugim uređajima"</string>
     <string name="more_about_passkeys_title" msgid="7797903098728837795">"Više o pristupnim ključevima"</string>
@@ -20,8 +20,8 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Poboljšana sigurnost računa"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Svaki ključ je isključivo povezan s aplikacijom ili web lokacijom za koju je kreiran, tako da se nikada ne možete greškom prijaviti u prevarantsku aplikaciju ili na prevarantsku web lokaciju. Osim toga, hakiranje je puno teže zahvaljujući serverima koji čuvaju samo javne ključeve."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Neometani prijelaz"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Kako se krećemo prema budućnosti bez lozinki, lozinke će i dalje biti dostupne uz pristupne ključeve."</string>
-    <string name="choose_provider_title" msgid="8870795677024868108">"Odaberite gdje sačuvati stavku <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
+    <string name="seamless_transition_detail" msgid="3440478759491650823">"Kako idemo u smjeru budućnosti bez zaporki, one će i dalje biti dostupne uz pristupne ključeve"</string>
+    <string name="choose_provider_title" msgid="8870795677024868108">"Odaberite gdje će se pohranjivati <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Odaberite upravitelja lozinki da sačuvate svoje informacije i brže se prijavite sljedeći put"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Kreirati pristupni ključ za aplikaciju <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
     <string name="choose_create_option_password_title" msgid="7097275038523578687">"Sačuvati lozinku za aplikaciju <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -32,10 +32,10 @@
     <string name="passwords" msgid="5419394230391253816">"lozinke"</string>
     <string name="sign_ins" msgid="4710739369149469208">"prijave"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"informacije o prijavi"</string>
-    <string name="save_credential_to_title" msgid="3172811692275634301">"Sačuvajte vrstu akreditiva \"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>\" na"</string>
+    <string name="save_credential_to_title" msgid="3172811692275634301">"Sačuvaj <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> na"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Kreirati pristupni ključ na drugom uređaju?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Koristiti uslugu <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> za sve vaše prijave?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Ovaj upravitelj lozinki će pohraniti vaše lozinke i pristupne ključeve da vam olakša prijavu"</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"Upravitelj zaporki za korisničko ime <xliff:g id="USERNAME">%1$s</xliff:g> pohranit će vaše zaporke i pristupne ključeve radi jednostavnije prijave"</string>
     <string name="set_as_default" msgid="4415328591568654603">"Postavi kao zadano"</string>
     <string name="use_once" msgid="9027366575315399714">"Koristi jednom"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Broj lozinki: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • Broj pristupnih ključeva: <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
@@ -47,8 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Drugi upravitelji lozinki"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Zatvaranje tabele"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Povratak na prethodnu stranicu"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Zatvaranje"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Odbacivanje"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Koristiti sačuvani pristupni ključ za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Koristiti sačuvanu prijavu za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Odaberite sačuvanu prijavu za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +60,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Zaključani upravitelji lozinki"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Dodirnite da otključate"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nema podataka za prijavu"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nema informacija za prijavu na <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Upravljajte prijavama"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"S drugog uređaja"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Upotrijebite drugi uređaj"</string>
diff --git a/packages/CredentialManager/res/values-ca/strings.xml b/packages/CredentialManager/res/values-ca/strings.xml
index 0d115d5..9211b50 100644
--- a/packages/CredentialManager/res/values-ca/strings.xml
+++ b/packages/CredentialManager/res/values-ca/strings.xml
@@ -11,16 +11,17 @@
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Més seguretat amb les claus d\'accés"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Amb les claus d\'accés, no cal que creïs ni recordis contrasenyes difícils"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Les claus d\'accés són claus digitals encriptades que pots crear amb la teva cara, l\'empremta digital o el bloqueig de pantalla"</string>
-    <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Es desen a un gestor de contrasenyes perquè puguis iniciar la sessió en altres dispositius"</string>
+    <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Es desen en un gestor de contrasenyes perquè puguis iniciar la sessió en altres dispositius"</string>
     <string name="more_about_passkeys_title" msgid="7797903098728837795">"Més sobre les claus d\'accés"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Tecnologia sense contrasenyes"</string>
     <string name="passwordless_technology_detail" msgid="6853928846532955882">"Les claus d\'accés et permeten iniciar la sessió sense dependre de cap contrasenya. Només necessites utilitzar l\'empremta digital, el reconeixement facial, el PIN o lliscar el patró per verificar la teva identitat i crear una clau d\'accés."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"Criptografia de la clau pública"</string>
-    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"D\'acord amb FIDO Alliance i els estàndards W3C, les claus d\'accés utilitzen parells de claus criptogràfiques. En lloc del nom d\'usuari i la cadena de caràcters que utilitzem per a les contrasenyes, es crea un parell de claus per a una app o web. La clau privada es desa de manera segura al dispositiu o al gestor de contrasenyes i confirma la teva identitat. La clau pública es comparteix amb l\'app o el servidor del lloc web. Amb les claus corresponents, pots registrar-te i iniciar sessió a l\'instant."</string>
+    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"D\'acord amb FIDO Alliance i els estàndards W3C, les claus d\'accés utilitzen parells de claus criptogràfiques. En lloc del nom d\'usuari i la cadena de caràcters que utilitzem per a les contrasenyes, es crea un parell de claus per a una app o un lloc web. La clau privada es desa de manera segura al dispositiu o al gestor de contrasenyes i confirma la teva identitat. La clau pública es comparteix amb l\'app o el servidor del lloc web. Amb les claus corresponents, pots registrar-te i iniciar sessió a l\'instant."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"Seguretat dels comptes millorada"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Cada clau està exclusivament enllaçada a l\'aplicació o al lloc web per als quals s\'ha creat. D\'aquesta manera, mai iniciaràs la sessió en una aplicació o un lloc web fraudulents per error. A més, com que els servidors només conserven les claus públiques, el hacking és molt més difícil."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Transició fluida"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Tot i que avancem cap a un futur sense contrasenyes, continuaran estant disponibles juntament amb les claus d\'accés."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Tria on vols desar les <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Selecciona un gestor de contrasenyes per desar la teva informació i iniciar la sessió més ràpidament la pròxima vegada"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Vols crear la clau d\'accés per a <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -32,10 +33,11 @@
     <string name="passwords" msgid="5419394230391253816">"contrasenyes"</string>
     <string name="sign_ins" msgid="4710739369149469208">"inicis de sessió"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"informació d\'inici de sessió"</string>
-    <string name="save_credential_to_title" msgid="3172811692275634301">"Desa <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> a"</string>
+    <string name="save_credential_to_title" msgid="3172811692275634301">"Desa la <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> a"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Vols crear una clau d\'accés en un altre dispositiu?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Vols utilitzar <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> per a tots els teus inicis de sessió?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Aquest gestor de contrasenyes emmagatzemarà les teves contrasenyes i claus d\'accés per ajudar-te a iniciar la sessió fàcilment"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Estableix com a predeterminada"</string>
     <string name="use_once" msgid="9027366575315399714">"Utilitza un cop"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> contrasenyes • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> claus d\'accés"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Altres gestors de contrasenyes"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Tanca el full"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Torna a la pàgina anterior"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Tanca"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Ignora"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Vols utilitzar la clau d\'accés desada per a <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Vols utilitzar l\'inici de sessió desat per a <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Tria un inici de sessió desat per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Gestors de contrasenyes bloquejats"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Toca per desbloquejar"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Sense informació d\'inici de sessió"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Sense informació d\'inici de sessió per a <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gestiona els inicis de sessió"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Des d\'un altre dispositiu"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Utilitza un dispositiu diferent"</string>
diff --git a/packages/CredentialManager/res/values-cs/strings.xml b/packages/CredentialManager/res/values-cs/strings.xml
index f3e290b..0a80fe7 100644
--- a/packages/CredentialManager/res/values-cs/strings.xml
+++ b/packages/CredentialManager/res/values-cs/strings.xml
@@ -20,7 +20,8 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Vylepšené zabezpečení účtu"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Každý klíč je propojen výhradně s aplikací nebo webem, pro které byl vytvořen, takže se nikdy nemůžete omylem přihlásit k podvodné aplikaci nebo webu. Protože na serverech jsou uloženy pouze veřejné klíče, je hackování navíc mnohem obtížnější."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Bezproblémový přechod"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Ačkoliv směřujeme k budoucnosti bez hesel, vedle přístupových klíčů budou stále k dispozici i hesla."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Určete, kam ukládat <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Vyberte správce hesel k uložení svých údajů, abyste se příště mohli přihlásit rychleji"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Vytvořit přístupový klíč pro aplikaci <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Uložit <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> do"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Vytvořit přístupový klíč v jiném zařízení?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Používat <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> pro všechna přihlášení?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Tento správce hesel bude ukládat vaše hesla a přístupové klíče, abyste se mohli snadno přihlásit"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Nastavit jako výchozí"</string>
     <string name="use_once" msgid="9027366575315399714">"Použít jednou"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Hesla: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • Přístupové klíče: <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Další správci hesel"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Zavřít list"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Zpět na předchozí stránku"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Zavřít"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Zavřít"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Použít uložený přístupový klíč pro aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Použít uložené přihlášení pro aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Vyberte uložené přihlášení pro <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Uzamčení správci hesel"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Klepnutím odemknete"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Žádné informace o přihlášení"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> neobsahuje žádné přihlašovací údaje"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Spravovat přihlášení"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Z jiného zařízení"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Použít jiné zařízení"</string>
diff --git a/packages/CredentialManager/res/values-da/strings.xml b/packages/CredentialManager/res/values-da/strings.xml
index 76c8a81..f24fdb0 100644
--- a/packages/CredentialManager/res/values-da/strings.xml
+++ b/packages/CredentialManager/res/values-da/strings.xml
@@ -20,7 +20,8 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Forbedret kontosikkerhed"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Hver nøgle er udelukkende tilknyttet den app eller det website, som nøglen blev oprettet til. På denne måde kan du aldrig logge ind i en svigagtig app eller på et svigagtigt website ved en fejl. Og da serverne kun opbevarer offentlige nøgler, er kontoer meget sværere at hacke."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Problemfri overgang"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Selvom vi nærmer os en fremtid, hvor adgangskoder er mindre fremtrædende, kan de stadig bruges i samspil med adgangsnøgler."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Vælg, hvor du vil gemme dine <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Vælg en adgangskodeadministrator for at gemme dine oplysninger, så du kan logge ind hurtigere næste gang"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Vil du oprette en adgangsnøgle til <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -32,10 +33,11 @@
     <string name="passwords" msgid="5419394230391253816">"adgangskoder"</string>
     <string name="sign_ins" msgid="4710739369149469208">"loginmetoder"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"loginoplysninger"</string>
-    <string name="save_credential_to_title" msgid="3172811692275634301">"Gem <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> her:"</string>
+    <string name="save_credential_to_title" msgid="3172811692275634301">"Gem <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> i"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Vil du oprette en adgangsnøgle på en anden enhed?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Vil du bruge <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> til alle dine loginmetoder?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Denne adgangskodeadministrator gemmer dine adgangskoder og adgangsnøgler for at hjælpe dig med nemt at logge ind"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Angiv som standard"</string>
     <string name="use_once" msgid="9027366575315399714">"Brug én gang"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> adgangskoder • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> adgangsnøgler"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Andre adgangskodeadministratorer"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Luk arket"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Gå tilbage til den forrige side"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Luk"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Luk"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Vil du bruge din gemte adgangsnøgle til <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Vil du bruge din gemte loginmetode til <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Vælg en gemt loginmetode til <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Låste adgangskodeadministratorer"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tryk for at låse op"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ingen loginoplysninger"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Der er ingen loginoplysninger i <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Administrer loginmetoder"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Fra en anden enhed"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Brug en anden enhed"</string>
diff --git a/packages/CredentialManager/res/values-de/strings.xml b/packages/CredentialManager/res/values-de/strings.xml
index adcaae4..dc6d81d 100644
--- a/packages/CredentialManager/res/values-de/strings.xml
+++ b/packages/CredentialManager/res/values-de/strings.xml
@@ -16,11 +16,12 @@
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Passwortlose Technologie"</string>
     <string name="passwordless_technology_detail" msgid="6853928846532955882">"Passkeys ermöglichen die Anmeldung, ohne dass Passwörter erforderlich sind. Du verwendest einfach die Fingerabdruck- oder Gesichtserkennung, eine PIN oder ein Muster, um deine Identität zu bestätigen und einen Passkey zu erstellen."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"Asymmetrisches Kryptosystem"</string>
-    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Passkeys beruhen auf FIDO Alliance- (zu der auch Google und Apple gehören) und W3C-Standards. Anstelle von Nutzername und Passwort wird ein kryptografisches Paar aus privatem und öffentlichem Schlüssel für eine App oder Website erstellt. Der private Schlüssel wird sicher auf deinem Gerät oder im Passwortmanager gespeichert und bestätigt deine Identität. Der öffentliche Schlüssel wird mit dem App- oder Websiteserver geteilt. Stimmen beide überein, kannst du dich sofort registrieren und anmelden."</string>
+    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Passkeys beruhen auf FIDO Alliance- (zu der unter anderem auch Google, Apple und Microsoft gehören) und W3C-Standards. Anstelle von Nutzername und Passwort wird ein kryptografisches Paar aus privatem und öffentlichem Schlüssel für eine App oder Website erstellt. Der private Schlüssel wird sicher auf deinem Gerät oder im Passwortmanager gespeichert und bestätigt deine Identität. Der öffentliche Schlüssel wird mit dem App- oder Websiteserver geteilt. Stimmen beide überein, kannst du dich sofort registrieren und anmelden."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"Verbesserte Kontosicherheit"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Jeder Schlüssel ist ausschließlich mit der App oder Website verknüpft, für die er erstellt wurde. Du kannst dich also nicht aus Versehen bei einer betrügerischen App oder Website anmelden. Da auf Servern nur öffentliche Schlüssel verwaltet werden, wird das Hacking außerdem erheblich erschwert."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Nahtlose Umstellung"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Auch wenn wir uns auf eine passwortlose Zukunft zubewegen, werden neben Passkeys weiter Passwörter verfügbar sein."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Wähle aus, wo deine <xliff:g id="CREATETYPES">%1$s</xliff:g> gespeichert werden sollen"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Du kannst einen Passwortmanager auswählen, um deine Anmeldedaten zu speichern, damit du dich nächstes Mal schneller anmelden kannst"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Passkey für <xliff:g id="APPNAME">%1$s</xliff:g> erstellen?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> speichern unter"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Passkey auf einem anderen Gerät erstellen?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> für alle Anmeldungen verwenden?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Mit diesem Passwortmanager werden deine Passwörter und Passkeys gespeichert, damit du dich problemlos anmelden kannst"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Als Standard festlegen"</string>
     <string name="use_once" msgid="9027366575315399714">"Einmal verwenden"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> Passwörter • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> Passkeys"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Andere Passwortmanager"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Tabellenblatt schließen"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Zurück zur vorherigen Seite"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Schließen"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Schließen"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Gespeicherten Passkey für <xliff:g id="APP_NAME">%1$s</xliff:g> verwenden?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Gespeicherte Anmeldedaten für <xliff:g id="APP_NAME">%1$s</xliff:g> verwenden?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Gespeicherte Anmeldedaten für <xliff:g id="APP_NAME">%1$s</xliff:g> auswählen"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Gesperrte Passwortmanager"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Zum Entsperren tippen"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Keine Anmeldedaten"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Keine Anmeldedaten in <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Anmeldedaten verwalten"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Von einem anderen Gerät"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Anderes Gerät verwenden"</string>
diff --git a/packages/CredentialManager/res/values-el/strings.xml b/packages/CredentialManager/res/values-el/strings.xml
index df1b1a7..0abc8de 100644
--- a/packages/CredentialManager/res/values-el/strings.xml
+++ b/packages/CredentialManager/res/values-el/strings.xml
@@ -20,7 +20,8 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Επιλέξτε πού θα αποθηκεύονται τα <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Επιλέξτε ένα πρόγραμμα διαχείρισης κωδικών πρόσβασης για να αποθηκεύσετε τα στοιχεία σας και να συνδεθείτε πιο γρήγορα την επόμενη φορά."</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Δημιουργία κλειδιού πρόσβασης για <xliff:g id="APPNAME">%1$s</xliff:g>;"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Αποθήκευση <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> σε"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Δημιουργία κλειδιού πρόσβασης σε άλλη συσκευή;"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Να χρησιμοποιηθεί το <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> για όλες τις συνδέσεις σας;"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Αυτός ο διαχειριστής κωδικών πρόσβασης θα αποθηκεύει τους κωδικούς πρόσβασης και τα κλειδιά πρόσβασης, για να συνδέεστε εύκολα."</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Ορισμός ως προεπιλογής"</string>
     <string name="use_once" msgid="9027366575315399714">"Χρήση μία φορά"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> κωδικοί πρόσβασης • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> κλειδιά πρόσβασης"</string>
@@ -48,6 +50,7 @@
     <string name="close_sheet" msgid="1393792015338908262">"Κλείσιμο φύλλου"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Επιστροφή στην προηγούμενη σελίδα"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Κλείσιμο"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Παράβλεψη"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Να χρησιμοποιηθεί το αποθηκευμένο κλειδί πρόσβασης για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>;"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Να χρησιμοποιηθούν τα αποθηκευμένα στοιχεία σύνδεσης για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>;"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Επιλογή αποθηκευμένων στοιχείων σύνδεσης για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-en-rAU/strings.xml b/packages/CredentialManager/res/values-en-rAU/strings.xml
index e350449c..5a5480d 100644
--- a/packages/CredentialManager/res/values-en-rAU/strings.xml
+++ b/packages/CredentialManager/res/values-en-rAU/strings.xml
@@ -20,7 +20,7 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Improved account security"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Each key is exclusively linked with the app or website they were created for, so you can never sign in to a fraudulent app or website by mistake. Plus, with servers only keeping public keys, hacking is a lot harder."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Seamless transition"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"As we move towards a passwordless future, passwords will still be available alongside passkeys."</string>
+    <string name="seamless_transition_detail" msgid="3440478759491650823">"As we move towards a passwordless future, passwords will still be available alongside passkeys"</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"Choose where to save your <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Select a password manager to save your info and sign in faster next time"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Create passkey for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +35,7 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Save <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> to"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Create passkey on another device?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Use <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> for all your sign-ins?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"This password manager will store your passwords and passkeys to help you easily sign in"</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"This password manager for <xliff:g id="USERNAME">%1$s</xliff:g> will store your passwords and passkeys to help you easily sign in"</string>
     <string name="set_as_default" msgid="4415328591568654603">"Set as default"</string>
     <string name="use_once" msgid="9027366575315399714">"Use once"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> passwords • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> passkeys"</string>
@@ -48,6 +48,7 @@
     <string name="close_sheet" msgid="1393792015338908262">"Close sheet"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Go back to the previous page"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Close"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Dismiss"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Use your saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Use your saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Choose a saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-en-rCA/strings.xml b/packages/CredentialManager/res/values-en-rCA/strings.xml
index f6ab350..23091e7 100644
--- a/packages/CredentialManager/res/values-en-rCA/strings.xml
+++ b/packages/CredentialManager/res/values-en-rCA/strings.xml
@@ -20,7 +20,7 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Improved account security"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Each key is exclusively linked with the app or website they were created for, so you can never sign in to a fraudulent app or website by mistake. Plus, with servers only keeping public keys, hacking is a lot harder."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Seamless transition"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"As we move towards a passwordless future, passwords will still be available alongside passkeys."</string>
+    <string name="seamless_transition_detail" msgid="3440478759491650823">"As we move towards a passwordless future, passwords will still be available alongside passkeys"</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"Choose where to save your <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Select a password manager to save your info and sign in faster next time"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Create passkey for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +35,7 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Save <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> to"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Create passkey in another device?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Use <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> for all your sign-ins?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"This password manager will store your passwords and passkeys to help you easily sign in"</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"This password manager for <xliff:g id="USERNAME">%1$s</xliff:g> will store your passwords and passkeys to help you easily sign in"</string>
     <string name="set_as_default" msgid="4415328591568654603">"Set as default"</string>
     <string name="use_once" msgid="9027366575315399714">"Use once"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> passwords • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> passkeys"</string>
@@ -48,6 +48,7 @@
     <string name="close_sheet" msgid="1393792015338908262">"Close sheet"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Go back to the previous page"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Close"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Dismiss"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Use your saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Use your saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Choose a saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-en-rGB/strings.xml b/packages/CredentialManager/res/values-en-rGB/strings.xml
index e350449c..5a5480d 100644
--- a/packages/CredentialManager/res/values-en-rGB/strings.xml
+++ b/packages/CredentialManager/res/values-en-rGB/strings.xml
@@ -20,7 +20,7 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Improved account security"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Each key is exclusively linked with the app or website they were created for, so you can never sign in to a fraudulent app or website by mistake. Plus, with servers only keeping public keys, hacking is a lot harder."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Seamless transition"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"As we move towards a passwordless future, passwords will still be available alongside passkeys."</string>
+    <string name="seamless_transition_detail" msgid="3440478759491650823">"As we move towards a passwordless future, passwords will still be available alongside passkeys"</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"Choose where to save your <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Select a password manager to save your info and sign in faster next time"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Create passkey for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +35,7 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Save <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> to"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Create passkey on another device?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Use <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> for all your sign-ins?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"This password manager will store your passwords and passkeys to help you easily sign in"</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"This password manager for <xliff:g id="USERNAME">%1$s</xliff:g> will store your passwords and passkeys to help you easily sign in"</string>
     <string name="set_as_default" msgid="4415328591568654603">"Set as default"</string>
     <string name="use_once" msgid="9027366575315399714">"Use once"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> passwords • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> passkeys"</string>
@@ -48,6 +48,7 @@
     <string name="close_sheet" msgid="1393792015338908262">"Close sheet"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Go back to the previous page"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Close"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Dismiss"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Use your saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Use your saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Choose a saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-en-rIN/strings.xml b/packages/CredentialManager/res/values-en-rIN/strings.xml
index e350449c..5a5480d 100644
--- a/packages/CredentialManager/res/values-en-rIN/strings.xml
+++ b/packages/CredentialManager/res/values-en-rIN/strings.xml
@@ -20,7 +20,7 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Improved account security"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Each key is exclusively linked with the app or website they were created for, so you can never sign in to a fraudulent app or website by mistake. Plus, with servers only keeping public keys, hacking is a lot harder."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Seamless transition"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"As we move towards a passwordless future, passwords will still be available alongside passkeys."</string>
+    <string name="seamless_transition_detail" msgid="3440478759491650823">"As we move towards a passwordless future, passwords will still be available alongside passkeys"</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"Choose where to save your <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Select a password manager to save your info and sign in faster next time"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Create passkey for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +35,7 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Save <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> to"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Create passkey on another device?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Use <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> for all your sign-ins?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"This password manager will store your passwords and passkeys to help you easily sign in"</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"This password manager for <xliff:g id="USERNAME">%1$s</xliff:g> will store your passwords and passkeys to help you easily sign in"</string>
     <string name="set_as_default" msgid="4415328591568654603">"Set as default"</string>
     <string name="use_once" msgid="9027366575315399714">"Use once"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> passwords • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> passkeys"</string>
@@ -48,6 +48,7 @@
     <string name="close_sheet" msgid="1393792015338908262">"Close sheet"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Go back to the previous page"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Close"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Dismiss"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Use your saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Use your saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Choose a saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-en-rXC/strings.xml b/packages/CredentialManager/res/values-en-rXC/strings.xml
index 7f5f0c1..465fd2c 100644
--- a/packages/CredentialManager/res/values-en-rXC/strings.xml
+++ b/packages/CredentialManager/res/values-en-rXC/strings.xml
@@ -20,7 +20,7 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‏‎‎‎‏‏‎‏‎‏‏‏‏‎‎‎‏‏‏‎‎‏‎‏‏‎‎‏‏‏‎‏‏‏‎‏‏‎‎‏‎‎‎‎‏‏‎‏‎‎‎‎‎Improved account security‎‏‎‎‏‎"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‎‎‎‏‎‎‏‎‏‎‎‎‎‎‏‏‏‎‎‏‏‎‏‏‎‎‏‎‎‎‎‎‏‏‏‎‏‎‎‏‏‏‏‏‏‏‎‎‎Each key is exclusively linked with the app or website they were created for, so you can never sign in to a fraudulent app or website by mistake. Plus, with servers only keeping public keys, hacking is a lot harder.‎‏‎‎‏‎"</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎‎‏‎‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‏‎‎‏‎‎‎‏‎‏‎‎‏‏‎‏‏‎‏‎‎‎‏‎‏‎‏‎‏‏‏‎‎‏‎Seamless transition‎‏‎‎‏‎"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‎‏‏‏‎‎‎‎‏‏‎‎‏‏‏‏‏‏‎‎‎‎‎‏‎‏‏‏‏‎‏‎‎‏‏‎‎‏‏‏‎‏‏‏‎‎‏‏‎‎‎‎‏‏‎As we move towards a passwordless future, passwords will still be available alongside passkeys.‎‏‎‎‏‎"</string>
+    <string name="seamless_transition_detail" msgid="3440478759491650823">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‏‎‎‏‎‎‏‏‎‏‎‎‎‎‎‎‏‏‎‎‏‏‎‎‎‏‏‎‏‏‎‎‎‏‎‏‎‎‎‎‎‏‏‏‎As we move towards a passwordless future, passwords will still be available alongside passkeys‎‏‎‎‏‎"</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‏‎‏‏‎‎‏‎‏‏‎‏‎‏‎‏‏‎‎‏‏‎‏‎‎‎‎‏‎‎‎‏‏‎‏‎‏‎‏‏‏‎‎‎‎‏‏‎‎‎Choose where to save your ‎‏‎‎‏‏‎<xliff:g id="CREATETYPES">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‏‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‎‏‏‏‎‎‎‎‏‎‏‎‎‎‎‏‎‏‏‎‎‏‎‏‎‏‎‎Select a password manager to save your info and sign in faster next time‎‏‎‎‏‎"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‏‏‎‏‎‎‏‎‏‎‎‏‎‎‏‏‏‎‏‎‎‎‎‏‎‏‏‎‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‎‏‎‎‎‏‏‏‎‎Create passkey for ‎‏‎‎‏‏‎<xliff:g id="APPNAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
@@ -35,7 +35,7 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‎‎‎‎‏‎‎‎‎‎‎‏‎‏‏‏‎‏‏‎‏‏‎‎‏‎‎‎‎‎‎‏‎‏‎‎‏‎‏‏‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎Save ‎‏‎‎‏‏‎<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to‎‏‎‎‏‎"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‏‎‏‎‎‏‏‎‏‏‎‎‏‎‎‏‎‎‏‎‎‎‎‎‎‏‎‏‏‏‎‎‏‎‏‏‎‎‏‏‎‎‏‏‏‎‎Create passkey in another device?‎‏‎‎‏‎"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‎‎‏‏‎‏‎‎‎‎‎‏‎‏‏‎‎‏‏‏‎‎‎‎‎‎‎‏‎‎‏‎‏‏‏‎‏‏‏‎‎‏‎‏‏‏‏‎‎‏‎‏‎‏‎Use ‎‏‎‎‏‏‎<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ for all your sign-ins?‎‏‎‎‏‎"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‏‎‎‏‏‎‏‎‏‏‏‏‎‎‏‎‏‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎This password manager will store your passwords and passkeys to help you easily sign in‎‏‎‎‏‎"</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‏‎‏‏‏‏‎‏‎‎‎‏‎‎‎‏‎‎‏‏‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎‏‎‎‎‎‎‏‏‎‎‏‎‏‏‏‎‏‎‏‎‏‎This password manager for ‎‏‎‎‏‏‎<xliff:g id="USERNAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ will store your passwords and passkeys to help you easily sign in‎‏‎‎‏‎"</string>
     <string name="set_as_default" msgid="4415328591568654603">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‎‏‏‎‎‏‏‎‎‏‎‏‏‏‏‏‎‏‎‏‏‏‏‎‏‎‏‏‎‎‎‏‎‎‏‏‎‏‎‏‎‎‎‏‎‎‎‎‏‎‏‏‎Set as default‎‏‎‎‏‎"</string>
     <string name="use_once" msgid="9027366575315399714">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‏‏‎‏‎‎‏‏‎‎‎‎‏‎‎‏‎‎‎‏‏‏‎‏‎‏‏‏‎‏‎‎‎‏‎‏‏‎‏‎‎‎‎‏‎‎‎‏‎‎Use once‎‏‎‎‏‎"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‎‏‎‎‎‎‏‎‏‎‎‏‎‎‎‏‏‏‏‏‎‏‎‏‏‏‏‏‎‏‏‏‎‎‎‏‎‏‎‎‎‏‎‎‎‏‎‎‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g>‎‏‎‎‏‏‏‎ passwords • ‎‏‎‎‏‏‎<xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>‎‏‎‎‏‏‏‎ passkeys‎‏‎‎‏‎"</string>
@@ -48,6 +48,7 @@
     <string name="close_sheet" msgid="1393792015338908262">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‏‎‏‏‏‏‎‏‏‏‏‏‎‎‏‏‏‎‏‎‎‎‎‎‎‏‏‎‏‎‎‎‎‏‏‎‏‎‎‏‎‏‎‏‎‎‏‏‎‎‏‏‎‎Close sheet‎‏‎‎‏‎"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‎‏‏‏‏‎‏‎‏‎‎‎‎‎‏‎‎‏‏‏‏‎‎‎‎‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‏‏‏‎‎‎Go back to the previous page‎‏‎‎‏‎"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‎‎‏‎‏‎‏‎‏‏‎‏‎‏‎‎‎‎‎‎‎‏‎‏‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‏‎‏‎‏‏‏‎‎‏‎‏‏‏‎Close‎‏‎‎‏‎"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‏‎‏‏‏‏‎‏‎‎‎‎‏‏‏‎‏‎‏‎‏‎‎‎‎‎‏‏‎‎‎‏‎‎‎‎‏‎‏‏‎‎‎‎Dismiss‎‏‎‎‏‎"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‏‏‎‎‏‏‏‎‎‎‏‎‏‎‏‏‏‎‏‎‎‎‎‎‏‏‎‎‏‏‎‎‏‏‏‏‏‎‎‏‏‏‏‎‎‎‎‎‎‏‏‏‎Use your saved passkey for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‎‎‎‏‎‏‎‏‎‏‏‏‎‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‏‏‏‏‎‏‎‎‎Use your saved sign-in for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‏‏‏‎‎‏‎‏‏‏‎‎‏‎‎‎‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‎‏‎‏‎‏‏‎‎‏‎‏‏‎‎‏‎‏‎‎‎‎‏‎‏‎Choose a saved sign-in for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
diff --git a/packages/CredentialManager/res/values-es-rUS/strings.xml b/packages/CredentialManager/res/values-es-rUS/strings.xml
index d700ed6..9c006a1 100644
--- a/packages/CredentialManager/res/values-es-rUS/strings.xml
+++ b/packages/CredentialManager/res/values-es-rUS/strings.xml
@@ -20,7 +20,8 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Mayor seguridad para las cuentas"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Cada llave está vinculada exclusivamente con el sitio web o la app para la que fue creada, por lo que nunca podrás acceder por error a una app o sitio web fraudulentos. Además, como los servidores solo guardan claves públicas, hackearlas es mucho más difícil."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Transición fluida"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"A medida que avanzamos hacia un futuro sin contraseñas, estas seguirán estando disponibles junto a las llaves de acceso."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Elige dónde guardar tus <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Selecciona un administrador de contraseñas para guardar tu información y acceder más rápido la próxima vez"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"¿Quieres crear una llave de acceso para <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Guardar <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> en"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"¿Quieres crear una llave de acceso en otro dispositivo?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"¿Quieres usar <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> para todos tus accesos?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Este administrador de contraseñas almacenará tus contraseñas y llaves de acceso para ayudarte a acceder fácilmente"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Establecer como predeterminado"</string>
     <string name="use_once" msgid="9027366575315399714">"Usar una vez"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> contraseñas • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> llaves de acceso"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Otros administradores de contraseñas"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Cerrar hoja"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Volver a la página anterior"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Cerrar"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Descartar"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"¿Quieres usar tu llave de acceso guardada para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"¿Quieres usar tu acceso guardado para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Elige un acceso guardado para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Administradores de contraseñas bloqueados"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Presiona para desbloquear"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"No hay información de acceso"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"No hay información de acceso en <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Administrar accesos"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Desde otro dispositivo"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Usar otra voz"</string>
diff --git a/packages/CredentialManager/res/values-es/strings.xml b/packages/CredentialManager/res/values-es/strings.xml
index ee056af..54097f8 100644
--- a/packages/CredentialManager/res/values-es/strings.xml
+++ b/packages/CredentialManager/res/values-es/strings.xml
@@ -20,7 +20,8 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Seguridad de las cuentas mejorada"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Cada llave está vinculada exclusivamente con la aplicación o sitio web para los que se crearon, por lo que nunca puedes iniciar sesión en una aplicación o sitio web fraudulentos por error. Además, dado que los servidores solo mantienen claves públicas, es muy difícil que las pirateen."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Transición fluida"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Aunque nos dirigimos hacia un mundo sin contraseñas, estas seguirán estando disponibles junto con las llaves de acceso."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Elige dónde guardar tus <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Selecciona un gestor de contraseñas para guardar tu información e iniciar sesión más rápido la próxima vez"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"¿Crear llave de acceso para <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Guardar <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> en"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"¿Crear llave de acceso en otro dispositivo?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"¿Usar <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> para todos tus inicios de sesión?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Este gestor de contraseñas almacenará tus contraseñas y llaves de acceso para que puedas iniciar sesión fácilmente"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Fijar como predeterminado"</string>
     <string name="use_once" msgid="9027366575315399714">"Usar una vez"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> contraseñas • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> llaves de acceso"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Otros gestores de contraseñas"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Cerrar hoja"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Volver a la página anterior"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Cerrar"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Cerrar"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"¿Usar la llave de acceso guardada para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"¿Usar el inicio de sesión guardado para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Elige un inicio de sesión guardado para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Gestores de contraseñas bloqueados"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tocar para desbloquear"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"No hay información de inicio de sesión"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"No hay información de inicio de sesión en <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gestionar inicios de sesión"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"De otro dispositivo"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Usar otro dispositivo"</string>
diff --git a/packages/CredentialManager/res/values-et/strings.xml b/packages/CredentialManager/res/values-et/strings.xml
index accdea5..066a98e 100644
--- a/packages/CredentialManager/res/values-et/strings.xml
+++ b/packages/CredentialManager/res/values-et/strings.xml
@@ -20,35 +20,37 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Konto täiustatud turvalisus"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Iga võti on lingitud vaid rakenduse või veebisaidiga, mille jaoks see loodi, seega ei saa te petturlikku rakendusse või veebisaidile kunagi kogemata sisse logida. Ja kuna serverid säilitavad vaid avalikke võtmeid, on häkkimine palju keerulisem."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Sujuv üleminek"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Liikudes paroolivaba tuleviku poole, jäävad paroolid pääsuvõtmete kõrval siiski kättesaadavaks."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Valige, kuhu soovite oma <xliff:g id="CREATETYPES">%1$s</xliff:g> salvestada"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Valige paroolihaldur, et salvestada oma teave ja järgmisel korral kiiremini sisse logida"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Kas luua rakenduse <xliff:g id="APPNAME">%1$s</xliff:g> jaoks pääsuvõti?"</string>
     <string name="choose_create_option_password_title" msgid="7097275038523578687">"Kas salvestada rakenduse <xliff:g id="APPNAME">%1$s</xliff:g> jaoks parool?"</string>
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Kas salvestada rakenduse <xliff:g id="APPNAME">%1$s</xliff:g> jaoks sisselogimisandmed?"</string>
-    <string name="passkey" msgid="632353688396759522">"pääsukood"</string>
+    <string name="passkey" msgid="632353688396759522">"pääsuvõti"</string>
     <string name="password" msgid="6738570945182936667">"parool"</string>
     <string name="passkeys" msgid="5733880786866559847">"pääsuvõtmed"</string>
     <string name="passwords" msgid="5419394230391253816">"paroolid"</string>
     <string name="sign_ins" msgid="4710739369149469208">"sisselogimisandmed"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"sisselogimisteave"</string>
-    <string name="save_credential_to_title" msgid="3172811692275634301">"Salvestage <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>:"</string>
+    <string name="save_credential_to_title" msgid="3172811692275634301">"Salvesta <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>:"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Kas luua pääsuvõti muus seadmes?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Kas kasutada teenust <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> kõigi teie sisselogimisandmete puhul?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"See paroolihaldur salvestab teie paroolid ja pääsuvõtmed, et aidata teil hõlpsalt sisse logida"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Määra vaikeseadeks"</string>
     <string name="use_once" msgid="9027366575315399714">"Kasuta ühe korra"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> parooli • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> pääsuvõtit"</string>
     <string name="more_options_usage_passwords" msgid="1632047277723187813">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> parooli"</string>
     <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> pääsuvõtit"</string>
     <string name="more_options_usage_credentials" msgid="1785697001787193984">"<xliff:g id="TOTALCREDENTIALSNUMBER">%1$s</xliff:g> mandaati"</string>
-    <string name="passkey_before_subtitle" msgid="2448119456208647444">"Pääsukood"</string>
+    <string name="passkey_before_subtitle" msgid="2448119456208647444">"Pääsuvõti"</string>
     <string name="another_device" msgid="5147276802037801217">"Teine seade"</string>
     <string name="other_password_manager" msgid="565790221427004141">"Muud paroolihaldurid"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Sule leht"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Minge tagasi eelmisele lehele"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Sule"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Loobu"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Kas kasutada rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> jaoks salvestatud pääsuvõtit?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Kas kasutada rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> jaoks salvestatud sisselogimisandmeid?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Valige rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> jaoks salvestatud sisselogimisandmed"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Lukustatud paroolihaldurid"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Avamiseks puudutage"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Sisselogimisteave puudub"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Kontol <xliff:g id="SOURCE">%1$s</xliff:g> puudub sisselogimisteave"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Sisselogimisandmete haldamine"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Muus seadmes"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Kasuta teist seadet"</string>
diff --git a/packages/CredentialManager/res/values-eu/strings.xml b/packages/CredentialManager/res/values-eu/strings.xml
index 18d6532..34a3e05 100644
--- a/packages/CredentialManager/res/values-eu/strings.xml
+++ b/packages/CredentialManager/res/values-eu/strings.xml
@@ -8,19 +8,19 @@
     <string name="string_learn_more" msgid="4541600451688392447">"Lortu informazio gehiago"</string>
     <string name="content_description_show_password" msgid="3283502010388521607">"Erakutsi pasahitza"</string>
     <string name="content_description_hide_password" msgid="6841375971631767996">"Ezkutatu pasahitza"</string>
-    <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Sarbide-gako seguruagoak"</string>
+    <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Sarbide-gakoekin, seguruago"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Sarbide-gakoei esker, ez duzu pasahitz konplexurik sortu edo gogoratu beharrik"</string>
-    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Hatz-marka, aurpegia edo pantailaren blokeoa erabilita sortzen dituzun giltza digital enkriptatuak dira sarbide-gakoak"</string>
+    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Hatz-marka, aurpegia edo pantailaren blokeoa erabilita sortzen dituzun gako digital enkriptatuak dira sarbide-gakoak"</string>
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Pasahitz-kudeatzaile batean gordetzen dira, beste gailu batzuen bidez saioa hasi ahal izateko"</string>
     <string name="more_about_passkeys_title" msgid="7797903098728837795">"Sarbide-gakoei buruzko informazio gehiago"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Pasahitzik gabeko teknologia"</string>
     <string name="passwordless_technology_detail" msgid="6853928846532955882">"Sarbide-gakoekin, pasahitzik erabili behar gabe has dezakezu saioa. Hatz-marka, aurpegi-hautematea, PINa edo desblokeatzeko eredua baino ez duzu erabili behar zure identitatea egiaztatu, eta sarbide-gako bat sortzeko."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"Gako publikoen kriptografia"</string>
-    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"FIDO itunean (Google, Apple, Microsoft eta beste enpresa batzuk daude sartuta) eta W3C-ren arauetan oinarritzen dira sarbide-gakoak, eta giltza pare kriptografikoak erabiltzen dituzte. Pasahitzetarako erabiltzen diren erabiltzaile-izenak eta karaktere-kateak ez bezala, giltza pare bat sortzen da (bata pribatua, eta bestea publikoa) aplikazio edo webgune bakoitzerako. Gako pribatua gailuan edo pasahitz-kudeatzailean gordetzen da modu seguruan, eta zure identitatea berresteko balio du. Gako publikoa, aldiz, aplikazioaren edo webgunearen zerbitzariarekin partekatzen da. Aplikazio edo webgune bakoitzari dagokion giltzarekin, berehala erregistra zaitezke, bai eta saioa hasi ere."</string>
+    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"FIDO itunean (Google, Apple, Microsoft eta beste enpresa batzuk daude sartuta) eta W3C-ren arauetan oinarritzen dira sarbide-gakoak, eta gako pare kriptografikoak erabiltzen dituzte. Pasahitzetarako erabiltzen diren erabiltzaile-izenak eta karaktere-kateak ez bezala, gako pare bat sortzen da (bata pribatua, eta bestea publikoa) aplikazio edo webgune bakoitzerako. Gako pribatua gailuan edo pasahitz-kudeatzailean gordetzen da modu seguruan, eta zure identitatea berresteko balio du. Gako publikoa, aldiz, aplikazioaren edo webgunearen zerbitzariarekin partekatzen da. Aplikazio edo webgune bakoitzari dagokion gakoarekin, berehala erregistra zaitezke, bai eta saioa hasi ere."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"Kontuaren segurtasun areagotua"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Gako bakoitza harekin batera erabili behar den aplikazioarekin edo webgunearekin soilik lotzen da. Hala, ezingo duzu inoiz hasi saioa nahi gabe iruzurrezko aplikazio edo webgune batean. Gainera, zerbitzarietan gako publikoak soilik gordetzen direnez, askoz zailagoa da sarbide-gakoak hackeatzea."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Etenik gabeko trantsizioa"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Pasahitzik gabeko etorkizun baterantz goazen arren, pasahitzek sarbide-gakoen bizikide izaten jarraituko dute."</string>
+    <string name="seamless_transition_detail" msgid="3440478759491650823">"Pasahitzik gabeko etorkizun baterantz goazen arren, pasahitzek sarbide-gakoen bizikide izaten jarraituko dute"</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"Aukeratu non gorde <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Hautatu informazioa gordetzeko pasahitz-kudeatzaile bat eta hasi saioa bizkorrago hurrengoan"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> atzitzeko sarbide-gako bat sortu nahi duzu?"</string>
@@ -35,7 +35,7 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Gorde <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> hemen:"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Beste gailu batean sortu nahi duzu sarbide-gakoa?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> erabili nahi duzu kredentzial guztietarako?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Pasahitz-kudeatzaile honek pasahitzak eta sarbide-gakoak gordeko ditu saioa erraz has dezazun"</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"<xliff:g id="USERNAME">%1$s</xliff:g> erabiltzailearen pasahitz-kudeatzaile honek pasahitzak eta sarbide-gakoak gordeko ditu saioa erraz has dezazun"</string>
     <string name="set_as_default" msgid="4415328591568654603">"Ezarri lehenetsi gisa"</string>
     <string name="use_once" msgid="9027366575315399714">"Erabili behin"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> pasahitz • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> sarbide-gako"</string>
@@ -47,8 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Beste pasahitz-kudeatzaile batzuk"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Itxi orria"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Itzuli aurreko orrira"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Itxi"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Baztertu"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikaziorako gorde duzun sarbide-gakoa erabili nahi duzu?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikaziorako gorde dituzun kredentzialak erabili nahi dituzu?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Aukeratu <xliff:g id="APP_NAME">%1$s</xliff:g> aplikaziorako gorde dituzun kredentzialak"</string>
@@ -60,8 +60,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Blokeatutako pasahitz-kudeatzaileak"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Desblokeatzeko, sakatu hau"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ez dago saioa hasteko informaziorik"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Ez dago saioa hasteko informaziorik <xliff:g id="SOURCE">%1$s</xliff:g> kontuan"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Kudeatu kredentzialak"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Beste gailu batean gordetakoak"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Erabili beste gailu bat"</string>
diff --git a/packages/CredentialManager/res/values-fa/strings.xml b/packages/CredentialManager/res/values-fa/strings.xml
index 68ec685..9bef4b3 100644
--- a/packages/CredentialManager/res/values-fa/strings.xml
+++ b/packages/CredentialManager/res/values-fa/strings.xml
@@ -20,7 +20,8 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"جایی را برای ذخیره کردن <xliff:g id="CREATETYPES">%1$s</xliff:g> انتخاب کنید"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"مدیر گذرواژه‌ای انتخاب کنید تا اطلاعاتتان ذخیره شود و دفعه بعدی سریع‌تر به سیستم وارد شوید"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"برای <xliff:g id="APPNAME">%1$s</xliff:g> گذرکلید ایجاد شود؟"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"ذخیره <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> در"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"گذرکلید در دستگاه دیگر ایجاد شود؟"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"از <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> برای همه ورود به سیستم‌ها استفاده شود؟"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"این مدیر گذرواژه گذرکلیدها و گذرواژه‌های شما را ذخیره خواهد کرد تا به‌راحتی بتوانید به سیستم وارد شوید"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"تنظیم به‌عنوان پیش‌فرض"</string>
     <string name="use_once" msgid="9027366575315399714">"یک‌بار استفاده"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> گذرواژه • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> گذرکلید"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"دیگر مدیران گذرواژه"</string>
     <string name="close_sheet" msgid="1393792015338908262">"بستن برگ"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"برگشتن به صفحه قبلی"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"بستن"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"بستن"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"گذرکلید ذخیره‌شده برای <xliff:g id="APP_NAME">%1$s</xliff:g> استفاده شود؟"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"ورود به سیستم ذخیره‌شده برای <xliff:g id="APP_NAME">%1$s</xliff:g> استفاده شود؟"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"انتخاب ورود به سیستم ذخیره‌شده برای <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"مدیران گذرواژه قفل‌شده"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"برای باز کردن قفل ضربه بزنید"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"اطلاعات ورود به سیستم موجود نیست"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"هیچ اطلاعات ورود به سیستمی در <xliff:g id="SOURCE">%1$s</xliff:g> وجود ندارد"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"مدیریت ورود به سیستم‌ها"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"از دستگاهی دیگر"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"استفاده از دستگاه دیگری"</string>
diff --git a/packages/CredentialManager/res/values-fi/strings.xml b/packages/CredentialManager/res/values-fi/strings.xml
index 266a2a9..950d410 100644
--- a/packages/CredentialManager/res/values-fi/strings.xml
+++ b/packages/CredentialManager/res/values-fi/strings.xml
@@ -20,7 +20,8 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Parempi tilin tietoturva"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Kukin avain yhdistetään vain sovellukseen tai sivustoon, jota varten se on luotu, joten et voi koskaan kirjautua vilpilliseen sovellukseen tai sivustolle vahingossa. Lisäksi palvelimet säilyttävät vain julkisia avaimia, mikä tekee hakkeroinnista paljon vaikeampaa."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Saumaton siirtymä"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Kehitys kulkee kohti salasanatonta tulevaisuutta, mutta salasanat ovat edelleen käytettävissä avainkoodien ohella."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Valitse, minne <xliff:g id="CREATETYPES">%1$s</xliff:g> tallennetaan"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Valitse salasanojen ylläpitotyökalu, niin voit tallentaa tietosi ja kirjautua ensi kerralla nopeammin sisään"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Luodaanko avainkoodi (<xliff:g id="APPNAME">%1$s</xliff:g>)?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Tallenna <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> tänne:"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Luodaanko avainkoodi toisella laitteella?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Otetaanko <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> käyttöön kaikissa sisäänkirjautumisissa?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Tämä salasanojen ylläpitotyökalu tallentaa salasanat ja avainkoodit, jotta voit kirjautua helposti sisään"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Aseta oletukseksi"</string>
     <string name="use_once" msgid="9027366575315399714">"Käytä kerran"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> salasanaa • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> avainkoodia"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Muut salasanojen ylläpitotyökalut"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Sulje taulukko"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Takaisin edelliselle sivulle"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Sulje"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Sulje"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Käytetäänkö tallennettua avainkoodiasi täällä: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Käytetäänkö tallennettuja kirjautumistietoja täällä: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Valitse tallennetut kirjautumistiedot (<xliff:g id="APP_NAME">%1$s</xliff:g>)"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Lukitut salasanojen ylläpitotyökalut"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Avaa napauttamalla"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ei kirjautumistietoja"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Ei kirjautumistietoja (<xliff:g id="SOURCE">%1$s</xliff:g>)"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Muuta kirjautumistietoja"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Toiselta laitteelta"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Käytä toista laitetta"</string>
diff --git a/packages/CredentialManager/res/values-fr-rCA/strings.xml b/packages/CredentialManager/res/values-fr-rCA/strings.xml
index 914ee55..230b29c 100644
--- a/packages/CredentialManager/res/values-fr-rCA/strings.xml
+++ b/packages/CredentialManager/res/values-fr-rCA/strings.xml
@@ -11,16 +11,17 @@
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Une sécurité accrue grâce aux clés d\'accès"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Avec les clés d\'accès, nul besoin de créer ou de mémoriser des mots de passe complexes"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Les clés d\'accès sont des clés numériques chiffrées que vous créez en utilisant votre empreinte digitale, votre visage ou le verrouillage de votre écran"</string>
-    <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Ils sont enregistrés dans un gestionnaire de mots de passe pour vous permettre de vous connecter sur d\'autres appareils"</string>
+    <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Elles sont enregistrées dans un gestionnaire de mots de passe pour vous permettre de vous connecter sur d\'autres appareils"</string>
     <string name="more_about_passkeys_title" msgid="7797903098728837795">"En savoir plus sur les clés d\'accès"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Technologie sans mot de passe"</string>
     <string name="passwordless_technology_detail" msgid="6853928846532955882">"Les clés d\'accès vous permettent de vous connecter sans utiliser de mots de passe. Il vous suffit d\'utiliser votre empreinte digitale, la reconnaissance faciale, un NIP ou un schéma de balayage pour vérifier votre identité et créer un mot de passe."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"Cryptographie des clés publiques"</string>
     <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Selon les normes de l\'Alliance FIDO (y compris Google, Apple, Microsoft et plus) et du W3C, les clés d\'accès utilisent des biclés cryptographiques. Contrairement au nom d\'utilisateur et à la chaîne de caractères que nous utilisons pour les mots de passe, une biclé privée-publique est créée pour une appli ou un site Web. La clé privée est stockée en toute sécurité sur votre appareil ou votre gestionnaire de mots de passe et confirme votre identité. La clé publique est partagée avec le serveur de l\'appli ou du site Web. Avec les clés correspondantes, vous pouvez vous inscrire et vous connecter instantanément."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"Sécurité accrue du compte"</string>
-    <string name="improved_account_security_detail" msgid="9123750251551844860">"Chaque clé est exclusivement liée à l\'application ou au site Web pour lequel elle a été créée, de sorte que vous ne pourrez jamais vous connecter par erreur à une application ou un site Web frauduleux. En outre, comme les serveurs ne conservent que les clés publiques, le piratage informatique est beaucoup plus difficile."</string>
+    <string name="improved_account_security_detail" msgid="9123750251551844860">"Chaque clé est exclusivement liée à l\'application ou au site Web pour lequel elle a été créée, de sorte que vous ne pourrez jamais vous connecter par erreur à une application ou à un site Web frauduleux. En outre, comme les serveurs ne conservent que les clés publiques, le piratage informatique est beaucoup plus difficile."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Transition fluide"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"À mesure que nous nous dirigeons vers un avenir sans mot de passe, les mots de passe seront toujours utilisés parallèlement aux clés d\'accès."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Choisir où sauvegarder vos <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Sélectionnez un gestionnaire de mots de passe pour enregistrer vos renseignements et vous connecter plus rapidement la prochaine fois"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Créer une clé d\'accès pour <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -32,10 +33,11 @@
     <string name="passwords" msgid="5419394230391253816">"mots de passe"</string>
     <string name="sign_ins" msgid="4710739369149469208">"connexions"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"renseignements de connexion"</string>
-    <string name="save_credential_to_title" msgid="3172811692275634301">"Enregistrer <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> dans"</string>
+    <string name="save_credential_to_title" msgid="3172811692275634301">"Enregistrer la <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> dans"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Créer une clé d\'accès dans un autre appareil?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Utiliser <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> pour toutes vos connexions?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Ce gestionnaire de mots de passe stockera vos mots de passe et vos clés d\'accès pour vous permettre de vous connecter facilement"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Définir par défaut"</string>
     <string name="use_once" msgid="9027366575315399714">"Utiliser une fois"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> mots de passe • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> clés d\'accès"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Autres gestionnaires de mots de passe"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Fermer la feuille"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Retourner à la page précédente"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Fermer"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Fermer"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Utiliser votre clé d\'accès enregistrée pour <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Utiliser votre connexion enregistrée pour <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Choisir une connexion enregistrée pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Gestionnaires de mots de passe verrouillés"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Touchez pour déverrouiller"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Aucun renseignement de connexion"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Aucun renseignement de connexion dans <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gérer les connexions"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"À partir d\'un autre appareil"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Utiliser un autre appareil"</string>
diff --git a/packages/CredentialManager/res/values-fr/strings.xml b/packages/CredentialManager/res/values-fr/strings.xml
index faca62d..1c1189a 100644
--- a/packages/CredentialManager/res/values-fr/strings.xml
+++ b/packages/CredentialManager/res/values-fr/strings.xml
@@ -20,7 +20,8 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Des comptes plus sécurisés"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Chaque clé est liée exclusivement à l\'appli ou au site Web pour lequel elle a été créée, pour que vous ne puissiez jamais vous connecter par erreur à une appli ou un site Web frauduleux. De plus, le piratage est bien plus difficile, car les serveurs ne conservent que les clés publiques."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Une transition fluide"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Nous nous dirigeons vers un futur sans mots de passe, mais ceux-ci resteront disponibles en plus des clés d\'accès."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Choisissez où enregistrer vos <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Sélectionnez un gestionnaire de mots de passe pour enregistrer vos informations et vous connecter plus rapidement la prochaine fois"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Créer une clé d\'accès pour <xliff:g id="APPNAME">%1$s</xliff:g> ?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Enregistrer la <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> dans"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Créer une clé d\'accès sur un autre appareil ?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Utiliser <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> pour toutes vos connexions ?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Ce gestionnaire de mots de passe stockera vos mots de passe et clés d\'accès pour vous permettre de vous connecter facilement"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Définir par défaut"</string>
     <string name="use_once" msgid="9027366575315399714">"Utiliser une fois"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> mot(s) de passe • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> clé(s) d\'accès"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Autres gestionnaires de mots de passe"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Fermer la feuille"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Revenir à la page précédente"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Fermer"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Fermer"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Utiliser votre clé d\'accès enregistrée pour <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Utiliser vos informations de connexion enregistrées pour <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Choisir des informations de connexion enregistrées pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Gestionnaires de mots de passe verrouillés"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Appuyer pour déverrouiller"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Aucune information de connexion"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Aucune info de connexion dans <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gérer les connexions"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Depuis un autre appareil"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Utiliser un autre appareil"</string>
diff --git a/packages/CredentialManager/res/values-gl/strings.xml b/packages/CredentialManager/res/values-gl/strings.xml
index 3b2d6f6..0cd444c 100644
--- a/packages/CredentialManager/res/values-gl/strings.xml
+++ b/packages/CredentialManager/res/values-gl/strings.xml
@@ -9,7 +9,7 @@
     <string name="content_description_show_password" msgid="3283502010388521607">"Mostrar contrasinal"</string>
     <string name="content_description_hide_password" msgid="6841375971631767996">"Ocultar contrasinal"</string>
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Máis protección coas claves de acceso"</string>
-    <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Cunha clave de acceso, non é necesario que crees ou lembres contrasinais complexos"</string>
+    <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Cunha clave de acceso non é necesario que crees ou lembres contrasinais complexos"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"As claves de acceso son claves dixitais encriptadas que creas usando a túa impresión dixital, a túa cara ou o teu bloqueo de pantalla"</string>
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"As claves de acceso gárdanse nun xestor de contrasinais para que poidas iniciar sesión noutros dispositivos"</string>
     <string name="more_about_passkeys_title" msgid="7797903098728837795">"Máis información sobre as claves de acceso"</string>
@@ -18,9 +18,10 @@
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"Criptografía das claves públicas"</string>
     <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Segundo os estándares da Alianza FIDO (con Google, Apple, Microsoft…) e o W3C, as claves de acceso usan pares de claves criptográficas. A diferenza do nome de usuario e contrasinal, créase un par de claves público-privado para unha aplicación ou sitio web. A clave privada, que confirma a identidade, almacénase de xeito seguro no dispositivo ou xestor de contrasinais. A pública compártese co servidor da aplicación ou sitio web. Coas claves vinculadas, podes rexistrarte e conectarte ao momento."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"Mellora na seguranza das contas"</string>
-    <string name="improved_account_security_detail" msgid="9123750251551844860">"Cada clave está vinculada de xeito exclusivo coa aplicación ou o sitio web para o que foi creada, de tal forma que nunca poidas iniciar sesión nunha aplicación ou un sitio web fraudulentos por erro. Ademais, como os servidores só gardan as claves públicas, resulta moito máis difícil piratear."</string>
+    <string name="improved_account_security_detail" msgid="9123750251551844860">"Cada clave está vinculada de xeito exclusivo coa aplicación ou o sitio web para o que foi creada, de tal forma que nunca poidas iniciar sesión nunha aplicación ou un sitio web fraudulentos por erro. Ademais, como os servidores só gardan as claves públicas, resultan moito máis difíciles de piratear."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Transición fluída"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Durante este percorrido cara a un futuro sen contrasinais, estes seguirán estando dispoñibles a canda as claves de acceso."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Escolle onde queres gardar: <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Selecciona un xestor de contrasinais para gardar a túa información e iniciar sesión máis rápido a próxima vez"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Queres crear unha clave de acceso para <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Gardar <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> en"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Queres crear unha clave de acceso noutro dispositivo?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Queres usar <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> cada vez que inicies sesión?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Este xestor de contrasinais almacenará os contrasinais e as claves de acceso para axudarche a iniciar sesión facilmente"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Establecer como predeterminado"</string>
     <string name="use_once" msgid="9027366575315399714">"Usar unha vez"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> contrasinais • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> claves de acceso"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Outros xestores de contrasinais"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Pechar folla"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Volver á páxina anterior"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Pechar"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Pechar"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Queres usar a clave de acceso gardada para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Queres usar o método de inicio de sesión gardado para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Escolle un método de inicio de sesión gardado para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Xestores de contrasinais bloqueados"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Toca para desbloquear"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Sen información de inicio de sesión"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Non hai información de inicio de sesión para <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Xestionar os métodos de inicio de sesión"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Doutro dispositivo"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Usar outro dispositivo"</string>
diff --git a/packages/CredentialManager/res/values-gu/strings.xml b/packages/CredentialManager/res/values-gu/strings.xml
index d3339b7..c9151ae 100644
--- a/packages/CredentialManager/res/values-gu/strings.xml
+++ b/packages/CredentialManager/res/values-gu/strings.xml
@@ -11,7 +11,7 @@
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"પાસકી સાથે વધુ સલામત"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"પાસકી હોવાથી, તમારે જટિલ પાસવર્ડ બનાવવાની કે યાદ રાખવાની જરૂર રહેતી નથી"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"પાસકી એ એન્ક્રિપ્ટેડ ડિજિટલ કી છે, જેને તમે તમારી ફિંગરપ્રિન્ટ, ચહેરા અથવા સ્ક્રીન લૉકનો ઉપયોગ કરીને બનાવો છો"</string>
-    <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"તેને પાસવર્ડ મેનેજરમાં સાચવવામાં આવે છે, જેથી તમે અન્ય ડિવાઇસમાં સાઇન ઇન ન કરી શકો"</string>
+    <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"તેને પાસવર્ડ મેનેજરમાં સાચવવામાં આવે છે, જેથી તમે અન્ય ડિવાઇસમાં સાઇન ઇન કરી શકો"</string>
     <string name="more_about_passkeys_title" msgid="7797903098728837795">"પાસકી વિશે વધુ"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"પાસવર્ડ રહિત ટેક્નોલોજી"</string>
     <string name="passwordless_technology_detail" msgid="6853928846532955882">"પાસકી તમને પાસવર્ડ પર આધાર રાખ્યા વિના સાઇન ઇન કરવાની મંજૂરી આપે છે. તમારી ઓળખની ચકાસણી કરીને તમારી પાસકી બનાવવા માટે, તમારે માત્ર તમારી ફિંગરપ્રિન્ટ, ચહેરાની ઓળખ, પિન અથવા સ્વાઇપ પૅટર્નનો ઉપયોગ કરવાની જરૂર છે."</string>
@@ -20,7 +20,8 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"તમારી <xliff:g id="CREATETYPES">%1$s</xliff:g> ક્યાં સાચવવી તે પસંદ કરો"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"તમારી માહિતી સાચવવા માટે પાસવર્ડ મેનેજર પસંદ કરો અને આગલી વખતે વધુ ઝડપથી સાઇન ઇન કરો"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> માટે પાસકી બનાવીએ?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>ને આમાં સાચવો"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"અન્ય ડિવાઇસ પર પાસકી બનાવીએ?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"શું તમારા બધા સાઇન-ઇન માટે <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>નો ઉપયોગ કરીએ?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"આ પાસવર્ડ મેનેજર તમને સરળતાથી સાઇન ઇન કરવામાં સહાય કરવા માટે, તમારા પાસવર્ડ અને પાસકી સ્ટોર કરશે"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"ડિફૉલ્ટ તરીકે સેટ કરો"</string>
     <string name="use_once" msgid="9027366575315399714">"એકવાર ઉપયોગ કરો"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> પાસવર્ડ • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> પાસકી"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"અન્ય પાસવર્ડ મેનેજર"</string>
     <string name="close_sheet" msgid="1393792015338908262">"શીટ બંધ કરો"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"પાછલા પેજ પર પરત જાઓ"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"બંધ કરો"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"છોડી દો"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે શું તમારી સાચવેલી પાસકીનો ઉપયોગ કરીએ?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે શું તમારા સાચવેલા સાઇન-ઇનનો ઉપયોગ કરીએ?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે કોઈ સાચવેલું સાઇન-ઇન પસંદ કરો"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"લૉક કરેલા પાસવર્ડ મેનેજર"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"અનલૉક કરવા માટે ટૅપ કરો"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"સાઇન-ઇનની કોઈ માહિતી નથી"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>માં સાઇન-ઇનની કોઈ માહિતી નથી"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"સાઇન-ઇન મેનેજ કરો"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"કોઈ અન્ય ડિવાઇસમાંથી"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"કોઈ અન્ય ડિવાઇસનો ઉપયોગ કરો"</string>
diff --git a/packages/CredentialManager/res/values-hi/strings.xml b/packages/CredentialManager/res/values-hi/strings.xml
index f2790f4..60a7d15 100644
--- a/packages/CredentialManager/res/values-hi/strings.xml
+++ b/packages/CredentialManager/res/values-hi/strings.xml
@@ -10,19 +10,20 @@
     <string name="content_description_hide_password" msgid="6841375971631767996">"पासवर्ड छिपाएं"</string>
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"पासकी के साथ सुरक्षित रहें"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"पासकी होने पर, आपको जटिल पासवर्ड बनाने या याद रखने की ज़रूरत नहीं पड़ती"</string>
-    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"पासकी, एन्क्रिप्ट (सुरक्षित) की गई डिजिटल की होती हैं. इन्हें फ़िंगरप्रिंट, चेहरे या स्क्रीन लॉक का इस्तेमाल करके बनाया जाता है"</string>
+    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"पासकी, एन्क्रिप्ट (सुरक्षित) की गई \'डिजिटल की\' होती हैं. इन्हें फ़िंगरप्रिंट, चेहरे या स्क्रीन लॉक का इस्तेमाल करके बनाया जाता है"</string>
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"पासकी को पासवर्ड मैनेजर में सेव किया जाता है, ताकि इनका इस्तेमाल करके आप अन्य डिवाइसों में साइन इन कर सकें"</string>
     <string name="more_about_passkeys_title" msgid="7797903098728837795">"पासकी के बारे में ज़्यादा जानकारी"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"बिना पासवर्ड वाली टेक्नोलॉजी"</string>
     <string name="passwordless_technology_detail" msgid="6853928846532955882">"पासकी की मदद से, पासवर्ड के बिना साइन इन किया जा सकता है. अपनी पहचान की पुष्टि करने और पासकी बनाने के लिए, फ़िंगरप्रिंट, चेहरे की पहचान करने की सुविधा, पिन या स्वाइप पैटर्न का इस्तेमाल करें."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"सार्वजनिक कुंजी क्रिप्टोग्राफ़ी"</string>
-    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"W3C के तय मानकों और FIDO एलायंस (Google, Apple, Microsoft वगैरह) के मुताबिक, पासकी में क्रिप्टोग्राफ़िक कुंजी के जोड़े इस्तेमाल किए जाते हैं. पासवर्ड में उपयोगकर्ता नाम और वर्णों की स्ट्रिंग इस्तेमाल की जाती है, जबकि ऐप्लिकेशन या वेबसाइट के लिए निजी-सार्वजनिक कुंजी का जोड़ा बनाया जाता है. निजी कुंजी, Password Manager या डिवाइस में सुरक्षित रहती है और आपकी पहचान की पुष्टि करती है. सार्वजनिक कुंजी, ऐप्लिकेशन या वेबसाइट सर्वर के साथ शेयर होती है. दोनों कुंजियों से, ऐप्लिकेशन या वेबसाइट पर तुरंत रजिस्टर और साइन इन किया जा सकता है."</string>
+    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"W3C के तय मानकों और FIDO अलायंस (इसमें Google, Apple, Microsoft वगैरह शामिल हैं) के मुताबिक, पासकी में क्रिप्टोग्राफ़िक कुंजी के जोड़े इस्तेमाल किए जाते हैं. पासवर्ड में उपयोगकर्ता नाम और वर्णों की स्ट्रिंग इस्तेमाल की जाती है, जबकि ऐप्लिकेशन या वेबसाइट के लिए निजी-सार्वजनिक कुंजी का जोड़ा बनाया जाता है. निजी कुंजी, Password Manager या डिवाइस में सुरक्षित रहती है और आपकी पहचान की पुष्टि करती है. सार्वजनिक कुंजी, ऐप्लिकेशन या वेबसाइट सर्वर के साथ शेयर होती है. दोनों कुंजियों से, ऐप्लिकेशन या वेबसाइट पर तुरंत रजिस्टर और साइन इन किया जा सकता है."</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>
+    <string name="improved_account_security_detail" msgid="9123750251551844860">"हर कुंजी खास तौर पर उस ऐप्लिकेशन या वेबसाइट से लिंक होती है जिसके लिए उसे बनाया गया है. ऐसा इसलिए किया जाता है, ताकि कोई भी व्यक्ति धोखाधड़ी करने वाले ऐप्लिकेशन या वेबसाइट पर कभी भी गलती से साइन इन न करे. साथ ही, सर्वर के पास सिर्फ़ सार्वजनिक कुंजी होती हैं, इसलिए पूरी कुंजी को हैक करना काफ़ी मुश्किल होता है."</string>
+    <string name="seamless_transition_title" msgid="5335622196351371961">"आसान ट्रांज़िशन"</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"चुनें कि अपनी <xliff:g id="CREATETYPES">%1$s</xliff:g> कहां सेव करनी हैं"</string>
-    <string name="choose_provider_body" msgid="4967074531845147434">"अपनी जानकारी सेव करने के लिए, कोई पासवर्ड मैनेजर चुनें और अगली बार तेज़ी से साइन इन करें"</string>
+    <string name="choose_provider_body" msgid="4967074531845147434">"अपनी जानकारी सेव करने के लिए, पासवर्ड मैनेजर चुनें और अगली बार ज़्यादा तेज़ी से साइन इन करें"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"क्या आपको <xliff:g id="APPNAME">%1$s</xliff:g> के लिए पासकी बनानी है?"</string>
     <string name="choose_create_option_password_title" msgid="7097275038523578687">"क्या आपको <xliff:g id="APPNAME">%1$s</xliff:g> के लिए पासवर्ड सेव करना है?"</string>
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"क्या आपको <xliff:g id="APPNAME">%1$s</xliff:g> के लिए साइन-इन की जानकारी सेव करनी है?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> को यहां सेव करें"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"क्या किसी दूसरे डिवाइस में पासकी सेव करनी है?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"क्या आपको साइन इन से जुड़ी सारी जानकारी सेव करने के लिए, <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> का इस्तेमाल करना है?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"यह पासवर्ड मैनेजर, आपके पासवर्ड और पासकी सेव करेगा, ताकि आपको साइन इन करने में आसानी हो"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"डिफ़ॉल्ट के तौर पर सेट करें"</string>
     <string name="use_once" msgid="9027366575315399714">"इसका इस्तेमाल एक बार किया जा सकता है"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> पासवर्ड • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> पासकी"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"दूसरे पासवर्ड मैनेजर"</string>
     <string name="close_sheet" msgid="1393792015338908262">"शीट बंद करें"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"पिछले पेज पर वापस जाएं"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"बंद करें"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"खारिज करें"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"क्या आपको <xliff:g id="APP_NAME">%1$s</xliff:g> पर साइन इन करने के लिए, सेव की गई पासकी का इस्तेमाल करना है?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"क्या आपको <xliff:g id="APP_NAME">%1$s</xliff:g> पर साइन इन करने के लिए, सेव की गई जानकारी का इस्तेमाल करना है?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> पर साइन इन करने के लिए, सेव की गई जानकारी में से चुनें"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"लॉक किए गए पासवर्ड मैनेजर"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"अनलॉक करने के लिए टैप करें"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"साइन-इन करने से जुड़ी कोई जानकारी उपलब्ध नहीं है"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> में साइन-इन की जानकारी नहीं है"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"साइन इन करने की सुविधा को मैनेज करें"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"किसी दूसरे डिवाइस से"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"दूसरे डिवाइस का इस्तेमाल करें"</string>
diff --git a/packages/CredentialManager/res/values-hr/strings.xml b/packages/CredentialManager/res/values-hr/strings.xml
index 3d813f9..b454c41 100644
--- a/packages/CredentialManager/res/values-hr/strings.xml
+++ b/packages/CredentialManager/res/values-hr/strings.xml
@@ -16,14 +16,14 @@
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Tehnologija bez upotrebe zaporke"</string>
     <string name="passwordless_technology_detail" msgid="6853928846532955882">"Pristupni ključevi omogućuju prijavu bez upotrebe zaporki. Treba vam samo otisak prsta, prepoznavanje lica, PIN ili uzorak pokreta prstom da biste potvrdili svoj identitet i izradili pristupni ključ."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"Kriptografija javnog ključa"</string>
-    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Na temelju saveza FIDO (koji uključuje Google, Apple, Microsoft i mnoge druge) i standarda W3C pristupni ključevi koriste kriptografske ključeve. Za razliku od korisničkog imena i niza znakova za zaporke, privatno-javni ključ izrađen je za aplikaciju ili web-lokaciju. Privatni ključ pohranjen je na vašem uređaju ili upravitelju zaporki i potvrđuje vaš identitet. Javni se ključ dijeli s poslužiteljem aplikacije ili web-lokacije. Uz odgovarajuće ključeve možete se odmah registrirati i prijaviti."</string>
+    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Na temelju organizacije FIDO Alliance (koja uključuje Google, Apple, Microsoft i mnoge druge) i standarda W3C pristupni ključevi koriste kriptografske ključeve. Za razliku od korisničkog imena i niza znakova za zaporke, privatno-javni ključ izrađen je za aplikaciju ili web-lokaciju. Privatni ključ pohranjen je na vašem uređaju ili upravitelju zaporki i potvrđuje vaš identitet. Javni se ključ dijeli s poslužiteljem aplikacije ili web-lokacije. Uz odgovarajuće ključeve možete se odmah registrirati i prijaviti."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"Poboljšana sigurnost računa"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Svaki ključ povezan isključivo s aplikacijom ili web-lokacijom za koju je izrađen, stoga se nikad ne možete pogreškom prijaviti u prijevarnu aplikaciju ili na web-lokaciju. Osim toga, kad je riječ o poslužiteljima na kojem se nalaze samo javni ključevi, hakiranje je mnogo teže."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Besprijekorni prijelaz"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Kako idemo u smjeru budućnosti bez zaporki, one će i dalje biti dostupne uz pristupne ključeve."</string>
-    <string name="choose_provider_title" msgid="8870795677024868108">"Odaberite mjesto za spremanje: <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
+    <string name="seamless_transition_detail" msgid="3440478759491650823">"Kako idemo u smjeru budućnosti bez zaporki, one će i dalje biti dostupne uz pristupne ključeve"</string>
+    <string name="choose_provider_title" msgid="8870795677024868108">"Odaberite gdje će se spremati <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Odaberite upravitelja zaporki kako biste spremili svoje informacije i drugi se put brže prijavili"</string>
-    <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Izraditi pristupni ključ za <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
+    <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Želite li izraditi pristupni ključ za <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
     <string name="choose_create_option_password_title" msgid="7097275038523578687">"Spremiti zaporku za <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Spremiti informacije o prijavi za <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
     <string name="passkey" msgid="632353688396759522">"pristupni ključ"</string>
@@ -35,7 +35,7 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Spremi <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> u"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Želite li izraditi pristupni ključ na drugom uređaju?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Želite li upotrebljavati uslugu <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> za sve prijave?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Upravitelj zaporki pohranit će vaše zaporke i pristupne ključeve radi jednostavnije prijave"</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"Upravitelj zaporki za korisničko ime <xliff:g id="USERNAME">%1$s</xliff:g> pohranit će vaše zaporke i pristupne ključeve radi jednostavnije prijave"</string>
     <string name="set_as_default" msgid="4415328591568654603">"Postavi kao zadano"</string>
     <string name="use_once" msgid="9027366575315399714">"Upotrijebi jednom"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Broj zaporki: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • broj pristupnih ključeva: <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
@@ -47,8 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Drugi upravitelji zaporki"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Zatvaranje lista"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Vratite se na prethodnu stranicu"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Zatvori"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Odbaci"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Želite li upotrijebiti spremljeni pristupni ključ za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Želite li upotrijebiti spremljene podatke za prijavu za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Odaberite spremljene podatke za prijavu za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +60,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Upravitelji zaključanih zaporki"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Dodirnite za otključavanje"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nema podataka o prijavi"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nema podataka o prijavi u aplikaciji <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Upravljanje prijavama"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Na drugom uređaju"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Upotrijebite drugi uređaj"</string>
diff --git a/packages/CredentialManager/res/values-hu/strings.xml b/packages/CredentialManager/res/values-hu/strings.xml
index e3b0fec..df8210b 100644
--- a/packages/CredentialManager/res/values-hu/strings.xml
+++ b/packages/CredentialManager/res/values-hu/strings.xml
@@ -16,11 +16,11 @@
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Jelszó nélküli technológia"</string>
     <string name="passwordless_technology_detail" msgid="6853928846532955882">"Az azonosítókulcsok lehetővé teszik a jelszó nélküli bejelentkezést. Csak ujjlenyomatát, arcfelismerést, PIN-kódot vagy csúsztatási mintát kell használnia személyazonosságának igazolásához és azonosítókulcs létrehozásához."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"A nyilvános kulcs kriptográfiája"</string>
-    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Az azonosítókulcsok a FIDO Alliance (amely tagja a Google, az Apple és a Microsoft is) és a W3C szabványai alapján titkosítási kulcspárokat használnak. A felhasználónevekkel és a jelszavaknál megszokott karaktersorozattal ellentétben az adott apphoz vagy webhelyhez egy titkos és egy nyilvános kulcsból álló kulcspárt hoz létre a rendszer. A titkos kulcs tárolása biztonságosan történik az eszközén vagy a Jelszókezelőben, és ez a kulcs igazolja az Ön személyazonosságát. A nyilvános kulcsot osztja meg a rendszer az appal vagy a webhely szerverével. A kapcsolódó kulcsok révén Ön azonnal regisztrálhat és bejelentkezhet."</string>
+    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Az azonosítókulcsok a FIDO Alliance (melynek a Google, az Apple és a Microsoft is tagja) és a W3C szabványai alapján titkosítási kulcspárokat használnak. A felhasználónevekkel és a jelszavaknál megszokott karaktersorozattal ellentétben az adott apphoz vagy webhelyhez egy titkos és egy nyilvános kulcsból álló kulcspárt hoz létre a rendszer. A titkos kulcs tárolása biztonságosan történik az eszközén vagy a Jelszókezelőben, és ez a kulcs igazolja az Ön személyazonosságát. A nyilvános kulcsot osztja meg a rendszer az appal vagy a webhely szerverével. A kapcsolódó kulcsok révén Ön azonnal regisztrálhat és bejelentkezhet."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"Nagyobb fiókbiztonság"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Minden kulcs kizárólag ahhoz az alkalmazáshoz vagy weboldalhoz kapcsolódik, amelyhez létrehozták, így soha nem fordulhat elő, hogy Ön tévedésből csalárd alkalmazásba vagy webhelyre jelentkezik be. Ráadásul – mivel a szerverek csak nyilvános kulcsokat tárolnak – a hackelés jóval nehezebb."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Zökkenőmentes átmenet"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Miközben a jelszó nélküli jövő felé haladunk, a jelszavak továbbra is rendelkezésre állnak majd az azonosítókulcsok mellett."</string>
+    <string name="seamless_transition_detail" msgid="3440478759491650823">"Miközben a jelszó nélküli jövő felé haladunk, a jelszavak továbbra is rendelkezésre állnak majd az azonosítókulcsok mellett."</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"Válassza ki, hogy hova szeretné menteni <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Válasszon jelszókezelőt, hogy menthesse az adatait, és gyorsabban jelentkezhessen be a következő alkalommal."</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Létrehoz azonosítókulcsot a következőhöz: <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +35,7 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> mentése ide:"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Egy másik eszközön szeretne azonosítókulcsot létrehozni?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Szeretné a következőt használni az összes bejelentkezési adatához: <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Ez a jelszókezelő fogja tárolni a jelszavait és azonosítókulcsait a bejelentkezés megkönnyítése érdekében."</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"Ez a jelszókezelő fogja tárolni a(z) <xliff:g id="USERNAME">%1$s</xliff:g> fiókhoz tartozó jelszavait és azonosítókulcsait a bejelentkezés megkönnyítése érdekében."</string>
     <string name="set_as_default" msgid="4415328591568654603">"Beállítás alapértelmezettként"</string>
     <string name="use_once" msgid="9027366575315399714">"Egyszeri használat"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> jelszó, <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> azonosítókulcs"</string>
@@ -47,8 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Egyéb jelszókezelők"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Munkalap bezárása"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Vissza az előző oldalra"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Bezárás"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Elvetés"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Szeretné a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazáshoz mentett azonosítókulcsot használni?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Szeretné a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazáshoz mentett bejelentkezési adatait használni?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Mentett bejelentkezési adatok választása a következő számára: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +60,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Zárolt jelszókezelők"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Koppintson a feloldáshoz"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nincsenek bejelentkezési adatok"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nem találhatók bejelentkezési adatok itt: <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Bejelentkezési adatok kezelése"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Másik eszközről"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Másik eszköz használata"</string>
diff --git a/packages/CredentialManager/res/values-hy/strings.xml b/packages/CredentialManager/res/values-hy/strings.xml
index 6cdc76f..7e1c36e6d 100644
--- a/packages/CredentialManager/res/values-hy/strings.xml
+++ b/packages/CredentialManager/res/values-hy/strings.xml
@@ -20,7 +20,8 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Նշեք, թե որտեղ եք ուզում պահել ձեր <xliff:g id="CREATETYPES">%1$s</xliff:g>ը"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Ընտրեք գաղտնաբառերի կառավարիչ՝ ձեր տեղեկությունները պահելու և հաջորդ անգամ ավելի արագ մուտք գործելու համար"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Ստեղծե՞լ անցաբառ «<xliff:g id="APPNAME">%1$s</xliff:g>» հավելվածի համար"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Պահել <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>ն այստեղ՝"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Ստեղծե՞լ անցաբառ այլ սարքում"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Միշտ մուտք գործե՞լ <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> հավելվածի միջոցով"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Գաղտնաբառերի այս կառավարիչը կպահի ձեր գաղտնաբառերն ու անցաբառերը՝ օգնելու ձեզ հեշտությամբ մուտք գործել հաշիվ"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Նշել որպես կանխադրված"</string>
     <string name="use_once" msgid="9027366575315399714">"Օգտագործել մեկ անգամ"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> գաղտնաբառ • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> անցաբառ"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Գաղտնաբառերի այլ կառավարիչներ"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Փակել թերթը"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Անցնել նախորդ էջ"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Փակել"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Փակել"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Օգտագործե՞լ պահված անցաբառը <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Օգտագործե՞լ մուտքի պահված տվյալները <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Ընտրեք մուտքի պահված տվյալներ <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Գաղտնաբառերի կողպված կառավարիչներ"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Հպեք ապակողպելու համար"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Մուտքի տվյալներ չկան"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Մուտքի տվյալներ չկան այստեղ՝ <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Մուտքի կառավարում"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Մեկ այլ սարքից"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Օգտագործել այլ սարք"</string>
diff --git a/packages/CredentialManager/res/values-in/strings.xml b/packages/CredentialManager/res/values-in/strings.xml
index f0f0089..64c6a9f 100644
--- a/packages/CredentialManager/res/values-in/strings.xml
+++ b/packages/CredentialManager/res/values-in/strings.xml
@@ -11,18 +11,19 @@
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Lebih aman dengan kunci sandi"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Dengan kunci sandi, Anda tidak perlu membuat atau mengingat sandi yang rumit"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Kunci sandi adalah kunci digital terenkripsi yang Anda buat menggunakan sidik jari, wajah, atau kunci layar"</string>
-    <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Kunci sandi disimpan ke pengelola sandi, sehingga Anda dapat login di perangkat lainnya"</string>
+    <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Kunci sandi disimpan ke pengelola sandi, sehingga Anda dapat login di perangkat lain"</string>
     <string name="more_about_passkeys_title" msgid="7797903098728837795">"Selengkapnya tentang kunci sandi"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Teknologi tanpa sandi"</string>
     <string name="passwordless_technology_detail" msgid="6853928846532955882">"Kunci sandi memungkinkan Anda login tanpa mengandalkan sandi. Anda hanya perlu menggunakan sidik jari, pengenalan wajah, PIN, atau pola geser untuk memverifikasi identitas Anda dan membuat kunci sandi."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"Kriptografi kunci publik"</string>
-    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Berdasarkan FIDO Alliance (yang mencakup Google, Apple, Microsoft, dan lainnya) dan standar W3C, kunci sandi menggunakan pasangan kunci kriptografis. Tidak seperti nama pengguna dan string karakter yang digunakan untuk sandi, pasangan kunci pribadi-publik dibuat untuk aplikasi atau situs. Kunci pribadi disimpan dengan aman di perangkat atau pengelola sandi dan mengonfirmasi identitas Anda. Kunci publik dibagikan ke server aplikasi atau situs. Dengan kunci yang sesuai, Anda dapat langsung mendaftar dan login."</string>
+    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Berdasarkan FIDO Alliance (yang mencakup Google, Apple, Microsoft, dan lainnya) dan standar W3C, kunci sandi menggunakan pasangan kunci kriptografis. Tidak seperti nama pengguna dan string karakter yang digunakan untuk sandi, pasangan kunci pribadi-publik dibuat untuk aplikasi atau situs. Kunci pribadi disimpan dengan aman di perangkat atau pengelola sandi, dan digunakan untuk mengonfirmasi identitas Anda. Kunci publik dibagikan ke server aplikasi atau situs. Dengan kunci yang sesuai, Anda dapat langsung mendaftar dan login."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"Keamanan akun yang ditingkatkan"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Setiap kunci ditautkan secara eksklusif dengan aplikasi atau situs tempatnya dibuat, sehingga Anda tidak akan login ke aplikasi atau situs yang menipu secara tidak sengaja. Selain itu, peretasan lebih sulit dilakukan karena server hanya menyimpan kunci publik."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Transisi yang lancar"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Seiring kita menuju masa depan tanpa sandi, sandi akan tetap tersedia bersama kunci sandi."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Pilih tempat penyimpanan <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
-    <string name="choose_provider_body" msgid="4967074531845147434">"Pilih pengelola sandi untuk menyimpan info Anda dan login lebih cepat pada waktu berikutnya"</string>
+    <string name="choose_provider_body" msgid="4967074531845147434">"Pilih pengelola sandi untuk menyimpan info Anda dan login lebih cepat lain kali"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Buat kunci sandi untuk <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
     <string name="choose_create_option_password_title" msgid="7097275038523578687">"Simpan sandi untuk <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Simpan info login untuk <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Simpan <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> ke"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Buat kunci sandi di perangkat lain?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Gunakan <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> untuk semua info login Anda?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Pengelola sandi ini akan menyimpan sandi dan kunci sandi untuk membantu Anda login dengan mudah"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Setel sebagai default"</string>
     <string name="use_once" msgid="9027366575315399714">"Gunakan sekali"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> sandi • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> kunci sandi"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Pengelola sandi lainnya"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Tutup sheet"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Kembali ke halaman sebelumnya"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Tutup"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Tutup"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Gunakan kunci sandi tersimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Gunakan info login tersimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Pilih info login tersimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Pengelola sandi terkunci"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Ketuk untuk membuka kunci"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Tidak ada info login"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Tidak ada info login di <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Kelola login"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Dari perangkat lain"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Gunakan perangkat lain"</string>
diff --git a/packages/CredentialManager/res/values-is/strings.xml b/packages/CredentialManager/res/values-is/strings.xml
index 7ee8b5d..16794c2 100644
--- a/packages/CredentialManager/res/values-is/strings.xml
+++ b/packages/CredentialManager/res/values-is/strings.xml
@@ -14,13 +14,14 @@
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Þeir eru vistaðir í aðgangsorðastjórnun svo þú getir skráð þig inn í öðrum tækjum"</string>
     <string name="more_about_passkeys_title" msgid="7797903098728837795">"Nánar um aðgangslykla"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Aðgangsorðalaus tækni"</string>
-    <string name="passwordless_technology_detail" msgid="6853928846532955882">"Aðgangslyklar gera þér kleift að skrá þig inn án þess að þurfa aðgangsorð. Þú þarft aðeins og nota fingrafarið, andlitsgreiningu, PIN-númer eða strokmynstur til að staðfesta hver þú ert og búa til aðgangslykil."</string>
+    <string name="passwordless_technology_detail" msgid="6853928846532955882">"Aðgangslyklar gera þér kleift að skrá þig inn án þess að þurfa aðgangsorð. Þú þarft aðeins að nota fingrafarið, andlitsgreiningu, PIN-númer eða strokmynstur til að staðfesta hver þú ert og búa til aðgangslykil."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"Dulritun opinberra lykla"</string>
     <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Aðgangslyklar nota dulkóðuð lyklasett byggð á stöðlum FIDO Alliance (sem nær til Google, Apple, Microsoft og fleiri) og W3C. Ólíkt notandanafni og stafarunu aðgangsorðs er lyklasett opinbers lykils og einkalykils búið til fyrir forrit eða vefsvæði. Einkalykillinn er vistaður á öruggan hátt í tækinu eða í aðgangsorðastjórnun og hann staðfestir auðkenni þitt. Opinbera lyklinum er deilt með þjóni forritsins eða vefsvæðisins. Samsvarandi lyklar tryggja tafarlausa skráningu og innskráningu."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"Bætt reikningsöryggi"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Hver lykill er eingöngu tengdur forritinu eða vefsvæðinu sem hann var búinn til fyrir. Því er engin hætta á að þú skráir þig óvart inn á sviksamlegt forrit eða vefsvæði. Einnig er erfiðara að hakka þegar þjónar geyma aðeins opinbera lykla."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Snurðulaus skipti"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Við stefnum að framtíð án aðgangsorða en aðgangsorð verða áfram í boði samhliða aðgangslyklum."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Veldu hvar þú vilt vista <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Veldu aðgangsorðastjórnun til að vista upplýsingarnar og vera fljótari að skrá þig inn næst"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Viltu búa til aðgangslykil fyrir <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -28,14 +29,15 @@
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Viltu vista innskráningarupplýsingar fyrir <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
     <string name="passkey" msgid="632353688396759522">"aðgangslykill"</string>
     <string name="password" msgid="6738570945182936667">"aðgangsorð"</string>
-    <string name="passkeys" msgid="5733880786866559847">"aðgangslyklar"</string>
+    <string name="passkeys" msgid="5733880786866559847">"aðgangslykla"</string>
     <string name="passwords" msgid="5419394230391253816">"aðgangsorð"</string>
     <string name="sign_ins" msgid="4710739369149469208">"innskráningar"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"innskráningarupplýsingar"</string>
     <string name="save_credential_to_title" msgid="3172811692275634301">"Vista <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> í"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Viltu búa til aðgangslykil í öðru tæki?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Nota <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> fyrir allar innskráningar?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Þessi aðgangsorðastjórnun vistar aðgangsorð og aðgangslykla til að auðvelda þér að skrá þig inn"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Stilla sem sjálfgefið"</string>
     <string name="use_once" msgid="9027366575315399714">"Nota einu sinni"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> aðgangsorð • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> aðgangslyklar"</string>
@@ -47,9 +49,9 @@
     <string name="other_password_manager" msgid="565790221427004141">"Önnur aðgangsorðastjórnun"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Loka blaði"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Fara aftur á fyrri síðu"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
-    <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Notað vistaðan aðgangslykil fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Loka"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Hunsa"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Nota vistaðan aðgangslykil fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Nota vistaða innskráningu fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Veldu vistaða innskráningu fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Skrá inn með öðrum hætti"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Læst aðgangsorðastjórnun"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Ýttu til að opna"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Engar innskráningarupplýsingar"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Engar innskráningarupplýsingar á <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Stjórna innskráningu"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Úr öðru tæki"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Nota annað tæki"</string>
diff --git a/packages/CredentialManager/res/values-it/strings.xml b/packages/CredentialManager/res/values-it/strings.xml
index 7f39c1d..97de0fb 100644
--- a/packages/CredentialManager/res/values-it/strings.xml
+++ b/packages/CredentialManager/res/values-it/strings.xml
@@ -14,14 +14,14 @@
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Vengono salvate in un gestore delle password, così potrai accedere su altri dispositivi"</string>
     <string name="more_about_passkeys_title" msgid="7797903098728837795">"Scopri di più sulle passkey"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Tecnologia senza password"</string>
-    <string name="passwordless_technology_detail" msgid="6853928846532955882">"Le passkey ti consentono di accedere senza usare le password. Devi soltanto usare la tua impronta, il riconoscimento del volto, il tuo PIN o la tua sequenza per verificare la tua identità e creare una passkey."</string>
+    <string name="passwordless_technology_detail" msgid="6853928846532955882">"Le passkey ti consentono di accedere senza usare le password. Basta usare l\'impronta, il riconoscimento del volto, il PIN o la sequenza per verificare la tua identità e creare una passkey."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"Crittografia a chiave pubblica"</string>
-    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Basate su standard FIDO Alliance (che include Google, Apple, Microsoft e non solo) e W3C, le passkey usano coppie di chiavi di crittografia. Diversamente dal nome utente e dalla stringa di caratteri usata per le password, per un\'app o un sito web viene creata una coppia di chiavi (privata e pubblica). La chiave privata viene memorizzata in sicurezza sul dispositivo o nel gestore delle password e conferma la tua identità. La chiave pubblica viene condivisa con il server dell\'app o del sito. Con chiavi corrispondenti puoi registrarti e accedere subito."</string>
-    <string name="improved_account_security_title" msgid="1069841917893513424">"Sicurezza degli account migliorata"</string>
+    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Basate su standard FIDO Alliance (che include Google, Apple, Microsoft e non solo) e W3C, le passkey usano coppie di chiavi di crittografia. Diversamente dal nome utente e dalla stringa di caratteri usata per le password, per un\'app o un sito web viene creata una coppia di chiavi (privata e pubblica). La chiave privata viene memorizzata in sicurezza sul dispositivo o nel gestore delle password e conferma la tua identità. La chiave pubblica viene condivisa con il server dell\'app o del sito web. Con chiavi corrispondenti puoi registrarti e accedere subito."</string>
+    <string name="improved_account_security_title" msgid="1069841917893513424">"Account ancora più sicuri"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Ogni chiave è collegata in modo esclusivo all\'app o al sito web per cui è stata creata, quindi non puoi mai accedere a un\'app o un sito web fraudolenti per sbaglio. Inoltre, le compromissioni diventano molto più difficili perché i server conservano soltanto le chiavi pubbliche."</string>
-    <string name="seamless_transition_title" msgid="5335622196351371961">"Transizione senza interruzioni"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Mentre ci dirigiamo verso un futuro senza password, queste ultime saranno ancora disponibili insieme alle passkey."</string>
-    <string name="choose_provider_title" msgid="8870795677024868108">"Scegli dove salvare: <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
+    <string name="seamless_transition_title" msgid="5335622196351371961">"Transizione graduale"</string>
+    <string name="seamless_transition_detail" msgid="3440478759491650823">"Mentre ci dirigiamo verso un futuro senza password, queste ultime saranno ancora disponibili insieme alle passkey"</string>
+    <string name="choose_provider_title" msgid="8870795677024868108">"Scegli dove salvare le <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Seleziona un gestore delle password per salvare i tuoi dati e accedere più velocemente la prossima volta"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Vuoi creare una passkey per <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
     <string name="choose_create_option_password_title" msgid="7097275038523578687">"Vuoi salvare la password di <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +35,7 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Salva <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> in"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Creare la passkey in un altro dispositivo?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Vuoi usare <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> per tutti gli accessi?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Questo gestore delle password archivierà le password e le passkey per aiutarti ad accedere facilmente"</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"Questo gestore delle password di <xliff:g id="USERNAME">%1$s</xliff:g> archivierà le password e le passkey per aiutarti ad accedere facilmente"</string>
     <string name="set_as_default" msgid="4415328591568654603">"Imposta come valore predefinito"</string>
     <string name="use_once" msgid="9027366575315399714">"Usa una volta"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> password • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> passkey"</string>
@@ -47,8 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Altri gestori delle password"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Chiudi il foglio"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Torna alla pagina precedente"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Chiudi"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Chiudi"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Vuoi usare la passkey salvata per <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Vuoi usare l\'accesso salvato per <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Scegli un accesso salvato per <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +60,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Gestori delle password bloccati"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tocca per sbloccare"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nessuna informazione di accesso"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Non sono presenti dati di accesso in <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gestisci gli accessi"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Da un altro dispositivo"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Usa un dispositivo diverso"</string>
diff --git a/packages/CredentialManager/res/values-iw/strings.xml b/packages/CredentialManager/res/values-iw/strings.xml
index 9100b51..f4b1906 100644
--- a/packages/CredentialManager/res/values-iw/strings.xml
+++ b/packages/CredentialManager/res/values-iw/strings.xml
@@ -20,7 +20,7 @@
     <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>
+    <string name="seamless_transition_detail" msgid="3440478759491650823">"אנחנו מתקדמים לעבר עתיד ללא סיסמאות, אבל עדיין אפשר יהיה להשתמש בסיסמאות וגם במפתחות גישה"</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"בחירת המקום לשמירה של <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"אפשר לבחור באחד משירותי ניהול הסיסמאות כדי לשמור את הפרטים ולהיכנס לחשבון מהר יותר בפעם הבאה"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"ליצור מפתח גישה ל-<xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +35,7 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"שמירת <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> ב-"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"ליצור מפתח גישה במכשיר אחר?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"להשתמש ב-<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> בכל הכניסות?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"במנהל הסיסמאות הזה יאוחסנו הסיסמאות ומפתחות הגישה שלך, כדי לעזור לך להיכנס לחשבון בקלות"</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"מנהל הסיסמאות הזה של <xliff:g id="USERNAME">%1$s</xliff:g> יאחסן את הסיסמאות ומפתחות הגישה שלך, כדי לעזור לך להיכנס לחשבון בקלות"</string>
     <string name="set_as_default" msgid="4415328591568654603">"הגדרה כברירת מחדל"</string>
     <string name="use_once" msgid="9027366575315399714">"שימוש פעם אחת"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> סיסמאות • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> מפתחות גישה"</string>
@@ -47,8 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"מנהלי סיסמאות אחרים"</string>
     <string name="close_sheet" msgid="1393792015338908262">"סגירת הגיליון"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"חזרה לדף הקודם"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"סגירה"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"סגירה"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"להשתמש במפתח גישה שנשמר עבור <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"להשתמש בפרטי הכניסה שנשמרו עבור <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"בחירת פרטי כניסה שמורים עבור <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +60,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"מנהלי סיסמאות נעולים"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"יש להקיש כדי לבטל את הנעילה"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"אין פרטי כניסה"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"אין פרטי כניסה ב-<xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"ניהול כניסות"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"ממכשיר אחר"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"צריך להשתמש במכשיר אחר"</string>
diff --git a/packages/CredentialManager/res/values-ja/strings.xml b/packages/CredentialManager/res/values-ja/strings.xml
index c49dd39..35d011c 100644
--- a/packages/CredentialManager/res/values-ja/strings.xml
+++ b/packages/CredentialManager/res/values-ja/strings.xml
@@ -20,8 +20,8 @@
     <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>
-    <string name="choose_provider_title" msgid="8870795677024868108">"<xliff:g id="CREATETYPES">%1$s</xliff:g> の保存先の選択"</string>
+    <string name="seamless_transition_detail" msgid="3440478759491650823">"将来的にパスワードレスに移行するにあたり、パスワードもパスキーと並行して引き続きご利用いただけます"</string>
+    <string name="choose_provider_title" msgid="8870795677024868108">"<xliff:g id="CREATETYPES">%1$s</xliff:g>の保存先を選択"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"パスワード マネージャーを選択して情報を保存しておくと、次回からすばやくログインできます"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> のパスキーを作成しますか?"</string>
     <string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> のパスワードを保存しますか?"</string>
@@ -35,7 +35,7 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>の保存先"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"別のデバイスにパスキーを作成しますか?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"ログインのたびに <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> を使用しますか?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"このパスワード マネージャーに、パスワードやパスキーが保存され、簡単にログインできるようになります"</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"<xliff:g id="USERNAME">%1$s</xliff:g> のパスワード マネージャーにパスワードやパスキーが保存され、簡単にログインできるようになります"</string>
     <string name="set_as_default" msgid="4415328591568654603">"デフォルトに設定"</string>
     <string name="use_once" msgid="9027366575315399714">"1 回使用"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> 件のパスワード • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> 件のパスキー"</string>
@@ -48,6 +48,7 @@
     <string name="close_sheet" msgid="1393792015338908262">"シートを閉じます"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"前のページに戻ります"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"閉じる"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"閉じる"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> の保存したパスキーを使用しますか?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> の保存したログイン情報を使用しますか?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> の保存したログイン情報の選択"</string>
diff --git a/packages/CredentialManager/res/values-ka/strings.xml b/packages/CredentialManager/res/values-ka/strings.xml
index f5eb7c9..5e8a6dc 100644
--- a/packages/CredentialManager/res/values-ka/strings.xml
+++ b/packages/CredentialManager/res/values-ka/strings.xml
@@ -20,7 +20,8 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"აირჩიეთ სად შეინახოთ თქვენი <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"აირჩიეთ პაროლების მმართველი თქვენი ინფორმაციის შესანახად, რომ მომავალში უფრო სწრაფად შეხვიდეთ."</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"შექმნით წვდომის გასაღებს <xliff:g id="APPNAME">%1$s</xliff:g> აპისთვის?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>-ის შენახვა"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"გსურთ პაროლის შექმნა სხვა მოწყობილობაში?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"გსურთ, გამოიყენოთ<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> სისტემაში ყველა შესვლისთვის?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"მოცემული პაროლების მმართველი შეინახავს თქვენს პაროლებს და წვდომის გასაღებს, რომლებიც დაგეხმარებათ სისტემაში მარტივად შესვლაში."</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"ნაგულისხმევად დაყენება"</string>
     <string name="use_once" msgid="9027366575315399714">"ერთხელ გამოყენება"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> პაროლები • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> წვდომის გასაღებები"</string>
@@ -48,6 +50,7 @@
     <string name="close_sheet" msgid="1393792015338908262">"ფურცლის დახურვა"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"წინა გვერდზე დაბრუნება"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"დახურვა"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"დახურვა"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"გსურთ თქვენი დამახსოვრებული წვდომის გასაღების გამოყენება აპისთვის: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"გსურთ თქვენი დამახსოვრებული სისტემაში შესვლის მონაცემების გამოყენება აპისთვის: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"აირჩიეთ სისტემაში შესვლის ინფორმაცია აპისთვის: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-kk/strings.xml b/packages/CredentialManager/res/values-kk/strings.xml
index 8864cb4..9613989 100644
--- a/packages/CredentialManager/res/values-kk/strings.xml
+++ b/packages/CredentialManager/res/values-kk/strings.xml
@@ -20,22 +20,24 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"<xliff:g id="CREATETYPES">%1$s</xliff:g> қайда сақталатынын таңдаңыз"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Мәліметіңізді сақтап, келесіде жылдам кіру үшін құпия сөз менеджерін таңдаңыз."</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> үшін кіру кілтін жасау керек пе?"</string>
     <string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> үшін құпия сөзді сақтау керек пе?"</string>
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> үшін кіру мәліметін сақтау керек пе?"</string>
-    <string name="passkey" msgid="632353688396759522">"кіру кілті"</string>
+    <string name="passkey" msgid="632353688396759522">"Кіру кілті"</string>
     <string name="password" msgid="6738570945182936667">"құпия сөз"</string>
     <string name="passkeys" msgid="5733880786866559847">"Кіру кілттері"</string>
     <string name="passwords" msgid="5419394230391253816">"Құпия сөздер"</string>
     <string name="sign_ins" msgid="4710739369149469208">"кіру әрекеттері"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"кіру мәліметі"</string>
-    <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> тіркелу дерегін сақтау орны:"</string>
+    <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> дерегін сақтау орны:"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Кіру кілтін басқа құрылғыда жасау керек пе?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Барлық кіру әрекеті үшін <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> пайдаланылсын ба?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Аккаунтқа кіру оңай болуы үшін, құпия сөз менеджері құпия сөздер мен кіру кілттерін сақтайды."</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Әдепкі етіп орнату"</string>
     <string name="use_once" msgid="9027366575315399714">"Бір рет пайдалану"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> құпия сөз • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> кіру кілті"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Басқа құпия сөз менеджерлері"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Парақты жабу"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Алдыңғы бетке оралу"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Жабу"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Жабу"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін сақталған кіру кілті пайдаланылсын ба?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін сақталған тіркелу деректері пайдаланылсын ба?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін сақталған тіркелу деректерін таңдаңыз"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Құлыпталған құпия сөз менеджерлері"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Құлыпты ашу үшін түртіңіз."</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Кіру ақпараты жоқ."</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> аккаунтында кіру туралы ешқандай ақпарат жоқ."</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Кіру әрекеттерін басқару"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Басқа құрылғыдан жасау"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Басқа құрылғыны пайдалану"</string>
diff --git a/packages/CredentialManager/res/values-km/strings.xml b/packages/CredentialManager/res/values-km/strings.xml
index f257789..1e7b4e6 100644
--- a/packages/CredentialManager/res/values-km/strings.xml
+++ b/packages/CredentialManager/res/values-km/strings.xml
@@ -10,7 +10,7 @@
     <string name="content_description_hide_password" msgid="6841375971631767996">"លាក់​ពាក្យ​សម្ងាត់"</string>
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"កាន់តែមានសុវត្ថិភាពដោយប្រើកូដសម្ងាត់"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"តាមរយៈ​កូដសម្ងាត់ អ្នកមិនចាំបាច់​បង្កើត ឬចងចាំពាក្យសម្ងាត់ស្មុគស្មាញ​នោះទេ"</string>
-    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"កូដសម្ងាត់​ត្រូវបានអ៊ីនគ្រីប​ឃីឌីជីថលដែលអ្នកបង្កើតដោយប្រើ​ស្នាមម្រាមដៃ មុខ ឬចាក់សោអេក្រង់​របស់អ្នក"</string>
+    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"កូដសម្ងាត់​គឺជាសោឌីជីថលដែលត្រូវបានអ៊ីនគ្រីប ​ដែលអ្នកបង្កើតដោយប្រើ​ស្នាមម្រាមដៃ មុខ ឬមុខងារចាក់សោអេក្រង់​របស់អ្នក"</string>
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"កូដសម្ងាត់ត្រូវបានរក្សាទុក​ទៅក្នុង​កម្មវិធីគ្រប់គ្រងពាក្យសម្ងាត់ ដូច្នេះអ្នកអាច​ចូលនៅលើឧបករណ៍ផ្សេងទៀត"</string>
     <string name="more_about_passkeys_title" msgid="7797903098728837795">"ច្រើនទៀតអំពីកូដសម្ងាត់"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"បច្ចេកវិទ្យាគ្មានពាក្យសម្ងាត់"</string>
@@ -20,7 +20,7 @@
     <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>
+    <string name="seamless_transition_detail" msgid="3440478759491650823">"នៅពេលដែលយើងឈានទៅរកអនាគតដែលគ្មានពាក្យសម្ងាត់ ពាក្យសម្ងាត់នៅតែអាចប្រើបានរួមជាមួយកូដសម្ងាត់"</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"ជ្រើសរើសកន្លែង​ដែលត្រូវរក្សាទុក<xliff:g id="CREATETYPES">%1$s</xliff:g>របស់អ្នក"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"ជ្រើសរើស​កម្មវិធីគ្រប់គ្រងពាក្យសម្ងាត់ ដើម្បីរក្សាទុក​ព័ត៌មានរបស់អ្នក និងចូលគណនី​បានកាន់តែរហ័ស​នៅពេលលើកក្រោយ"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"បង្កើត​កូដសម្ងាត់​សម្រាប់ <xliff:g id="APPNAME">%1$s</xliff:g> ឬ?"</string>
@@ -32,10 +32,10 @@
     <string name="passwords" msgid="5419394230391253816">"ពាក្យសម្ងាត់"</string>
     <string name="sign_ins" msgid="4710739369149469208">"ការចូល​គណនី"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"ព័ត៌មានអំពី​ការចូលគណនី"</string>
-    <string name="save_credential_to_title" msgid="3172811692275634301">"រក្សាទុក <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> ទៅកាន់"</string>
+    <string name="save_credential_to_title" msgid="3172811692275634301">"រក្សាទុក​<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>​ទៅកាន់"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"បង្កើតកូដសម្ងាត់​នៅក្នុងឧបករណ៍​ផ្សេងទៀតឬ?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"ប្រើ <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> សម្រាប់ការចូលគណនីទាំងអស់របស់អ្នកឬ?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"កម្មវិធីគ្រប់គ្រងពាក្យសម្ងាត់នេះ​នឹងរក្សាទុកពាក្យសម្ងាត់ និងកូដសម្ងាត់​របស់អ្នក ដើម្បីជួយឱ្យអ្នក​ចូលគណនី​បានយ៉ាងងាយស្រួល"</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"កម្មវិធីគ្រប់គ្រងពាក្យសម្ងាត់សម្រាប់ <xliff:g id="USERNAME">%1$s</xliff:g> ​នេះនឹងរក្សាទុកពាក្យសម្ងាត់ និងកូដសម្ងាត់​របស់អ្នក ដើម្បីជួយឱ្យអ្នក​ចូលគណនី​បានយ៉ាងងាយស្រួល"</string>
     <string name="set_as_default" msgid="4415328591568654603">"កំណត់ជាលំនាំដើម"</string>
     <string name="use_once" msgid="9027366575315399714">"ប្រើម្ដង"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"ពាក្យសម្ងាត់ <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • កូដសម្ងាត់<xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
@@ -48,6 +48,7 @@
     <string name="close_sheet" msgid="1393792015338908262">"បិទសន្លឹក"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ត្រឡប់ទៅ​ទំព័រ​មុនវិញ"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"បិទ"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"ច្រានចោល"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"ប្រើកូដសម្ងាត់ដែលបានរក្សាទុករបស់អ្នកសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g> ឬ?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"ប្រើការចូល​គណនីដែលបានរក្សាទុករបស់អ្នកសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g> ឬ?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"ជ្រើសរើសការចូលគណនីដែលបានរក្សាទុកសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-kn/strings.xml b/packages/CredentialManager/res/values-kn/strings.xml
index c41bd63..561348e 100644
--- a/packages/CredentialManager/res/values-kn/strings.xml
+++ b/packages/CredentialManager/res/values-kn/strings.xml
@@ -8,7 +8,7 @@
     <string name="string_learn_more" msgid="4541600451688392447">"ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</string>
     <string name="content_description_show_password" msgid="3283502010388521607">"ಪಾಸ್‌ವರ್ಡ್ ತೋರಿಸಿ"</string>
     <string name="content_description_hide_password" msgid="6841375971631767996">"ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಮರೆಮಾಡಿ"</string>
-    <string name="passkey_creation_intro_title" msgid="4251037543787718844">"ಪಾಸ್‌ಕೀಗಳೊಂದಿಗೆ ಸುರಕ್ಷಿತವಾಗಿರುತ್ತವೆ"</string>
+    <string name="passkey_creation_intro_title" msgid="4251037543787718844">"ಪಾಸ್‌ಕೀಗಳ ಸಹಾಯದಿಂದ ಸುರಕ್ಷಿತವಾಗಿರಿ"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"ಪಾಸ್‌ಕೀಗಳ ಮೂಲಕ, ನೀವು ಕ್ಲಿಷ್ಟ ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು ರಚಿಸುವ ಅಥವಾ ನೆನಪಿಟ್ಟುಕೊಳ್ಳುವ ಅಗತ್ಯವಿಲ್ಲ"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"ಪಾಸ್‌ಕೀಗಳು ನಿಮ್ಮ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್, ಫೇಸ್ ಅಥವಾ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಅನ್ನು ಬಳಸಿಕೊಂಡು ನೀವು ರಚಿಸುವ ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಿದ ಡಿಜಿಟಲ್ ಕೀಗಳಾಗಿವೆ"</string>
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"ಅವುಗಳನ್ನು ಪಾಸ್‌ವರ್ಡ್ ನಿರ್ವಾಹಕದಲ್ಲಿ ಉಳಿಸಲಾಗಿದೆ, ಹಾಗಾಗಿ ನೀವು ಇತರ ಸಾಧನಗಳಲ್ಲಿ ಸೈನ್ ಇನ್ ಮಾಡಬಹುದು"</string>
@@ -20,7 +20,7 @@
     <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>
+    <string name="seamless_transition_detail" msgid="3440478759491650823">"ನಾವು ಪಾಸ್‌ವರ್ಡ್ ರಹಿತ ಭವಿಷ್ಯದತ್ತ ಸಾಗುತ್ತಿರುವಾಗ, ಪಾಸ್‌ಕೀಗಳ ಜೊತೆಗೆ ಪಾಸ್‌ವರ್ಡ್‌ಗಳು ಇನ್ನೂ ಲಭ್ಯವಿರುತ್ತವೆ"</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"ನಿಮ್ಮ <xliff:g id="CREATETYPES">%1$s</xliff:g> ಅನ್ನು ಎಲ್ಲಿ ಉಳಿಸಬೇಕು ಎಂದು ಆರಿಸಿ"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"ನಿಮ್ಮ ಮಾಹಿತಿಯನ್ನು ಉಳಿಸಲು ಪಾಸ್‌ವರ್ಡ್ ನಿರ್ವಾಹಕವನ್ನು ಆಯ್ಕೆಮಾಡಿ ಹಾಗೂ ಮುಂದಿನ ಬಾರಿ ವೇಗವಾಗಿ ಸೈನ್ ಇನ್ ಮಾಡಿ"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> ಗಾಗಿ ಪಾಸ್‌ಕೀ ಅನ್ನು ರಚಿಸುವುದೇ?"</string>
@@ -35,7 +35,7 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"ಇಲ್ಲಿಗೆ <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> ಅನ್ನು ಉಳಿಸಿ"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"ಮತ್ತೊಂದು ಸಾಧನದಲ್ಲಿ ಪಾಸ್‌ಕೀಯನ್ನು ರಚಿಸಬೇಕೇ?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"ನಿಮ್ಮ ಎಲ್ಲಾ ಸೈನ್-ಇನ್‌ಗಳಿಗಾಗಿ <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> ಅನ್ನು ಬಳಸುವುದೇ?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"ಈ ಪಾಸ್‌ವರ್ಡ್ ನಿರ್ವಾಹಕವು ನಿಮಗೆ ಸುಲಭವಾಗಿ ಸೈನ್ ಇನ್ ಮಾಡುವುದಕ್ಕೆ ಸಹಾಯ ಮಾಡಲು ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್‌ಗಳು ಮತ್ತು ಪಾಸ್‌ಕೀಗಳನ್ನು ಸಂಗ್ರಹಿಸುತ್ತದೆ"</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"<xliff:g id="USERNAME">%1$s</xliff:g> ಗಾಗಿ ಈ ಪಾಸ್‌ವರ್ಡ್ ನಿರ್ವಾಹಕವು ನಿಮಗೆ ಸುಲಭವಾಗಿ ಸೈನ್ ಇನ್ ಮಾಡುವುದಕ್ಕೆ ಸಹಾಯ ಮಾಡಲು ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್‌ಗಳು ಮತ್ತು ಪಾಸ್‌ಕೀಗಳನ್ನು ಸಂಗ್ರಹಿಸುತ್ತದೆ"</string>
     <string name="set_as_default" msgid="4415328591568654603">"ಡೀಫಾಲ್ಟ್ ಆಗಿ ಸೆಟ್ ಮಾಡಿ"</string>
     <string name="use_once" msgid="9027366575315399714">"ಒಂದು ಬಾರಿ ಬಳಸಿ"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> ಪಾಸ್‌ವರ್ಡ್‌ಗಳು • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> ಪಾಸ್‌ಕೀಗಳು"</string>
@@ -48,6 +48,7 @@
     <string name="close_sheet" msgid="1393792015338908262">"ಶೀಟ್ ಮುಚ್ಚಿರಿ"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ಹಿಂದಿನ ಪುಟಕ್ಕೆ ಹಿಂದಿರುಗಿ"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"ಮುಚ್ಚಿರಿ"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"ವಜಾಗೊಳಿಸಿ"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ಉಳಿಸಲಾದ ನಿಮ್ಮ ಪಾಸ್‌ಕೀ ಅನ್ನು ಬಳಸಬೇಕೆ?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ಉಳಿಸಲಾದ ನಿಮ್ಮ ಸೈನ್-ಇನ್ ಅನ್ನು ಬಳಸಬೇಕೆ?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ಉಳಿಸಲಾದ ಸೈನ್-ಇನ್ ಮಾಹಿತಿಯನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
diff --git a/packages/CredentialManager/res/values-ko/strings.xml b/packages/CredentialManager/res/values-ko/strings.xml
index 20b734a..b65f693 100644
--- a/packages/CredentialManager/res/values-ko/strings.xml
+++ b/packages/CredentialManager/res/values-ko/strings.xml
@@ -20,7 +20,8 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"<xliff:g id="CREATETYPES">%1$s</xliff:g> 저장 위치 선택"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"정보를 저장해서 다음에 더 빠르게 로그인하려면 비밀번호 관리자를 선택하세요."</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g>의 패스키를 만드시겠습니까?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> 저장 위치"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"다른 기기에서 패스키를 만드시겠습니까?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"모든 로그인에 <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>을(를) 사용하시겠습니까?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"이 비밀번호 관리자는 비밀번호와 패스키를 저장하여 사용자가 간편하게 로그인할 수 있도록 돕습니다."</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"기본값으로 설정"</string>
     <string name="use_once" msgid="9027366575315399714">"한 번 사용"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"비밀번호 <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g>개 • 패스키 <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>개"</string>
@@ -47,9 +49,9 @@
     <string name="other_password_manager" msgid="565790221427004141">"기타 비밀번호 관리자"</string>
     <string name="close_sheet" msgid="1393792015338908262">"시트 닫기"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"이전 페이지로 돌아가기"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
-    <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱용 저장된 패스키를 사용하시겠습니까?"</string>
+    <string name="accessibility_close_button" msgid="1163435587545377687">"닫기"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"닫기"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱용으로 저장된 패스키를 사용하시겠습니까?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱용 저장된 로그인 정보를 사용하시겠습니까?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱용 저장된 로그인 정보 선택"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"다른 방법으로 로그인"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"잠긴 비밀번호 관리자"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"탭하여 잠금 해제"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"로그인 정보 없음"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>의 로그인 정보 없음"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"로그인 관리"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"다른 기기에서"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"다른 기기 사용"</string>
diff --git a/packages/CredentialManager/res/values-ky/strings.xml b/packages/CredentialManager/res/values-ky/strings.xml
index 895d0e7..8df3219 100644
--- a/packages/CredentialManager/res/values-ky/strings.xml
+++ b/packages/CredentialManager/res/values-ky/strings.xml
@@ -20,36 +20,38 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"<xliff:g id="CREATETYPES">%1$s</xliff:g> кайда сакталарын тандаңыз"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Маалыматыңызды сактоо жана кийинки жолу тезирээк кирүү үчүн сырсөздөрдү башкаргычты тандаңыз"</string>
-    <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> үчүн мүмкүндүк алуу ачкычын түзөсүзбү?"</string>
+    <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> колдонмосуна киргизүүчү ачкыч түзөсүзбү?"</string>
     <string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> үчүн сырсөз сакталсынбы?"</string>
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> үчүн кирүү маалыматы сакталсынбы?"</string>
-    <string name="passkey" msgid="632353688396759522">"мүмкүндүк алуу ачкычы"</string>
+    <string name="passkey" msgid="632353688396759522">"киргизүүчү ачкыч"</string>
     <string name="password" msgid="6738570945182936667">"сырсөз"</string>
     <string name="passkeys" msgid="5733880786866559847">"мүмкүндүк алуу ачкычтары"</string>
     <string name="passwords" msgid="5419394230391253816">"сырсөздөр"</string>
     <string name="sign_ins" msgid="4710739369149469208">"кирүүлөр"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"кирүү маалыматы"</string>
     <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> төмөнкүгө сакталсын:"</string>
-    <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Мүмкүндүк алуу ачкычы башка түзмөктө түзүлсүнбү?"</string>
+    <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Киргизүүчү ачкыч башка түзмөктө түзүлсүнбү?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> бардык аккаунттарга кирүү үчүн колдонулсунбу?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Сырсөздөрүңүздү жана ачкычтарыңызды Сырсөздөрдү башкаргычка сактап коюп, каалаган убакта колдоно берсеңиз болот"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Демейки катары коюу"</string>
     <string name="use_once" msgid="9027366575315399714">"Бир жолу колдонуу"</string>
-    <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> сырсөз • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> мүмкүндүк алуу ачкычы"</string>
+    <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> сырсөз • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> киргизүүчү ачкыч"</string>
     <string name="more_options_usage_passwords" msgid="1632047277723187813">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> сырсөз"</string>
-    <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> мүмкүндүк алуу ачкычы"</string>
+    <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> киргизүүчү ачкыч"</string>
     <string name="more_options_usage_credentials" msgid="1785697001787193984">"<xliff:g id="TOTALCREDENTIALSNUMBER">%1$s</xliff:g> эсептик дайындары"</string>
-    <string name="passkey_before_subtitle" msgid="2448119456208647444">"Мүмкүндүк алуу ачкычы"</string>
+    <string name="passkey_before_subtitle" msgid="2448119456208647444">"Киргизүүчү ачкыч"</string>
     <string name="another_device" msgid="5147276802037801217">"Башка түзмөк"</string>
     <string name="other_password_manager" msgid="565790221427004141">"Башка сырсөздөрдү башкаргычтар"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Баракты жабуу"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Мурунку бетке кайтуу"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
-    <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> үчүн сакталган мүмкүндүк алуу ачкычын колдоносузбу?"</string>
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Жабуу"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Жабуу"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосуна кирүү үчүн сакталган ачкычты колдоносузбу?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> үчүн сакталган кирүү параметрин колдоносузбу?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> үчүн кирүү маалыматын тандаңыз"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Башка жол менен кирүү"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Кулпуланган сырсөздөрдү башкаргычтар"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Кулпусун ачуу үчүн таптаңыз"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Аккаунтка кирүү тууралуу маалымат жок"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> аккаунтунда кирүү маалыматы жок"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Кирүү параметрлерин тескөө"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Башка түзмөктөн"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Башка түзмөктү колдонуу"</string>
diff --git a/packages/CredentialManager/res/values-lo/strings.xml b/packages/CredentialManager/res/values-lo/strings.xml
index 757bf13..cd074a8 100644
--- a/packages/CredentialManager/res/values-lo/strings.xml
+++ b/packages/CredentialManager/res/values-lo/strings.xml
@@ -20,7 +20,8 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"ເລືອກບ່ອນທີ່ຈະບັນທຶກ <xliff:g id="CREATETYPES">%1$s</xliff:g> ຂອງທ່ານ"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"ເລືອກຕົວຈັດການລະຫັດຜ່ານເພື່ອບັນທຶກຂໍ້ມູນຂອງທ່ານ ແລະ ເຂົ້າສູ່ລະບົບໄວຂຶ້ນໃນເທື່ອຕໍ່ໄປ"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"ສ້າງກະແຈຜ່ານສຳລັບ <xliff:g id="APPNAME">%1$s</xliff:g> ບໍ?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"ບັນທຶກ <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> ໃສ່"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"ສ້າງກະແຈຜ່ານໃນອຸປະກອນອື່ນບໍ?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"ໃຊ້ <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> ສຳລັບການເຂົ້າສູ່ລະບົບທັງໝົດຂອງທ່ານບໍ?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"ຕົວຈັດການລະຫັດຜ່ານນີ້ຈະຈັດເກັບລະຫັດຜ່ານ ແລະ ກະແຈຜ່ານຂອງທ່ານໄວ້ເພື່ອຊ່ວຍໃຫ້ທ່ານເຂົ້າສູ່ລະບົບໄດ້ໂດຍງ່າຍ"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"ຕັ້ງເປັນຄ່າເລີ່ມຕົ້ນ"</string>
     <string name="use_once" msgid="9027366575315399714">"ໃຊ້ເທື່ອດຽວ"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> ລະຫັດຜ່ານ • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> ກະແຈຜ່ານ"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"ຕົວຈັດການລະຫັດຜ່ານອື່ນໆ"</string>
     <string name="close_sheet" msgid="1393792015338908262">"ປິດຊີດ"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ກັບຄືນໄປຫາໜ້າກ່ອນໜ້ານີ້"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"ປິດ"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"ປິດໄວ້"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"ໃຊ້ກະແຈຜ່ານທີ່ບັນທຶກໄວ້ຂອງທ່ານສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"ໃຊ້ການເຂົ້າສູ່ລະບົບທີ່ບັນທຶກໄວ້ຂອງທ່ານສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"ເລືອກການເຂົ້າສູ່ລະບົບທີ່ບັນທຶກໄວ້ສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"ຕົວຈັດການລະຫັດຜ່ານທີ່ລັອກໄວ້"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"ແຕະເພື່ອປົດລັອກ"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"ບໍ່ມີຂໍ້ມູນການເຂົ້າສູ່ລະບົບ"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"ບໍ່ມີຂໍ້ມູນການເຂົ້າສູ່ລະບົບໃນ <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"ຈັດການການເຂົ້າສູ່ລະບົບ"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"ຈາກອຸປະກອນອື່ນ"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"ໃຊ້ອຸປະກອນອື່ນ"</string>
diff --git a/packages/CredentialManager/res/values-lt/strings.xml b/packages/CredentialManager/res/values-lt/strings.xml
index d75993f..133b357 100644
--- a/packages/CredentialManager/res/values-lt/strings.xml
+++ b/packages/CredentialManager/res/values-lt/strings.xml
@@ -20,7 +20,8 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Geresnė paskyros sauga"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Kiekvienas raktas išskirtinai susietas su programa ar svetaine, kuriai buvo sukurtas, todėl niekada per klaidą neprisijungsite prie apgavikiškos programos ar svetainės. Be to, viešieji raktai laikomi tik serveriuose, todėl įsilaužti tampa gerokai sudėtingiau."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Sklandus perėjimas"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Kol stengiamės padaryti, kad ateityje nereikėtų naudoti slaptažodžių, jie vis dar bus pasiekiami kartu su slaptaisiais raktais."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Pasirinkite, kur išsaugoti „<xliff:g id="CREATETYPES">%1$s</xliff:g>“"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Pasirinkite slaptažodžių tvarkyklę, kurią naudodami galėsite išsaugoti informaciją ir kitą kartą prisijungti greičiau"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Sukurti „passkey“, skirtą „<xliff:g id="APPNAME">%1$s</xliff:g>“?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Išsaugoti <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Kurti „passkey“ kitame įrenginyje?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Naudoti <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> visada prisijungiant?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Šioje slaptažodžių tvarkyklėje bus saugomi jūsų slaptažodžiai ir „passkey“, kad galėtumėte lengvai prisijungti"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Nustatyti kaip numatytąjį"</string>
     <string name="use_once" msgid="9027366575315399714">"Naudoti vieną kartą"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Slaptažodžių: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • „Passkey“: <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Kitos slaptažodžių tvarkyklės"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Uždaryti lapą"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Grįžti į ankstesnį puslapį"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Uždaryti"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Atsisakyti"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Naudoti išsaugotą „passkey“ programai „<xliff:g id="APP_NAME">%1$s</xliff:g>“?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Naudoti išsaugotą prisijungimo informaciją programai „<xliff:g id="APP_NAME">%1$s</xliff:g>“?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Pasirinkite išsaugotą prisijungimo informaciją programai „<xliff:g id="APP_NAME">%1$s</xliff:g>“"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Užrakintos slaptažodžių tvarkyklės"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Palieskite, kad atrakintumėte"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Prisijungimo informacijos nėra"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nėra prisijungimo informacijos <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Tvarkyti prisijungimo informaciją"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Naudojant kitą įrenginį"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Naudoti kitą įrenginį"</string>
diff --git a/packages/CredentialManager/res/values-lv/strings.xml b/packages/CredentialManager/res/values-lv/strings.xml
index 01c6d55..5222d52 100644
--- a/packages/CredentialManager/res/values-lv/strings.xml
+++ b/packages/CredentialManager/res/values-lv/strings.xml
@@ -20,7 +20,8 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Uzlabota kontu drošība"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Katra atslēga ir saistīta tikai ar to lietotni vai vietni, kurai tā tika izveidota, tādēļ jūs nevarēsiet nejauši pierakstīties krāpnieciskā lietotnē vai vietnē. Turklāt uzlaušanu ievērojami sarežģī tas, ka serveros tiek glabātas tikai publiskās atslēgas."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Ērta pāreja"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Lai arī pamazām notiek pāreja uz darbu bez parolēm, tās joprojām būs pieejamas līdzās piekļuves atslēgām."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Izvēlieties, kur saglabāt savas <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Lai saglabātu informāciju un nākamreiz varētu pierakstīties ātrāk, atlasiet paroļu pārvaldnieku."</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Vai izveidot piekļuves atslēgu lietotnei <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Kur jāsaglabā <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Vai izveidot piekļuves atslēgu citā ierīcē?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Vai vienmēr izmantot <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>, lai pierakstītos?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Šis paroļu pārvaldnieks glabās jūsu paroles un piekļuves atslēgas, lai atvieglotu pierakstīšanos."</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Iestatīt kā noklusējumu"</string>
     <string name="use_once" msgid="9027366575315399714">"Izmantot vienreiz"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Paroļu skaits: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • Piekļuves atslēgu skaits: <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Citi paroļu pārvaldnieki"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Aizvērt lapu"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Atgriezties iepriekšējā lapā"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Aizvērt"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Nerādīt"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Vai izmantot saglabāto piekļuves atslēgu lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Vai izmantot saglabāto pierakstīšanās informāciju lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Saglabātas pierakstīšanās informācijas izvēle lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Paroļu pārvaldnieki, kuros nepieciešams autentificēties"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Pieskarieties, lai atbloķētu"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nav pierakstīšanās informācijas"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Kontā <xliff:g id="SOURCE">%1$s</xliff:g> nav pierakstīšanās informācijas."</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Pierakstīšanās informācijas pārvaldība"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"No citas ierīces"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Izmantot citu ierīci"</string>
diff --git a/packages/CredentialManager/res/values-mk/strings.xml b/packages/CredentialManager/res/values-mk/strings.xml
index a844bc9..3287246 100644
--- a/packages/CredentialManager/res/values-mk/strings.xml
+++ b/packages/CredentialManager/res/values-mk/strings.xml
@@ -20,9 +20,9 @@
     <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>
+    <string name="seamless_transition_detail" msgid="3440478759491650823">"Како што се движиме кон иднина без лозинки, лозинките сепак ќе бидат достапни покрај криптографските клучеви"</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"Изберете каде да ги зачувате вашите <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
-    <string name="choose_provider_body" msgid="4967074531845147434">"Изберете Password Manager за да ги зачувате вашите податоци и да се најавите побрзо следниот пат"</string>
+    <string name="choose_provider_body" msgid="4967074531845147434">"Изберете управник со лозинки за да ги зачувате вашите податоци и да се најавите побрзо следниот пат"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Да се создаде криптографски клуч за <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
     <string name="choose_create_option_password_title" msgid="7097275038523578687">"Дали да се зачува лозинката за <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Да се зачуваат податоците за најавување за <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +35,7 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Зачувајте <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> во"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Да се создаде криптографски клуч во друг уред?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Да се користи <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> за сите ваши најавувања?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Овој Password Manager ќе ги складира вашите лозинки и криптографски клучеви за да ви помогне лесно да се најавите"</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"Овој управник со лозинки за <xliff:g id="USERNAME">%1$s</xliff:g> ќе ги складира вашите лозинки и криптографски клучеви за да ви помогне лесно да се најавите"</string>
     <string name="set_as_default" msgid="4415328591568654603">"Постави како стандардна опција"</string>
     <string name="use_once" msgid="9027366575315399714">"Употребете еднаш"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Лозинки: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • Криптографски клучеви: <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
@@ -47,8 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Други управници со лозинки"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Затворете го листот"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Врати се на претходната страница"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Затвори"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Отфрли"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Да се користи вашиот зачуван криптографски клуч за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Да се користи вашето зачувано најавување за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Изберете зачувано најавување за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +60,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Заклучени управници со лозинки"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Допрете за да отклучите"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Нема податоци за најавување"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Нема податоци за најавување во <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Управувајте со најавувањата"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Од друг уред"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Употребете друг уред"</string>
diff --git a/packages/CredentialManager/res/values-ml/strings.xml b/packages/CredentialManager/res/values-ml/strings.xml
index de88b28..ecf06b2 100644
--- a/packages/CredentialManager/res/values-ml/strings.xml
+++ b/packages/CredentialManager/res/values-ml/strings.xml
@@ -20,7 +20,8 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"നിങ്ങളുടെ <xliff:g id="CREATETYPES">%1$s</xliff:g> എവിടെയാണ് സംരക്ഷിക്കേണ്ടതെന്ന് തിരഞ്ഞെടുക്കുക"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"നിങ്ങളുടെ വിവരങ്ങൾ സംരക്ഷിക്കാനും അടുത്ത തവണ വേഗത്തിൽ സൈൻ ഇൻ ചെയ്യാനും ഒരു പാസ്‌വേഡ് മാനേജർ തിരഞ്ഞെടുക്കുക"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> എന്നതിനായി പാസ്‌കീ സൃഷ്ടിക്കണോ?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> ഇനിപ്പറയുന്നതിലേക്ക് സംരക്ഷിക്കുക"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"മറ്റൊരു ഉപകരണത്തിൽ പാസ്‌കീ സൃഷ്ടിക്കണോ?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"നിങ്ങളുടെ എല്ലാ സൈൻ ഇന്നുകൾക്കും <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> ഉപയോഗിക്കണോ?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"എളുപ്പത്തിൽ സൈൻ ഇൻ ചെയ്യാൻ സഹായിക്കുന്നതിന് ഈ Password Manager നിങ്ങളുടെ പാസ്‌വേഡുകളും പാസ്‌കീകളും സംഭരിക്കും"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"ഡിഫോൾട്ടായി സജ്ജീകരിക്കുക"</string>
     <string name="use_once" msgid="9027366575315399714">"ഒരു തവണ ഉപയോഗിക്കുക"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> പാസ്‌വേഡുകൾ • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> പാസ്‌കീകൾ"</string>
@@ -48,6 +50,7 @@
     <string name="close_sheet" msgid="1393792015338908262">"ഷീറ്റ് അടയ്ക്കുക"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"മുമ്പത്തെ പേജിലേക്ക് മടങ്ങുക"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"അടയ്ക്കുക"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"ഡിസ്‌മിസ് ചെയ്യുക"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനായി നിങ്ങൾ സംരക്ഷിച്ച പാസ്‌കീ ഉപയോഗിക്കണോ?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനായി നിങ്ങൾ സംരക്ഷിച്ച സൈൻ ഇൻ ഉപയോഗിക്കണോ?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനായി ഒരു സംരക്ഷിച്ച സൈൻ ഇൻ തിരഞ്ഞെടുക്കുക"</string>
diff --git a/packages/CredentialManager/res/values-mn/strings.xml b/packages/CredentialManager/res/values-mn/strings.xml
index ee5d66f..46f5434 100644
--- a/packages/CredentialManager/res/values-mn/strings.xml
+++ b/packages/CredentialManager/res/values-mn/strings.xml
@@ -20,7 +20,8 @@
     <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">"Бид нууц үггүй ирээдүй рүү урагшлахын хэрээр нууц үг нь passkey-н хамтаар боломжтой хэвээр байх болно."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"<xliff:g id="CREATETYPES">%1$s</xliff:g>-г хаана хадгалахаа сонгоно уу"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Мэдээллээ хадгалж, дараагийн удаа илүү хурдан нэвтрэхийн тулд нууц үгний менежерийг сонгоно уу"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g>-д passkey үүсгэх үү?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>-г дараахад хадгалах"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Өөр төхөөрөмжид passkey үүсгэх үү?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>-г бүх нэвтрэлтдээ ашиглах уу?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Хялбархан нэвтрэхэд туслахын тулд энэ нууц үгний менежер таны нууц үг болон passkeys-г хадгална"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Өгөгдмөлөөр тохируулах"</string>
     <string name="use_once" msgid="9027366575315399714">"Нэг удаа ашиглах"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> нууц үг • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> passkey"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Нууц үгний бусад менежер"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Хүснэгтийг хаах"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Өмнөх хуудас руу буцах"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Хаах"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Хаах"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д өөрийн хадгалсан passkey-г ашиглах уу?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д хадгалсан нэвтрэх мэдээллээ ашиглах уу?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д зориулж хадгалсан нэвтрэх мэдээллийг сонгоно уу"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Түгжээтэй нууц үгний менежерүүд"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Түгжээг тайлахын тулд товшино уу"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ямар ч нэвтрэх мэдээлэл байхгүй"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>-д ямар ч нэвтрэх мэдээлэл алга"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Нэвтрэлтийг удирдах"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Өөр төхөөрөмжөөс"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Өөр төхөөрөмж ашиглах"</string>
diff --git a/packages/CredentialManager/res/values-mr/strings.xml b/packages/CredentialManager/res/values-mr/strings.xml
index bc03212..adc6121 100644
--- a/packages/CredentialManager/res/values-mr/strings.xml
+++ b/packages/CredentialManager/res/values-mr/strings.xml
@@ -20,7 +20,8 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"तुमची <xliff:g id="CREATETYPES">%1$s</xliff:g> कुठे सेव्ह करायची ते निवडा"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"तुमची माहिती सेव्ह करण्यासाठी आणि पुढच्या वेळी जलद साइन इन करण्याकरिता Password Manager निवडा"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> साठी पासकी तयार करायची का?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> येथे सेव्ह करा"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"दुसऱ्या डिव्हाइसमध्ये पासकी तयार करायची का?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"तुमच्या सर्व साइन-इन साठी <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>वापरायचे का?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"तुम्हाला सहजरीत्या साइन इन करण्यात मदत करण्यासाठी हा पासवर्ड व्यवस्थापक तुमचे पासवर्ड आणि पासकी स्टोअर करेल"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"डिफॉल्ट म्हणून सेट करा"</string>
     <string name="use_once" msgid="9027366575315399714">"एकदा वापरा"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> पासवर्ड • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> पासकी"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"इतर पासवर्ड व्यवस्थापक"</string>
     <string name="close_sheet" msgid="1393792015338908262">"शीट बंद करा"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"मागील पेजवर परत जा"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"बंद करा"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"डिसमिस करा"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी तुमची सेव्ह केलेली पासकी वापरायची का?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी तुमचे सेव्ह केलेले साइन-इन वापरायचे का?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी सेव्ह केलेले साइन-इन निवडा"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"लॉक केलेले पासवर्ड व्यवस्थापक"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"अनलॉक करण्यासाठी टॅप करा"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"साइन-इन माहिती नाही"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> मध्ये कोणतीही साइन-इन माहिती नाही"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"साइन-इन व्यवस्थापित करा"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"दुसऱ्या डिव्हाइस वरून"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"वेगळे डिव्हाइस वापरा"</string>
diff --git a/packages/CredentialManager/res/values-ms/strings.xml b/packages/CredentialManager/res/values-ms/strings.xml
index ab2d9536..fb96a43 100644
--- a/packages/CredentialManager/res/values-ms/strings.xml
+++ b/packages/CredentialManager/res/values-ms/strings.xml
@@ -16,11 +16,11 @@
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Teknologi tanpa kata laluan"</string>
     <string name="passwordless_technology_detail" msgid="6853928846532955882">"Kunci laluan membolehkan anda log masuk tanpa bergantung pada kata laluan. Anda hanya perlu menggunakan cap jari anda, pengecaman wajah, PIN atau corak leret untuk mengesahkan identiti anda dan mencipta kunci laluan."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"Kriptografi kunci awam"</string>
-    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Berdasarkan standard Perikatan FIDO (termasuk Google, Apple, Microsoft dll) &amp; W3C, kunci laluan menggunakan pasangan kunci kriptografi. Tidak seperti nama pengguna &amp; rentetan aksara yang digunakan untuk kata laluan, pasangan kunci peribadi-umum dicipta untuk apl/laman web. Kunci persendirian akan disimpan dengan selamat pada peranti atau pengurus kata laluan dan ia mengesahkan identiti anda. Kunci awam dikongsi dengan pelayan apl/laman web. Dengan kunci sepadan, anda boleh mendaftar dan log masuk dengan segera."</string>
+    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Berdasarkan standard Perikatan FIDO (termasuk Google, Apple, Microsoft dll) &amp; W3C, kunci laluan menggunakan pasangan kunci kriptografi. Tidak seperti nama pengguna &amp; rentetan aksara yang digunakan untuk kata laluan, pasangan kunci peribadi-umum dicipta untuk apl/laman web. Kunci persendirian akan disimpan dengan selamat pada peranti atau pengurus kata laluan dan digunakan untuk mengesahkan identiti anda. Kunci awam dikongsi dengan pelayan apl/laman web. Dengan kunci sepadan, anda boleh mendaftar dan log masuk dengan segera."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"Keselamatan akaun yang dipertingkatkan"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Setiap kunci dipautkan secara eksklusif dengan apl atau laman web kunci dicipta, jadi anda tidak boleh log masuk ke apl atau laman web penipuan secara tidak sengaja. Selain itu, dengan pelayan yang hanya menyimpan kunci awam, penggodaman menjadi jauh lebih sukar."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Peralihan yang lancar"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Semasa kita bergerak menuju ke arah masa depan tanpa kata laluan, kata laluan masih akan tersedia bersama dengan kunci laluan."</string>
+    <string name="seamless_transition_detail" msgid="3440478759491650823">"Walaupun kita semakin menghampiri masa hadapan tanpa kata laluan, kata laluan masih akan tersedia bersama dengan kunci laluan"</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"Pilih tempat untuk menyimpan <xliff:g id="CREATETYPES">%1$s</xliff:g> anda"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Pilih Password Manager untuk menyimpan maklumat anda dan log masuk lebih pantas pada kali seterusnya"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Cipta kunci laluan untuk <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +35,7 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Simpan <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> pada"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Cipta kunci laluan dalam peranti lain?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Gunakan <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> untuk semua log masuk anda?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Password Manager ini akan menyimpan kata laluan dan kunci laluan anda untuk membantu anda log masuk dengan mudah"</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"Password Manager untuk <xliff:g id="USERNAME">%1$s</xliff:g> akan menyimpan kata laluan dan kunci laluan anda untuk membantu anda log masuk dengan mudah"</string>
     <string name="set_as_default" msgid="4415328591568654603">"Tetapkan sebagai lalai"</string>
     <string name="use_once" msgid="9027366575315399714">"Gunakan sekali"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> kata laluan • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> kunci laluan"</string>
@@ -48,6 +48,7 @@
     <string name="close_sheet" msgid="1393792015338908262">"Tutup helaian"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Kembali ke halaman sebelumnya"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Tutup"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Ketepikan"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Gunakan kunci laluan anda yang telah disimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Gunakan maklumat log masuk anda yang telah disimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Pilih log masuk yang telah disimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-my/strings.xml b/packages/CredentialManager/res/values-my/strings.xml
index 92a9e49..ba9b59a 100644
--- a/packages/CredentialManager/res/values-my/strings.xml
+++ b/packages/CredentialManager/res/values-my/strings.xml
@@ -20,7 +20,8 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"သင်၏ <xliff:g id="CREATETYPES">%1$s</xliff:g> သိမ်းရန်နေရာ ရွေးခြင်း"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"သင့်အချက်အလက်သိမ်းပြီး နောက်တစ်ကြိမ်၌ ပိုမိုမြန်ဆန်စွာ လက်မှတ်ထိုးဝင်ရန် စကားဝှက်မန်နေဂျာကို ရွေးပါ"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> အတွက် လျှို့ဝှက်ကီးပြုလုပ်မလား။"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> သိမ်းမည့်နေရာ"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"အခြားစက်ပစ္စည်းတွင် လျှို့ဝှက်ကီး ပြုလုပ်မလား။"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"သင်၏လက်မှတ်ထိုးဝင်မှု အားလုံးအတွက် <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> သုံးမလား။"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"သင်အလွယ်တကူ လက်မှတ်ထိုးဝင်နိုင်ရန် ဤစကားဝှက်မန်နေဂျာက စကားဝှက်နှင့် လျှို့ဝှက်ကီးများကို သိမ်းပေးပါမည်"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"မူရင်းအဖြစ် သတ်မှတ်ရန်"</string>
     <string name="use_once" msgid="9027366575315399714">"တစ်ကြိမ်သုံးရန်"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"စကားဝှက် <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> ခု • လျှို့ဝှက်ကီး <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> ခု"</string>
@@ -47,9 +49,9 @@
     <string name="other_password_manager" msgid="565790221427004141">"အခြားစကားဝှက်မန်နေဂျာများ"</string>
     <string name="close_sheet" msgid="1393792015338908262">"စာမျက်နှာ ပိတ်ရန်"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ယခင်စာမျက်နှာကို ပြန်သွားပါ"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
-    <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် သိမ်းထားသောလျှို့ဝှက်ကီး သုံးမလား။"</string>
+    <string name="accessibility_close_button" msgid="1163435587545377687">"ပိတ်ရန်"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"ပယ်ရန်"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"သိမ်းထားသောလျှို့ဝှက်ကီးကို <xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် သုံးမလား။"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် သိမ်းထားသောလက်မှတ်ထိုးဝင်မှု သုံးမလား။"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် သိမ်းထားသော လက်မှတ်ထိုးဝင်မှုကို ရွေးပါ"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"နောက်တစ်နည်းဖြင့် လက်မှတ်ထိုးဝင်ရန်"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"လော့ခ်ချထားသည့် စကားဝှက်မန်နေဂျာများ"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"ဖွင့်ရန် တို့ပါ"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"လက်မှတ်ထိုးဝင်သည့် အချက်အလက် မရှိပါ"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> တွင် လက်မှတ်ထိုးဝင်ရန်အချက်အလက် မရှိပါ"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"လက်မှတ်ထိုးဝင်မှုများ စီမံခြင်း"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"စက်နောက်တစ်ခုမှ"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"အခြားစက်သုံးရန်"</string>
diff --git a/packages/CredentialManager/res/values-nb/strings.xml b/packages/CredentialManager/res/values-nb/strings.xml
index ac8f7c1..50a4b47 100644
--- a/packages/CredentialManager/res/values-nb/strings.xml
+++ b/packages/CredentialManager/res/values-nb/strings.xml
@@ -20,7 +20,8 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Forbedret kontosikkerhet"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Hver nøkkel er eksklusivt tilknyttet appen eller nettstedet den er laget for. Dermed kan du aldri logge på falske apper eller nettsteder ved et uhell. Og siden tjenerne bare har offentlige nøkler, blir det mye vanskeligere å hacke deg."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Sømløs overgang"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Vi går mot en fremtid uten passord, men passord fortsetter å være tilgjengelige ved siden av tilgangsnøkler."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Velg hvor du vil lagre <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Velg et verktøy for passordlagring for å lagre informasjonen din og logge på raskere neste gang"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Vil du opprette en tilgangsnøkkel for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Lagre <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> i"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Vil du opprette en tilgangsnøkkel på en annen enhet?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Vil du bruke <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> for alle pålogginger?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Dette verktøyet for passordlagring lagrer passord og tilgangsnøkler, så det blir lett å logge på"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Angi som standard"</string>
     <string name="use_once" msgid="9027366575315399714">"Bruk én gang"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> passord • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> tilgangsnøkler"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Andre løsninger for passordlagring"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Lukk arket"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Gå tilbake til den forrige siden"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Lukk"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Lukk"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Vil du bruke den lagrede tilgangsnøkkelen for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Vil du bruke den lagrede påloggingen for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Velg en lagret pålogging for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Låste løsninger for passordlagring"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Trykk for å låse opp"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ingen påloggingsinformasjon"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Ingen påloggingsinformasjon i <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Administrer pålogginger"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Fra en annen enhet"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Bruk en annen enhet"</string>
diff --git a/packages/CredentialManager/res/values-ne/strings.xml b/packages/CredentialManager/res/values-ne/strings.xml
index 70ae649..f77a372 100644
--- a/packages/CredentialManager/res/values-ne/strings.xml
+++ b/packages/CredentialManager/res/values-ne/strings.xml
@@ -20,9 +20,10 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"तपाईं आफ्ना <xliff:g id="CREATETYPES">%1$s</xliff:g> कहाँ सेभ गर्न चाहनुहुन्छ भन्ने कुरा छनौट गर्नुहोस्"</string>
-    <string name="choose_provider_body" msgid="4967074531845147434">"कुनै पासवर्ड म्यानेजरमा आफ्नो जानकारी सेभ गरी अर्को टपक अझ छिटो साइन एन गर्नुहोस्"</string>
+    <string name="choose_provider_body" msgid="4967074531845147434">"कुनै पासवर्ड म्यानेजरमा आफ्नो जानकारी सेभ गरी अर्को पटक अझ छिटो साइन एन गर्नुहोस्"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> को पासकी बनाउने हो?"</string>
     <string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> को पासवर्ड सेभ गर्ने हो?"</string>
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> मा साइन गर्न प्रयोग गरिनु पर्ने जानकारी सेभ गर्ने हो?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> यहाँ सेभ गर्नुहोस्:"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"अर्को डिभाइसमा पासकी बनाउने हो?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"तपाईंले साइन इन गर्ने सबै डिभाइसहरूमा <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> प्रयोग गर्ने हो?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"तपाईं सजिलैसँग साइन इन गर्न सक्नुहोस् भन्नाका लागि यो पासवर्ड म्यानेजरले तपाईंका पासवर्ड र पासकीहरू सेभ गर्छ"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"डिफल्ट जानकारीका रूपमा सेट गर्नुहोस्"</string>
     <string name="use_once" msgid="9027366575315399714">"एक पटक प्रयोग गर्नुहोस्"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> वटा पासवर्ड • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> वटा पासकी"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"अन्य पासवर्ड म्यानेजरहरू"</string>
     <string name="close_sheet" msgid="1393792015338908262">"पाना बन्द गर्नुहोस्"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"अघिल्लो पेजमा फर्कनुहोस्"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"बन्द गर्नुहोस्"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"हटाउनुहोस्"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"आफूले सेभ गरेको पासकी प्रयोग गरी <xliff:g id="APP_NAME">%1$s</xliff:g> मा साइन इन गर्ने हो?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"आफूले सेभ गरेको साइन इनसम्बन्धी जानकारी प्रयोग गरी <xliff:g id="APP_NAME">%1$s</xliff:g> मा साइन इन गर्ने हो?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> मा साइन इन गर्नका लागि सेभ गरिएका साइन इनसम्बन्धी जानकारी छनौट गर्नुहोस्"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"लक गरिएका पासवर्ड म्यानेजरहरू"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"अनलक गर्न ट्याप गर्नुहोस्"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"साइन गर्न प्रयोग गरिनु पर्ने जानकारी उपलब्ध छैन"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> मा साइन इन गर्नेसम्बन्धी कुनै पनि जानकारी छैन"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"साइन इनसम्बन्धी विकल्पहरू व्यवस्थापन गर्नुहोस्"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"अर्को डिभाइसका लागि"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"अर्कै डिभाइस प्रयोग गरी हेर्नुहोस्"</string>
diff --git a/packages/CredentialManager/res/values-nl/strings.xml b/packages/CredentialManager/res/values-nl/strings.xml
index f3d7288..c5c2a1c 100644
--- a/packages/CredentialManager/res/values-nl/strings.xml
+++ b/packages/CredentialManager/res/values-nl/strings.xml
@@ -20,7 +20,8 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Verbeterde accountbeveiliging"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Elke sleutel is exclusief gekoppeld aan de app of website waarvoor deze is gemaakt. Je kunt dus nooit per ongeluk inloggen bij een bedrieglijke app of website. Bovendien bewaren servers alleen openbare sleutels, wat hacken een stuk lastiger maakt."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Naadloze overgang"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"We zijn op weg naar een wachtwoordloze toekomst, maar naast toegangssleutels kun je nog steeds gebruikmaken van wachtwoorden."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Kies waar je je <xliff:g id="CREATETYPES">%1$s</xliff:g> wilt opslaan"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Selecteer een wachtwoordmanager om je informatie op te slaan en de volgende keer sneller in te loggen"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Toegangssleutel maken voor <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> opslaan in"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Toegangssleutel maken op een ander apparaat?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> elke keer gebruiken als je inlogt?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Deze wachtwoordmanager slaat je wachtwoorden en toegangssleutels op zodat je makkelijk kunt inloggen"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Instellen als standaard"</string>
     <string name="use_once" msgid="9027366575315399714">"Eén keer gebruiken"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> wachtwoorden • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> toegangssleutels"</string>
@@ -47,12 +49,12 @@
     <string name="other_password_manager" msgid="565790221427004141">"Andere wachtwoordmanagers"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Blad sluiten"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Ga terug naar de vorige pagina"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
-    <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Je opgeslagen toegangssleutel voor <xliff:g id="APP_NAME">%1$s</xliff:g> gebruiken?"</string>
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Sluiten"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Sluiten"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Je opgeslagen toegangssleutel gebruiken voor <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Je opgeslagen inloggegevens voor <xliff:g id="APP_NAME">%1$s</xliff:g> gebruiken?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Opgeslagen inloggegevens kiezen voor <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Inloggen via een andere methode"</string>
+    <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Op een andere manier inloggen"</string>
     <string name="snackbar_action" msgid="37373514216505085">"Opties bekijken"</string>
     <string name="get_dialog_button_label_continue" msgid="6446201694794283870">"Doorgaan"</string>
     <string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Opties voor inloggen"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Vergrendelde wachtwoordmanagers"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tik om te ontgrendelen"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Geen inloggegevens"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Geen inloggevens in <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Inloggegevens beheren"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Via een ander apparaat"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Een ander apparaat gebruiken"</string>
diff --git a/packages/CredentialManager/res/values-or/strings.xml b/packages/CredentialManager/res/values-or/strings.xml
index 539b3dd..1f5312c 100644
--- a/packages/CredentialManager/res/values-or/strings.xml
+++ b/packages/CredentialManager/res/values-or/strings.xml
@@ -20,8 +20,9 @@
     <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>
-    <string name="choose_provider_title" msgid="8870795677024868108">"ଆପଣଙ୍କ <xliff:g id="CREATETYPES">%1$s</xliff:g>କୁ କେଉଁଠାରେ ସେଭ କରିବେ ତାହା ବାଛନ୍ତୁ"</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
+    <string name="choose_provider_title" msgid="8870795677024868108">"ଆପଣଙ୍କ <xliff:g id="CREATETYPES">%1$s</xliff:g> କେଉଁଠାରେ ସେଭ କରିବେ ତାହା ବାଛନ୍ତୁ"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"ଆପଣଙ୍କ ସୂଚନା ସେଭ କରି ପରବର୍ତ୍ତୀ ସମୟରେ ଶୀଘ୍ର ସାଇନ ଇନ କରିବା ପାଇଁ ଏକ Password Manager ଚୟନ କରନ୍ତୁ"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> ପାଇଁ ପାସକୀ ତିଆରି କରିବେ?"</string>
     <string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> ପାଇଁ ପାସୱାର୍ଡ ସେଭ କରିବେ?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>କୁ ଏଥିରେ ସେଭ କରନ୍ତୁ"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"ଅନ୍ୟ ଏକ ଡିଭାଇସରେ ପାସକୀ ତିଆରି କରିବେ?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"ଆପଣଙ୍କ ସମସ୍ତ ସାଇନ-ଇନ ପାଇଁ <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> ବ୍ୟବହାର କରିବେ?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"ଏହି Password Manager ସହଜରେ ସାଇନ ଇନ କରିବାରେ ଆପଣଙ୍କୁ ସାହାଯ୍ୟ କରିବା ପାଇଁ ଆପଣଙ୍କ ପାସୱାର୍ଡ ଏବଂ ପାସକୀଗୁଡ଼ିକୁ ଷ୍ଟୋର କରିବ"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"ଡିଫଲ୍ଟ ଭାବେ ସେଟ କରନ୍ତୁ"</string>
     <string name="use_once" msgid="9027366575315399714">"ଥରେ ବ୍ୟବହାର କରନ୍ତୁ"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g>ଟି ପାସୱାର୍ଡ • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>ଟି ପାସକୀ"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"ଅନ୍ୟ Password Manager"</string>
     <string name="close_sheet" msgid="1393792015338908262">"ସିଟ ବନ୍ଦ କରନ୍ତୁ"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ପୂର୍ବବର୍ତ୍ତୀ ପୃଷ୍ଠାକୁ ଫେରନ୍ତୁ"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"ବନ୍ଦ କରନ୍ତୁ"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"ଖାରଜ କରନ୍ତୁ"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ସେଭ କରାଯାଇଥିବା ଆପଣଙ୍କ ପାସକୀ ବ୍ୟବହାର କରିବେ?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ସେଭ କରାଯାଇଥିବା ଆପଣଙ୍କ ସାଇନ-ଇନ ବ୍ୟବହାର କରିବେ?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ସେଭ କରାଯାଇଥିବା ଏକ ସାଇନ-ଇନ ବାଛନ୍ତୁ"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"ଲକ ଥିବା Password Manager"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"ଅନଲକ କରିବାକୁ ଟାପ କରନ୍ତୁ"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"କୌଣସି ସାଇନ-ଇନ ସୂଚନା ନାହିଁ"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>ରେ କୌଣସି ସାଇନ-ଇନ ସୂଚନା ନାହିଁ"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"ସାଇନ-ଇନ ପରିଚାଳନା କରନ୍ତୁ"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"ଅନ୍ୟ ଏକ ଡିଭାଇସରୁ"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"ଏକ ଭିନ୍ନ ଡିଭାଇସ ବ୍ୟବହାର କରନ୍ତୁ"</string>
diff --git a/packages/CredentialManager/res/values-pa/strings.xml b/packages/CredentialManager/res/values-pa/strings.xml
index 7e4676a..98be412 100644
--- a/packages/CredentialManager/res/values-pa/strings.xml
+++ b/packages/CredentialManager/res/values-pa/strings.xml
@@ -16,12 +16,13 @@
     <string name="passwordless_technology_title" msgid="2497513482056606668">"ਪਾਸਵਰਡ ਰਹਿਤ ਤਕਨਾਲੋਜੀ"</string>
     <string name="passwordless_technology_detail" msgid="6853928846532955882">"ਪਾਸਕੀਆਂ ਤੁਹਾਨੂੰ ਪਾਸਵਰਡਾਂ \'ਤੇ ਭਰੋਸਾ ਕੀਤੇ ਬਿਨਾਂ ਸਾਈਨ-ਇਨ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦੀਆਂ ਹਨ। ਤੁਹਾਨੂੰ ਆਪਣੀ ਪਛਾਣ ਦੀ ਪੁਸ਼ਟੀ ਕਰਨ ਅਤੇ ਪਾਸਕੀ ਬਣਾਉਣ ਲਈ ਸਿਰਫ਼ ਆਪਣੇ ਫਿੰਗਰਪ੍ਰਿੰਟ, ਚਿਹਰਾ ਪਛਾਣ, ਪਿੰਨ ਜਾਂ ਸਵਾਈਪ ਪੈਟਰਨ ਦੀ ਵਰਤੋਂ ਕਰਨ ਦੀ ਲੋੜ ਹੈ।"</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"ਜਨਤਕ ਕੁੰਜੀ ਕ੍ਰਿਪਟੋਗ੍ਰਾਫ਼ੀ"</string>
-    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"FIDO ਗਠਜੋੜ (ਜਿਸ ਵਿੱਚ Google, Apple, Microsoft ਅਤੇ ਹੋਰ ਸ਼ਾਮਲ ਹਨ) ਅਤੇ W3C ਮਿਆਰਾਂ ਦੇ ਆਧਾਰ \'ਤੇ ਪਾਸਕੀਆਂ ਕ੍ਰਿਪਟੋਗ੍ਰਾਫ਼ਿਕ ਕੁੰਜੀਆਂ ਦੇ ਜੋੜੇ ਵਰਤਦੀਆਂ ਹਨ। ਪਾਸਵਰਡ ਲਈ ਵਰਤੇ ਜਾਂਦੇ ਵਰਤੋਂਕਾਰ ਨਾਮ ਅਤੇ ਅੱਖਰ-ਚਿੰਨ੍ਹਾਂ ਦੀ ਸਤਰ ਤੋਂ ਅਲੱਗ, ਐਪ ਜਾਂ ਵੈੱਬਸਾਈਟ ਲਈ ਨਿੱਜੀ-ਜਨਤਕ ਕੁੰਜੀ ਜੋੜਾ ਬਣਾਇਆ ਜਾਂਦਾ ਹੈ। ਨਿੱਜੀ ਕੁੰਜੀ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਜਾਂ ਪਾਸਵਰਡ ਪ੍ਰਬੰਧਕ \'ਤੇ ਸੁਰੱਖਿਅਤ ਢੰਗ ਨਾਲ ਸਟੋਰ ਕੀਤੀ ਜਾਂਦੀ ਹੈ ਅਤੇ ਇਹ ਤੁਹਾਡੀ ਪਛਾਣ ਦੀ ਪੁਸ਼ਟੀ ਕਰਦੀ ਹੈ। ਜਨਤਕ ਕੁੰਜੀ ਐਪ ਜਾਂ ਵੈੱਬਸਾਈਟ ਸਰਵਰ ਨਾਲ ਸਾਂਝੀ ਕੀਤੀ ਜਾਂਦੀ ਹੈ। ਸੰਬੰਧਿਤ ਕੁੰਜੀਆਂ ਨਾਲ, ਤੁਸੀਂ ਤੁਰੰਤ ਰਜਿਸਟਰ ਅਤੇ ਸਾਈਨ-ਇਨ ਕਰ ਸਕਦੇ ਹੋ।"</string>
+    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"FIDO ਗਠਜੋੜ (ਜਿਸ ਵਿੱਚ Google, Apple, Microsoft ਅਤੇ ਹੋਰ ਸ਼ਾਮਲ ਹਨ) ਅਤੇ W3C ਮਿਆਰਾਂ ਦੇ ਆਧਾਰ \'ਤੇ ਪਾਸਕੀਆਂ ਕ੍ਰਿਪਟੋਗ੍ਰਾਫ਼ਿਕ ਕੁੰਜੀਆਂ ਦੇ ਜੋੜੇ ਵਰਤਦੀਆਂ ਹਨ। ਪਾਸਵਰਡ ਲਈ ਵਰਤੀ ਜਾਂਦੀ ਅੱਖਰ-ਚਿੰਨ੍ਹਾਂ ਦੀ ਸਤਰ ਅਤੇ ਵਰਤੋਂਕਾਰ ਨਾਮ ਤੋਂ ਅਲੱਗ, ਐਪ ਜਾਂ ਵੈੱਬਸਾਈਟ ਲਈ ਨਿੱਜੀ-ਜਨਤਕ ਕੁੰਜੀ ਜੋੜਾ ਬਣਾਇਆ ਜਾਂਦਾ ਹੈ। ਨਿੱਜੀ ਕੁੰਜੀ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਜਾਂ ਪਾਸਵਰਡ ਪ੍ਰਬੰਧਕ \'ਤੇ ਸੁਰੱਖਿਅਤ ਢੰਗ ਨਾਲ ਸਟੋਰ ਕੀਤੀ ਜਾਂਦੀ ਹੈ ਅਤੇ ਤੁਹਾਡੀ ਪਛਾਣ ਦੀ ਪੁਸ਼ਟੀ ਕਰਦੀ ਹੈ। ਜਨਤਕ ਕੁੰਜੀ ਐਪ ਜਾਂ ਵੈੱਬਸਾਈਟ ਸਰਵਰ ਨਾਲ ਸਾਂਝੀ ਕੀਤੀ ਜਾਂਦੀ ਹੈ। ਸੰਬੰਧਿਤ ਕੁੰਜੀਆਂ ਨਾਲ, ਤੁਸੀਂ ਤੁਰੰਤ ਰਜਿਸਟਰ ਅਤੇ ਸਾਈਨ-ਇਨ ਕਰ ਸਕਦੇ ਹੋ।"</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>
-    <string name="choose_provider_title" msgid="8870795677024868108">"ਚੁਣੋ ਕਿ ਆਪਣੇ <xliff:g id="CREATETYPES">%1$s</xliff:g> ਨੂੰ ਕਿੱਥੇ ਰੱਖਿਅਤ ਕਰਨਾ ਹੈ"</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
+    <string name="choose_provider_title" msgid="8870795677024868108">"ਚੁਣੋ ਕਿ ਆਪਣੀਆਂ <xliff:g id="CREATETYPES">%1$s</xliff:g> ਨੂੰ ਕਿੱਥੇ ਰੱਖਿਅਤ ਕਰਨਾ ਹੈ"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"ਆਪਣੀ ਜਾਣਕਾਰੀ ਨੂੰ ਰੱਖਿਅਤ ਕਰਨ ਅਤੇ ਅਗਲੀ ਵਾਰ ਤੇਜ਼ੀ ਨਾਲ ਸਾਈਨ-ਇਨ ਕਰਨ ਲਈ ਪਾਸਵਰਡ ਪ੍ਰਬੰਧਕ ਚੁਣੋ"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"ਕੀ <xliff:g id="APPNAME">%1$s</xliff:g> ਲਈ ਪਾਸਕੀ ਬਣਾਉਣੀ ਹੈ?"</string>
     <string name="choose_create_option_password_title" msgid="7097275038523578687">"ਕੀ <xliff:g id="APPNAME">%1$s</xliff:g> ਲਈ ਪਾਸਵਰਡ ਰੱਖਿਅਤ ਕਰਨਾ ਹੈ?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> ਨੂੰ ਇੱਥੇ ਰੱਖਿਅਤ ਕਰੋ"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"ਕੀ ਕਿਸੇ ਹੋਰ ਡੀਵਾਈਸ ਨਾਲ ਪਾਸਕੀ ਬਣਾਉਣੀ ਹੈ?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"ਕੀ ਆਪਣੇ ਸਾਰੇ ਸਾਈਨ-ਇਨਾਂ ਲਈ<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰਨੀ ਹੈ?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"ਇਹ ਪਾਸਵਰਡ ਪ੍ਰਬੰਧਕ ਆਸਾਨੀ ਨਾਲ ਸਾਈਨ-ਇਨ ਕਰਨ ਵਿੱਚ ਤੁਹਾਡੀ ਮਦਦ ਕਰਨ ਲਈ ਤੁਹਾਡੇ ਪਾਸਵਰਡਾਂ ਅਤੇ ਪਾਸਕੀਆਂ ਨੂੰ ਸਟੋਰ ਕਰੇਗਾ"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਵਜੋਂ ਸੈੱਟ ਕਰੋ"</string>
     <string name="use_once" msgid="9027366575315399714">"ਇੱਕ ਵਾਰ ਵਰਤੋ"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> ਪਾਸਵਰਡ • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> ਪਾਸਕੀਆਂ"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"ਹੋਰ ਪਾਸਵਰਡ ਪ੍ਰਬੰਧਕ"</string>
     <string name="close_sheet" msgid="1393792015338908262">"ਸ਼ੀਟ ਬੰਦ ਕਰੋ"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ਪਿਛਲੇ ਪੰਨੇ \'ਤੇ ਵਾਪਸ ਜਾਓ"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"ਬੰਦ ਕਰੋ"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"ਖਾਰਜ ਕਰੋ"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"ਕੀ <xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਆਪਣੀ ਰੱਖਿਅਤ ਕੀਤੀ ਪਾਸਕੀ ਦੀ ਵਰਤੋਂ ਕਰਨੀ ਹੈ?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"ਕੀ <xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਆਪਣੀ ਰੱਖਿਅਤ ਕੀਤੀ ਸਾਈਨ-ਇਨ ਜਾਣਕਾਰੀ ਦੀ ਵਰਤੋਂ ਕਰਨੀ ਹੈ?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਰੱਖਿਅਤ ਕੀਤੀ ਸਾਈਨ-ਇਨ ਜਾਣਕਾਰੀ ਚੁਣੋ"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"ਲਾਕ ਕੀਤੇ ਪਾਸਵਰਡ ਪ੍ਰਬੰਧਕ"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"ਅਣਲਾਕ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"ਸਾਈਨ-ਇਨ ਜਾਣਕਾਰੀ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> ਵਿੱਚ ਕੋਈ ਸਾਈਨ-ਇਨ ਜਾਣਕਾਰੀ ਨਹੀਂ"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"ਸਾਈਨ-ਇਨਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"ਹੋਰ ਡੀਵਾਈਸ ਤੋਂ"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"ਵੱਖਰੇ ਡੀਵਾਈਸ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
diff --git a/packages/CredentialManager/res/values-pl/strings.xml b/packages/CredentialManager/res/values-pl/strings.xml
index c77d846..e3b3a8c 100644
--- a/packages/CredentialManager/res/values-pl/strings.xml
+++ b/packages/CredentialManager/res/values-pl/strings.xml
@@ -10,7 +10,7 @@
     <string name="content_description_hide_password" msgid="6841375971631767996">"Ukryj hasło"</string>
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Klucze zwiększają Twoje bezpieczeństwo"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Dzięki kluczom nie musisz tworzyć ani zapamiętywać skomplikowanych haseł"</string>
-    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Klucze są szyfrowanymi kluczami cyfrowymi, które tworzysz za pomocą funkcji rozpoznawania odcisku palca lub twarzy bądź blokady ekranu"</string>
+    <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Klucze są szyfrowanymi kluczami cyfrowymi, które tworzysz za pomocą blokady ekranu bądź funkcji rozpoznawania twarzy lub odcisku palca"</string>
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Klucze są zapisane w menedżerze haseł, dzięki czemu możesz logować się na innych urządzeniach"</string>
     <string name="more_about_passkeys_title" msgid="7797903098728837795">"Więcej informacji o kluczach"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Technologia niewymagająca haseł"</string>
@@ -20,7 +20,8 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Zwiększone bezpieczeństwo konta"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Każdy klucz jest połączony wyłącznie z aplikacją lub stroną, dla której został utworzony, więc nie zalogujesz się przypadkowo w fałszywej aplikacji ani na fałszywej stronie. Ponadto na serwerach są przechowywane wyłącznie klucze publiczne, co znacznie utrudnia hakowanie."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Płynne przechodzenie"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"W czasie przechodzenia na technologie niewymagające haseł możliwość stosowania haseł – niezależnie od kluczy – wciąż będzie dostępna."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Wybierz, gdzie zapisywać <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Wybierz menedżera haseł, aby zapisywać informacje i logować się szybciej"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Utworzyć klucz dla aplikacji <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -32,10 +33,11 @@
     <string name="passwords" msgid="5419394230391253816">"hasła"</string>
     <string name="sign_ins" msgid="4710739369149469208">"dane logowania"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"informacje dotyczące logowania"</string>
-    <string name="save_credential_to_title" msgid="3172811692275634301">"Zapisać: <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> w:"</string>
+    <string name="save_credential_to_title" msgid="3172811692275634301">"Zapisać <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> w:"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Utworzyć klucz na innym urządzeniu?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Używać usługi <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> w przypadku wszystkich danych logowania?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Menedżer haseł będzie zapisywał Twoje hasła i klucze, aby ułatwić Ci logowanie"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Ustaw jako domyślną"</string>
     <string name="use_once" msgid="9027366575315399714">"Użyj raz"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Hasła: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • Klucze: <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Inne menedżery haseł"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Zamknij arkusz"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Wróć do poprzedniej strony"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Zamknij"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Zamknij"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Użyć zapisanego klucza dla aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Użyć zapisanych danych logowania dla aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Wybierz zapisane dane logowania dla aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Zablokowane menedżery haseł"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Kliknij, aby odblokować"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Brak danych logowania"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>: brak danych logowania"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Zarządzanie danymi logowania"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Na innym urządzeniu"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Użyj innego urządzenia"</string>
diff --git a/packages/CredentialManager/res/values-pt-rBR/strings.xml b/packages/CredentialManager/res/values-pt-rBR/strings.xml
index 90433e1..289cdea 100644
--- a/packages/CredentialManager/res/values-pt-rBR/strings.xml
+++ b/packages/CredentialManager/res/values-pt-rBR/strings.xml
@@ -20,7 +20,8 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Mais segurança para sua conta"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Cada chave está vinculada exclusivamente ao app ou site para a qual foi criada. Isso impede que você faça login em um app ou site fraudulento por engano. Além disso, os servidores mantêm apenas chaves públicas, dificultando qualquer invasão."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Transição simplificada"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Estamos avançando em direção a um futuro sem senhas, mas elas ainda vão estar disponíveis junto às chaves de acesso."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Escolha onde salvar suas <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Selecione um gerenciador de senhas para salvar suas informações e fazer login mais rapidamente na próxima vez"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Criar uma chave de acesso para o app <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Salvar <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> em"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Criar chave de acesso em outro dispositivo?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Usar <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> para todos os seus logins?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Esse gerenciador de senhas vai armazenar suas senhas e chaves de acesso para facilitar o processo de login"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Definir como padrão"</string>
     <string name="use_once" msgid="9027366575315399714">"Usar uma vez"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> senhas • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> chaves de acesso"</string>
@@ -48,6 +50,7 @@
     <string name="close_sheet" msgid="1393792015338908262">"Fechar página"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Voltar à página anterior"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Fechar"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Dispensar"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Usar sua chave de acesso salva para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Usar suas informações de login salvas para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Escolher um login salvo para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-pt-rPT/strings.xml b/packages/CredentialManager/res/values-pt-rPT/strings.xml
index 1abc85d..9bf350c 100644
--- a/packages/CredentialManager/res/values-pt-rPT/strings.xml
+++ b/packages/CredentialManager/res/values-pt-rPT/strings.xml
@@ -20,22 +20,22 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Segurança melhorada nas contas"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Cada chave é exclusivamente associada à app ou ao Website para o qual foi criada, por isso, nunca pode iniciar sessão numa app ou num Website fraudulento acidentalmente. Além disso, os servidores só mantêm chaves públicas, o que dificulta a pirataria."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Transição sem complicações"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"À medida que avançamos para um futuro sem palavras-passe, as palavras-passe continuam disponíveis juntamente com as chaves de acesso."</string>
+    <string name="seamless_transition_detail" msgid="3440478759491650823">"À medida que avançamos para um futuro sem palavras-passe, as palavras-passe continuam disponíveis juntamente com as chaves de acesso"</string>
     <string name="choose_provider_title" msgid="8870795677024868108">"Escolha onde guardar as suas <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Selecione um gestor de palavras-passe para guardar as suas informações e iniciar sessão mais rapidamente da próxima vez"</string>
-    <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Criar uma token de acesso para a app <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
+    <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Criar uma chave de acesso para a app <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
     <string name="choose_create_option_password_title" msgid="7097275038523578687">"Guardar a palavra-passe da app <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Guardar as informações de início de sessão da app <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
-    <string name="passkey" msgid="632353688396759522">"token de acesso"</string>
+    <string name="passkey" msgid="632353688396759522">"chave de acesso"</string>
     <string name="password" msgid="6738570945182936667">"palavra-passe"</string>
     <string name="passkeys" msgid="5733880786866559847">"chaves de acesso"</string>
     <string name="passwords" msgid="5419394230391253816">"palavras-passe"</string>
     <string name="sign_ins" msgid="4710739369149469208">"inícios de sessão"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"informações de início de sessão"</string>
-    <string name="save_credential_to_title" msgid="3172811692275634301">"Guarde <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> em"</string>
+    <string name="save_credential_to_title" msgid="3172811692275634301">"Guardar <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> em:"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Criar token de acesso noutro dispositivo?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Usar <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> para todos os seus inícios de sessão?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Este gestor de palavras-passe armazena as suas palavras-passe e chaves de acesso para ajudar a iniciar sessão facilmente"</string>
+    <string name="use_provider_for_all_description" msgid="1998772715863958997">"Este gestor de palavras-passe de <xliff:g id="USERNAME">%1$s</xliff:g> armazena as suas palavras-passe e chaves de acesso para ajudar a iniciar sessão facilmente"</string>
     <string name="set_as_default" msgid="4415328591568654603">"Definir como predefinição"</string>
     <string name="use_once" msgid="9027366575315399714">"Usar uma vez"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> palavras-passe • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> chaves de acesso"</string>
@@ -48,7 +48,8 @@
     <string name="close_sheet" msgid="1393792015338908262">"Fechar folha"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Volte à página anterior"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Fechar"</string>
-    <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Usar a sua token de acesso guardada na app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Ignorar"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Usar a sua chave de acesso guardada na app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Usar o seu início de sessão guardado na app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Escolha um início de sessão guardado para a app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Iniciar sessão de outra forma"</string>
diff --git a/packages/CredentialManager/res/values-pt/strings.xml b/packages/CredentialManager/res/values-pt/strings.xml
index 90433e1..289cdea 100644
--- a/packages/CredentialManager/res/values-pt/strings.xml
+++ b/packages/CredentialManager/res/values-pt/strings.xml
@@ -20,7 +20,8 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Mais segurança para sua conta"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Cada chave está vinculada exclusivamente ao app ou site para a qual foi criada. Isso impede que você faça login em um app ou site fraudulento por engano. Além disso, os servidores mantêm apenas chaves públicas, dificultando qualquer invasão."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Transição simplificada"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Estamos avançando em direção a um futuro sem senhas, mas elas ainda vão estar disponíveis junto às chaves de acesso."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Escolha onde salvar suas <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Selecione um gerenciador de senhas para salvar suas informações e fazer login mais rapidamente na próxima vez"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Criar uma chave de acesso para o app <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Salvar <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> em"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Criar chave de acesso em outro dispositivo?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Usar <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> para todos os seus logins?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Esse gerenciador de senhas vai armazenar suas senhas e chaves de acesso para facilitar o processo de login"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Definir como padrão"</string>
     <string name="use_once" msgid="9027366575315399714">"Usar uma vez"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> senhas • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> chaves de acesso"</string>
@@ -48,6 +50,7 @@
     <string name="close_sheet" msgid="1393792015338908262">"Fechar página"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Voltar à página anterior"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Fechar"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Dispensar"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Usar sua chave de acesso salva para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Usar suas informações de login salvas para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Escolher um login salvo para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-ro/strings.xml b/packages/CredentialManager/res/values-ro/strings.xml
index 11b3b49..46147a3 100644
--- a/packages/CredentialManager/res/values-ro/strings.xml
+++ b/packages/CredentialManager/res/values-ro/strings.xml
@@ -14,19 +14,20 @@
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Acestea sunt salvate într-un manager de parole, ca să te poți conecta pe alte dispozitive"</string>
     <string name="more_about_passkeys_title" msgid="7797903098728837795">"Mai multe despre cheile de acces"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Tehnologie fără parole"</string>
-    <string name="passwordless_technology_detail" msgid="6853928846532955882">"Cu ajutorul cheilor de acces, poți să te conectezi fără să te bazezi pe parole. Pentru a-ți verifica identitatea și a crea o cheie de acces, nu trebuie decât să folosești amprenta, recunoașterea facială, PIN-ul sau modelul."</string>
+    <string name="passwordless_technology_detail" msgid="6853928846532955882">"Cu ajutorul cheilor de acces, poți să te conectezi fără să te bazezi pe parole. Pentru a-ți confirma identitatea și a crea o cheie de acces, nu trebuie decât să folosești amprenta, recunoașterea facială, PIN-ul sau modelul."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"Criptografia cheilor publice"</string>
     <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Conform standardelor FIDO Alliance (din care fac parte Google, Apple, Microsoft etc.) și W3C, cheile de acces folosesc perechi de chei criptografice. Spre deosebire de numele de utilizator și șirul de caractere pe care le folosim pentru parole, perechea de chei publică/privată este creată pentru o aplicație sau un site. Cheia privată este stocată în siguranță pe dispozitivul sau în managerul tău de parole și îți confirmă identitatea. Cheia publică este trimisă aplicației sau serverului site-ului. Cu ajutorul cheilor corespunzătoare, poți să te înregistrezi și să te conectezi instantaneu."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"Securitate îmbunătățită a contului"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Fiecare cheie este conectată în mod exclusiv cu aplicația sau site-ul pentru care a fost creată, prin urmare nu te poți conecta niciodată din greșeală la o aplicație sau un site fraudulos. În plus, întrucât pe servere sunt stocate doar chei publice, hackingul este mult mai dificil."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Tranziție fluidă"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Ne îndreptăm spre un viitor fără parole, în care parolele vor fi disponibile pe lângă cheile de acces."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Alege unde dorești să salvezi <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Selectează un manager de parole pentru a salva informațiile și a te conecta mai rapid data viitoare"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Creezi o cheie de acces pentru <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
     <string name="choose_create_option_password_title" msgid="7097275038523578687">"Salvezi parola pentru <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Salvezi informațiile de conectare pentru <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
-    <string name="passkey" msgid="632353688396759522">"cheie de acces"</string>
+    <string name="passkey" msgid="632353688396759522">"cheia de acces"</string>
     <string name="password" msgid="6738570945182936667">"parolă"</string>
     <string name="passkeys" msgid="5733880786866559847">"cheile de acces"</string>
     <string name="passwords" msgid="5419394230391253816">"parolele"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Salvează <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> în"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Creezi cheia de acces pe alt dispozitiv?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Folosești <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> pentru toate conectările?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Managerul de parole îți va stoca parolele și cheile de acces, pentru a te ajuta să te conectezi cu ușurință"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Setează ca prestabilite"</string>
     <string name="use_once" msgid="9027366575315399714">"Folosește o dată"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> parole • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> chei de acces"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Alți manageri de parole"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Închide foaia"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Revino la pagina precedentă"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Închide"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Închide"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Folosești cheia de acces salvată pentru <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Folosești datele de conectare salvate pentru <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Alege o conectare salvată pentru <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Manageri de parole blocate"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Atinge pentru a debloca"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Fără informații de conectare"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nu există informații de conectare în contul <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gestionează acreditările"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"De pe alt dispozitiv"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Folosește alt dispozitiv"</string>
diff --git a/packages/CredentialManager/res/values-ru/strings.xml b/packages/CredentialManager/res/values-ru/strings.xml
index c7d253e..a76f79a 100644
--- a/packages/CredentialManager/res/values-ru/strings.xml
+++ b/packages/CredentialManager/res/values-ru/strings.xml
@@ -4,7 +4,7 @@
     <string name="app_name" msgid="4539824758261855508">"Менеджер учетных данных"</string>
     <string name="string_cancel" msgid="6369133483981306063">"Отмена"</string>
     <string name="string_continue" msgid="1346732695941131882">"Продолжить"</string>
-    <string name="string_more_options" msgid="7990658711962795124">"Ещё"</string>
+    <string name="string_more_options" msgid="7990658711962795124">"Другие варианты"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Подробнее"</string>
     <string name="content_description_show_password" msgid="3283502010388521607">"Показать пароль"</string>
     <string name="content_description_hide_password" msgid="6841375971631767996">"Скрыть пароль"</string>
@@ -20,7 +20,8 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Укажите, куда нужно сохранить <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Выберите менеджер паролей, чтобы сохранять учетные данные и быстро выполнять вход."</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Создать ключ доступа для приложения \"<xliff:g id="APPNAME">%1$s</xliff:g>\"?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Сохранить <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> в"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Создать ключ доступа на другом устройстве?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Всегда входить с помощью приложения \"<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>\"?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"В этом менеджере паролей можно сохранять учетные данные, например ключи доступа, чтобы потом использовать их для быстрого входа."</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Использовать по умолчанию"</string>
     <string name="use_once" msgid="9027366575315399714">"Использовать один раз"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Пароли (<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g>) и ключи доступа (<xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>)"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Другие менеджеры паролей"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Закрыть лист"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Вернуться на предыдущую страницу"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Закрыть"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Закрыть"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Использовать сохраненный ключ доступа для приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Использовать сохраненные учетные данные для приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Выберите сохраненные данные для приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Заблокированные менеджеры паролей"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Нажмите для разблокировки"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Необходимо ввести учетные данные"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"В аккаунте <xliff:g id="SOURCE">%1$s</xliff:g> нет учетных данных"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Управление входом"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"С другого устройства"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Использовать другое устройство"</string>
diff --git a/packages/CredentialManager/res/values-si/strings.xml b/packages/CredentialManager/res/values-si/strings.xml
index 36ce3f8..9b7337b 100644
--- a/packages/CredentialManager/res/values-si/strings.xml
+++ b/packages/CredentialManager/res/values-si/strings.xml
@@ -20,7 +20,8 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"ඔබේ <xliff:g id="CREATETYPES">%1$s</xliff:g> සුරැකිය යුතු ස්ථානය තෝරා ගන්න"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"ඔබේ තතු සුරැකීමට සහ මීළඟ වතාවේ වේගයෙන් පුරනය වීමට මුරපද කළමනාකරුවෙකු තෝරන්න"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> සඳහා මුරයතුර තනන්න ද?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"වෙත <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> සුරකින්න"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"වෙනත් උපාංගයක මුරයතුර තනන්න ද?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"ඔබේ සියලු පුරනය වීම් සඳහා <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> භාවිතා කරන්න ද?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"මෙම මුරපද කළමනාකරු ඔබට පහසුවෙන් පුරනය වීමට උදවු කිරීම සඳහා ඔබේ මුරපද සහ මුරයතුරු ගබඩා කරනු ඇත"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"පෙරනිමි ලෙස සකසන්න"</string>
     <string name="use_once" msgid="9027366575315399714">"වරක් භාවිතා කරන්න"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"මුරපද <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g>ක් • මුරයතුරු <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>ක්"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"වෙනත් මුරපද කළමනාකරුවන්"</string>
     <string name="close_sheet" msgid="1393792015338908262">"පත්‍රය වසන්න"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"පෙර පිටුවට ආපසු යන්න"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"වසන්න"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"අස් කරන්න"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා ඔබේ සුරැකි මුරයතුර භාවිතා කරන්න ද?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා ඔබේ සුරැකි පුරනය භාවිතා කරන්න ද?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා සුරැකි පුරනයක් තෝරා ගන්න"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"අගුළු දැමූ මුරපද කළමනාකරුවන්"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"අගුළු හැරීමට තට්ටු කරන්න"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"පුරනය වීමේ තතු නැත"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> තුළ පුරනය වීමේ තතු නැත"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"පුරනය වීම් කළමනාකරණය කරන්න"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"වෙනත් උපාංගයකින්"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"වෙනස් උපාංගයක් භාවිතා කරන්න"</string>
diff --git a/packages/CredentialManager/res/values-sk/strings.xml b/packages/CredentialManager/res/values-sk/strings.xml
index 09bf265..8d33eab 100644
--- a/packages/CredentialManager/res/values-sk/strings.xml
+++ b/packages/CredentialManager/res/values-sk/strings.xml
@@ -14,13 +14,14 @@
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Ukladajú sa do správcu hesiel, aby ste sa mohli prihlasovať v iných zariadeniach"</string>
     <string name="more_about_passkeys_title" msgid="7797903098728837795">"Viac o prístupových kľúčoch"</string>
     <string name="passwordless_technology_title" msgid="2497513482056606668">"Technológia bez hesiel"</string>
-    <string name="passwordless_technology_detail" msgid="6853928846532955882">"Prístupový kľúče vám umožňujú prihlásiť sa bez využitia hesiel. Stačí overiť totožnosť odtlačkom prsta, rozpoznávaním tváre, kódom PIN alebo vzorom potiahnutia a vytvoriť prístupový kľúč."</string>
+    <string name="passwordless_technology_detail" msgid="6853928846532955882">"Prístupové kľúče vám umožňujú prihlásiť sa bez použitia hesiel. Stačí overiť totožnosť odtlačkom prsta, rozpoznávaním tváre, kódom PIN alebo vzorom potiahnutia a vytvoriť prístupový kľúč."</string>
     <string name="public_key_cryptography_title" msgid="6751970819265298039">"Kryptografia verejných kľúčov"</string>
     <string name="public_key_cryptography_detail" msgid="6937631710280562213">"Prístup. kľúče firiem patriacich do združenia FIDO (zahŕňajúceho Google, Apple, Microsoft a ďalšie) využívajú páry kryptograf. kľúčov a štandardy W3C. Na rozdiel od použív. mena a reťazca znakov využívaných v prípade hesiel sa pár súkr. a verej. kľúča vytvára pre aplikáciu alebo web. Súkr. kľúč sa bezpečne ukladá v zar. či správcovi hesiel a slúži na overenie totožnosti. Verej. kľúč sa zdieľa so serverom danej aplik. alebo webu. Príslušnými kľúčami sa môžete okamžite registrovať a prihlasovať."</string>
     <string name="improved_account_security_title" msgid="1069841917893513424">"Lepšie zabezpečenie účtu"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Každý kľúč je výhradne prepojený s aplikáciou alebo webom, pre ktorý bol vytvorený, takže sa nikdy nemôžete omylom prihlásiť do podvodnej aplikácie alebo na podvodnom webe. Servery navyše uchovávajú iba verejné kľúče, čím podstatne sťažujú hackovanie."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Plynulý prechod"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Blížime sa k budúcnosti bez hesiel, ale heslá budú popri prístupových kľúčoch stále k dispozícii."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Vyberte, kam sa majú ukladať <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Vyberte správcu hesiel, do ktorého sa budú ukladať vaše údaje, aby ste sa nabudúce mohli rýchlejšie prihlásiť"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Chcete vytvoriť prístupový kľúč pre aplikáciu <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Uložiť <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> do"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Chcete vytvoriť prístupový kľúč v inom zariadení?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Chcete pre všetky svoje prihlasovacie údaje použiť <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Tento správca hesiel uchová vaše heslá a prístupové kľúče, aby vám pomohol ľahšie sa prihlasovať"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Nastaviť ako predvolené"</string>
     <string name="use_once" msgid="9027366575315399714">"Použiť raz"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Počet hesiel: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • Počet prístupových kľúčov: <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
@@ -47,12 +49,12 @@
     <string name="other_password_manager" msgid="565790221427004141">"Iní správcovia hesiel"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Zavrieť hárok"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Prejsť späť na predchádzajúcu stránku"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Zavrieť"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Zavrieť"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Chcete pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g> použiť uložený prístupový kľúč?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Chcete pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g> použiť uložené prihlasovacie údaje?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Vyberte uložené prihlasovacie údaje pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Prihláste sa inak"</string>
+    <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Prihlásiť sa inak"</string>
     <string name="snackbar_action" msgid="37373514216505085">"Zobraziť možnosti"</string>
     <string name="get_dialog_button_label_continue" msgid="6446201694794283870">"Pokračovať"</string>
     <string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Možnosti prihlásenia"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Správcovia uzamknutých hesiel"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Odomknúť klepnutím"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Žiadne prihlasovacie údaje"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Žiadne prihlasovacie údaje v zdroji <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Spravovať prihlasovacie údaje"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Z iného zariadenia"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Použiť iné zariadenie"</string>
diff --git a/packages/CredentialManager/res/values-sl/strings.xml b/packages/CredentialManager/res/values-sl/strings.xml
index 29b6410..666e046 100644
--- a/packages/CredentialManager/res/values-sl/strings.xml
+++ b/packages/CredentialManager/res/values-sl/strings.xml
@@ -20,7 +20,8 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Večja varnost računov"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Vsak ključ je neločljivo povezan z aplikacijo ali spletnim mestom, za katero je bil ustvarjen, zato se nikoli ne morete pomotoma prijaviti v goljufivo aplikacijo ali spletno mesto. Poleg tega so v strežnikih shranjeni le javni ključi, zato je vdiranje v račune precej oteženo."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Prehod brez zapletov"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Na poti v prihodnost brez gesel bodo poleg ključev za dostop še vedno v uporabi tudi gesla."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Izbira mesta za shranjevanje <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Izberite upravitelja gesel za shranjevanje podatkov za prijavo, da se boste naslednjič lahko hitreje prijavili."</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Želite ustvariti ključ za dostop do aplikacije <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -32,10 +33,11 @@
     <string name="passwords" msgid="5419394230391253816">"gesel"</string>
     <string name="sign_ins" msgid="4710739369149469208">"prijave"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"podatkov za prijavo"</string>
-    <string name="save_credential_to_title" msgid="3172811692275634301">"Mesto shranjevanja <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>"</string>
+    <string name="save_credential_to_title" msgid="3172811692275634301">"Mesto shranjevanja: <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Želite ustvariti ključ za dostop v drugi napravi?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Želite za vse prijave uporabiti »<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>«?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"V tem upravitelju gesel bodo shranjeni gesla in ključi za dostop, kar vam bo olajšalo prijavo."</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Nastavi kot privzeto"</string>
     <string name="use_once" msgid="9027366575315399714">"Uporabi enkrat"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Št. gesel: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • Št. ključev za dostop: <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
@@ -48,6 +50,7 @@
     <string name="close_sheet" msgid="1393792015338908262">"Zapri list"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Nazaj na prejšnjo stran"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Zapri"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Opusti"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Želite uporabiti shranjeni ključ za dostop do aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Želite uporabiti shranjene podatke za prijavo v aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Izberite shranjene podatke za prijavo v aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-sq/strings.xml b/packages/CredentialManager/res/values-sq/strings.xml
index 6650668..83a4f61 100644
--- a/packages/CredentialManager/res/values-sq/strings.xml
+++ b/packages/CredentialManager/res/values-sq/strings.xml
@@ -20,22 +20,24 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Siguri e përmirësuar e llogarisë"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Secili çelës është i lidhur ekskluzivisht me aplikacionin ose sajtin e uebit për të cilin është krijuar, kështu që nuk do të identifikohesh asnjëherë gabimisht në një aplikacion ose sajt uebi mashtrues. Gjithashtu, me serverët që mbajnë vetëm çelësa publikë, pirateria informatike është shumë më e vështirë."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Kalim i thjeshtuar"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Teksa shkojmë drejt një të ardhmeje pa fjalëkalime, këto të fundit do të ofrohen ende së bashku me çelësat e kalimit."</string>
-    <string name="choose_provider_title" msgid="8870795677024868108">"Zgjidh se ku të ruash <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
+    <string name="choose_provider_title" msgid="8870795677024868108">"Zgjidh se ku t\'i ruash <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Zgjidh një menaxher fjalëkalimesh për të ruajtur informacionet e tua dhe për t\'u identifikuar më shpejt herën tjetër"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Të krijohet çelësi i kalimit për <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
     <string name="choose_create_option_password_title" msgid="7097275038523578687">"Të ruhet fjalëkalimi për <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Të ruhen informacionet e identifikimit për <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
-    <string name="passkey" msgid="632353688396759522">"çelësi i kalimit"</string>
+    <string name="passkey" msgid="632353688396759522">"çelësin e kalimit"</string>
     <string name="password" msgid="6738570945182936667">"fjalëkalimi"</string>
-    <string name="passkeys" msgid="5733880786866559847">"çelësa kalimi"</string>
+    <string name="passkeys" msgid="5733880786866559847">"çelësat e kalimit"</string>
     <string name="passwords" msgid="5419394230391253816">"fjalëkalime"</string>
     <string name="sign_ins" msgid="4710739369149469208">"identifikimet"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"informacionet e identifikimit"</string>
     <string name="save_credential_to_title" msgid="3172811692275634301">"Ruaj <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> te"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Të krijohet çelës kalimi në një pajisje tjetër?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Të përdoret <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> për të gjitha identifikimet?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Ky menaxher i fjalëkalimeve do të ruajë fjalëkalimet dhe çelësat e kalimit për të të ndihmuar të identifikohesh me lehtësi"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Cakto si parazgjedhje"</string>
     <string name="use_once" msgid="9027366575315399714">"Përdor një herë"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> fjalëkalime • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> çelësa kalimi"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Menaxherët e tjerë të fjalëkalimeve"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Mbyll fletën"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Kthehu te faqja e mëparshme"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Mbyll"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Hiq"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Të përdoret fjalëkalimi yt i ruajtur për <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Të përdoret identifikimi yt i ruajtur për <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Zgjidh një identifikim të ruajtur për <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Menaxherët e fjalëkalimeve të kyçura"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Trokit për të shkyçur"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nuk ka informacione për identifikimin"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nuk ka informacione regjistrimi në <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Identifikimet e menaxhimit"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Nga një pajisje tjetër"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Përdor një pajisje tjetër"</string>
diff --git a/packages/CredentialManager/res/values-sr/strings.xml b/packages/CredentialManager/res/values-sr/strings.xml
index 877d45c..aa7ae11 100644
--- a/packages/CredentialManager/res/values-sr/strings.xml
+++ b/packages/CredentialManager/res/values-sr/strings.xml
@@ -20,7 +20,8 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Одаберите где ћете сачувати ставке <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Изаберите менаџера лозинки да бисте сачували податке и брже се пријавили следећи пут"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Желите да направите приступни кôд за: <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -32,10 +33,11 @@
     <string name="passwords" msgid="5419394230391253816">"лозинке"</string>
     <string name="sign_ins" msgid="4710739369149469208">"пријављивања"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"подаци за пријављивање"</string>
-    <string name="save_credential_to_title" msgid="3172811692275634301">"Сачувајте ставку<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> у"</string>
+    <string name="save_credential_to_title" msgid="3172811692275634301">"Сачувај ставку <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> у"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Желите да направите приступни кôд на другом уређају?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Желите да за сва пријављивања користите: <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Овај менаџер лозинки ће чувати лозинке и приступне кодове да бисте се лако пријављивали"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Подеси као подразумевано"</string>
     <string name="use_once" msgid="9027366575315399714">"Користи једном"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Лозинки: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • Приступних кодова:<xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Други менаџери лозинки"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Затворите табелу"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Вратите се на претходну страницу"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Затворите"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Одбаци"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Желите да користите сачувани приступни кôд за: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Желите да користите сачуване податке за пријављивање за: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Одаберите сачувано пријављивање за: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Менаџери закључаних лозинки"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Додирните да бисте откључали"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Нема података за пријављивање"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Нема података за пријављивање у: <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Управљајте пријављивањима"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Са другог уређаја"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Користи други уређај"</string>
diff --git a/packages/CredentialManager/res/values-sv/strings.xml b/packages/CredentialManager/res/values-sv/strings.xml
index 9ec317e..89fa783 100644
--- a/packages/CredentialManager/res/values-sv/strings.xml
+++ b/packages/CredentialManager/res/values-sv/strings.xml
@@ -9,7 +9,7 @@
     <string name="content_description_show_password" msgid="3283502010388521607">"Visa lösenord"</string>
     <string name="content_description_hide_password" msgid="6841375971631767996">"Dölj lösenord"</string>
     <string name="passkey_creation_intro_title" msgid="4251037543787718844">"Säkrare med nycklar"</string>
-    <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Med nycklar behöver du inte skapa eller komma ihop invecklade lösenord"</string>
+    <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Med nycklar behöver du inte skapa eller komma ihåg invecklade lösenord"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Nycklar är krypterade digitala nycklar som du skapar med ditt fingeravtryck, ansikte eller skärmlås"</string>
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"De sparas i lösenordshanteraren så att du kan logga in på andra enheter"</string>
     <string name="more_about_passkeys_title" msgid="7797903098728837795">"Mer om nycklar"</string>
@@ -20,7 +20,8 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Förbättrad kontosäkerhet"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Varje nyckel är exklusivt länkad till appen eller webbplatsen den skapades för, så du kan aldrig logga in i en bedräglig app eller webbplats av misstag. Hackning blir dessutom mycket svårare eftersom servrar bara behåller offentliga nycklar."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"En sömlös övergång"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Medan vi beger oss mot en lösenordslös framtid kommer lösenord fortfarande att vara tillgängliga utöver nycklar."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Välj var du vill spara <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Välj en lösenordshanterare för att spara dina uppgifter och logga in snabbare nästa gång"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Vill du skapa en nyckel för <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Spara <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> i"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Vill du skapa en nyckel på en annan enhet?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Vill du använda <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> för alla dina inloggningar?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Den här lösenordshanteraren sparar dina lösenord och nycklar för att underlätta inloggning"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Ange som standard"</string>
     <string name="use_once" msgid="9027366575315399714">"Använd en gång"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> lösenord • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> nycklar"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Andra lösenordshanterare"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Stäng kalkylarket"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Gå tillbaka till föregående sida"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Stäng"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Stäng"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Vill du använda din sparade nyckel för <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Vill du använda dina sparade inloggningsuppgifter för <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Välj en sparad inloggning för <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Låsta lösenordshanterare"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tryck för att låsa upp"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ingen inloggningsinformation"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Det finns inga inloggningsuppgifter i <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Hantera inloggningar"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Via en annan enhet"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Använd en annan enhet"</string>
diff --git a/packages/CredentialManager/res/values-sw/strings.xml b/packages/CredentialManager/res/values-sw/strings.xml
index 1a5499c..e0cab52 100644
--- a/packages/CredentialManager/res/values-sw/strings.xml
+++ b/packages/CredentialManager/res/values-sw/strings.xml
@@ -20,7 +20,8 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Ulinzi wa akaunti ulioboreshwa"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Kila ufunguo umeunganishwa kwa upekee na programu au tovuti husika, kwa hivyo kamwe huwezi kuingia katika akaunti ya programu au tovuti ya kilaghai kwa bahati mbaya. Pia, kwa kuwa seva huhifadhi tu funguo za umma, udukuzi si rahisi."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Mabadiliko rahisi"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Tunavyoelekea katika enzi isiyo ya manenosiri, manenosiri yataendelea kupatikana pamoja na funguo za siri."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Chagua ambako unahifadhi <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Chagua kidhibiti cha manenosiri ili uhifadhi taarifa zako na uingie kwenye akaunti kwa urahisi wakati mwingine"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Ungependa kuunda ufunguo wa siri kwa ajili ya <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Hifadhi <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> kwenye"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Ungependa kuunda ufunguo wa siri kwenye kifaa kingine?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Ungependa kutumia <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> kwa ajili ya michakato yako yote ya kuingia katika akaunti?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Kidhibiti hiki cha manenosiri kitahifadhi manenosiri na funguo zako za siri ili kukusaidia uingie katika akaunti kwa urahisi"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Weka iwe chaguomsingi"</string>
     <string name="use_once" msgid="9027366575315399714">"Tumia mara moja"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Manenosiri <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • funguo <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> za siri"</string>
@@ -47,9 +49,9 @@
     <string name="other_password_manager" msgid="565790221427004141">"Vidhibiti vinginevyo vya manenosiri"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Funga laha"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Rudi kwenye ukurasa uliotangulia"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
-    <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Ungependa kutumia ufunguo wa siri uliohifadhiwa wa<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Funga"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Ondoa"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Ungependa kutumia ufunguo wa siri uliohifadhiwa wa <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Ungependa kutumia kitambulisho kilichohifadhiwa cha kuingia katika akaunti ya <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Chagua vitambulisho vilivyohifadhiwa kwa ajili ya kuingia katika akaunti ya <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Ingia katika akaunti kwa kutumia njia nyingine"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Vidhibiti vya manenosiri vilivyofungwa"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Gusa ili ufungue"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Hakuna maelezo ya kuingia katika akaunti"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Hakuna maelezo ya kuingia katika akaunti kwenye <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Dhibiti michakato ya kuingia katika akaunti"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Kutoka kwenye kifaa kingine"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Tumia kifaa tofauti"</string>
diff --git a/packages/CredentialManager/res/values-ta/strings.xml b/packages/CredentialManager/res/values-ta/strings.xml
index 19a871f..b340c2e 100644
--- a/packages/CredentialManager/res/values-ta/strings.xml
+++ b/packages/CredentialManager/res/values-ta/strings.xml
@@ -20,13 +20,14 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"உங்கள் <xliff:g id="CREATETYPES">%1$s</xliff:g> எங்கே சேமிக்கப்பட வேண்டும் என்பதைத் தேர்வுசெய்யுங்கள்"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"உங்கள் தகவல்களைச் சேமித்து அடுத்த முறை விரைவாக உள்நுழைய ஒரு கடவுச்சொல் நிர்வாகியைத் தேர்வுசெய்யுங்கள்"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> ஆப்ஸுக்கான கடவுச்சாவியை உருவாக்கவா?"</string>
     <string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> ஆப்ஸுக்கான கடவுச்சொல்லைச் சேமிக்கவா?"</string>
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> ஆப்ஸுக்கான உள்நுழைவு விவரங்களைச் சேமிக்கவா?"</string>
-    <string name="passkey" msgid="632353688396759522">"கடவுக்குறியீடு"</string>
+    <string name="passkey" msgid="632353688396759522">"கடவுச்சாவி"</string>
     <string name="password" msgid="6738570945182936667">"கடவுச்சொல்"</string>
     <string name="passkeys" msgid="5733880786866559847">"கடவுச்சாவிகள்"</string>
     <string name="passwords" msgid="5419394230391253816">"கடவுச்சொற்கள்"</string>
@@ -35,20 +36,21 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> ஐ இதில் சேமியுங்கள்"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"வேறொரு சாதனத்தில் கடவுச்சாவியை உருவாக்க வேண்டுமா?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"உங்கள் அனைத்து உள்நுழைவுகளுக்கும் <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>ஐப் பயன்படுத்தவா?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"இந்தக் கடவுச்சொல் நிர்வாகி உங்கள் கடவுச்சொற்களையும் கடவுச்சாவிகளையும் சேமித்து நீங்கள் எளிதாக உள்நுழைய உதவும்"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"இயல்பானதாக அமை"</string>
     <string name="use_once" msgid="9027366575315399714">"ஒருமுறை பயன்படுத்தவும்"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> கடவுச்சொற்கள் • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> கடவுச்சாவிகள்"</string>
     <string name="more_options_usage_passwords" msgid="1632047277723187813">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> கடவுச்சொற்கள்"</string>
     <string name="more_options_usage_passkeys" msgid="5390320437243042237">"<xliff:g id="PASSKEYSNUMBER">%1$s</xliff:g> கடவுக்குறியீடுகள்"</string>
     <string name="more_options_usage_credentials" msgid="1785697001787193984">"<xliff:g id="TOTALCREDENTIALSNUMBER">%1$s</xliff:g> அனுமதிச் சான்றுகள்"</string>
-    <string name="passkey_before_subtitle" msgid="2448119456208647444">"கடவுக்குறியீடு"</string>
+    <string name="passkey_before_subtitle" msgid="2448119456208647444">"கடவுச்சாவி"</string>
     <string name="another_device" msgid="5147276802037801217">"மற்றொரு சாதனம்"</string>
     <string name="other_password_manager" msgid="565790221427004141">"பிற கடவுச்சொல் நிர்வாகிகள்"</string>
     <string name="close_sheet" msgid="1393792015338908262">"ஷீட்டை மூடும்"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"முந்தைய பக்கத்திற்குச் செல்லும்"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"மூடும்"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"நிராகரிக்கும்"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கு ஏற்கெனவே சேமிக்கப்பட்ட கடவுக்குறியீட்டைப் பயன்படுத்தவா?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கு ஏற்கெனவே சேமிக்கப்பட்ட உள்நுழைவுத் தகவலைப் பயன்படுத்தவா?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கு ஏற்கெனவே சேமிக்கப்பட்ட உள்நுழைவுத் தகவலைத் தேர்வுசெய்யவும்"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"பூட்டப்பட்ட கடவுச்சொல் நிர்வாகிகள்"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"அன்லாக் செய்ய தட்டவும்"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"உள்நுழைவு விவரங்கள் இல்லை"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> கணக்கில் உள்நுழைவு விவரங்கள் இல்லை"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"உள்நுழைவுகளை நிர்வகித்தல்"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"மற்றொரு சாதனத்திலிருந்து பயன்படுத்து"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"வேறு சாதனத்தைப் பயன்படுத்து"</string>
diff --git a/packages/CredentialManager/res/values-te/strings.xml b/packages/CredentialManager/res/values-te/strings.xml
index 04ee0fe..3b9c57f 100644
--- a/packages/CredentialManager/res/values-te/strings.xml
+++ b/packages/CredentialManager/res/values-te/strings.xml
@@ -8,7 +8,7 @@
     <string name="string_learn_more" msgid="4541600451688392447">"మరింత తెలుసుకోండి"</string>
     <string name="content_description_show_password" msgid="3283502010388521607">"పాస్‌వర్డ్‌ను చూపండి"</string>
     <string name="content_description_hide_password" msgid="6841375971631767996">"పాస్‌వర్డ్‌ను చూపవద్దు"</string>
-    <string name="passkey_creation_intro_title" msgid="4251037543787718844">"పాస్-కీలతో సురక్షితంగా చెల్లించవచ్చు"</string>
+    <string name="passkey_creation_intro_title" msgid="4251037543787718844">"పాస్-కీలతో సురక్షితంగా పేమెంట్ చేయవచ్చు"</string>
     <string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"పాస్-కీలతో, మీరు క్లిష్టమైన పాస్‌వర్డ్‌లను క్రియేట్ చేయనవసరం లేదు లేదా గుర్తుంచుకోనవసరం లేదు"</string>
     <string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"పాస్-కీలు అనేవి మీ వేలిముద్రను, ముఖాన్ని లేదా స్క్రీన్ లాక్‌ను ఉపయోగించి మీరు క్రియేట్ చేసే ఎన్‌క్రిప్ట్ చేసిన డిజిటల్ కీలు"</string>
     <string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"అవి Password Managerకు సేవ్ చేయబడతాయి, తద్వారా మీరు ఇతర పరికరాలలో సైన్ ఇన్ చేయవచ్చు"</string>
@@ -16,14 +16,15 @@
     <string name="passwordless_technology_title" msgid="2497513482056606668">"పాస్‌వర్డ్ రహిత టెక్నాలజీ"</string>
     <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="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_detail" msgid="9123750251551844860">"ప్రతి కీ దానిని క్రియేట్ చేసిన యాప్ లేదా వెబ్‌సైట్‌తో ప్రత్యేకంగా లింక్ చేయబడి ఉంటుంది, కాబట్టి మీరు పొరపాటున కూడా మోసపూరిత యాప్ లేదా వెబ్‌సైట్‌కు సైన్ ఇన్ చేయలేరు. అంతే కాకుండా, సర్వర్‌లు పబ్లిక్ కీలను మాత్రమే స్టోర్ చేయడం వల్ల, హ్యాకింగ్ చేయడం చాలా కష్టం."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"అవాంతరాలు లేని పరివర్తన"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"మనం భవిష్యత్తులో పాస్‌వర్డ్ రహిత టెక్నాలజీని ఉపయోగించినా, పాస్‌కీలతో పాటు పాస్‌వర్డ్‌లు కూడా అందుబాటులో ఉంటాయి."</string>
-    <string name="choose_provider_title" msgid="8870795677024868108">"మీ <xliff:g id="CREATETYPES">%1$s</xliff:g>ని ఎక్కడ సేవ్ చేయాలో ఎంచుకోండి"</string>
-    <string name="choose_provider_body" msgid="4967074531845147434">"మీ సమాచారాన్ని సేవ్ చేయడం కోసం ఒక Password Managerను ఎంచుకొని, తర్వాతసారి వేగంగా సైన్ ఇన్ చేయండి"</string>
-    <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> కోసం పాస్‌కీని క్రియేట్ చేయాలా?"</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
+    <string name="choose_provider_title" msgid="8870795677024868108">"మీ <xliff:g id="CREATETYPES">%1$s</xliff:g> ఎక్కడ సేవ్ చేయాలో ఎంచుకోండి"</string>
+    <string name="choose_provider_body" msgid="4967074531845147434">"మీ సమాచారాన్ని సేవ్ చేయడం కోసం ఒక Password Managerను ఎంచుకొని, తర్వాతిసారి వేగంగా సైన్ ఇన్ చేయండి"</string>
+    <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> కోసం పాస్‌-కీని క్రియేట్ చేయాలా?"</string>
     <string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> కోసం పాస్‌వర్డ్‌ను సేవ్ చేయాలా?"</string>
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> కోసం సైన్ ఇన్ సమాచారాన్ని సేవ్ చేయాలా?"</string>
     <string name="passkey" msgid="632353688396759522">"పాస్-కీ"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>‌లో సేవ్ చేయండి"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"మరొక పరికరంలో పాస్‌కీని క్రియేట్ చేయాలా?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"మీ అన్ని సైన్-ఇన్ వివరాల కోసం <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>ను ఉపయోగించాలా?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"మీరు సులభంగా సైన్ ఇన్ చేయడంలో సహాయపడటానికి ఈ పాస్‌వర్డ్ మేనేజర్ మీ పాస్‌వర్డ్‌లు, పాస్-కీలను స్టోర్ చేస్తుంది"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"ఆటోమేటిక్ సెట్టింగ్‌గా సెట్ చేయండి"</string>
     <string name="use_once" msgid="9027366575315399714">"ఒకసారి ఉపయోగించండి"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> పాస్‌వర్డ్‌లు • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> పాస్-కీలు"</string>
@@ -48,7 +50,8 @@
     <string name="close_sheet" msgid="1393792015338908262">"షీట్‌ను మూసివేయండి"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"మునుపటి పేజీకి తిరిగి వెళ్లండి"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"మూసివేస్తుంది"</string>
-    <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం మీ సేవ్ చేసిన పాస్-కీ వివరాలను ఉపయోగించాలా?"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"విస్మరించండి"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం మీ సేవ్ చేసిన పాస్-కీని ఉపయోగించాలా?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం మీరు సేవ్ చేసిన సైన్ ఇన్ వివరాలను ఉపయోగించాలా?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం సేవ్ చేసిన సైన్ ఇన్ వివరాలను ఎంచుకోండి"</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"మరొక పద్ధతిలో సైన్ ఇన్ చేయండి"</string>
diff --git a/packages/CredentialManager/res/values-th/strings.xml b/packages/CredentialManager/res/values-th/strings.xml
index 29e87a0..bc20001 100644
--- a/packages/CredentialManager/res/values-th/strings.xml
+++ b/packages/CredentialManager/res/values-th/strings.xml
@@ -20,7 +20,8 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"เลือกว่าต้องการบันทึก<xliff:g id="CREATETYPES">%1$s</xliff:g>ไว้ที่ใด"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"เลือกเครื่องมือจัดการรหัสผ่านเพื่อบันทึกข้อมูลและลงชื่อเข้าใช้เร็วขึ้นในครั้งถัดไป"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"สร้างพาสคีย์สำหรับ <xliff:g id="APPNAME">%1$s</xliff:g> ไหม"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"บันทึก<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>ไปยัง"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"สร้างพาสคีย์ในอุปกรณ์อื่นไหม"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"ใช้ <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> สำหรับการลงชื่อเข้าใช้ทั้งหมดใช่ไหม"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"เครื่องมือจัดการรหัสผ่านนี้จะจัดเก็บรหัสผ่านและพาสคีย์ไว้เพื่อช่วยให้คุณลงชื่อเข้าใช้ได้โดยง่าย"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"ตั้งเป็นค่าเริ่มต้น"</string>
     <string name="use_once" msgid="9027366575315399714">"ใช้ครั้งเดียว"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"รหัสผ่าน <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> รายการ • พาสคีย์ <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> รายการ"</string>
@@ -47,9 +49,9 @@
     <string name="other_password_manager" msgid="565790221427004141">"เครื่องมือจัดการรหัสผ่านอื่นๆ"</string>
     <string name="close_sheet" msgid="1393792015338908262">"ปิดชีต"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"กลับไปยังหน้าก่อนหน้า"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
-    <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"ใช้พาสคีย์ที่บันทึกไว้สำหรับ \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" ใช่ไหม"</string>
+    <string name="accessibility_close_button" msgid="1163435587545377687">"ปิด"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"ปิด"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"ใช้พาสคีย์ที่บันทึกไว้สำหรับ <xliff:g id="APP_NAME">%1$s</xliff:g> ใช่ไหม"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"ใช้การลงชื่อเข้าใช้ที่บันทึกไว้สำหรับ \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" ใช่ไหม"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"เลือกการลงชื่อเข้าใช้ที่บันทึกไว้สำหรับ \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"ลงชื่อเข้าใช้ด้วยวิธีอื่น"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"เครื่องมือจัดการรหัสผ่านที่ล็อกไว้"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"แตะเพื่อปลดล็อก"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"ไม่มีข้อมูลการลงชื่อเข้าใช้"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"ไม่มีข้อมูลการลงชื่อเข้าใช้ใน <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"จัดการการลงชื่อเข้าใช้"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"จากอุปกรณ์อื่น"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"ใช้อุปกรณ์อื่น"</string>
diff --git a/packages/CredentialManager/res/values-tl/strings.xml b/packages/CredentialManager/res/values-tl/strings.xml
index 773039f..f4814bc 100644
--- a/packages/CredentialManager/res/values-tl/strings.xml
+++ b/packages/CredentialManager/res/values-tl/strings.xml
@@ -20,9 +20,10 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Pinahusay na seguridad sa account"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Eksklusibong naka-link sa app o website kung para saan ginawa ang bawat key, kaya hindi ka makakapag-sign in sa isang mapanlokong app o website nang hindi sinasadya. Bukod pa rito, dahil mga pampublikong key lang ang itinatabi ng mga server, lubos na mas mahirap ang pag-hack."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Madaling transition"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Habang lumalayo tayo sa mga password, magiging available pa rin ang mga password kasama ng mga passkey."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Piliin kung saan mo ise-save ang iyong <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
-    <string name="choose_provider_body" msgid="4967074531845147434">"Pumili ng password manger para ma-save ang iyong impormasyon at makapag-sign in nang mas mabilis sa susunod na pagkakataon"</string>
+    <string name="choose_provider_body" msgid="4967074531845147434">"Pumili ng password manager para ma-save ang iyong impormasyon at makapag-sign in nang mas mabilis sa susunod na pagkakataon"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Gumawa ng passkey para sa <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
     <string name="choose_create_option_password_title" msgid="7097275038523578687">"I-save ang password para sa <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"I-save ang impormasyon sa pag-sign in para sa <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"I-save ang <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> sa"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Gumawa ng passkey sa ibang device?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Gamitin ang <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> para sa lahat ng iyong pag-sign in?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Iso-store ng password manager na ito ang iyong mga password at passkey para madali kang makapag-sign in"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Itakda bilang default"</string>
     <string name="use_once" msgid="9027366575315399714">"Gamitin nang isang beses"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> (na) password • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> (na) passkey"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Iba pang password manager"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Isara ang sheet"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Bumalik sa nakaraang page"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Isara"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"I-dismiss"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Gamitin ang iyong naka-save na passkey para sa <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Gamitin ang iyong naka-save na sign-in para sa <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Pumili ng naka-save na sign-in para sa <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Mga naka-lock na password manager"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"I-tap para i-unlock"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Walang impormasyon sa pag-sign in"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Walang impormasyon sa pag-sign in sa <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Pamahalaan ang mga sign-in"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Mula sa ibang device"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Gumamit ng ibang device"</string>
diff --git a/packages/CredentialManager/res/values-tr/strings.xml b/packages/CredentialManager/res/values-tr/strings.xml
index 083add3..bc3c4e2 100644
--- a/packages/CredentialManager/res/values-tr/strings.xml
+++ b/packages/CredentialManager/res/values-tr/strings.xml
@@ -20,22 +20,24 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Daha iyi hesap güvenliği"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Her anahtar, oluşturulduğu uygulama veya web sitesiyle özel olarak bağlantılı olduğu için sahte bir uygulamaya veya web sitesine hiçbir zaman yanlışlıkla giriş yapamazsınız. Ayrıca, sunucularda yalnızca ortak anahtarlar saklandığı için saldırıya uğramak daha zordur."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Sorunsuz geçiş"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Şifresiz bir geleceğe doğru ilerlerken şifreler, şifre anahtarlarıyla birlikte kullanılmaya devam edecektir."</string>
-    <string name="choose_provider_title" msgid="8870795677024868108">"<xliff:g id="CREATETYPES">%1$s</xliff:g> bilgilerinizin kaydedileceği yeri seçin"</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
+    <string name="choose_provider_title" msgid="8870795677024868108">"<xliff:g id="CREATETYPES">%1$s</xliff:g> kaydedileceği yeri seçin"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Bilgilerinizi kaydedip bir dahaki sefere daha hızlı oturum açmak için bir şifre yöneticisi seçin"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> için şifre anahtarı oluşturulsun mu?"</string>
     <string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> için şifre kaydedilsin mi?"</string>
     <string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> için oturum açma bilgileri kaydedilsin mi?"</string>
-    <string name="passkey" msgid="632353688396759522">"şifre anahtarı"</string>
+    <string name="passkey" msgid="632353688396759522">"Şifre anahtarının"</string>
     <string name="password" msgid="6738570945182936667">"şifre"</string>
-    <string name="passkeys" msgid="5733880786866559847">"şifre anahtarları"</string>
+    <string name="passkeys" msgid="5733880786866559847">"Şifre anahtarlarınızın"</string>
     <string name="passwords" msgid="5419394230391253816">"şifreler"</string>
     <string name="sign_ins" msgid="4710739369149469208">"oturum aç"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"oturum açma bilgileri"</string>
-    <string name="save_credential_to_title" msgid="3172811692275634301">"Şuraya kaydet: <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>"</string>
+    <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> kaydedileceği yeri seçin"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Başka bir cihazda şifre anahtarı oluşturulsun mu?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Tüm oturum açma işlemlerinizde <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> kullanılsın mı?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Bu şifre yöneticisi, şifrelerinizi ve şifre anahtarlarınızı saklayarak kolayca oturum açmanıza yardımcı olur"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Varsayılan olarak ayarla"</string>
     <string name="use_once" msgid="9027366575315399714">"Bir kez kullanın"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> şifre • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> şifre anahtarı"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Diğer şifre yöneticileri"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Sayfayı kapat"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Önceki sayfaya geri dön"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Kapat"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Kapat"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı şifre anahtarınız kullanılsın mı?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı oturum açma bilgileriniz kullanılsın mı?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı oturum açma bilgilerini kullanın"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Kilitli şifre yöneticileri"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Kilidi açmak için dokunun"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Oturum açma bilgisi yok"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> hesabında oturum açma bilgisi yok"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Oturum açma bilgilerini yönetin"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Başka bir cihazdan"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Farklı bir cihaz kullan"</string>
diff --git a/packages/CredentialManager/res/values-uk/strings.xml b/packages/CredentialManager/res/values-uk/strings.xml
index dd112e03..abba261 100644
--- a/packages/CredentialManager/res/values-uk/strings.xml
+++ b/packages/CredentialManager/res/values-uk/strings.xml
@@ -20,7 +20,8 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Виберіть, де зберігати <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Виберіть менеджер паролів, щоб зберігати свої дані й надалі входити в облікові записи швидше"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Створити ключ доступу для додатка <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Зберегти <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> в"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Створити ключ доступу на іншому пристрої?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Використовувати сервіс <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> в усіх випадках входу?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Цей менеджер паролів зберігатиме ваші паролі та ключі доступу, щоб ви могли легко входити в облікові записи"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Вибрати за умовчанням"</string>
     <string name="use_once" msgid="9027366575315399714">"Скористатися раз"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Кількість паролів: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • Кількість ключів доступу: <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Інші менеджери паролів"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Закрити аркуш"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Повернутися на попередню сторінку"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Закрити"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Закрити"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Використати збережений ключ доступу для додатка <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Використати збережені дані для входу для додатка <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Виберіть збережені дані для входу в додаток <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Заблоковані менеджери паролів"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Торкніться, щоб розблокувати"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Немає даних для входу"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Немає даних для входу в обліковий запис <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Керування даними для входу"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"З іншого пристрою"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Використовувати інший пристрій"</string>
diff --git a/packages/CredentialManager/res/values-ur/strings.xml b/packages/CredentialManager/res/values-ur/strings.xml
index 3a704fe..12da924 100644
--- a/packages/CredentialManager/res/values-ur/strings.xml
+++ b/packages/CredentialManager/res/values-ur/strings.xml
@@ -20,7 +20,8 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"منتخب کریں کہ آپ کی <xliff:g id="CREATETYPES">%1$s</xliff:g> کو کہاں محفوظ کرنا ہے"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"اپنی معلومات کو محفوظ کرنے اور اگلی بار تیزی سے سائن ان کرنے کے لیے پاس ورڈ مینیجر منتخب کریں"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> کے لیے پاس کی تخلیق کریں؟"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> کو اس میں محفوظ کریں"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"کسی دوسرے آلے میں پاس کی تخلیق کریں؟"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"اپنے سبھی سائن انز کے لیے <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> کا استعمال کریں؟"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"آسانی سے سائن ان کرنے میں آپ کی مدد کرنے کے لیے یہ پاس ورڈ مینیجر آپ کے پاس ورڈز اور پاس کیز کو اسٹور کرے گا"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"بطور ڈیفالٹ سیٹ کریں"</string>
     <string name="use_once" msgid="9027366575315399714">"ایک بار استعمال کریں"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> پاس ورڈز • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> پاس کیز"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"دیگر پاس ورڈ مینیجرز"</string>
     <string name="close_sheet" msgid="1393792015338908262">"شیٹ بند کریں"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"گزشتہ صفحے پر واپس جائیں"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"بند کریں"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"برخاست کریں"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لیے اپنی محفوظ کردہ پاس کی استعمال کریں؟"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لیے اپنے محفوظ کردہ سائن ان کو استعمال کریں؟"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لیے محفوظ کردہ سائن انز منتخب کریں"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"مقفل کردہ پاس ورڈ مینیجرز"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"غیر مقفل کرنے کیلئے تھپتھپائیں"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"سائن ان کی کوئی معلومات نہیں"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> میں سائن ان کی کوئی معلومات نہیں ہے"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"سائن انز کا نظم کریں"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"دوسرے آلے سے"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"ایک مختلف آلہ استعمال کریں"</string>
diff --git a/packages/CredentialManager/res/values-uz/strings.xml b/packages/CredentialManager/res/values-uz/strings.xml
index 8248d52..3f177d0 100644
--- a/packages/CredentialManager/res/values-uz/strings.xml
+++ b/packages/CredentialManager/res/values-uz/strings.xml
@@ -20,8 +20,9 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Hisob xavfsizligi yaxshilandi"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Har bir kalit faqat ular uchun yaratilgan ilova yoki veb-sayt bilan ulangan, shuning uchun siz hech qachon xatolik bilan soxta ilova yoki veb-saytga kira olmaysiz. Shuningdek, serverlar bilan faqat ochiq kalitlarni saqlagan holda, buzib kirish ancha qiyinroq boʻladi."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Uzluksiz oʻtish"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Parolsiz kelajak sari borayotganimizda, parollar kodlar bilan birga ishlatilishda davom etadi."</string>
-    <string name="choose_provider_title" msgid="8870795677024868108">"<xliff:g id="CREATETYPES">%1$s</xliff:g> qayerga saqlanishini tanlang"</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
+    <string name="choose_provider_title" msgid="8870795677024868108">"Bu <xliff:g id="CREATETYPES">%1$s</xliff:g> qayerga saqlanishini tanlang"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Maʼlumotlaringizni saqlash va keyingi safar tez kirish uchun parollar menejerini tanlang"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> uchun kod yaratilsinmi?"</string>
     <string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> uchun parol saqlansinmi?"</string>
@@ -32,10 +33,11 @@
     <string name="passwords" msgid="5419394230391253816">"parollar"</string>
     <string name="sign_ins" msgid="4710739369149469208">"kirishlar"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"kirish maʼlumoti"</string>
-    <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>ni saqlash"</string>
+    <string name="save_credential_to_title" msgid="3172811692275634301">"Bu <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>ni saqlash"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Boshqa qurilmada kod yaratilsinmi?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Hamma kirishlarda <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> ishlatilsinmi?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Bu parollar menejerida hisobga oson kirishga yordam beruvchi parol va kalitlar saqlanadi"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Birlamchi deb belgilash"</string>
     <string name="use_once" msgid="9027366575315399714">"Bir marta ishlatish"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> ta parol • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> ta kod"</string>
@@ -48,6 +50,7 @@
     <string name="close_sheet" msgid="1393792015338908262">"Varaqni yopish"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Avvalgi sahifaga qaytish"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Yopish"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Yopish"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun saqlangan kalit ishlatilsinmi?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun saqlangan maʼlumotlar ishlatilsinmi?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> hisob maʼlumotlarini tanlang"</string>
diff --git a/packages/CredentialManager/res/values-vi/strings.xml b/packages/CredentialManager/res/values-vi/strings.xml
index 058e207..a45d37e 100644
--- a/packages/CredentialManager/res/values-vi/strings.xml
+++ b/packages/CredentialManager/res/values-vi/strings.xml
@@ -20,7 +20,8 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Cải thiện tính bảo mật của tài khoản"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Mỗi khoá được liên kết riêng với ứng dụng hoặc trang web mà khoá đó được tạo. Vì vậy, bạn sẽ không bao giờ đăng nhập nhầm vào một ứng dụng hoặc trang web lừa đảo. Ngoài ra, với các máy chủ chỉ lưu giữ khoá công khai, việc xâm nhập càng khó hơn nhiều."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Chuyển đổi liền mạch"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Trong quá trình chúng tôi hướng đến tương lai không dùng mật khẩu, bạn vẫn sẽ dùng được mật khẩu cùng với mã xác thực."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Chọn vị trí lưu <xliff:g id="CREATETYPES">%1$s</xliff:g> của bạn"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Hãy chọn một trình quản lý mật khẩu để lưu thông tin của bạn và đăng nhập nhanh hơn trong lần tới"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Tạo mã xác thực cho <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Lưu <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> vào"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Tạo mã xác thực trên thiết bị khác?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Dùng <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> cho mọi thông tin đăng nhập của bạn?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Trình quản lý mật khẩu này sẽ lưu trữ mật khẩu và mã xác thực của bạn để bạn dễ dàng đăng nhập"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Đặt làm mặc định"</string>
     <string name="use_once" msgid="9027366575315399714">"Dùng một lần"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> mật khẩu • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> mã xác thực"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Trình quản lý mật khẩu khác"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Đóng trang tính"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Quay lại trang trước"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Đóng"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Đóng"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Dùng mã xác thực bạn đã lưu cho <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Dùng thông tin đăng nhập bạn đã lưu cho <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Chọn thông tin đăng nhập đã lưu cho <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Trình quản lý mật khẩu đã khoá"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Nhấn để mở khoá"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Không có thông tin đăng nhập"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Không có thông tin đăng nhập trong <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Quản lý thông tin đăng nhập"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Từ một thiết bị khác"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Dùng thiết bị khác"</string>
diff --git a/packages/CredentialManager/res/values-zh-rCN/strings.xml b/packages/CredentialManager/res/values-zh-rCN/strings.xml
index 976ef57..2e30de6 100644
--- a/packages/CredentialManager/res/values-zh-rCN/strings.xml
+++ b/packages/CredentialManager/res/values-zh-rCN/strings.xml
@@ -16,11 +16,12 @@
     <string name="passwordless_technology_title" msgid="2497513482056606668">"无密码技术"</string>
     <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 联盟(成员包括 Google、Apple、Microsoft 等)和 W3C 的标准,通行密钥使用加密密钥对。不同于用户名及可在密码中使用的一系列字符,系统会为应用或网站创建一个私钥-公钥对。私钥会安全地存储在您的设备上或密码管理工具中,用于证实您的身份。公钥会被共享给应用或网站服务器。您只要使用相应密钥,就能瞬间注册并登录。"</string>
+    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"根据 FIDO 联盟(成员包括 Google、Apple、Microsoft 等)和 W3C 的标准,通行密钥使用加密密钥对。不同于“用户名+密码字符串”的传统登录凭据,采用通行密钥时,系统会为应用或网站创建一个私钥-公钥对。私钥会安全地存储在您的设备上或密码管理工具中,用于证实您的身份。公钥会被共享给应用或网站服务器。您只要使用相应密钥,就能瞬间注册并登录。"</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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"选择保存<xliff:g id="CREATETYPES">%1$s</xliff:g>的位置"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"请选择一款密码管理工具来保存您的信息,以便下次更快地登录"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"要为“<xliff:g id="APPNAME">%1$s</xliff:g>”创建通行密钥吗?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"将<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>保存到"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"在其他设备上创建通行密钥?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"将“<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>”用于您的所有登录信息?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"此密码管理工具将会存储您的密码和通行密钥,以帮助您轻松登录"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"设为默认项"</string>
     <string name="use_once" msgid="9027366575315399714">"使用一次"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> 个密码 • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> 个通行密钥"</string>
@@ -47,12 +49,12 @@
     <string name="other_password_manager" msgid="565790221427004141">"其他密码管理工具"</string>
     <string name="close_sheet" msgid="1393792015338908262">"关闭工作表"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"返回上一页"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
-    <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"将您已保存的通行密钥用于<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+    <string name="accessibility_close_button" msgid="1163435587545377687">"关闭"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"忽略"</string>
+    <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"要使用您已保存的\"<xliff:g id="APP_NAME">%1$s</xliff:g>\"通行密钥吗?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"将您已保存的登录信息用于<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"为<xliff:g id="APP_NAME">%1$s</xliff:g>选择已保存的登录信息"</string>
-    <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"以另一种方式登录"</string>
+    <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"使用其他登录方式"</string>
     <string name="snackbar_action" msgid="37373514216505085">"查看选项"</string>
     <string name="get_dialog_button_label_continue" msgid="6446201694794283870">"继续"</string>
     <string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"登录选项"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"已锁定的密码管理工具"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"点按即可解锁"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"无登录信息"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> 中没有任何登录信息"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"管理登录信息"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"通过另一台设备"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"使用其他设备"</string>
diff --git a/packages/CredentialManager/res/values-zh-rHK/strings.xml b/packages/CredentialManager/res/values-zh-rHK/strings.xml
index 0014d7d..9a11e0f 100644
--- a/packages/CredentialManager/res/values-zh-rHK/strings.xml
+++ b/packages/CredentialManager/res/values-zh-rHK/strings.xml
@@ -20,7 +20,8 @@
     <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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"選擇儲存<xliff:g id="CREATETYPES">%1$s</xliff:g>的位置"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"選取密碼管理工具即可儲存自己的資料,縮短下次登入的時間"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"要為「<xliff:g id="APPNAME">%1$s</xliff:g>」建立密鑰嗎?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"將<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>儲存至"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"要在其他裝置上建立密鑰嗎?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"要將「<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>」用於所有的登入資料嗎?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"此密碼管理工具將儲存您的密碼和密鑰,協助您輕鬆登入"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"設定為預設"</string>
     <string name="use_once" msgid="9027366575315399714">"單次使用"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> 個密碼 • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> 個密鑰"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"其他密碼管理工具"</string>
     <string name="close_sheet" msgid="1393792015338908262">"閂工作表"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"返回上一頁"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"關閉"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"關閉"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"要使用已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」密鑰嗎?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"要使用已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」登入資料嗎?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"選擇已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」登入資料"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"已鎖定的密碼管理工具"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"輕按即可解鎖"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"沒有登入資料"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> 中沒有登入資料"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"管理登入資料"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"透過其他裝置"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"使用其他裝置"</string>
diff --git a/packages/CredentialManager/res/values-zh-rTW/strings.xml b/packages/CredentialManager/res/values-zh-rTW/strings.xml
index 6173584..1f8afa8 100644
--- a/packages/CredentialManager/res/values-zh-rTW/strings.xml
+++ b/packages/CredentialManager/res/values-zh-rTW/strings.xml
@@ -16,11 +16,12 @@
     <string name="passwordless_technology_title" msgid="2497513482056606668">"無密碼技術"</string>
     <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 聯盟 (包括 Google、Apple、Microsoft 等) 及 W3C 標準,使用加密編譯金鑰技術。私密 - 公開金鑰組專為應用程式或網站建立,有別於建立密碼時使用的使用者名稱和做為密碼的字元字串。私密金鑰會安全地儲存在裝置或 Google 密碼管理工具中,並用來確認你的身分。公開金鑰會提供給應用程式或網站伺服器。只要有相對應的金鑰,就能立即註冊和登入。"</string>
+    <string name="public_key_cryptography_detail" msgid="6937631710280562213">"密碼金鑰根據 FIDO 聯盟 (包括 Google、Apple、Microsoft 等) 及 W3C 標準,使用加密編譯金鑰組。有別於傳統密碼,系統會針對應用程式或網站建立專屬的私密 - 公開金鑰組,因此你不再需要輸入使用者名稱和一串密碼字元。私密金鑰會安全地儲存在裝置或密碼管理工具中,並用來確認你的身分。公開金鑰會提供給應用程式或網站伺服器。只要有相對應的金鑰,就能立即註冊和登入。"</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>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"選擇要將<xliff:g id="CREATETYPES">%1$s</xliff:g>存在哪裡"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"選取密碼管理工具並儲存資訊,下次就能更快登入"</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"要為「<xliff:g id="APPNAME">%1$s</xliff:g>」建立密碼金鑰嗎?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"選擇儲存<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>的位置"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"要在其他裝置上建立密碼金鑰嗎?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"要將「<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>」用於所有的登入資訊嗎?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"這個密碼管理工具會儲存密碼和密碼金鑰,協助你輕鬆登入"</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"設為預設"</string>
     <string name="use_once" msgid="9027366575315399714">"單次使用"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> 個密碼 • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> 個密碼金鑰"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"其他密碼管理工具"</string>
     <string name="close_sheet" msgid="1393792015338908262">"關閉功能表"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"返回上一頁"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"關閉"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"關閉"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"要使用已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」密碼金鑰嗎?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"要使用已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」登入資訊嗎?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"選擇已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」登入資訊"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"已鎖定的密碼管理工具"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"輕觸即可解鎖"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"沒有登入資訊"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> 中沒有登入資訊"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"管理登入資訊"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"透過其他裝置"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"使用其他裝置"</string>
diff --git a/packages/CredentialManager/res/values-zu/strings.xml b/packages/CredentialManager/res/values-zu/strings.xml
index a1c3230..01a5b2e 100644
--- a/packages/CredentialManager/res/values-zu/strings.xml
+++ b/packages/CredentialManager/res/values-zu/strings.xml
@@ -20,7 +20,8 @@
     <string name="improved_account_security_title" msgid="1069841917893513424">"Ukuvikeleka kwe-akhawunti okuthuthukisiwe"</string>
     <string name="improved_account_security_detail" msgid="9123750251551844860">"Ukhiye ngamunye olinkwe ngokukhethekile ne-app noma iwebhusayithi usungulelwe yona, ngakho awukwazi ukungena ngemvume ku-app noma kuwebhusayithi yomgunyathi ngephutha. Futhi, ngamaseva agcina okhiye basesidlangalaleni kuphela, ukugebengu be-inthanethi bunzima kakhulu."</string>
     <string name="seamless_transition_title" msgid="5335622196351371961">"Ushintsho olulula"</string>
-    <string name="seamless_transition_detail" msgid="4475509237171739843">"Njengoba sibhekela kwikusasa elingenaphasiwedi, amagama ayimfihlo asazotholakala eceleni kokhiye bokudlula."</string>
+    <!-- no translation found for seamless_transition_detail (3440478759491650823) -->
+    <skip />
     <string name="choose_provider_title" msgid="8870795677024868108">"Khetha lapho ongagcina khona i-<xliff:g id="CREATETYPES">%1$s</xliff:g> yakho"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"Khetha isiphathi sephasiwedi ukuze ulondoloze ulwazi lwakho futhi ungene ngemvume ngokushesha ngesikhathi esizayo."</string>
     <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Sungula ukhiye wokudlula we-<xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
@@ -35,7 +36,8 @@
     <string name="save_credential_to_title" msgid="3172811692275634301">"Londoloza i-<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> ku-"</string>
     <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Sungula ukhiye wokudlula kwenye idivayisi?"</string>
     <string name="use_provider_for_all_title" msgid="4201020195058980757">"Sebenzisa i-<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> kukho konke ukungena kwakho ngemvume?"</string>
-    <string name="use_provider_for_all_description" msgid="8466427781848268490">"Lesi siphathi sephasiwedi sizogcina amaphasiwedi akho nezikhiye zokungena ukuze zikusize ungene ngemvume kalula."</string>
+    <!-- no translation found for use_provider_for_all_description (1998772715863958997) -->
+    <skip />
     <string name="set_as_default" msgid="4415328591568654603">"Setha njengokuzenzakalelayo"</string>
     <string name="use_once" msgid="9027366575315399714">"Sebenzisa kanye"</string>
     <string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Amaphasiwedi angu-<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • okhiye bokudlula abangu-<xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
@@ -47,8 +49,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Abanye abaphathi bephasiwedi"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Vala ishidi"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Buyela emuva ekhasini langaphambilini"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
-    <skip />
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Vala"</string>
+    <string name="accessibility_snackbar_dismiss" msgid="3456598374801836120">"Chitha"</string>
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Sebenzisa ukhiye wakho wokungena olondoloziwe <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Sebenzisa ukungena kwakho ngemvume okulondoloziwe <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Khetha ukungena ngemvume okulondoloziwe kwakho <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -60,8 +62,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Abaphathi bephasiwedi abakhiyiwe"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Thepha ukuze uvule"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Alukho ulwazi lokungena ngemvume"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Alukho ulwazi lokungena ngemvume lwe-<xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Phatha ukungena ngemvume"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Kusukela kwenye idivayisi"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Sebenzisa idivayisi ehlukile"</string>
diff --git a/packages/CredentialManager/res/values/strings.xml b/packages/CredentialManager/res/values/strings.xml
index ee51242..f655d6b 100644
--- a/packages/CredentialManager/res/values/strings.xml
+++ b/packages/CredentialManager/res/values/strings.xml
@@ -42,7 +42,7 @@
   <!-- Title for subsection of "Learn more about passkeys" screen about seamless transition. [CHAR LIMIT=80] -->
   <string name="seamless_transition_title">Seamless transition</string>
   <!-- Detail for subsection of "Learn more about passkeys" screen about seamless transition. [CHAR LIMIT=500] -->
-  <string name="seamless_transition_detail">As we move towards a passwordless future, passwords will still be available alongside passkeys.</string>
+  <string name="seamless_transition_detail">As we move towards a passwordless future, passwords will still be available alongside passkeys</string>
   <!-- This appears as the title of the modal bottom sheet which provides all available providers for users to choose. [CHAR LIMIT=200] -->
   <string name="choose_provider_title">Choose where to save your <xliff:g id="createTypes" example="passkeys">%1$s</xliff:g></string>
   <!-- This appears as the description body of the modal bottom sheet which provides all available providers for users to choose. [CHAR LIMIT=200] -->
@@ -67,9 +67,8 @@
   <string name="create_passkey_in_other_device_title">Create passkey in another device?</string>
   <!-- This appears as the title of the modal bottom sheet for users to confirm whether they should use the selected provider as default or not. [CHAR LIMIT=200] -->
   <string name="use_provider_for_all_title">Use <xliff:g id="providerInfoDisplayName" example="Google Password Manager">%1$s</xliff:g> for all your sign-ins?</string>
-  <!-- TODO: Check the wording here. -->
-  <!-- This appears as the description body of the modal bottom sheet for users to confirm whether they should use the selected provider as default or not. [CHAR LIMIT=200] -->
-  <string name="use_provider_for_all_description">This password manager will store your passwords and passkeys to help you easily sign in</string>
+  <!-- This appears as the description body of the modal bottom sheet for users to confirm whether they should use the selected provider as default or not. [CHAR LIMIT=300] -->
+  <string name="use_provider_for_all_description">This password manager for <xliff:g id="username" example="becket@gmail.com">%1$s</xliff:g> will store your passwords and passkeys to help you easily sign in</string>
   <!-- This is a label for a button that sets this password manager as the default. [CHAR LIMIT=20] -->
   <string name="set_as_default">Set as default</string>
   <!-- This is a label for a button that makes this password manager be used just in this specific case. [CHAR LIMIT=20] -->
@@ -111,7 +110,7 @@
   <!-- This is a label for a button that takes user to the next screen. [CHAR LIMIT=20] -->
   <string name="get_dialog_button_label_continue">Continue</string>
   <!-- Separator for sign-in type and username in a sign-in entry. -->
-  <string name="get_dialog_sign_in_type_username_separator" translatable="false">" - "</string>
+  <string name="get_dialog_sign_in_type_username_separator" translatable="false">" • "</string>
   <!-- This text is followed by a list of one or more options. [CHAR LIMIT=80] -->
   <string name="get_dialog_title_sign_in_options">Sign-in options</string>
   <!-- Column heading for displaying sign-ins for a specific username. [CHAR LIMIT=80] -->
diff --git a/packages/CredentialManager/res/values/themes.xml b/packages/CredentialManager/res/values/themes.xml
index c7e4796..428c85a 100644
--- a/packages/CredentialManager/res/values/themes.xml
+++ b/packages/CredentialManager/res/values/themes.xml
@@ -1,11 +1,9 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-  <style name="Theme.CredentialSelector" parent="@android:style/ThemeOverlay.Material">
+  <style name="Theme.CredentialSelector" parent="@*android:style/ThemeOverlay.DeviceDefault.Accent.DayNight">
     <item name="android:windowContentOverlay">@null</item>
     <item name="android:windowNoTitle">true</item>
     <item name="android:windowBackground">@android:color/transparent</item>
     <item name="android:windowIsTranslucent">true</item>
-    <item name="android:statusBarColor">@android:color/transparent</item>
-    <item name="android:navigationBarColor">@android:color/transparent</item>
   </style>
 </resources>
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
index 3d718a2..b32fe3f 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
@@ -42,9 +42,13 @@
 import com.android.credentialmanager.createflow.EnabledProviderInfo
 import com.android.credentialmanager.createflow.RequestDisplayInfo
 import com.android.credentialmanager.getflow.GetCredentialUiState
+import com.android.credentialmanager.getflow.findAutoSelectEntry
 import androidx.credentials.CreateCredentialRequest.DisplayInfo
 import androidx.credentials.CreatePublicKeyCredentialRequest
 import androidx.credentials.CreatePasswordRequest
+import androidx.credentials.GetPasswordOption
+import androidx.credentials.GetPublicKeyCredentialOption
+import com.android.credentialmanager.common.ProviderActivityState
 
 import java.time.Instant
 
@@ -71,7 +75,7 @@
         requestInfo = intent.extras?.getParcelable(
             RequestInfo.EXTRA_REQUEST_INFO,
             RequestInfo::class.java
-        ) ?: testCreatePasswordRequestInfo()
+        ) ?: testGetRequestInfo()
 
         val originName: String? = when (requestInfo.type) {
             RequestInfo.TYPE_CREATE -> requestInfo.createCredentialRequest?.origin
@@ -120,17 +124,26 @@
                         providerDisableListUiState,
                         defaultProviderId,
                         requestDisplayInfoUiState,
-                        /** isOnPasskeyIntroStateAlready */
-                        false,
+                        isOnPasskeyIntroStateAlready = false,
                         isPasskeyFirstUse
                     )!!,
                     getCredentialUiState = null,
                 )
             }
-            RequestInfo.TYPE_GET -> UiState(
-                createCredentialUiState = null,
-                getCredentialUiState = getCredentialInitialUiState(originName)!!,
-            )
+            RequestInfo.TYPE_GET -> {
+                val getCredentialInitialUiState = getCredentialInitialUiState(originName)!!
+                val autoSelectEntry =
+                    findAutoSelectEntry(getCredentialInitialUiState.providerDisplayInfo)
+                UiState(
+                    createCredentialUiState = null,
+                    getCredentialUiState = getCredentialInitialUiState,
+                    selectedEntry = autoSelectEntry,
+                    providerActivityState =
+                    if (autoSelectEntry == null) ProviderActivityState.NOT_APPLICABLE
+                    else ProviderActivityState.READY_TO_LAUNCH,
+                    isAutoSelectFlow = autoSelectEntry != null,
+                )
+            }
             else -> throw IllegalStateException("Unrecognized request type: ${requestInfo.type}")
         }
     }
@@ -400,13 +413,14 @@
                 "                   \"authenticatorSelection\": {\n" +
                 "                     \"residentKey\": \"required\",\n" +
                 "                     \"requireResidentKey\": true\n" +
-                "                   }}"
+                "                   }}",
+            preferImmediatelyAvailableCredentials = true,
         )
         val credentialData = request.credentialData
         return RequestInfo.newCreateRequestInfo(
                 Binder(),
-                CreateCredentialRequest.Builder(credentialData, Bundle())
-                        .setType("androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL")
+                CreateCredentialRequest.Builder("androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL",
+                credentialData, Bundle())
                         .setIsSystemProviderRequired(false)
                         .setAlwaysSendAppInfoToProvider(true)
                         .build(),
@@ -418,8 +432,8 @@
         val request = CreatePasswordRequest("beckett-bakert@gmail.com", "password123")
         return RequestInfo.newCreateRequestInfo(
                 Binder(),
-                CreateCredentialRequest.Builder(request.credentialData, request.candidateQueryData)
-                        .setType(TYPE_PASSWORD_CREDENTIAL)
+                CreateCredentialRequest.Builder(TYPE_PASSWORD_CREDENTIAL,
+                request.credentialData, request.candidateQueryData)
                         .setIsSystemProviderRequired(false)
                         .setAlwaysSendAppInfoToProvider(true)
                         .build(),
@@ -436,8 +450,7 @@
         )
         return RequestInfo.newCreateRequestInfo(
                 Binder(),
-                CreateCredentialRequest.Builder(data, Bundle())
-                        .setType("other-sign-ins")
+                CreateCredentialRequest.Builder("other-sign-ins", data, Bundle())
                         .setIsSystemProviderRequired(false)
                         .setAlwaysSendAppInfoToProvider(true)
                         .build(),
@@ -446,19 +459,28 @@
     }
 
     private fun testGetRequestInfo(): RequestInfo {
+        val passwordOption = GetPasswordOption()
+        val passkeyOption = GetPublicKeyCredentialOption(
+            "json", preferImmediatelyAvailableCredentials = false)
         return RequestInfo.newGetRequestInfo(
             Binder(),
             GetCredentialRequest.Builder(
                 Bundle()
             ).addCredentialOption(
                 CredentialOption(
-                    "androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL",
-                    Bundle(),
-                    Bundle(), /*isSystemProviderRequired=*/
-                    false
+                    passwordOption.type,
+                    passwordOption.requestData,
+                    passwordOption.candidateQueryData,
+                    passwordOption.isSystemProviderRequired
                 )
-            )
-                .build(),
+            ).addCredentialOption(
+                CredentialOption(
+                    passkeyOption.type,
+                    passkeyOption.requestData,
+                    passkeyOption.candidateQueryData,
+                    passkeyOption.isSystemProviderRequired
+                )
+            ).build(),
             "com.google.android.youtube"
         )
     }
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
index 9b7139c..e49e3f1 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
@@ -22,6 +22,7 @@
 import androidx.activity.compose.ManagedActivityResultLauncher
 import androidx.activity.result.ActivityResult
 import androidx.activity.result.IntentSenderRequest
+import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.setValue
@@ -36,6 +37,9 @@
 import com.android.credentialmanager.createflow.CreateScreenState
 import com.android.credentialmanager.getflow.GetCredentialUiState
 import com.android.credentialmanager.getflow.GetScreenState
+import com.android.credentialmanager.logging.LifecycleEvent
+import com.android.credentialmanager.logging.UIMetrics
+import com.android.internal.logging.UiEventLogger.UiEventEnum
 
 /** One and only one of create or get state can be active at any given time. */
 data class UiState(
@@ -44,6 +48,9 @@
     val selectedEntry: BaseEntry? = null,
     val providerActivityState: ProviderActivityState = ProviderActivityState.NOT_APPLICABLE,
     val dialogState: DialogState = DialogState.ACTIVE,
+    // True if the UI has one and only one auto selectable entry. Its provider activity will be
+    // launched immediately, and canceling it will cancel the whole UI flow.
+    val isAutoSelectFlow: Boolean = false,
 )
 
 class CredentialSelectorViewModel(
@@ -53,6 +60,13 @@
     var uiState by mutableStateOf(credManRepo.initState())
         private set
 
+    var uiMetrics: UIMetrics = UIMetrics()
+
+    init{
+        uiMetrics.logNormal(LifecycleEvent.CREDMAN_ACTIVITY_INIT,
+                credManRepo.requestInfo.appPackageName)
+    }
+
     /**************************************************************************/
     /*****                       Shared Callbacks                         *****/
     /**************************************************************************/
@@ -73,6 +87,12 @@
     fun onNewCredentialManagerRepo(credManRepo: CredentialManagerRepo) {
         this.credManRepo = credManRepo
         uiState = credManRepo.initState()
+
+        if (this.credManRepo.requestInfo.token != credManRepo.requestInfo.token) {
+            this.uiMetrics.resetInstanceId()
+            this.uiMetrics.logNormal(LifecycleEvent.CREDMAN_ACTIVITY_NEW_REQUEST,
+                    credManRepo.requestInfo.appPackageName)
+        }
     }
 
     fun launchProviderUi(
@@ -96,13 +116,20 @@
         val resultCode = providerActivityResult.resultCode
         val resultData = providerActivityResult.data
         if (resultCode == Activity.RESULT_CANCELED) {
-            // Re-display the CredMan UI if the user canceled from the provider UI.
-            Log.d(Constants.LOG_TAG, "The provider activity was cancelled," +
-                " re-displaying our UI.")
-            uiState = uiState.copy(
-                selectedEntry = null,
-                providerActivityState = ProviderActivityState.NOT_APPLICABLE,
-            )
+            // Re-display the CredMan UI if the user canceled from the provider UI, or cancel
+            // the UI if this is the auto select flow.
+            if (uiState.isAutoSelectFlow) {
+                Log.d(Constants.LOG_TAG, "The auto selected provider activity was cancelled," +
+                    " ending the credential manager activity.")
+                onUserCancel()
+            } else {
+                Log.d(Constants.LOG_TAG, "The provider activity was cancelled," +
+                    " re-displaying our UI.")
+                uiState = uiState.copy(
+                    selectedEntry = null,
+                    providerActivityState = ProviderActivityState.NOT_APPLICABLE,
+                )
+            }
         } else {
             if (entry != null) {
                 Log.d(
@@ -130,8 +157,15 @@
         onInternalError()
     }
 
+    fun onIllegalUiState(errorMessage: String) {
+        Log.w(Constants.LOG_TAG, errorMessage)
+        onInternalError()
+    }
+
     private fun onInternalError() {
         Log.w(Constants.LOG_TAG, "UI closed due to illegal internal state")
+        this.uiMetrics.logNormal(LifecycleEvent.CREDMAN_ACTIVITY_INTERNAL_ERROR,
+                credManRepo.requestInfo.appPackageName)
         credManRepo.onParsingFailureCancel()
         uiState = uiState.copy(dialogState = DialogState.COMPLETE)
     }
@@ -359,4 +393,9 @@
             onInternalError()
         }
     }
+
+    @Composable
+    fun logUiEvent(uiEventEnum: UiEventEnum) {
+        this.uiMetrics.log(uiEventEnum, credManRepo.requestInfo.appPackageName)
+    }
 }
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
index 9c9c2a3..b5c8989 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
@@ -50,7 +50,9 @@
 import androidx.credentials.CreateCredentialRequest
 import androidx.credentials.CreateCustomCredentialRequest
 import androidx.credentials.CreatePasswordRequest
+import androidx.credentials.CredentialOption
 import androidx.credentials.CreatePublicKeyCredentialRequest
+import androidx.credentials.GetPublicKeyCredentialOption
 import androidx.credentials.PublicKeyCredential.Companion.TYPE_PUBLIC_KEY_CREDENTIAL
 import androidx.credentials.provider.Action
 import androidx.credentials.provider.AuthenticationAction
@@ -58,8 +60,7 @@
 import androidx.credentials.provider.CustomCredentialEntry
 import androidx.credentials.provider.PasswordCredentialEntry
 import androidx.credentials.provider.PublicKeyCredentialEntry
-import androidx.credentials.provider.RemoteCreateEntry
-import androidx.credentials.provider.RemoteCredentialEntry
+import androidx.credentials.provider.RemoteEntry
 import org.json.JSONObject
 
 // TODO: remove all !! checks
@@ -147,7 +148,10 @@
                         icon = providerIcon,
                         displayName = providerLabel,
                         credentialEntryList = getCredentialOptionInfoList(
-                            it.providerFlattenedComponentName, it.credentialEntries, context
+                            providerId = it.providerFlattenedComponentName,
+                            providerLabel = providerLabel,
+                            credentialEntries = it.credentialEntries,
+                            context = context
                         ),
                         authenticationEntryList = getAuthenticationEntryList(
                             it.providerFlattenedComponentName,
@@ -172,10 +176,25 @@
             context: Context,
             originName: String?,
         ): com.android.credentialmanager.getflow.RequestDisplayInfo? {
+            val getCredentialRequest = requestInfo.getCredentialRequest ?: return null
+            val preferImmediatelyAvailableCredentials = getCredentialRequest.credentialOptions.any {
+                val credentialOptionJetpack = CredentialOption.createFrom(
+                    it.type,
+                    it.credentialRetrievalData,
+                    it.credentialRetrievalData,
+                    it.isSystemProviderRequired
+                )
+                if (credentialOptionJetpack is GetPublicKeyCredentialOption) {
+                    credentialOptionJetpack.preferImmediatelyAvailableCredentials
+                } else {
+                    false
+                }
+            }
             return com.android.credentialmanager.getflow.RequestDisplayInfo(
                 appName = originName
                     ?: getAppLabel(context.packageManager, requestInfo.appPackageName)
-                    ?: return null
+                    ?: return null,
+                preferImmediatelyAvailableCredentials = preferImmediatelyAvailableCredentials
             )
         }
 
@@ -185,6 +204,7 @@
          */
         private fun getCredentialOptionInfoList(
             providerId: String,
+            providerLabel: String,
             credentialEntries: List<Entry>,
             context: Context,
         ): List<CredentialEntryInfo> {
@@ -195,6 +215,7 @@
                     is PasswordCredentialEntry -> {
                         result.add(CredentialEntryInfo(
                             providerId = providerId,
+                            providerDisplayName = providerLabel,
                             entryKey = it.key,
                             entrySubkey = it.subkey,
                             pendingIntent = credentialEntry.pendingIntent,
@@ -203,13 +224,17 @@
                             credentialTypeDisplayName = credentialEntry.typeDisplayName.toString(),
                             userName = credentialEntry.username.toString(),
                             displayName = credentialEntry.displayName?.toString(),
-                            icon = credentialEntry.icon?.loadDrawable(context),
+                            icon = credentialEntry.icon.loadDrawable(context),
+                            shouldTintIcon = credentialEntry.isDefaultIcon ?: false,
                             lastUsedTimeMillis = credentialEntry.lastUsedTime,
+                            isAutoSelectable = credentialEntry.isAutoSelectAllowed &&
+                                credentialEntry.autoSelectAllowedFromOption,
                         ))
                     }
                     is PublicKeyCredentialEntry -> {
                         result.add(CredentialEntryInfo(
                             providerId = providerId,
+                            providerDisplayName = providerLabel,
                             entryKey = it.key,
                             entrySubkey = it.subkey,
                             pendingIntent = credentialEntry.pendingIntent,
@@ -218,13 +243,17 @@
                             credentialTypeDisplayName = credentialEntry.typeDisplayName.toString(),
                             userName = credentialEntry.username.toString(),
                             displayName = credentialEntry.displayName?.toString(),
-                            icon = credentialEntry.icon?.loadDrawable(context),
+                            icon = credentialEntry.icon.loadDrawable(context),
+                            shouldTintIcon = credentialEntry.isDefaultIcon,
                             lastUsedTimeMillis = credentialEntry.lastUsedTime,
+                            isAutoSelectable = credentialEntry.isAutoSelectAllowed &&
+                                credentialEntry.autoSelectAllowedFromOption,
                         ))
                     }
                     is CustomCredentialEntry -> {
                         result.add(CredentialEntryInfo(
                             providerId = providerId,
+                            providerDisplayName = providerLabel,
                             entryKey = it.key,
                             entrySubkey = it.subkey,
                             pendingIntent = credentialEntry.pendingIntent,
@@ -233,8 +262,11 @@
                             credentialTypeDisplayName = credentialEntry.typeDisplayName.toString(),
                             userName = credentialEntry.title.toString(),
                             displayName = credentialEntry.subtitle?.toString(),
-                            icon = credentialEntry.icon?.loadDrawable(context),
+                            icon = credentialEntry.icon.loadDrawable(context),
+                            shouldTintIcon = credentialEntry.isDefaultIcon,
                             lastUsedTimeMillis = credentialEntry.lastUsedTime,
+                            isAutoSelectable = credentialEntry.isAutoSelectAllowed &&
+                                credentialEntry.autoSelectAllowedFromOption,
                         ))
                     }
                     else -> Log.d(
@@ -303,7 +335,7 @@
             if (remoteEntry == null) {
                 return null
             }
-            val structuredRemoteEntry = RemoteCredentialEntry.fromSlice(remoteEntry.slice)
+            val structuredRemoteEntry = RemoteEntry.fromSlice(remoteEntry.slice)
                 ?: return null
             return RemoteEntryInfo(
                 providerId = providerId,
@@ -415,24 +447,16 @@
                     createCredentialRequestJetpack.password,
                     CredentialType.PASSWORD,
                     appLabel,
-                    context.getDrawable(R.drawable.ic_password)!!
+                    context.getDrawable(R.drawable.ic_password_24) ?: return null,
+                    preferImmediatelyAvailableCredentials = false,
                 )
                 is CreatePublicKeyCredentialRequest -> {
-                    val requestJson = createCredentialRequestJetpack.requestJson
-                    val json = JSONObject(requestJson)
-                    var name = ""
-                    var displayName = ""
-                    if (json.has("user")) {
-                        val user: JSONObject = json.getJSONObject("user")
-                        name = user.getString("name")
-                        displayName = user.getString("displayName")
-                    }
-                    RequestDisplayInfo(
-                        name,
-                        displayName,
-                        CredentialType.PASSKEY,
-                        appLabel,
-                        context.getDrawable(R.drawable.ic_passkey)!!
+                    newRequestDisplayInfoFromPasskeyJson(
+                        requestJson = createCredentialRequestJetpack.requestJson,
+                        appLabel = appLabel,
+                        context = context,
+                        preferImmediatelyAvailableCredentials =
+                        createCredentialRequestJetpack.preferImmediatelyAvailableCredentials,
                     )
                 }
                 is CreateCustomCredentialRequest -> {
@@ -441,12 +465,13 @@
                         .parseFromCredentialDataBundle(createCredentialRequest.credentialData)
                         ?: return null
                     RequestDisplayInfo(
-                        title = displayInfo.userId,
-                        subtitle = displayInfo.userDisplayName,
+                        title = displayInfo.userId.toString(),
+                        subtitle = displayInfo.userDisplayName?.toString(),
                         type = CredentialType.UNKNOWN,
                         appName = appLabel,
                         typeIcon = displayInfo.credentialTypeIcon?.loadDrawable(context)
-                            ?: context.getDrawable(R.drawable.ic_other_sign_in)!!
+                            ?: context.getDrawable(R.drawable.ic_other_sign_in_24) ?: return null,
+                        preferImmediatelyAvailableCredentials = false,
                     )
                 }
                 else -> null
@@ -602,7 +627,7 @@
             remoteEntry: Entry?,
         ): RemoteInfo? {
             return if (remoteEntry != null) {
-                val structuredRemoteEntry = RemoteCreateEntry.fromSlice(remoteEntry.slice)
+                val structuredRemoteEntry = RemoteEntry.fromSlice(remoteEntry.slice)
                     ?: return null
                 RemoteInfo(
                     providerId = providerId,
@@ -613,5 +638,29 @@
                 )
             } else null
         }
+
+        private fun newRequestDisplayInfoFromPasskeyJson(
+            requestJson: String,
+            appLabel: String,
+            context: Context,
+            preferImmediatelyAvailableCredentials: Boolean,
+        ): RequestDisplayInfo? {
+            val json = JSONObject(requestJson)
+            var name = ""
+            var displayName = ""
+            if (json.has("user")) {
+                val user: JSONObject = json.getJSONObject("user")
+                name = user.getString("name")
+                displayName = user.getString("displayName")
+            }
+            return RequestDisplayInfo(
+                name,
+                displayName,
+                CredentialType.PASSKEY,
+                appLabel,
+                context.getDrawable(R.drawable.ic_passkey_24) ?: return null,
+                preferImmediatelyAvailableCredentials,
+            )
+        }
     }
 }
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/TestUtils.kt b/packages/CredentialManager/src/com/android/credentialmanager/TestUtils.kt
index 9216429..26aadd9 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/TestUtils.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/TestUtils.kt
@@ -25,12 +25,14 @@
 import android.credentials.ui.AuthenticationEntry
 import android.credentials.ui.Entry
 import android.net.Uri
+import android.os.Bundle
 import android.provider.Settings
+import androidx.credentials.provider.BeginGetPasswordOption
+import androidx.credentials.provider.BeginGetPublicKeyCredentialOption
 import androidx.credentials.provider.CreateEntry
 import androidx.credentials.provider.PasswordCredentialEntry
 import androidx.credentials.provider.PublicKeyCredentialEntry
-import androidx.credentials.provider.RemoteCreateEntry
-import androidx.credentials.provider.RemoteCredentialEntry
+import androidx.credentials.provider.RemoteEntry
 
 import java.time.Instant
 
@@ -82,7 +84,7 @@
             return Entry(
                 key,
                 subkey,
-                RemoteCredentialEntry(pendingIntent).slice
+                RemoteEntry(pendingIntent).slice
             )
         }
 
@@ -137,7 +139,8 @@
                 intent, (PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
                 or PendingIntent.FLAG_ONE_SHOT)
             )
-            val passwordEntry = PasswordCredentialEntry.Builder(context, userName, pendingIntent)
+            val passwordEntry = PasswordCredentialEntry.Builder(
+                context, userName, pendingIntent, BeginGetPasswordOption(Bundle(), "id"))
                 .setDisplayName(userDisplayName).setLastUsedTime(lastUsedTime).build()
             return Entry(key, subkey, passwordEntry.slice, Intent())
         }
@@ -149,17 +152,23 @@
             userName: String,
             userDisplayName: String?,
             lastUsedTime: Instant?,
+            isAutoSelectAllowed: Boolean = false,
         ): Entry {
-            val intent = Intent("com.androidauth.androidvault.CONFIRM_PASSWORD")
-                .setPackage("com.androidauth.androidvault")
-            intent.putExtra("provider_extra_sample", "testprovider")
-            val pendingIntent = PendingIntent.getActivity(
-                context, 1,
-                intent, (PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
-                or PendingIntent.FLAG_ONE_SHOT)
+            val intent = Intent(Settings.ACTION_SYNC_SETTINGS)
+            val pendingIntent =
+                PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
+            val candidateQueryData = Bundle()
+            candidateQueryData.putBoolean(
+                "androidx.credentials.BUNDLE_KEY_IS_AUTO_SELECT_ALLOWED",
+                isAutoSelectAllowed
             )
-            val passkeyEntry = PublicKeyCredentialEntry.Builder(context, userName, pendingIntent)
-                .setDisplayName(userDisplayName).setLastUsedTime(lastUsedTime).build()
+            val passkeyEntry = PublicKeyCredentialEntry.Builder(
+                context,
+                userName,
+                pendingIntent,
+                BeginGetPublicKeyCredentialOption(candidateQueryData, "id", "requestjson")
+            ).setDisplayName(userDisplayName).setLastUsedTime(lastUsedTime)
+                .setAutoSelectAllowed(isAutoSelectAllowed).build()
             return Entry(key, subkey, passkeyEntry.slice, Intent())
         }
     }
@@ -232,7 +241,7 @@
             return Entry(
                 key,
                 subkey,
-                RemoteCreateEntry(pendingIntent).slice
+                RemoteEntry(pendingIntent).slice
             )
         }
     }
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/DialogResult.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/DialogResult.kt
index 6d07df7..2971433 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/DialogResult.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/DialogResult.kt
@@ -24,8 +24,6 @@
 
 enum class ResultState {
   COMPLETE,
-  NORMAL_CANCELED,
-  LAUNCH_SETTING_CANCELED
 }
 
 data class DialogResult(
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/material/ModalBottomSheet.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/material/ModalBottomSheet.kt
index 335d58a..307d953 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/material/ModalBottomSheet.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/material/ModalBottomSheet.kt
@@ -306,10 +306,6 @@
  * @param sheetContentColor The preferred content color provided by the bottom sheet to its
  * children. Defaults to the matching content color for [sheetBackgroundColor], or if that is not
  * a color from the theme, this will keep the same content color set above the bottom sheet.
- * @param scrimColor The color of the scrim that is applied to the rest of the screen when the
- * bottom sheet is visible. If the color passed is [Color.Unspecified], then a scrim will no
- * longer be applied and the bottom sheet will not block interaction with the rest of the screen
- * when visible.
  * @param content The content of rest of the screen.
  */
 @Composable
@@ -322,7 +318,6 @@
     sheetElevation: Dp = ModalBottomSheetDefaults.Elevation,
     sheetBackgroundColor: Color = MaterialTheme.colorScheme.surface,
     sheetContentColor: Color = contentColorFor(sheetBackgroundColor),
-    scrimColor: Color = ModalBottomSheetDefaults.scrimColor,
     content: @Composable () -> Unit
 ) {
     val scope = rememberCoroutineScope()
@@ -332,7 +327,7 @@
         Box(Modifier.fillMaxSize()) {
             content()
             Scrim(
-                color = scrimColor,
+                color = ModalBottomSheetDefaults.scrimColor,
                 onDismiss = {
                     if (sheetState.confirmStateChange(Hidden)) {
                         scope.launch { sheetState.hide() }
@@ -505,5 +500,5 @@
      */
     val scrimColor: Color
         @Composable
-        get() = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.32f)
+        get() = MaterialTheme.colorScheme.scrim.copy(alpha = .32f)
 }
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ActionButton.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ActionButton.kt
index b94840f..04a2c07 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ActionButton.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ActionButton.kt
@@ -16,6 +16,7 @@
 
 package com.android.credentialmanager.common.ui
 
+import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.padding
 import com.android.credentialmanager.R
 import androidx.compose.material.Icon
@@ -33,7 +34,6 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.unit.dp
-import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme
 
 @Composable
 fun ActionButton(text: String, onClick: () -> Unit) {
@@ -42,12 +42,10 @@
         onClick = onClick,
         colors = ButtonDefaults.textButtonColors(
             contentColor = MaterialTheme.colorScheme.primary,
-        )
+        ),
+        contentPadding = PaddingValues(start = 12.dp, top = 10.dp, end = 12.dp, bottom = 10.dp),
     ) {
-        LargeLabelText(
-            text = text,
-            modifier = Modifier.padding(vertical = 10.dp, horizontal = 12.dp),
-        )
+        LargeLabelText(text = text)
     }
 }
 
@@ -69,7 +67,7 @@
             contentDescription = if (toggleState.value)
                 stringResource(R.string.content_description_show_password) else
                 stringResource(R.string.content_description_hide_password),
-            tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant
+            tint = MaterialTheme.colorScheme.onSurfaceVariant,
         )
     }
 }
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/BottomSheet.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/BottomSheet.kt
index c4d96cc..edc902e 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/BottomSheet.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/BottomSheet.kt
@@ -18,7 +18,6 @@
 
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.ColumnScope
-import androidx.compose.material3.MaterialTheme
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.ui.Modifier
@@ -27,6 +26,7 @@
 import com.android.credentialmanager.common.material.ModalBottomSheetValue
 import com.android.credentialmanager.common.material.rememberModalBottomSheetState
 import com.android.credentialmanager.ui.theme.EntryShape
+import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme
 
 /** Draws a modal bottom sheet with the same styles and effects shared by various flows. */
 @Composable
@@ -39,11 +39,10 @@
         skipHalfExpanded = true
     )
     ModalBottomSheetLayout(
-        sheetBackgroundColor = MaterialTheme.colorScheme.surface,
+        sheetBackgroundColor = LocalAndroidColorScheme.current.colorSurfaceBright,
         modifier = Modifier.background(Color.Transparent),
         sheetState = state,
         sheetContent = sheetContent,
-        scrimColor = MaterialTheme.colorScheme.scrim.copy(alpha = 0.8f),
         sheetShape = EntryShape.TopRoundedCorner,
     ) {}
     LaunchedEffect(state.currentValue) {
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Cards.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Cards.kt
index a622e07..3976f9a 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Cards.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Cards.kt
@@ -16,19 +16,22 @@
 
 package com.android.credentialmanager.common.ui
 
-import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.ColumnScope
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyListScope
 import androidx.compose.material3.Card
 import androidx.compose.material3.CardDefaults
-import androidx.compose.material3.MaterialTheme
 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.unit.dp
+import com.android.credentialmanager.ui.theme.Shapes
+import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme
 
 /**
  * Container card for the whole sheet.
@@ -40,21 +43,20 @@
 fun SheetContainerCard(
     topAppBar: (@Composable () -> Unit)? = null,
     modifier: Modifier = Modifier,
-    content: @Composable ColumnScope.() -> Unit,
+    contentVerticalArrangement: Arrangement.Vertical = Arrangement.Top,
+    content: LazyListScope.() -> Unit,
 ) {
     Card(
         modifier = modifier.fillMaxWidth().wrapContentHeight(),
         border = null,
         colors = CardDefaults.cardColors(
-            containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(
-                ElevationTokens.Level1
-            ),
+            containerColor = LocalAndroidColorScheme.current.colorSurfaceBright,
         ),
     ) {
         if (topAppBar != null) {
             topAppBar()
         }
-        Column(
+        LazyColumn(
             modifier = Modifier.padding(
                 start = 24.dp,
                 end = 24.dp,
@@ -63,6 +65,7 @@
             ).fillMaxWidth().wrapContentHeight(),
             horizontalAlignment = Alignment.CenterHorizontally,
             content = content,
+            verticalArrangement = contentVerticalArrangement,
         )
     }
 }
@@ -79,7 +82,7 @@
 ) {
     Card(
         modifier = modifier.fillMaxWidth().wrapContentHeight(),
-        shape = MaterialTheme.shapes.medium,
+        shape = Shapes.medium,
         border = null,
         colors = CardDefaults.cardColors(
             containerColor = Color.Transparent,
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ColorScheme.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ColorScheme.kt
deleted file mode 100644
index b2489fd..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ColorScheme.kt
+++ /dev/null
@@ -1,30 +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.credentialmanager.common.ui
-
-import androidx.compose.material3.ColorScheme
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.compositeOver
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.dp
-import kotlin.math.ln
-
-fun ColorScheme.surfaceColorAtElevation(elevation: Dp): Color {
-    if (elevation == 0.dp) return surface
-    val alpha = ((4.5f * ln(elevation.value + 1)) + 2f) / 100f
-    return surfaceTint.copy(alpha = alpha).compositeOver(surface)
-}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Columns.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Columns.kt
deleted file mode 100644
index 23ad53c..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Columns.kt
+++ /dev/null
@@ -1,31 +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.credentialmanager.common.ui
-
-import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.lazy.LazyColumn
-import androidx.compose.foundation.lazy.LazyListScope
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.unit.dp
-
-@Composable
-fun EntryListColumn(content: LazyListScope.() -> Unit) {
-    LazyColumn(
-        verticalArrangement = Arrangement.spacedBy(2.dp),
-        content = content,
-    )
-}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ConfirmButton.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ConfirmButton.kt
index 8f48f6b..c09a692 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ConfirmButton.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ConfirmButton.kt
@@ -16,6 +16,7 @@
 
 package com.android.credentialmanager.common.ui
 
+import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.padding
 import androidx.compose.material3.ButtonDefaults
 import androidx.compose.material3.FilledTonalButton
@@ -33,11 +34,9 @@
         colors = ButtonDefaults.filledTonalButtonColors(
             containerColor = MaterialTheme.colorScheme.primary,
             contentColor = MaterialTheme.colorScheme.onPrimary,
-        )
+        ),
+        contentPadding = PaddingValues(start = 24.dp, top = 10.dp, end = 24.dp, bottom = 10.dp),
     ) {
-        LargeLabelText(
-            text = text,
-            modifier = Modifier.padding(vertical = 10.dp, horizontal = 24.dp),
-        )
+        LargeLabelText(text = text)
     }
 }
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
index 0eaaf97..bba08f4 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
@@ -50,9 +50,11 @@
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.text.AnnotatedString
 import androidx.compose.ui.text.input.PasswordVisualTransformation
+import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 import com.android.credentialmanager.R
 import com.android.credentialmanager.ui.theme.EntryShape
+import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme
 import com.android.credentialmanager.ui.theme.Shapes
 
 @Composable
@@ -73,7 +75,14 @@
     passwordValue: String? = null,
     /** If true, draws a trailing lock icon. */
     isLockedAuthEntry: Boolean = false,
+    enforceOneLine: Boolean = false,
 ) {
+    val iconPadding = Modifier.wrapContentSize().padding(
+        // Horizontal padding should be 16dp, but the suggestion chip itself
+        // has 8dp horizontal elements padding
+        start = 8.dp, top = 16.dp, bottom = 16.dp
+    )
+    val iconSize = Modifier.size(24.dp)
     SuggestionChip(
         modifier = modifier.fillMaxWidth().wrapContentHeight(),
         onClick = onClick,
@@ -81,13 +90,23 @@
         label = {
             Row(
                 horizontalArrangement = Arrangement.SpaceBetween,
-                modifier = Modifier.fillMaxWidth().padding(all = 16.dp),
+                modifier = Modifier.fillMaxWidth().padding(
+                    // Total end padding should be 16dp, but the suggestion chip itself
+                    // has 8dp horizontal elements padding
+                    horizontal = 8.dp, vertical = 16.dp,
+                ),
+                // Make sure the trailing icon and text column are centered vertically.
                 verticalAlignment = Alignment.CenterVertically,
             ) {
-                Column(modifier = Modifier.wrapContentSize()) {
-                    SmallTitleText(entryHeadlineText)
+                // Apply weight so that the trailing icon can always show.
+                Column(modifier = Modifier.wrapContentHeight().fillMaxWidth().weight(1f)) {
+                    SmallTitleText(text = entryHeadlineText, enforceOneLine = enforceOneLine)
                     if (passwordValue != null) {
-                        Row(modifier = Modifier.fillMaxWidth()) {
+                        Row(
+                            modifier = Modifier.fillMaxWidth().padding(top = 4.dp),
+                            verticalAlignment = Alignment.CenterVertically,
+                            horizontalArrangement = Arrangement.Start,
+                        ) {
                             val visualTransformation = remember { PasswordVisualTransformation() }
                             val originalPassword by remember {
                                 mutableStateOf(passwordValue)
@@ -99,9 +118,14 @@
                                     ).text.text
                                 )
                             }
-                            BodySmallText(displayedPassword.value)
+                            BodySmallText(
+                                text = displayedPassword.value,
+                                // Apply weight to allow visibility button to render first so that
+                                // it doesn't get squeezed out by a super long password.
+                                modifier = Modifier.wrapContentSize().weight(1f, fill = false),
+                            )
                             ToggleVisibilityButton(
-                                modifier = Modifier.padding(start = 5.dp).size(24.dp),
+                                modifier = Modifier.padding(start = 12.dp).size(24.dp),
                                 onToggle = {
                                     if (it) {
                                         displayedPassword.value = originalPassword
@@ -114,14 +138,14 @@
                             )
                         }
                     } else if (entrySecondLineText != null) {
-                        BodySmallText(entrySecondLineText)
+                        BodySmallText(text = entrySecondLineText, enforceOneLine = enforceOneLine)
                     }
                     if (entryThirdLineText != null) {
-                        BodySmallText(entryThirdLineText)
+                        BodySmallText(text = entryThirdLineText, enforceOneLine = enforceOneLine)
                     }
                 }
                 if (isLockedAuthEntry) {
-                    Box(modifier = Modifier.wrapContentSize().padding(end = 16.dp)) {
+                    Box(modifier = Modifier.wrapContentSize().padding(start = 16.dp)) {
                         Icon(
                             imageVector = Icons.Outlined.Lock,
                             // Decorative purpose only.
@@ -137,10 +161,9 @@
         if (iconImageBitmap != null) {
             if (shouldApplyIconImageBitmapTint) {
                 {
-                    Box(modifier = Modifier.wrapContentSize()
-                        .padding(start = 16.dp, top = 16.dp, bottom = 16.dp)) {
+                    Box(modifier = iconPadding) {
                         Icon(
-                            modifier = Modifier.size(24.dp),
+                            modifier = iconSize,
                             bitmap = iconImageBitmap,
                             tint = MaterialTheme.colorScheme.onSurfaceVariant,
                             // Decorative purpose only.
@@ -150,10 +173,9 @@
                 }
             } else {
                 {
-                    Box(modifier = Modifier.wrapContentSize()
-                        .padding(start = 16.dp, top = 16.dp, bottom = 16.dp)) {
+                    Box(modifier = iconPadding) {
                         Image(
-                            modifier = Modifier.size(24.dp),
+                            modifier = iconSize,
                             bitmap = iconImageBitmap,
                             // Decorative purpose only.
                             contentDescription = null,
@@ -163,10 +185,9 @@
             }
         } else if (iconImageVector != null) {
             {
-                Box(modifier = Modifier.wrapContentSize()
-                    .padding(start = 16.dp, top = 16.dp, bottom = 16.dp)) {
+                Box(modifier = iconPadding) {
                     Icon(
-                        modifier = Modifier.size(24.dp),
+                        modifier = iconSize,
                         imageVector = iconImageVector,
                         tint = MaterialTheme.colorScheme.onSurfaceVariant,
                         // Decorative purpose only.
@@ -176,10 +197,9 @@
             }
         } else if (iconPainter != null) {
             {
-                Box(modifier = Modifier.wrapContentSize()
-                    .padding(start = 16.dp, top = 16.dp, bottom = 16.dp)) {
+                Box(modifier = iconPadding) {
                     Icon(
-                        modifier = Modifier.size(24.dp),
+                        modifier = iconSize,
                         painter = iconPainter,
                         tint = MaterialTheme.colorScheme.onSurfaceVariant,
                         // Decorative purpose only.
@@ -192,9 +212,7 @@
         },
         border = null,
         colors = SuggestionChipDefaults.suggestionChipColors(
-            containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(
-                ElevationTokens.Level3
-            ),
+            containerColor = LocalAndroidColorScheme.current.colorSurfaceContainerHigh,
             // TODO: remove?
             labelColor = MaterialTheme.colorScheme.onSurfaceVariant,
             iconContentColor = MaterialTheme.colorScheme.onSurfaceVariant,
@@ -298,6 +316,7 @@
 fun MoreOptionTopAppBar(
     text: String,
     onNavigationIconClicked: () -> Unit,
+    bottomPadding: Dp,
 ) {
     TopAppBar(
         title = {
@@ -305,7 +324,7 @@
         },
         navigationIcon = {
             IconButton(
-                modifier = Modifier.padding(top = 8.dp, bottom = 8.dp, start = 4.dp),
+                modifier = Modifier.padding(top = 8.dp, bottom = 8.dp, start = 4.dp).size(48.dp),
                 onClick = onNavigationIconClicked
             ) {
                 Box(
@@ -317,13 +336,13 @@
                         contentDescription = stringResource(
                             R.string.accessibility_back_arrow_button
                         ),
-                        modifier = Modifier.size(16.dp),
+                        modifier = Modifier.size(24.dp),
                         tint = MaterialTheme.colorScheme.onSurfaceVariant,
                     )
                 }
             }
         },
         colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent),
-        modifier = Modifier.padding(top = 12.dp, bottom = 8.dp)
+        modifier = Modifier.padding(top = 12.dp, bottom = bottomPadding)
     )
 }
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SectionHeader.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SectionHeader.kt
index c63771e..3581228 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SectionHeader.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SectionHeader.kt
@@ -38,7 +38,7 @@
 
 @Composable
 private fun InternalSectionHeader(text: String, color: Color) {
-    Row(modifier = Modifier.fillMaxWidth().wrapContentHeight()) {
+    Row(modifier = Modifier.fillMaxWidth().wrapContentHeight().padding(top = 8.dp)) {
         SectionHeaderText(
             text,
             modifier = Modifier.padding(top = 20.dp, bottom = 8.dp),
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SnackBar.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SnackBar.kt
index 8061da7..514ff90 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SnackBar.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SnackBar.kt
@@ -75,7 +75,7 @@
                         action()
                     }
                     IconButton(onClick = onDismiss, modifier = Modifier.padding(
-                        top = 18.dp, bottom = 18.dp, start = 16.dp, end = 24.dp,
+                        top = 4.dp, bottom = 4.dp, start = 2.dp, end = 10.dp,
                     )) {
                         Icon(
                             Icons.Filled.Close,
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SystemUiControllerUtils.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SystemUiControllerUtils.kt
new file mode 100644
index 0000000..a619523
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SystemUiControllerUtils.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.credentialmanager.common.ui
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.graphics.Color
+import com.android.compose.SystemUiController
+import com.android.credentialmanager.common.material.ModalBottomSheetDefaults
+import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme
+
+@Composable
+fun setTransparentSystemBarsColor(sysUiController: SystemUiController) {
+    sysUiController.setSystemBarsColor(color = Color.Transparent, darkIcons = false)
+}
+
+@Composable
+fun setBottomSheetSystemBarsColor(sysUiController: SystemUiController) {
+    sysUiController.setStatusBarColor(
+        color = ModalBottomSheetDefaults.scrimColor,
+        darkIcons = false
+    )
+    sysUiController.setNavigationBarColor(
+        color = LocalAndroidColorScheme.current.colorSurfaceBright,
+        darkIcons = false
+    )
+}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Texts.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Texts.kt
index 8f7c37e..22871bcb 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Texts.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Texts.kt
@@ -16,13 +16,14 @@
 
 package com.android.credentialmanager.common.ui
 
-import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.foundation.layout.wrapContentSize
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.style.TextOverflow
 
 /**
  * The headline for a screen. E.g. "Create a passkey for X", "Choose a saved sign-in for X".
@@ -32,7 +33,7 @@
 @Composable
 fun HeadlineText(text: String, modifier: Modifier = Modifier) {
     Text(
-        modifier = modifier.wrapContentHeight(),
+        modifier = modifier.wrapContentSize(),
         text = text,
         color = MaterialTheme.colorScheme.onSurface,
         textAlign = TextAlign.Center,
@@ -46,7 +47,7 @@
 @Composable
 fun BodyMediumText(text: String, modifier: Modifier = Modifier) {
     Text(
-        modifier = modifier.wrapContentHeight(),
+        modifier = modifier.wrapContentSize(),
         text = text,
         color = MaterialTheme.colorScheme.onSurfaceVariant,
         style = MaterialTheme.typography.bodyMedium,
@@ -57,12 +58,14 @@
  * Body-small typography; on-surface-variant color.
  */
 @Composable
-fun BodySmallText(text: String, modifier: Modifier = Modifier) {
+fun BodySmallText(text: String, modifier: Modifier = Modifier, enforceOneLine: Boolean = false) {
     Text(
-        modifier = modifier.wrapContentHeight(),
+        modifier = modifier.wrapContentSize(),
         text = text,
         color = MaterialTheme.colorScheme.onSurfaceVariant,
         style = MaterialTheme.typography.bodySmall,
+        overflow = TextOverflow.Ellipsis,
+        maxLines = if (enforceOneLine) 1 else Int.MAX_VALUE
     )
 }
 
@@ -72,7 +75,7 @@
 @Composable
 fun LargeTitleText(text: String, modifier: Modifier = Modifier) {
     Text(
-        modifier = modifier.wrapContentHeight(),
+        modifier = modifier.wrapContentSize(),
         text = text,
         color = MaterialTheme.colorScheme.onSurface,
         style = MaterialTheme.typography.titleLarge,
@@ -83,12 +86,14 @@
  * Title-small typography; on-surface color.
  */
 @Composable
-fun SmallTitleText(text: String, modifier: Modifier = Modifier) {
+fun SmallTitleText(text: String, modifier: Modifier = Modifier, enforceOneLine: Boolean = false) {
     Text(
-        modifier = modifier.wrapContentHeight(),
+        modifier = modifier.wrapContentSize(),
         text = text,
         color = MaterialTheme.colorScheme.onSurface,
         style = MaterialTheme.typography.titleSmall,
+        overflow = TextOverflow.Ellipsis,
+        maxLines = if (enforceOneLine) 1 else Int.MAX_VALUE
     )
 }
 
@@ -98,7 +103,7 @@
 @Composable
 fun SectionHeaderText(text: String, modifier: Modifier = Modifier, color: Color) {
     Text(
-        modifier = modifier.wrapContentHeight(),
+        modifier = modifier.wrapContentSize(),
         text = text,
         color = color,
         style = MaterialTheme.typography.titleSmall,
@@ -111,7 +116,7 @@
 @Composable
 fun SnackbarContentText(text: String, modifier: Modifier = Modifier) {
     Text(
-        modifier = modifier.wrapContentHeight(),
+        modifier = modifier.wrapContentSize(),
         text = text,
         color = MaterialTheme.colorScheme.inverseOnSurface,
         style = MaterialTheme.typography.bodyMedium,
@@ -124,7 +129,7 @@
 @Composable
 fun SnackbarActionText(text: String, modifier: Modifier = Modifier) {
     Text(
-        modifier = modifier.wrapContentHeight(),
+        modifier = modifier.wrapContentSize(),
         text = text,
         color = MaterialTheme.colorScheme.inversePrimary,
         style = MaterialTheme.typography.labelLarge,
@@ -137,7 +142,7 @@
 @Composable
 fun LargeLabelTextOnSurfaceVariant(text: String, modifier: Modifier = Modifier) {
     Text(
-        modifier = modifier.wrapContentHeight(),
+        modifier = modifier.wrapContentSize(),
         text = text,
         textAlign = TextAlign.Center,
         color = MaterialTheme.colorScheme.onSurfaceVariant,
@@ -151,7 +156,7 @@
 @Composable
 fun LargeLabelText(text: String, modifier: Modifier = Modifier) {
     Text(
-        modifier = modifier.wrapContentHeight(),
+        modifier = modifier.wrapContentSize(),
         text = text,
         textAlign = TextAlign.Center,
         style = MaterialTheme.typography.labelLarge,
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
index 379b3e3..bcf692f 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
@@ -1,4 +1,18 @@
-@file:OptIn(ExperimentalMaterial3Api::class)
+/*
+ * 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.credentialmanager.createflow
 
@@ -8,22 +22,22 @@
 import androidx.compose.foundation.isSystemInDarkTheme
 import androidx.compose.foundation.Image
 import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.layout.wrapContentHeight
-import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.material3.Divider
-import androidx.compose.material3.ExperimentalMaterial3Api
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.outlined.NewReleases
 import androidx.compose.material.icons.filled.Add
+import androidx.compose.material.icons.outlined.QrCodeScanner
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
-import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.asImageBitmap
@@ -31,6 +45,7 @@
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.unit.dp
 import androidx.core.graphics.drawable.toBitmap
+import com.android.compose.rememberSystemUiController
 import com.android.credentialmanager.CredentialSelectorViewModel
 import com.android.credentialmanager.R
 import com.android.credentialmanager.common.BaseEntry
@@ -43,7 +58,6 @@
 import com.android.credentialmanager.common.ui.CredentialContainerCard
 import com.android.credentialmanager.common.ui.CtaButtonRow
 import com.android.credentialmanager.common.ui.Entry
-import com.android.credentialmanager.common.ui.EntryListColumn
 import com.android.credentialmanager.common.ui.HeadlineIcon
 import com.android.credentialmanager.common.ui.LargeLabelTextOnSurfaceVariant
 import com.android.credentialmanager.common.ui.ModalBottomSheet
@@ -52,6 +66,9 @@
 import com.android.credentialmanager.common.ui.SheetContainerCard
 import com.android.credentialmanager.common.ui.PasskeyBenefitRow
 import com.android.credentialmanager.common.ui.HeadlineText
+import com.android.credentialmanager.common.ui.setBottomSheetSystemBarsColor
+import com.android.credentialmanager.logging.CreateCredentialEvent
+import com.android.internal.logging.UiEventLogger.UiEventEnum
 
 @Composable
 fun CreateCredentialScreen(
@@ -59,6 +76,8 @@
     createCredentialUiState: CreateCredentialUiState,
     providerActivityLauncher: ManagedActivityResultLauncher<IntentSenderRequest, ActivityResult>
 ) {
+    val sysUiController = rememberSystemUiController()
+    setBottomSheetSystemBarsColor(sysUiController)
     ModalBottomSheet(
         sheetContent = {
             // Hide the sheet content as opposed to the whole bottom sheet to maintain the scrim
@@ -68,71 +87,89 @@
                 ProviderActivityState.NOT_APPLICABLE -> {
                     when (createCredentialUiState.currentScreenState) {
                         CreateScreenState.PASSKEY_INTRO -> PasskeyIntroCard(
-                            onConfirm = viewModel::createFlowOnConfirmIntro,
-                            onLearnMore = viewModel::createFlowOnLearnMore,
+                                onConfirm = viewModel::createFlowOnConfirmIntro,
+                                onLearnMore = viewModel::createFlowOnLearnMore,
+                                onLog = { viewModel.logUiEvent(it) },
                         )
                         CreateScreenState.PROVIDER_SELECTION -> ProviderSelectionCard(
-                            requestDisplayInfo = createCredentialUiState.requestDisplayInfo,
-                            disabledProviderList = createCredentialUiState.disabledProviders,
-                            sortedCreateOptionsPairs =
-                            createCredentialUiState.sortedCreateOptionsPairs,
-                            hasRemoteEntry = createCredentialUiState.remoteEntry != null,
-                            onOptionSelected =
-                            viewModel::createFlowOnEntrySelectedFromFirstUseScreen,
-                            onDisabledProvidersSelected =
-                            viewModel::createFlowOnDisabledProvidersSelected,
-                            onMoreOptionsSelected =
-                            viewModel::createFlowOnMoreOptionsSelectedOnProviderSelection,
+                                requestDisplayInfo = createCredentialUiState.requestDisplayInfo,
+                                disabledProviderList = createCredentialUiState
+                                        .disabledProviders,
+                                sortedCreateOptionsPairs =
+                                createCredentialUiState.sortedCreateOptionsPairs,
+                                hasRemoteEntry = createCredentialUiState.remoteEntry != null,
+                                onOptionSelected =
+                                viewModel::createFlowOnEntrySelectedFromFirstUseScreen,
+                                onDisabledProvidersSelected =
+                                viewModel::createFlowOnDisabledProvidersSelected,
+                                onMoreOptionsSelected =
+                                viewModel::createFlowOnMoreOptionsSelectedOnProviderSelection,
+                                onLog = { viewModel.logUiEvent(it) },
                         )
                         CreateScreenState.CREATION_OPTION_SELECTION -> CreationSelectionCard(
-                            requestDisplayInfo = createCredentialUiState.requestDisplayInfo,
-                            enabledProviderList = createCredentialUiState.enabledProviders,
-                            providerInfo = createCredentialUiState.activeEntry?.activeProvider!!,
-                            hasDefaultProvider = createCredentialUiState.hasDefaultProvider,
-                            createOptionInfo =
-                            createCredentialUiState.activeEntry.activeEntryInfo
-                                as CreateOptionInfo,
-                            onOptionSelected = viewModel::createFlowOnEntrySelected,
-                            onConfirm = viewModel::createFlowOnConfirmEntrySelected,
-                            onMoreOptionsSelected =
-                            viewModel::createFlowOnMoreOptionsSelectedOnCreationSelection,
+                                requestDisplayInfo = createCredentialUiState.requestDisplayInfo,
+                                enabledProviderList = createCredentialUiState.enabledProviders,
+                                providerInfo = createCredentialUiState
+                                        .activeEntry?.activeProvider!!,
+                                hasDefaultProvider = createCredentialUiState.hasDefaultProvider,
+                                createOptionInfo =
+                                createCredentialUiState.activeEntry.activeEntryInfo
+                                        as CreateOptionInfo,
+                                onOptionSelected = viewModel::createFlowOnEntrySelected,
+                                onConfirm = viewModel::createFlowOnConfirmEntrySelected,
+                                onMoreOptionsSelected =
+                                viewModel::createFlowOnMoreOptionsSelectedOnCreationSelection,
+                                onLog = { viewModel.logUiEvent(it) },
                         )
                         CreateScreenState.MORE_OPTIONS_SELECTION -> MoreOptionsSelectionCard(
-                            requestDisplayInfo = createCredentialUiState.requestDisplayInfo,
-                            enabledProviderList = createCredentialUiState.enabledProviders,
-                            disabledProviderList = createCredentialUiState.disabledProviders,
-                            sortedCreateOptionsPairs =
-                            createCredentialUiState.sortedCreateOptionsPairs,
-                            hasDefaultProvider = createCredentialUiState.hasDefaultProvider,
-                            isFromProviderSelection =
-                            createCredentialUiState.isFromProviderSelection!!,
-                            onBackProviderSelectionButtonSelected =
-                            viewModel::createFlowOnBackProviderSelectionButtonSelected,
-                            onBackCreationSelectionButtonSelected =
-                            viewModel::createFlowOnBackCreationSelectionButtonSelected,
-                            onOptionSelected =
-                            viewModel::createFlowOnEntrySelectedFromMoreOptionScreen,
-                            onDisabledProvidersSelected =
-                            viewModel::createFlowOnDisabledProvidersSelected,
-                            onRemoteEntrySelected = viewModel::createFlowOnEntrySelected,
+                                requestDisplayInfo = createCredentialUiState.requestDisplayInfo,
+                                enabledProviderList = createCredentialUiState.enabledProviders,
+                                disabledProviderList = createCredentialUiState
+                                        .disabledProviders,
+                                sortedCreateOptionsPairs =
+                                createCredentialUiState.sortedCreateOptionsPairs,
+                                hasDefaultProvider = createCredentialUiState.hasDefaultProvider,
+                                isFromProviderSelection =
+                                createCredentialUiState.isFromProviderSelection!!,
+                                onBackProviderSelectionButtonSelected =
+                                viewModel::createFlowOnBackProviderSelectionButtonSelected,
+                                onBackCreationSelectionButtonSelected =
+                                viewModel::createFlowOnBackCreationSelectionButtonSelected,
+                                onOptionSelected =
+                                viewModel::createFlowOnEntrySelectedFromMoreOptionScreen,
+                                onDisabledProvidersSelected =
+                                viewModel::createFlowOnDisabledProvidersSelected,
+                                onRemoteEntrySelected = viewModel::createFlowOnEntrySelected,
+                                onLog = { viewModel.logUiEvent(it) },
                         )
-                        CreateScreenState.MORE_OPTIONS_ROW_INTRO -> MoreOptionsRowIntroCard(
-                            providerInfo = createCredentialUiState.activeEntry?.activeProvider!!,
-                            onChangeDefaultSelected = viewModel::createFlowOnChangeDefaultSelected,
-                            onUseOnceSelected = viewModel::createFlowOnUseOnceSelected,
-                        )
+                        CreateScreenState.MORE_OPTIONS_ROW_INTRO -> {
+                            if (createCredentialUiState.activeEntry == null) {
+                                viewModel.onIllegalUiState("Expect active entry to be non-null" +
+                                        " upon default provider dialog.")
+                            } else {
+                                MoreOptionsRowIntroCard(
+                                        selectedEntry = createCredentialUiState.activeEntry,
+                                        onIllegalScreenState = viewModel::onIllegalUiState,
+                                        onChangeDefaultSelected =
+                                        viewModel::createFlowOnChangeDefaultSelected,
+                                        onUseOnceSelected = viewModel::createFlowOnUseOnceSelected,
+                                        onLog = { viewModel.logUiEvent(it) },
+                                )
+                            }
+                        }
                         CreateScreenState.EXTERNAL_ONLY_SELECTION -> ExternalOnlySelectionCard(
-                            requestDisplayInfo = createCredentialUiState.requestDisplayInfo,
-                            activeRemoteEntry =
-                            createCredentialUiState.activeEntry?.activeEntryInfo!!,
-                            onOptionSelected = viewModel::createFlowOnEntrySelected,
-                            onConfirm = viewModel::createFlowOnConfirmEntrySelected,
+                                requestDisplayInfo = createCredentialUiState.requestDisplayInfo,
+                                activeRemoteEntry =
+                                createCredentialUiState.activeEntry?.activeEntryInfo!!,
+                                onOptionSelected = viewModel::createFlowOnEntrySelected,
+                                onConfirm = viewModel::createFlowOnConfirmEntrySelected,
+                                onLog = { viewModel.logUiEvent(it) },
                         )
-                        CreateScreenState.MORE_ABOUT_PASSKEYS_INTRO ->
-                            MoreAboutPasskeysIntroCard(
+                        CreateScreenState.MORE_ABOUT_PASSKEYS_INTRO -> MoreAboutPasskeysIntroCard(
                                 onBackPasskeyIntroButtonSelected =
                                 viewModel::createFlowOnBackPasskeyIntroButtonSelected,
-                            )
+                                onLog = { viewModel.logUiEvent(it) },
+                        )
                     }
                 }
                 ProviderActivityState.READY_TO_LAUNCH -> {
@@ -141,9 +178,14 @@
                     LaunchedEffect(viewModel.uiState.providerActivityState) {
                         viewModel.launchProviderUi(providerActivityLauncher)
                     }
+                    viewModel.uiMetrics.log(
+                            CreateCredentialEvent
+                                    .CREDMAN_CREATE_CRED_PROVIDER_ACTIVITY_READY_TO_LAUNCH)
                 }
                 ProviderActivityState.PENDING -> {
                     // Hide our content when the provider activity is active.
+                    viewModel.uiMetrics.log(
+                            CreateCredentialEvent.CREDMAN_CREATE_CRED_PROVIDER_ACTIVITY_PENDING)
                 }
             }
         },
@@ -155,56 +197,72 @@
 fun PasskeyIntroCard(
     onConfirm: () -> Unit,
     onLearnMore: () -> Unit,
+    onLog: @Composable (UiEventEnum) -> Unit,
 ) {
     SheetContainerCard {
-        val onboardingImageResource = remember {
-            mutableStateOf(R.drawable.ic_passkeys_onboarding)
+        item {
+            val onboardingImageResource = remember {
+                mutableStateOf(R.drawable.ic_passkeys_onboarding)
+            }
+            if (isSystemInDarkTheme()) {
+                onboardingImageResource.value = R.drawable.ic_passkeys_onboarding_dark
+            } else {
+                onboardingImageResource.value = R.drawable.ic_passkeys_onboarding
+            }
+            Row(
+                modifier = Modifier.wrapContentHeight().fillMaxWidth(),
+                horizontalArrangement = Arrangement.Center,
+            ) {
+                Image(
+                    painter = painterResource(onboardingImageResource.value),
+                    contentDescription = null,
+                    modifier = Modifier.size(316.dp, 168.dp)
+                )
+            }
         }
-        if (isSystemInDarkTheme()) {
-            onboardingImageResource.value = R.drawable.ic_passkeys_onboarding_dark
-        } else {
-            onboardingImageResource.value = R.drawable.ic_passkeys_onboarding
+        item { Divider(thickness = 16.dp, color = Color.Transparent) }
+        item { HeadlineText(text = stringResource(R.string.passkey_creation_intro_title)) }
+        item { Divider(thickness = 16.dp, color = Color.Transparent) }
+        item {
+            PasskeyBenefitRow(
+                leadingIconPainter = painterResource(R.drawable.ic_passkeys_onboarding_password),
+                text = stringResource(R.string.passkey_creation_intro_body_password),
+            )
         }
-        Image(
-            painter = painterResource(onboardingImageResource.value),
-            contentDescription = null,
-            modifier = Modifier
-                .align(alignment = Alignment.CenterHorizontally).size(316.dp, 168.dp)
-        )
-        Divider(thickness = 16.dp, color = Color.Transparent)
-        HeadlineText(text = stringResource(R.string.passkey_creation_intro_title))
-        Divider(thickness = 16.dp, color = Color.Transparent)
-        PasskeyBenefitRow(
-            leadingIconPainter = painterResource(R.drawable.ic_passkeys_onboarding_password),
-            text = stringResource(R.string.passkey_creation_intro_body_password),
-        )
-        Divider(thickness = 16.dp, color = Color.Transparent)
-        PasskeyBenefitRow(
-            leadingIconPainter = painterResource(R.drawable.ic_passkeys_onboarding_fingerprint),
-            text = stringResource(R.string.passkey_creation_intro_body_fingerprint),
-        )
-        Divider(thickness = 16.dp, color = Color.Transparent)
-        PasskeyBenefitRow(
-            leadingIconPainter = painterResource(R.drawable.ic_passkeys_onboarding_device),
-            text = stringResource(R.string.passkey_creation_intro_body_device),
-        )
-        Divider(thickness = 24.dp, color = Color.Transparent)
+        item { Divider(thickness = 16.dp, color = Color.Transparent) }
+        item {
+            PasskeyBenefitRow(
+                leadingIconPainter = painterResource(R.drawable.ic_passkeys_onboarding_fingerprint),
+                text = stringResource(R.string.passkey_creation_intro_body_fingerprint),
+            )
+        }
+        item { Divider(thickness = 16.dp, color = Color.Transparent) }
+        item {
+            PasskeyBenefitRow(
+                leadingIconPainter = painterResource(R.drawable.ic_passkeys_onboarding_device),
+                text = stringResource(R.string.passkey_creation_intro_body_device),
+            )
+        }
+        item { Divider(thickness = 24.dp, color = Color.Transparent) }
 
-        CtaButtonRow(
-            leftButton = {
-                ActionButton(
-                    stringResource(R.string.string_learn_more),
-                    onClick = onLearnMore
-                )
-            },
-            rightButton = {
-                ConfirmButton(
-                    stringResource(R.string.string_continue),
-                    onClick = onConfirm
-                )
-            },
-        )
+        item {
+            CtaButtonRow(
+                leftButton = {
+                    ActionButton(
+                        stringResource(R.string.string_learn_more),
+                        onClick = onLearnMore
+                    )
+                },
+                rightButton = {
+                    ConfirmButton(
+                        stringResource(R.string.string_continue),
+                        onClick = onConfirm
+                    )
+                },
+            )
+        }
     }
+    onLog(CreateCredentialEvent.CREDMAN_CREATE_CRED_PASSKEY_INTRO)
 }
 
 @Composable
@@ -216,32 +274,35 @@
     onOptionSelected: (ActiveEntry) -> Unit,
     onDisabledProvidersSelected: () -> Unit,
     onMoreOptionsSelected: () -> Unit,
+    onLog: @Composable (UiEventEnum) -> Unit,
 ) {
     SheetContainerCard {
-        HeadlineIcon(bitmap = requestDisplayInfo.typeIcon.toBitmap().asImageBitmap())
-        Divider(thickness = 16.dp, color = Color.Transparent)
-        HeadlineText(
-            text = stringResource(
-                R.string.choose_provider_title,
-                when (requestDisplayInfo.type) {
-                    CredentialType.PASSKEY ->
-                        stringResource(R.string.passkeys)
-                    CredentialType.PASSWORD ->
-                        stringResource(R.string.passwords)
-                    CredentialType.UNKNOWN -> stringResource(R.string.sign_in_info)
-                }
+        item { HeadlineIcon(bitmap = requestDisplayInfo.typeIcon.toBitmap().asImageBitmap()) }
+        item { Divider(thickness = 16.dp, color = Color.Transparent) }
+        item {
+            HeadlineText(
+                text = stringResource(
+                    R.string.choose_provider_title,
+                    when (requestDisplayInfo.type) {
+                        CredentialType.PASSKEY ->
+                            stringResource(R.string.passkeys)
+                        CredentialType.PASSWORD ->
+                            stringResource(R.string.passwords)
+                        CredentialType.UNKNOWN -> stringResource(R.string.sign_in_info)
+                    }
+                )
             )
-        )
-        Divider(thickness = 24.dp, color = Color.Transparent)
+        }
+        item { Divider(thickness = 24.dp, color = Color.Transparent) }
 
-        BodyMediumText(text = stringResource(R.string.choose_provider_body))
-        Divider(thickness = 16.dp, color = Color.Transparent)
-        CredentialContainerCard {
-            LazyColumn(
-                verticalArrangement = Arrangement.spacedBy(2.dp)
-            ) {
-                sortedCreateOptionsPairs.forEach { entry ->
-                    item {
+        item { BodyMediumText(text = stringResource(R.string.choose_provider_body)) }
+        item { Divider(thickness = 16.dp, color = Color.Transparent) }
+        item {
+            CredentialContainerCard {
+                Column(
+                    verticalArrangement = Arrangement.spacedBy(2.dp)
+                ) {
+                    sortedCreateOptionsPairs.forEach { entry ->
                         MoreOptionsInfoRow(
                             requestDisplayInfo = requestDisplayInfo,
                             providerInfo = entry.second,
@@ -256,8 +317,6 @@
                             }
                         )
                     }
-                }
-                item {
                     MoreOptionsDisabledProvidersRow(
                         disabledProviders = disabledProviderList,
                         onDisabledProvidersSelected = onDisabledProvidersSelected,
@@ -266,32 +325,36 @@
             }
         }
         if (hasRemoteEntry) {
-            Divider(thickness = 24.dp, color = Color.Transparent)
-            CtaButtonRow(
-                leftButton = {
-                    ActionButton(
-                        stringResource(R.string.string_more_options),
-                        onMoreOptionsSelected
-                    )
-                }
-            )
+            item { Divider(thickness = 24.dp, color = Color.Transparent) }
+            item {
+                CtaButtonRow(
+                    leftButton = {
+                        ActionButton(
+                            stringResource(R.string.string_more_options),
+                            onMoreOptionsSelected
+                        )
+                    }
+                )
+            }
         }
     }
+    onLog(CreateCredentialEvent.CREDMAN_CREATE_CRED_PROVIDER_SELECTION)
 }
 
 @Composable
 fun MoreOptionsSelectionCard(
-    requestDisplayInfo: RequestDisplayInfo,
-    enabledProviderList: List<EnabledProviderInfo>,
-    disabledProviderList: List<DisabledProviderInfo>?,
-    sortedCreateOptionsPairs: List<Pair<CreateOptionInfo, EnabledProviderInfo>>,
-    hasDefaultProvider: Boolean,
-    isFromProviderSelection: Boolean,
-    onBackProviderSelectionButtonSelected: () -> Unit,
-    onBackCreationSelectionButtonSelected: () -> Unit,
-    onOptionSelected: (ActiveEntry) -> Unit,
-    onDisabledProvidersSelected: () -> Unit,
-    onRemoteEntrySelected: (BaseEntry) -> Unit,
+        requestDisplayInfo: RequestDisplayInfo,
+        enabledProviderList: List<EnabledProviderInfo>,
+        disabledProviderList: List<DisabledProviderInfo>?,
+        sortedCreateOptionsPairs: List<Pair<CreateOptionInfo, EnabledProviderInfo>>,
+        hasDefaultProvider: Boolean,
+        isFromProviderSelection: Boolean,
+        onBackProviderSelectionButtonSelected: () -> Unit,
+        onBackCreationSelectionButtonSelected: () -> Unit,
+        onOptionSelected: (ActiveEntry) -> Unit,
+        onDisabledProvidersSelected: () -> Unit,
+        onRemoteEntrySelected: (BaseEntry) -> Unit,
+        onLog: @Composable (UiEventEnum) -> Unit,
 ) {
     SheetContainerCard(topAppBar = {
         MoreOptionTopAppBar(
@@ -308,16 +371,17 @@
             onNavigationIconClicked =
             if (isFromProviderSelection) onBackProviderSelectionButtonSelected
             else onBackCreationSelectionButtonSelected,
+            bottomPadding = 16.dp,
         )
     }) {
-        Divider(thickness = 16.dp, color = Color.Transparent)
-        CredentialContainerCard {
-            EntryListColumn {
-                // Only in the flows with default provider(not first time use) we can show the
-                // createOptions here, or they will be shown on ProviderSelectionCard
-                if (hasDefaultProvider) {
-                    sortedCreateOptionsPairs.forEach { entry ->
-                        item {
+        // bottom padding already
+        item {
+            CredentialContainerCard {
+                Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
+                    // Only in the flows with default provider(not first time use) we can show the
+                    // createOptions here, or they will be shown on ProviderSelectionCard
+                    if (hasDefaultProvider) {
+                        sortedCreateOptionsPairs.forEach { entry ->
                             MoreOptionsInfoRow(
                                 requestDisplayInfo = requestDisplayInfo,
                                 providerInfo = entry.second,
@@ -329,111 +393,131 @@
                                             entry.first
                                         )
                                     )
-                                })
+                                }
+                            )
                         }
-                    }
-                    item {
                         MoreOptionsDisabledProvidersRow(
                             disabledProviders = disabledProviderList,
                             onDisabledProvidersSelected =
                             onDisabledProvidersSelected,
                         )
                     }
-                }
-                enabledProviderList.forEach {
-                    if (it.remoteEntry != null) {
-                        item {
+                    enabledProviderList.forEach {
+                        if (it.remoteEntry != null) {
                             RemoteEntryRow(
                                 remoteInfo = it.remoteEntry!!,
                                 onRemoteEntrySelected = onRemoteEntrySelected,
                             )
+                            return@forEach
                         }
-                        return@forEach
                     }
                 }
             }
         }
     }
+    onLog(CreateCredentialEvent.CREDMAN_CREATE_CRED_MORE_OPTIONS_SELECTION)
 }
 
 @Composable
 fun MoreOptionsRowIntroCard(
-    providerInfo: EnabledProviderInfo,
-    onChangeDefaultSelected: () -> Unit,
-    onUseOnceSelected: () -> Unit,
+        selectedEntry: ActiveEntry,
+        onIllegalScreenState: (String) -> Unit,
+        onChangeDefaultSelected: () -> Unit,
+        onUseOnceSelected: () -> Unit,
+        onLog: @Composable (UiEventEnum) -> Unit,
 ) {
-    SheetContainerCard {
-        HeadlineIcon(imageVector = Icons.Outlined.NewReleases)
-        Divider(thickness = 24.dp, color = Color.Transparent)
-        HeadlineText(
-            text = stringResource(
-                R.string.use_provider_for_all_title,
-                providerInfo.displayName
-            )
-        )
-        Divider(thickness = 24.dp, color = Color.Transparent)
-        BodyMediumText(text = stringResource(R.string.use_provider_for_all_description))
-        CtaButtonRow(
-            leftButton = {
-                ActionButton(
-                    stringResource(R.string.use_once),
-                    onClick = onUseOnceSelected
-                )
-            },
-            rightButton = {
-                ConfirmButton(
-                    stringResource(R.string.set_as_default),
-                    onClick = onChangeDefaultSelected
-                )
-            },
-        )
+    val entryInfo = selectedEntry.activeEntryInfo
+    if (entryInfo !is CreateOptionInfo) {
+        onIllegalScreenState("Encountered unexpected type of entry during the default provider" +
+            " dialog: ${entryInfo::class}")
+        return
     }
+    SheetContainerCard {
+        item { HeadlineIcon(imageVector = Icons.Outlined.NewReleases) }
+        item { Divider(thickness = 24.dp, color = Color.Transparent) }
+        item {
+            HeadlineText(
+                text = stringResource(
+                    R.string.use_provider_for_all_title, selectedEntry.activeProvider.displayName)
+            )
+        }
+        item { Divider(thickness = 24.dp, color = Color.Transparent) }
+        item {
+            BodyMediumText(text = stringResource(
+                R.string.use_provider_for_all_description, entryInfo.userProviderDisplayName))
+        }
+        item { Divider(thickness = 24.dp, color = Color.Transparent) }
+        item {
+            CtaButtonRow(
+                leftButton = {
+                    ActionButton(
+                        stringResource(R.string.use_once),
+                        onClick = onUseOnceSelected
+                    )
+                },
+                rightButton = {
+                    ConfirmButton(
+                        stringResource(R.string.set_as_default),
+                        onClick = onChangeDefaultSelected
+                    )
+                },
+            )
+        }
+    }
+    onLog(CreateCredentialEvent.CREDMAN_CREATE_CRED_MORE_OPTIONS_ROW_INTRO)
 }
 
 @Composable
 fun CreationSelectionCard(
-    requestDisplayInfo: RequestDisplayInfo,
-    enabledProviderList: List<EnabledProviderInfo>,
-    providerInfo: EnabledProviderInfo,
-    createOptionInfo: CreateOptionInfo,
-    onOptionSelected: (BaseEntry) -> Unit,
-    onConfirm: () -> Unit,
-    onMoreOptionsSelected: () -> Unit,
-    hasDefaultProvider: Boolean,
+        requestDisplayInfo: RequestDisplayInfo,
+        enabledProviderList: List<EnabledProviderInfo>,
+        providerInfo: EnabledProviderInfo,
+        createOptionInfo: CreateOptionInfo,
+        onOptionSelected: (BaseEntry) -> Unit,
+        onConfirm: () -> Unit,
+        onMoreOptionsSelected: () -> Unit,
+        hasDefaultProvider: Boolean,
+        onLog: @Composable (UiEventEnum) -> Unit,
 ) {
     SheetContainerCard {
-        HeadlineIcon(
-            bitmap = providerInfo.icon.toBitmap().asImageBitmap(),
-            tint = Color.Unspecified,
-        )
-        Divider(thickness = 4.dp, color = Color.Transparent)
-        LargeLabelTextOnSurfaceVariant(text = providerInfo.displayName)
-        Divider(thickness = 16.dp, color = Color.Transparent)
-        HeadlineText(
-            text = when (requestDisplayInfo.type) {
-                CredentialType.PASSKEY -> stringResource(
-                    R.string.choose_create_option_passkey_title,
-                    requestDisplayInfo.appName
-                )
-                CredentialType.PASSWORD -> stringResource(
-                    R.string.choose_create_option_password_title,
-                    requestDisplayInfo.appName
-                )
-                CredentialType.UNKNOWN -> stringResource(
-                    R.string.choose_create_option_sign_in_title,
-                    requestDisplayInfo.appName
-                )
-            }
-        )
-        Divider(thickness = 24.dp, color = Color.Transparent)
-        CredentialContainerCard {
-            PrimaryCreateOptionRow(
-                requestDisplayInfo = requestDisplayInfo,
-                entryInfo = createOptionInfo,
-                onOptionSelected = onOptionSelected
+        item {
+            HeadlineIcon(
+                bitmap = providerInfo.icon.toBitmap().asImageBitmap(),
+                tint = Color.Unspecified,
             )
         }
-        Divider(thickness = 24.dp, color = Color.Transparent)
+        item { Divider(thickness = 4.dp, color = Color.Transparent) }
+        item { LargeLabelTextOnSurfaceVariant(text = providerInfo.displayName) }
+        item { Divider(thickness = 16.dp, color = Color.Transparent) }
+        item {
+            HeadlineText(
+                text = when (requestDisplayInfo.type) {
+                    CredentialType.PASSKEY -> stringResource(
+                        R.string.choose_create_option_passkey_title,
+                        requestDisplayInfo.appName
+                    )
+                    CredentialType.PASSWORD -> stringResource(
+                        R.string.choose_create_option_password_title,
+                        requestDisplayInfo.appName
+                    )
+                    CredentialType.UNKNOWN -> stringResource(
+                        R.string.choose_create_option_sign_in_title,
+                        requestDisplayInfo.appName
+                    )
+                }
+            )
+        }
+        item { Divider(thickness = 24.dp, color = Color.Transparent) }
+        item {
+            CredentialContainerCard {
+                PrimaryCreateOptionRow(
+                    requestDisplayInfo = requestDisplayInfo,
+                    entryInfo = createOptionInfo,
+                    onOptionSelected = onOptionSelected
+                )
+            }
+        }
+        item { Divider(thickness = 24.dp, color = Color.Transparent) }
         var createOptionsSize = 0
         var remoteEntry: RemoteInfo? = null
         enabledProviderList.forEach { enabledProvider ->
@@ -450,107 +534,119 @@
         } else {
             createOptionsSize > 1 || remoteEntry != null
         }
-        CtaButtonRow(
-            leftButton = if (shouldShowMoreOptionsButton) {
-                {
-                    ActionButton(
-                        stringResource(R.string.string_more_options),
-                        onMoreOptionsSelected
+        item {
+            CtaButtonRow(
+                leftButton = if (shouldShowMoreOptionsButton) {
+                    {
+                        ActionButton(
+                            stringResource(R.string.string_more_options),
+                            onMoreOptionsSelected
+                        )
+                    }
+                } else null,
+                rightButton = {
+                    ConfirmButton(
+                        stringResource(R.string.string_continue),
+                        onClick = onConfirm
                     )
-                }
-            } else null,
-            rightButton = {
-                ConfirmButton(
-                    stringResource(R.string.string_continue),
-                    onClick = onConfirm
-                )
-            },
-        )
-        if (createOptionInfo.footerDescription != null) {
-            Divider(
-                thickness = 1.dp,
-                color = MaterialTheme.colorScheme.outlineVariant,
-                modifier = Modifier.padding(vertical = 16.dp)
+                },
             )
-            BodySmallText(text = createOptionInfo.footerDescription)
+        }
+        if (createOptionInfo.footerDescription != null) {
+            item {
+                Divider(
+                    thickness = 1.dp,
+                    color = MaterialTheme.colorScheme.outlineVariant,
+                    modifier = Modifier.padding(vertical = 16.dp)
+                )
+            }
+            item {
+                Row(modifier = Modifier.fillMaxWidth().wrapContentHeight()) {
+                    BodySmallText(text = createOptionInfo.footerDescription)
+                }
+            }
         }
     }
+    onLog(CreateCredentialEvent.CREDMAN_CREATE_CRED_CREATION_OPTION_SELECTION)
 }
 
 @Composable
 fun ExternalOnlySelectionCard(
-    requestDisplayInfo: RequestDisplayInfo,
-    activeRemoteEntry: BaseEntry,
-    onOptionSelected: (BaseEntry) -> Unit,
-    onConfirm: () -> Unit,
+        requestDisplayInfo: RequestDisplayInfo,
+        activeRemoteEntry: BaseEntry,
+        onOptionSelected: (BaseEntry) -> Unit,
+        onConfirm: () -> Unit,
+        onLog: @Composable (UiEventEnum) -> Unit,
 ) {
     SheetContainerCard {
-        HeadlineIcon(painter = painterResource(R.drawable.ic_other_devices))
-        Divider(thickness = 16.dp, color = Color.Transparent)
-        HeadlineText(text = stringResource(R.string.create_passkey_in_other_device_title))
-        Divider(
-            thickness = 24.dp,
-            color = Color.Transparent
-        )
-        CredentialContainerCard {
-            PrimaryCreateOptionRow(
-                requestDisplayInfo = requestDisplayInfo,
-                entryInfo = activeRemoteEntry,
-                onOptionSelected = onOptionSelected
+        item { HeadlineIcon(imageVector = Icons.Outlined.QrCodeScanner) }
+        item { Divider(thickness = 16.dp, color = Color.Transparent) }
+        item { HeadlineText(text = stringResource(R.string.create_passkey_in_other_device_title)) }
+        item { Divider(thickness = 24.dp, color = Color.Transparent) }
+        item {
+            CredentialContainerCard {
+                PrimaryCreateOptionRow(
+                    requestDisplayInfo = requestDisplayInfo,
+                    entryInfo = activeRemoteEntry,
+                    onOptionSelected = onOptionSelected
+                )
+            }
+        }
+        item { Divider(thickness = 24.dp, color = Color.Transparent) }
+        item {
+            CtaButtonRow(
+                rightButton = {
+                    ConfirmButton(
+                        stringResource(R.string.string_continue),
+                        onClick = onConfirm
+                    )
+                },
             )
         }
-        Divider(thickness = 24.dp, color = Color.Transparent)
-        CtaButtonRow(
-            rightButton = {
-                ConfirmButton(
-                    stringResource(R.string.string_continue),
-                    onClick = onConfirm
-                )
-            },
-        )
     }
+    onLog(CreateCredentialEvent.CREDMAN_CREATE_CRED_EXTERNAL_ONLY_SELECTION)
 }
 
 @Composable
 fun MoreAboutPasskeysIntroCard(
     onBackPasskeyIntroButtonSelected: () -> Unit,
+    onLog: @Composable (UiEventEnum) -> Unit,
 ) {
-    SheetContainerCard(topAppBar = {
-        MoreOptionTopAppBar(
-            text = stringResource(R.string.more_about_passkeys_title),
-            onNavigationIconClicked = onBackPasskeyIntroButtonSelected,
-        )
-    }) {
-        LazyColumn(
-            modifier = Modifier.fillMaxWidth().wrapContentHeight(),
-            verticalArrangement = Arrangement.spacedBy(8.dp)
-        ) {
-            item {
-                MoreAboutPasskeySectionHeader(
-                    text = stringResource(R.string.passwordless_technology_title)
-                )
-                BodyMediumText(text = stringResource(R.string.passwordless_technology_detail))
-            }
-            item {
-                MoreAboutPasskeySectionHeader(
-                    text = stringResource(R.string.public_key_cryptography_title)
-                )
-                BodyMediumText(text = stringResource(R.string.public_key_cryptography_detail))
-            }
-            item {
-                MoreAboutPasskeySectionHeader(
-                    text = stringResource(R.string.improved_account_security_title)
-                )
-                BodyMediumText(text = stringResource(R.string.improved_account_security_detail))
-            }
-            item {
-                MoreAboutPasskeySectionHeader(
-                    text = stringResource(R.string.seamless_transition_title)
-                )
-                BodyMediumText(text = stringResource(R.string.seamless_transition_detail))
-            }
+    SheetContainerCard(
+        topAppBar = {
+            MoreOptionTopAppBar(
+                text = stringResource(R.string.more_about_passkeys_title),
+                onNavigationIconClicked = onBackPasskeyIntroButtonSelected,
+                bottomPadding = 0.dp,
+            )
+        },
+    ) {
+        item {
+            MoreAboutPasskeySectionHeader(
+                text = stringResource(R.string.passwordless_technology_title)
+            )
+            BodyMediumText(text = stringResource(R.string.passwordless_technology_detail))
+        }
+        item {
+            MoreAboutPasskeySectionHeader(
+                text = stringResource(R.string.public_key_cryptography_title)
+            )
+            BodyMediumText(text = stringResource(R.string.public_key_cryptography_detail))
+        }
+        item {
+            MoreAboutPasskeySectionHeader(
+                text = stringResource(R.string.improved_account_security_title)
+            )
+            BodyMediumText(text = stringResource(R.string.improved_account_security_detail))
+        }
+        item {
+            MoreAboutPasskeySectionHeader(
+                text = stringResource(R.string.seamless_transition_title)
+            )
+            BodyMediumText(text = stringResource(R.string.seamless_transition_detail))
         }
     }
+    onLog(CreateCredentialEvent.CREDMAN_CREATE_CRED_MORE_ABOUT_PASSKEYS_INTRO)
 }
 
 @Composable
@@ -589,6 +685,7 @@
         // This subtitle would never be null for create password
             requestDisplayInfo.subtitle ?: ""
         else null,
+        enforceOneLine = true,
     )
 }
 
@@ -665,7 +762,7 @@
 ) {
     Entry(
         onClick = { onRemoteEntrySelected(remoteInfo) },
-        iconPainter = painterResource(R.drawable.ic_other_devices),
+        iconImageVector = Icons.Outlined.QrCodeScanner,
         entryHeadlineText = stringResource(R.string.another_device),
     )
 }
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
index ce4e936..4332fb3 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
@@ -38,7 +38,9 @@
 )
 
 internal fun hasContentToDisplay(state: CreateCredentialUiState): Boolean {
-    return state.sortedCreateOptionsPairs.isNotEmpty()
+    return state.sortedCreateOptionsPairs.isNotEmpty() ||
+        (!state.requestDisplayInfo.preferImmediatelyAvailableCredentials &&
+            state.remoteEntry != null)
 }
 
 open class ProviderInfo(
@@ -67,7 +69,7 @@
     entrySubkey: String,
     pendingIntent: PendingIntent?,
     fillInIntent: Intent?,
-    val userProviderDisplayName: String?,
+    val userProviderDisplayName: String,
     val profileIcon: Drawable?,
     val passwordCount: Int?,
     val passkeyCount: Int?,
@@ -104,6 +106,7 @@
   val type: CredentialType,
   val appName: String,
   val typeIcon: Drawable,
+  val preferImmediatelyAvailableCredentials: Boolean,
 )
 
 /**
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
index 54f8e5c..dd60763 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
@@ -22,11 +22,14 @@
 import androidx.activity.result.IntentSenderRequest
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.heightIn
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.wrapContentHeight
-import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.items
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.outlined.QrCodeScanner
 import androidx.compose.material3.Divider
 import androidx.compose.material3.TextButton
 import androidx.compose.runtime.Composable
@@ -38,6 +41,7 @@
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.unit.dp
 import androidx.core.graphics.drawable.toBitmap
+import com.android.compose.rememberSystemUiController
 import com.android.credentialmanager.CredentialSelectorViewModel
 import com.android.credentialmanager.R
 import com.android.credentialmanager.common.BaseEntry
@@ -56,6 +60,10 @@
 import com.android.credentialmanager.common.ui.HeadlineText
 import com.android.credentialmanager.common.ui.CredentialListSectionHeader
 import com.android.credentialmanager.common.ui.Snackbar
+import com.android.credentialmanager.common.ui.setTransparentSystemBarsColor
+import com.android.credentialmanager.common.ui.setBottomSheetSystemBarsColor
+import com.android.credentialmanager.logging.GetCredentialEvent
+import com.android.internal.logging.UiEventLogger.UiEventEnum
 
 @Composable
 fun GetCredentialScreen(
@@ -63,20 +71,29 @@
     getCredentialUiState: GetCredentialUiState,
     providerActivityLauncher: ManagedActivityResultLauncher<IntentSenderRequest, ActivityResult>
 ) {
+    val sysUiController = rememberSystemUiController()
     if (getCredentialUiState.currentScreenState == GetScreenState.REMOTE_ONLY) {
+        setTransparentSystemBarsColor(sysUiController)
         RemoteCredentialSnackBarScreen(
             onClick = viewModel::getFlowOnMoreOptionOnSnackBarSelected,
             onCancel = viewModel::onUserCancel,
+            onLog = { viewModel.logUiEvent(it) },
         )
+        viewModel.uiMetrics.log(GetCredentialEvent.CREDMAN_GET_CRED_SCREEN_REMOTE_ONLY)
     } else if (getCredentialUiState.currentScreenState
         == GetScreenState.UNLOCKED_AUTH_ENTRIES_ONLY) {
+        setTransparentSystemBarsColor(sysUiController)
         EmptyAuthEntrySnackBarScreen(
             authenticationEntryList =
             getCredentialUiState.providerDisplayInfo.authenticationEntryList,
             onCancel = viewModel::silentlyFinishActivity,
             onLastLockedAuthEntryNotFound = viewModel::onLastLockedAuthEntryNotFoundError,
+            onLog = { viewModel.logUiEvent(it) },
         )
+        viewModel.uiMetrics.log(GetCredentialEvent
+                .CREDMAN_GET_CRED_SCREEN_UNLOCKED_AUTH_ENTRIES_ONLY)
     } else {
+        setBottomSheetSystemBarsColor(sysUiController)
         ModalBottomSheet(
             sheetContent = {
                 // Hide the sheet content as opposed to the whole bottom sheet to maintain the scrim
@@ -94,7 +111,10 @@
                                 onEntrySelected = viewModel::getFlowOnEntrySelected,
                                 onConfirm = viewModel::getFlowOnConfirmEntrySelected,
                                 onMoreOptionSelected = viewModel::getFlowOnMoreOptionSelected,
+                                onLog = { viewModel.logUiEvent(it) },
                             )
+                            viewModel.uiMetrics.log(GetCredentialEvent
+                                    .CREDMAN_GET_CRED_SCREEN_PRIMARY_SELECTION)
                         } else {
                             AllSignInOptionCard(
                                 providerInfoList = getCredentialUiState.providerInfoList,
@@ -104,7 +124,10 @@
                                 viewModel::getFlowOnBackToPrimarySelectionScreen,
                                 onCancel = viewModel::onUserCancel,
                                 isNoAccount = getCredentialUiState.isNoAccount,
+                                onLog = { viewModel.logUiEvent(it) },
                             )
+                            viewModel.uiMetrics.log(GetCredentialEvent
+                                    .CREDMAN_GET_CRED_SCREEN_ALL_SIGN_IN_OPTIONS)
                         }
                     }
                     ProviderActivityState.READY_TO_LAUNCH -> {
@@ -113,9 +136,13 @@
                         LaunchedEffect(viewModel.uiState.providerActivityState) {
                             viewModel.launchProviderUi(providerActivityLauncher)
                         }
+                        viewModel.uiMetrics.log(GetCredentialEvent
+                                .CREDMAN_GET_CRED_PROVIDER_ACTIVITY_READY_TO_LAUNCH)
                     }
                     ProviderActivityState.PENDING -> {
                         // Hide our content when the provider activity is active.
+                        viewModel.uiMetrics.log(GetCredentialEvent
+                                .CREDMAN_GET_CRED_PROVIDER_ACTIVITY_PENDING)
                     }
                 }
             },
@@ -134,75 +161,83 @@
     onEntrySelected: (BaseEntry) -> Unit,
     onConfirm: () -> Unit,
     onMoreOptionSelected: () -> Unit,
+    onLog: @Composable (UiEventEnum) -> Unit,
 ) {
     val sortedUserNameToCredentialEntryList =
         providerDisplayInfo.sortedUserNameToCredentialEntryList
     val authenticationEntryList = providerDisplayInfo.authenticationEntryList
     SheetContainerCard {
-        HeadlineText(
-            text = stringResource(
-                if (sortedUserNameToCredentialEntryList
-                        .size == 1 && authenticationEntryList.isEmpty()
-                ) {
-                    if (sortedUserNameToCredentialEntryList.first()
-                            .sortedCredentialEntryList.first().credentialType
-                        == CredentialType.PASSKEY
-                    ) R.string.get_dialog_title_use_passkey_for
-                    else R.string.get_dialog_title_use_sign_in_for
-                } else if (
-                    sortedUserNameToCredentialEntryList
-                        .isEmpty() && authenticationEntryList.size == 1
-                ) {
-                    R.string.get_dialog_title_use_sign_in_for
-                } else R.string.get_dialog_title_choose_sign_in_for,
-                requestDisplayInfo.appName
-            ),
-        )
-        Divider(thickness = 24.dp, color = Color.Transparent)
-        CredentialContainerCard {
-            val usernameForCredentialSize = sortedUserNameToCredentialEntryList.size
-            val authenticationEntrySize = authenticationEntryList.size
-            LazyColumn(
-                verticalArrangement = Arrangement.spacedBy(2.dp)
-            ) {
-                // Show max 4 entries in this primary page
-                if (usernameForCredentialSize + authenticationEntrySize <= 4) {
-                    items(sortedUserNameToCredentialEntryList) {
-                        CredentialEntryRow(
-                            credentialEntryInfo = it.sortedCredentialEntryList.first(),
-                            onEntrySelected = onEntrySelected,
-                        )
-                    }
-                    items(authenticationEntryList) {
-                        AuthenticationEntryRow(
-                            authenticationEntryInfo = it,
-                            onEntrySelected = onEntrySelected,
-                        )
-                    }
-                } else if (usernameForCredentialSize < 4) {
-                    items(sortedUserNameToCredentialEntryList) {
-                        CredentialEntryRow(
-                            credentialEntryInfo = it.sortedCredentialEntryList.first(),
-                            onEntrySelected = onEntrySelected,
-                        )
-                    }
-                    items(authenticationEntryList.take(4 - usernameForCredentialSize)) {
-                        AuthenticationEntryRow(
-                            authenticationEntryInfo = it,
-                            onEntrySelected = onEntrySelected,
-                        )
-                    }
-                } else {
-                    items(sortedUserNameToCredentialEntryList.take(4)) {
-                        CredentialEntryRow(
-                            credentialEntryInfo = it.sortedCredentialEntryList.first(),
-                            onEntrySelected = onEntrySelected,
-                        )
+        item {
+            HeadlineText(
+                text = stringResource(
+                    if (sortedUserNameToCredentialEntryList
+                            .size == 1 && authenticationEntryList.isEmpty()
+                    ) {
+                        if (sortedUserNameToCredentialEntryList.first()
+                                .sortedCredentialEntryList.first().credentialType
+                            == CredentialType.PASSKEY
+                        ) R.string.get_dialog_title_use_passkey_for
+                        else R.string.get_dialog_title_use_sign_in_for
+                    } else if (
+                        sortedUserNameToCredentialEntryList
+                            .isEmpty() && authenticationEntryList.size == 1
+                    ) {
+                        R.string.get_dialog_title_use_sign_in_for
+                    } else R.string.get_dialog_title_choose_sign_in_for,
+                    requestDisplayInfo.appName
+                ),
+            )
+        }
+        item { Divider(thickness = 24.dp, color = Color.Transparent) }
+        item {
+            CredentialContainerCard {
+                Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
+                    val usernameForCredentialSize = sortedUserNameToCredentialEntryList.size
+                    val authenticationEntrySize = authenticationEntryList.size
+                    // Show max 4 entries in this primary page
+                    if (usernameForCredentialSize + authenticationEntrySize <= 4) {
+                        sortedUserNameToCredentialEntryList.forEach {
+                            CredentialEntryRow(
+                                credentialEntryInfo = it.sortedCredentialEntryList.first(),
+                                onEntrySelected = onEntrySelected,
+                                enforceOneLine = true,
+                            )
+                        }
+                        authenticationEntryList.forEach {
+                            AuthenticationEntryRow(
+                                authenticationEntryInfo = it,
+                                onEntrySelected = onEntrySelected,
+                                enforceOneLine = true,
+                            )
+                        }
+                    } else if (usernameForCredentialSize < 4) {
+                        sortedUserNameToCredentialEntryList.forEach {
+                            CredentialEntryRow(
+                                credentialEntryInfo = it.sortedCredentialEntryList.first(),
+                                onEntrySelected = onEntrySelected,
+                                enforceOneLine = true,
+                            )
+                        }
+                        authenticationEntryList.take(4 - usernameForCredentialSize).forEach {
+                            AuthenticationEntryRow(
+                                authenticationEntryInfo = it,
+                                onEntrySelected = onEntrySelected,
+                                enforceOneLine = true,
+                            )
+                        }
+                    } else {
+                        sortedUserNameToCredentialEntryList.take(4).forEach {
+                            CredentialEntryRow(
+                                credentialEntryInfo = it.sortedCredentialEntryList.first(),
+                                onEntrySelected = onEntrySelected,
+                                enforceOneLine = true,
+                            )
+                        }
                     }
                 }
             }
         }
-        Divider(thickness = 24.dp, color = Color.Transparent)
+        item { Divider(thickness = 24.dp, color = Color.Transparent) }
         var totalEntriesCount = sortedUserNameToCredentialEntryList
             .flatMap { it.sortedCredentialEntryList }.size + authenticationEntryList
             .size + providerInfoList.flatMap { it.actionEntryList }.size
@@ -210,25 +245,28 @@
         // Row horizontalArrangement differs on only one actionButton(should place on most
         // left)/only one confirmButton(should place on most right)/two buttons exist the same
         // time(should be one on the left, one on the right)
-        CtaButtonRow(
-            leftButton = if (totalEntriesCount > 1) {
-                {
-                    ActionButton(
-                        stringResource(R.string.get_dialog_use_saved_passkey_for),
-                        onMoreOptionSelected
-                    )
-                }
-            } else null,
-            rightButton = if (activeEntry != null) { // Only one sign-in options exist
-                {
-                    ConfirmButton(
-                        stringResource(R.string.string_continue),
-                        onClick = onConfirm
-                    )
-                }
-            } else null,
-        )
+        item {
+            CtaButtonRow(
+                leftButton = if (totalEntriesCount > 1) {
+                    {
+                        ActionButton(
+                            stringResource(R.string.get_dialog_use_saved_passkey_for),
+                            onMoreOptionSelected
+                        )
+                    }
+                } else null,
+                rightButton = if (activeEntry != null) { // Only one sign-in options exist
+                    {
+                        ConfirmButton(
+                            stringResource(R.string.string_continue),
+                            onClick = onConfirm
+                        )
+                    }
+                } else null,
+            )
+        }
     }
+    onLog(GetCredentialEvent.CREDMAN_GET_CRED_PRIMARY_SELECTION_CARD)
 }
 
 /** Draws the secondary credential selection page, where all sign-in options are listed. */
@@ -240,6 +278,7 @@
     onBackButtonClicked: () -> Unit,
     onCancel: () -> Unit,
     isNoAccount: Boolean,
+    onLog: @Composable (UiEventEnum) -> Unit,
 ) {
     val sortedUserNameToCredentialEntryList =
         providerDisplayInfo.sortedUserNameToCredentialEntryList
@@ -248,51 +287,44 @@
         MoreOptionTopAppBar(
             text = stringResource(R.string.get_dialog_title_sign_in_options),
             onNavigationIconClicked = if (isNoAccount) onCancel else onBackButtonClicked,
+            bottomPadding = 0.dp,
         )
     }) {
-        LazyColumn {
-            // For username
-            items(sortedUserNameToCredentialEntryList) { item ->
-                PerUserNameCredentials(
-                    perUserNameCredentialEntryList = item,
+        // For username
+        items(sortedUserNameToCredentialEntryList) { item ->
+            PerUserNameCredentials(
+                perUserNameCredentialEntryList = item,
+                onEntrySelected = onEntrySelected,
+            )
+        }
+        // Locked password manager
+        if (authenticationEntryList.isNotEmpty()) {
+            item {
+                LockedCredentials(
+                    authenticationEntryList = authenticationEntryList,
                     onEntrySelected = onEntrySelected,
                 )
             }
-            // Locked password manager
-            if (authenticationEntryList.isNotEmpty()) {
-                item {
-                    LockedCredentials(
-                        authenticationEntryList = authenticationEntryList,
-                        onEntrySelected = onEntrySelected,
-                    )
-                }
-            }
-            // From another device
-            val remoteEntry = providerDisplayInfo.remoteEntry
-            if (remoteEntry != null) {
-                item {
-                    RemoteEntryCard(
-                        remoteEntry = remoteEntry,
-                        onEntrySelected = onEntrySelected,
-                    )
-                }
-            }
+        }
+        // From another device
+        val remoteEntry = providerDisplayInfo.remoteEntry
+        if (remoteEntry != null) {
             item {
-                Divider(
-                    thickness = 1.dp,
-                    color = Color.LightGray,
-                    modifier = Modifier.padding(top = 16.dp)
-                )
-            }
-            // Manage sign-ins (action chips)
-            item {
-                ActionChips(
-                    providerInfoList = providerInfoList,
-                    onEntrySelected = onEntrySelected
+                RemoteEntryCard(
+                    remoteEntry = remoteEntry,
+                    onEntrySelected = onEntrySelected,
                 )
             }
         }
+        // Manage sign-ins (action chips)
+        item {
+            ActionChips(
+                providerInfoList = providerInfoList,
+                onEntrySelected = onEntrySelected
+            )
+        }
     }
+    onLog(GetCredentialEvent.CREDMAN_GET_CRED_ALL_SIGN_IN_OPTION_CARD)
 }
 
 // TODO: create separate rows for primary and secondary pages.
@@ -335,7 +367,7 @@
         ) {
             Entry(
                 onClick = { onEntrySelected(remoteEntry) },
-                iconPainter = painterResource(R.drawable.ic_other_devices),
+                iconImageVector = Icons.Outlined.QrCodeScanner,
                 entryHeadlineText = stringResource(
                     R.string.get_dialog_option_headline_use_a_different_device
                 ),
@@ -390,28 +422,32 @@
 fun CredentialEntryRow(
     credentialEntryInfo: CredentialEntryInfo,
     onEntrySelected: (BaseEntry) -> Unit,
+    enforceOneLine: Boolean = false,
 ) {
     Entry(
         onClick = { onEntrySelected(credentialEntryInfo) },
         iconImageBitmap = credentialEntryInfo.icon?.toBitmap()?.asImageBitmap(),
+        shouldApplyIconImageBitmapTint = credentialEntryInfo.shouldTintIcon,
         // Fall back to iconPainter if iconImageBitmap isn't available
         iconPainter =
-        if (credentialEntryInfo.icon == null) painterResource(R.drawable.ic_other_sign_in)
+        if (credentialEntryInfo.icon == null) painterResource(R.drawable.ic_other_sign_in_24)
         else null,
         entryHeadlineText = credentialEntryInfo.userName,
         entrySecondLineText = if (
             credentialEntryInfo.credentialType == CredentialType.PASSWORD) {
             "••••••••••••"
         } else {
-            if (TextUtils.isEmpty(credentialEntryInfo.displayName))
-                credentialEntryInfo.credentialTypeDisplayName
-            else
-                credentialEntryInfo.credentialTypeDisplayName +
-                    stringResource(
-                        R.string.get_dialog_sign_in_type_username_separator
-                    ) +
-                    credentialEntryInfo.displayName
+            val itemsToDisplay = listOf(
+                credentialEntryInfo.displayName,
+                credentialEntryInfo.credentialTypeDisplayName,
+                credentialEntryInfo.providerDisplayName
+            ).filterNot(TextUtils::isEmpty)
+            if (itemsToDisplay.isEmpty()) null
+            else itemsToDisplay.joinToString(
+                separator = stringResource(R.string.get_dialog_sign_in_type_username_separator)
+            )
         },
+        enforceOneLine = enforceOneLine,
     )
 }
 
@@ -419,6 +455,7 @@
 fun AuthenticationEntryRow(
     authenticationEntryInfo: AuthenticationEntryInfo,
     onEntrySelected: (BaseEntry) -> Unit,
+    enforceOneLine: Boolean = false,
 ) {
     Entry(
         onClick = { onEntrySelected(authenticationEntryInfo) },
@@ -430,6 +467,7 @@
             else R.string.locked_credential_entry_label_subtext_tap_to_unlock
         ),
         isLockedAuthEntry = !authenticationEntryInfo.isUnlockedAndEmpty,
+        enforceOneLine = enforceOneLine,
     )
 }
 
@@ -450,22 +488,24 @@
 fun RemoteCredentialSnackBarScreen(
     onClick: (Boolean) -> Unit,
     onCancel: () -> Unit,
+    onLog: @Composable (UiEventEnum) -> Unit,
 ) {
     Snackbar(
         action = {
             TextButton(
-                modifier = Modifier.padding(top = 12.dp, bottom = 12.dp, start = 16.dp),
+                modifier = Modifier.padding(top = 4.dp, bottom = 4.dp, start = 16.dp)
+                    .heightIn(min = 32.dp),
                 onClick = { onClick(true) },
+                contentPadding =
+                PaddingValues(start = 0.dp, top = 6.dp, end = 0.dp, bottom = 6.dp),
             ) {
-                SnackbarActionText(
-                    text = stringResource(R.string.snackbar_action),
-                    Modifier.padding(vertical = 6.dp)
-                )
+                SnackbarActionText(text = stringResource(R.string.snackbar_action))
             }
         },
         onDismiss = onCancel,
         contentText = stringResource(R.string.get_dialog_use_saved_passkey_for),
     )
+    onLog(GetCredentialEvent.CREDMAN_GET_CRED_REMOTE_CRED_SNACKBAR_SCREEN)
 }
 
 @Composable
@@ -473,6 +513,7 @@
     authenticationEntryList: List<AuthenticationEntryInfo>,
     onCancel: () -> Unit,
     onLastLockedAuthEntryNotFound: () -> Unit,
+    onLog: @Composable (UiEventEnum) -> Unit,
 ) {
     val lastLocked = authenticationEntryList.firstOrNull({ it.isLastUnlocked })
     if (lastLocked == null) {
@@ -484,4 +525,5 @@
         onDismiss = onCancel,
         contentText = stringResource(R.string.no_sign_in_info_in, lastLocked.providerDisplayName),
     )
+    onLog(GetCredentialEvent.CREDMAN_GET_CRED_SCREEN_EMPTY_AUTH_SNACKBAR_SCREEN)
 }
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
index d1f0f81..263a632 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
@@ -37,7 +37,25 @@
 internal fun hasContentToDisplay(state: GetCredentialUiState): Boolean {
     return state.providerDisplayInfo.sortedUserNameToCredentialEntryList.isNotEmpty() ||
         state.providerDisplayInfo.authenticationEntryList.isNotEmpty() ||
-        state.providerDisplayInfo.remoteEntry != null
+        (state.providerDisplayInfo.remoteEntry != null &&
+            !state.requestDisplayInfo.preferImmediatelyAvailableCredentials)
+}
+
+internal fun findAutoSelectEntry(providerDisplayInfo: ProviderDisplayInfo): CredentialEntryInfo? {
+    if (providerDisplayInfo.authenticationEntryList.isNotEmpty()) {
+        return null
+    }
+    if (providerDisplayInfo.sortedUserNameToCredentialEntryList.size == 1) {
+        val entryList = providerDisplayInfo.sortedUserNameToCredentialEntryList.firstOrNull()
+            ?: return null
+        if (entryList.sortedCredentialEntryList.size == 1) {
+            val entry = entryList.sortedCredentialEntryList.firstOrNull() ?: return null
+            if (entry.isAutoSelectable) {
+                return entry
+            }
+        }
+    }
+    return null
 }
 
 data class ProviderInfo(
@@ -76,10 +94,13 @@
     val credentialType: CredentialType,
     /** Localized type value of this credential used for display purpose. */
     val credentialTypeDisplayName: String,
+    val providerDisplayName: String,
     val userName: String,
     val displayName: String?,
     val icon: Drawable?,
+    val shouldTintIcon: Boolean,
     val lastUsedTimeMillis: Instant?,
+    val isAutoSelectable: Boolean,
 ) : BaseEntry(
     providerId,
     entryKey,
@@ -146,6 +167,7 @@
 
 data class RequestDisplayInfo(
     val appName: String,
+    val preferImmediatelyAvailableCredentials: Boolean,
 )
 
 /**
@@ -246,7 +268,6 @@
 private fun toGetScreenState(
     providerDisplayInfo: ProviderDisplayInfo
 ): GetScreenState {
-
     return if (providerDisplayInfo.sortedUserNameToCredentialEntryList.isEmpty() &&
         providerDisplayInfo.remoteEntry == null &&
         providerDisplayInfo.authenticationEntryList.all { it.isUnlockedAndEmpty })
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/logging/CreateCredentialEvent.kt b/packages/CredentialManager/src/com/android/credentialmanager/logging/CreateCredentialEvent.kt
new file mode 100644
index 0000000..daa42be
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/logging/CreateCredentialEvent.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.credentialmanager.logging
+
+import com.android.internal.logging.UiEvent
+import com.android.internal.logging.UiEventLogger
+
+enum class CreateCredentialEvent(private val id: Int) : UiEventLogger.UiEventEnum {
+
+    @UiEvent(doc = "The create credential bottomsheet became visible on the screen.")
+    CREDMAN_CREATE_CRED_BOTTOMSHEET(1318),
+
+    @UiEvent(doc = "The provider activity is launched on the screen.")
+    CREDMAN_CREATE_CRED_PROVIDER_ACTIVITY_READY_TO_LAUNCH(1319),
+
+    @UiEvent(doc = "The provider activity is launched and we are waiting for its result. " +
+            "Contents Hidden.")
+    CREDMAN_CREATE_CRED_PROVIDER_ACTIVITY_PENDING(1320),
+
+    @UiEvent(doc = "The provider activity is not active or ready launched on the screen.")
+    CREDMAN_CREATE_CRED_PROVIDER_ACTIVITY_NOT_APPLICABLE(1321),
+
+    @UiEvent(doc = "The passkey introduction card is visible on screen.")
+    CREDMAN_CREATE_CRED_PASSKEY_INTRO(1322),
+
+    @UiEvent(doc = "The provider selection card is visible on screen.")
+    CREDMAN_CREATE_CRED_PROVIDER_SELECTION(1323),
+
+    @UiEvent(doc = "The creation option selection card is visible on screen.")
+    CREDMAN_CREATE_CRED_CREATION_OPTION_SELECTION(1324),
+
+    @UiEvent(doc = "The more option selection card is visible on screen.")
+    CREDMAN_CREATE_CRED_MORE_OPTIONS_SELECTION(1325),
+
+    @UiEvent(doc = "The more options row intro card is visible on screen.")
+    CREDMAN_CREATE_CRED_MORE_OPTIONS_ROW_INTRO(1326),
+
+    @UiEvent(doc = "The external only selection card is visible on screen.")
+    CREDMAN_CREATE_CRED_EXTERNAL_ONLY_SELECTION(1327),
+
+    @UiEvent(doc = "The more about passkeys intro card is visible on screen.")
+    CREDMAN_CREATE_CRED_MORE_ABOUT_PASSKEYS_INTRO(1328);
+
+    override fun getId(): Int {
+        return this.id
+    }
+}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/logging/GetCredentialEvent.kt b/packages/CredentialManager/src/com/android/credentialmanager/logging/GetCredentialEvent.kt
new file mode 100644
index 0000000..8de8895
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/logging/GetCredentialEvent.kt
@@ -0,0 +1,62 @@
+/*
+ * 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.credentialmanager.logging
+
+import com.android.internal.logging.UiEvent
+import com.android.internal.logging.UiEventLogger
+
+enum class GetCredentialEvent(private val id: Int) : UiEventLogger.UiEventEnum {
+
+    @UiEvent(doc = "The The snackbar only page when there's no account but only a remoteEntry " +
+            "visible on the screen.")
+    CREDMAN_GET_CRED_SCREEN_REMOTE_ONLY(1332),
+
+    @UiEvent(doc = "The snackbar when there are only auth entries and all of them are empty.")
+    CREDMAN_GET_CRED_SCREEN_UNLOCKED_AUTH_ENTRIES_ONLY(1333),
+
+    @UiEvent(doc = "The primary credential selection page is displayed on screen.")
+    CREDMAN_GET_CRED_SCREEN_PRIMARY_SELECTION(1334),
+
+    @UiEvent(doc = "The secondary credential selection page, where all sign-in options are " +
+            "listed is displayed on the screen.")
+    CREDMAN_GET_CRED_SCREEN_ALL_SIGN_IN_OPTIONS(1335),
+
+    @UiEvent(doc = "The provider activity is not active nor is any ready for launch on the screen.")
+    CREDMAN_GET_CRED_PROVIDER_ACTIVITY_NOT_APPLICABLE(1336),
+
+    @UiEvent(doc = "The provider activity is ready to be launched on the screen.")
+    CREDMAN_GET_CRED_PROVIDER_ACTIVITY_READY_TO_LAUNCH(1337),
+
+    @UiEvent(doc = "The provider activity is launched and we are waiting for its result. " +
+            "Contents Hidden.")
+    CREDMAN_GET_CRED_PROVIDER_ACTIVITY_PENDING(1338),
+
+    @UiEvent(doc = "The remote credential snackbar screen is visible.")
+    CREDMAN_GET_CRED_REMOTE_CRED_SNACKBAR_SCREEN(1339),
+
+    @UiEvent(doc = "The empty auth snackbar screen is visible.")
+    CREDMAN_GET_CRED_SCREEN_EMPTY_AUTH_SNACKBAR_SCREEN(1340),
+
+    @UiEvent(doc = "The primary selection card is visible on screen.")
+    CREDMAN_GET_CRED_PRIMARY_SELECTION_CARD(1341),
+
+    @UiEvent(doc = "The all sign in option card is visible on screen.")
+    CREDMAN_GET_CRED_ALL_SIGN_IN_OPTION_CARD(1342);
+
+    override fun getId(): Int {
+        return this.id
+    }
+}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/logging/LifecycleEvent.kt b/packages/CredentialManager/src/com/android/credentialmanager/logging/LifecycleEvent.kt
new file mode 100644
index 0000000..1ede64d
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/logging/LifecycleEvent.kt
@@ -0,0 +1,37 @@
+/*
+ * 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.credentialmanager.logging
+
+import com.android.internal.logging.UiEventLogger.UiEventEnum.RESERVE_NEW_UI_EVENT_ID
+
+import com.android.internal.logging.UiEvent
+import com.android.internal.logging.UiEventLogger
+
+enum class LifecycleEvent(private val id: Int) : UiEventLogger.UiEventEnum {
+
+    @UiEvent(doc = "A new activity is initialized for processing the request.")
+    CREDMAN_ACTIVITY_INIT(1343),
+
+    @UiEvent(doc = "An existing activity received a new request to process.")
+    CREDMAN_ACTIVITY_NEW_REQUEST(1344),
+
+    @UiEvent(doc = "The UI closed due to illegal internal state.")
+    CREDMAN_ACTIVITY_INTERNAL_ERROR(1345);
+
+    override fun getId(): Int {
+        return this.id
+    }
+}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/logging/UIMetrics.kt b/packages/CredentialManager/src/com/android/credentialmanager/logging/UIMetrics.kt
new file mode 100644
index 0000000..035c1e4
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/logging/UIMetrics.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.credentialmanager.logging
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import com.android.internal.logging.InstanceId
+import com.android.internal.logging.InstanceIdSequence
+import com.android.internal.logging.UiEventLogger
+import com.android.internal.logging.UiEventLoggerImpl
+
+class UIMetrics() {
+    private val INSTANCE_ID_MAX = 1 shl 20
+    private val mUiEventLogger: UiEventLogger = UiEventLoggerImpl()
+    val mInstanceIdSequence: InstanceIdSequence = InstanceIdSequence(INSTANCE_ID_MAX)
+
+    var mInstanceId: InstanceId = mInstanceIdSequence.newInstanceId()
+
+    fun resetInstanceId() {
+        this.mInstanceId = mInstanceIdSequence.newInstanceId()
+    }
+
+    @Composable
+    fun log(event: UiEventLogger.UiEventEnum) {
+        val instanceId: InstanceId = mInstanceId
+        LaunchedEffect(true) {
+            mUiEventLogger.log(event, instanceId)
+        }
+    }
+
+    @Composable
+    fun log(event: UiEventLogger.UiEventEnum, packageName: String) {
+        val instanceId: InstanceId = mInstanceId
+        LaunchedEffect(true) {
+            mUiEventLogger.logWithInstanceId(event, /*uid=*/0, packageName, instanceId)
+        }
+    }
+
+    @Composable
+    fun log(event: UiEventLogger.UiEventEnum, instanceId: InstanceId, packageName: String) {
+        LaunchedEffect(true) {
+            mUiEventLogger.logWithInstanceId(event, /*uid=*/0, packageName, instanceId)
+        }
+    }
+
+    fun logNormal(event: UiEventLogger.UiEventEnum, packageName: String) {
+        mUiEventLogger.logWithInstanceId(event, /*uid=*/0, packageName, mInstanceId)
+    }
+}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/AndroidColorScheme.kt b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/AndroidColorScheme.kt
index 120e493..8928e18 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/AndroidColorScheme.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/AndroidColorScheme.kt
@@ -40,32 +40,8 @@
  * most of the colors in this class will be removed in favor of their M3 counterpart.
  */
 class AndroidColorScheme internal constructor(context: Context) {
-    val colorPrimary = getColor(context, R.attr.colorPrimary)
-    val colorPrimaryDark = getColor(context, R.attr.colorPrimaryDark)
-    val colorAccent = getColor(context, R.attr.colorAccent)
-    val colorAccentPrimary = getColor(context, R.attr.colorAccentPrimary)
-    val colorAccentSecondary = getColor(context, R.attr.colorAccentSecondary)
-    val colorAccentTertiary = getColor(context, R.attr.colorAccentTertiary)
-    val colorAccentPrimaryVariant = getColor(context, R.attr.colorAccentPrimaryVariant)
-    val colorAccentSecondaryVariant = getColor(context, R.attr.colorAccentSecondaryVariant)
-    val colorAccentTertiaryVariant = getColor(context, R.attr.colorAccentTertiaryVariant)
-    val colorSurface = getColor(context, R.attr.colorSurface)
-    val colorSurfaceHighlight = getColor(context, R.attr.colorSurfaceHighlight)
-    val colorSurfaceVariant = getColor(context, R.attr.colorSurfaceVariant)
-    val colorSurfaceHeader = getColor(context, R.attr.colorSurfaceHeader)
-    val colorError = getColor(context, R.attr.colorError)
-    val colorBackground = getColor(context, R.attr.colorBackground)
-    val colorBackgroundFloating = getColor(context, R.attr.colorBackgroundFloating)
-    val panelColorBackground = getColor(context, R.attr.panelColorBackground)
-    val textColorPrimary = getColor(context, R.attr.textColorPrimary)
-    val textColorSecondary = getColor(context, R.attr.textColorSecondary)
-    val textColorTertiary = getColor(context, R.attr.textColorTertiary)
-    val textColorPrimaryInverse = getColor(context, R.attr.textColorPrimaryInverse)
-    val textColorSecondaryInverse = getColor(context, R.attr.textColorSecondaryInverse)
-    val textColorTertiaryInverse = getColor(context, R.attr.textColorTertiaryInverse)
-    val textColorOnAccent = getColor(context, R.attr.textColorOnAccent)
-    val colorForeground = getColor(context, R.attr.colorForeground)
-    val colorForegroundInverse = getColor(context, R.attr.colorForegroundInverse)
+    val colorSurfaceBright = getColor(context, R.attr.materialColorSurfaceBright)
+    val colorSurfaceContainerHigh = getColor(context, R.attr.materialColorSurfaceContainerHigh)
 
     companion object {
         fun getColor(context: Context, attr: Int): Color {
diff --git a/packages/DynamicSystemInstallationService/AndroidManifest.xml b/packages/DynamicSystemInstallationService/AndroidManifest.xml
index b194738..c2aaeac 100644
--- a/packages/DynamicSystemInstallationService/AndroidManifest.xml
+++ b/packages/DynamicSystemInstallationService/AndroidManifest.xml
@@ -21,12 +21,7 @@
             android:exported="true"
             android:permission="android.permission.INSTALL_DYNAMIC_SYSTEM"
             android:foregroundServiceType="systemExempted"
-            android:process=":dynsystem">
-            <intent-filter>
-                <action android:name="android.os.image.action.NOTIFY_IF_IN_USE" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-        </service>
+            android:process=":dynsystem" />
 
         <activity android:name=".VerificationActivity"
             android:exported="true"
diff --git a/packages/PackageInstaller/res/values-et/strings.xml b/packages/PackageInstaller/res/values-et/strings.xml
index 71b22dba..d5b5316 100644
--- a/packages/PackageInstaller/res/values-et/strings.xml
+++ b/packages/PackageInstaller/res/values-et/strings.xml
@@ -61,14 +61,14 @@
     <string name="uninstall_update_text_multiuser" msgid="8992883151333057227">"Kas asendada see rakendus tehaseversiooniga? Kõik andmed eemaldatakse. See mõjutab kõiki seadme kasutajaid, sh neid, kellel on tööprofiilid."</string>
     <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? Üksuse <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> kloon kustutatakse samuti."</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="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>
     <string name="uninstalling_app" msgid="8866082646836981397">"Paketi <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> desinstallimine …"</string>
     <string name="uninstall_done" msgid="439354138387969269">"Desinstallimine on lõpetatud."</string>
     <string name="uninstall_done_app" msgid="4588850984473605768">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> on desinstallitud"</string>
-    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Kustutati üksuse <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> kloon"</string>
+    <string name="uninstall_done_clone_app" msgid="5578308154544195413">"Kustutati rakenduse <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> kloon"</string>
     <string name="uninstall_failed" msgid="1847750968168364332">"Desinstallimine ebaõnnestus."</string>
     <string name="uninstall_failed_app" msgid="5506028705017601412">"Üksuse <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> desinstallimine ebaõnnestus."</string>
     <string name="uninstalling_cloned_app" msgid="1826380164974984870">"Üksuse <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> klooni kustutamine …"</string>
@@ -92,7 +92,7 @@
     <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"Teie telefon ja isiklikud andmed on tundmatute rakenduste rünnakute suhtes haavatavamad. Selle rakenduse installimisel nõustute, et vastutate telefoni kahjude ja andmekao eest, mis võivad tuleneda selliste rakenduste kasutamisest."</string>
     <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">"Üksuse <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> kloon"</string>
+    <string name="cloned_app_label" msgid="7503612829833756160">"Rakenduse <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> kloon"</string>
     <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>
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index af20a4b..750c156 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -70,7 +70,7 @@
         "src/**/*.kt",
     ],
 
-    min_sdk_version: "29",
+    min_sdk_version: "30",
 
 }
 
diff --git a/packages/SettingsLib/DeviceStateRotationLock/src/com.android.settingslib.devicestate/DeviceStateRotationLockSettingsManager.java b/packages/SettingsLib/DeviceStateRotationLock/src/com.android.settingslib.devicestate/DeviceStateRotationLockSettingsManager.java
index 4ed7e19..10b004e 100644
--- a/packages/SettingsLib/DeviceStateRotationLock/src/com.android.settingslib.devicestate/DeviceStateRotationLockSettingsManager.java
+++ b/packages/SettingsLib/DeviceStateRotationLock/src/com.android.settingslib.devicestate/DeviceStateRotationLockSettingsManager.java
@@ -29,6 +29,7 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.text.TextUtils;
+import android.util.IndentingPrintWriter;
 import android.util.Log;
 import android.util.SparseIntArray;
 
@@ -36,6 +37,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
@@ -57,6 +59,7 @@
     private final SecureSettings mSecureSettings;
     private String[] mDeviceStateRotationLockDefaults;
     private SparseIntArray mDeviceStateRotationLockSettings;
+    private SparseIntArray mDeviceStateDefaultRotationLockSettings;
     private SparseIntArray mDeviceStateRotationLockFallbackSettings;
     private String mLastSettingValue;
     private List<SettableDeviceState> mSettableDeviceStates;
@@ -93,9 +96,7 @@
     /** Returns true if device-state based rotation lock settings are enabled. */
     public static boolean isDeviceStateRotationLockEnabled(Context context) {
         return context.getResources()
-                        .getStringArray(R.array.config_perDeviceStateRotationLockDefaults)
-                        .length
-                > 0;
+                .getStringArray(R.array.config_perDeviceStateRotationLockDefaults).length > 0;
     }
 
     private void listenForSettingsChange() {
@@ -228,6 +229,15 @@
             try {
                 key = Integer.parseInt(values[i++]);
                 value = Integer.parseInt(values[i++]);
+                boolean isPersistedValueIgnored = value == DEVICE_STATE_ROTATION_LOCK_IGNORED;
+                boolean isDefaultValueIgnored = mDeviceStateDefaultRotationLockSettings.get(key)
+                        == DEVICE_STATE_ROTATION_LOCK_IGNORED;
+                if (isPersistedValueIgnored != isDefaultValueIgnored) {
+                    Log.w(TAG, "Conflict for ignored device state " + key
+                            + ". Falling back on defaults");
+                    fallbackOnDefaults();
+                    return;
+                }
                 mDeviceStateRotationLockSettings.put(key, value);
             } catch (NumberFormatException e) {
                 Log.wtf(TAG, "Error deserializing one of the saved settings", e);
@@ -276,6 +286,9 @@
     }
 
     private void persistSettingIfChanged(String newSettingValue) {
+        Log.v(TAG, "persistSettingIfChanged: "
+                + "last=" + mLastSettingValue + ", "
+                + "new=" + newSettingValue);
         if (TextUtils.equals(mLastSettingValue, newSettingValue)) {
             return;
         }
@@ -288,6 +301,8 @@
 
     private void loadDefaults() {
         mSettableDeviceStates = new ArrayList<>(mDeviceStateRotationLockDefaults.length);
+        mDeviceStateDefaultRotationLockSettings = new SparseIntArray(
+                mDeviceStateRotationLockDefaults.length);
         mDeviceStateRotationLockSettings = new SparseIntArray(
                 mDeviceStateRotationLockDefaults.length);
         mDeviceStateRotationLockFallbackSettings = new SparseIntArray(1);
@@ -311,6 +326,7 @@
                 boolean isSettable = rotationLockSetting != DEVICE_STATE_ROTATION_LOCK_IGNORED;
                 mSettableDeviceStates.add(new SettableDeviceState(deviceState, isSettable));
                 mDeviceStateRotationLockSettings.put(deviceState, rotationLockSetting);
+                mDeviceStateDefaultRotationLockSettings.put(deviceState, rotationLockSetting);
             } catch (NumberFormatException e) {
                 Log.wtf(TAG, "Error parsing settings entry. Entry was: " + entry, e);
                 return;
@@ -318,6 +334,22 @@
         }
     }
 
+    /** Dumps internal state. */
+    public void dump(IndentingPrintWriter pw) {
+        pw.println("DeviceStateRotationLockSettingsManager");
+        pw.increaseIndent();
+        pw.println("mDeviceStateRotationLockDefaults: " + Arrays.toString(
+                mDeviceStateRotationLockDefaults));
+        pw.println("mDeviceStateDefaultRotationLockSettings: "
+                + mDeviceStateDefaultRotationLockSettings);
+        pw.println("mDeviceStateRotationLockSettings: " + mDeviceStateRotationLockSettings);
+        pw.println("mDeviceStateRotationLockFallbackSettings: "
+                + mDeviceStateRotationLockFallbackSettings);
+        pw.println("mSettableDeviceStates: " + mSettableDeviceStates);
+        pw.println("mLastSettingValue: " + mLastSettingValue);
+        pw.decreaseIndent();
+    }
+
     /**
      * Called when the persisted settings have changed, requiring a reinitialization of the
      * in-memory map.
@@ -372,5 +404,13 @@
         public int hashCode() {
             return Objects.hash(mDeviceState, mIsSettable);
         }
+
+        @Override
+        public String toString() {
+            return "SettableDeviceState{"
+                    + "mDeviceState=" + mDeviceState
+                    + ", mIsSettable=" + mIsSettable
+                    + '}';
+        }
     }
 }
diff --git a/packages/SettingsLib/MainSwitchPreference/lint-baseline.xml b/packages/SettingsLib/MainSwitchPreference/lint-baseline.xml
new file mode 100644
index 0000000..cfa64a4
--- /dev/null
+++ b/packages/SettingsLib/MainSwitchPreference/lint-baseline.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.0.0-dev" type="baseline" dependencies="true" variant="all" version="8.0.0-dev">
+
+    <issue
+        id="NewApi"
+        message="`@android:dimen/config_restrictedIconSize` requires API level 29 (current min is 28)"
+        errorLine1='    &lt;dimen name="settingslib_restricted_icon_size"&gt;@android:dimen/config_restrictedIconSize&lt;/dimen&gt;'
+        errorLine2="                                                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/MainSwitchPreference/res/values/dimens.xml"
+            line="21"
+            column="52"/>
+    </issue>
+
+</issues>
\ No newline at end of file
diff --git a/packages/SettingsLib/RestrictedLockUtils/lint-baseline.xml b/packages/SettingsLib/RestrictedLockUtils/lint-baseline.xml
new file mode 100644
index 0000000..26d05a6
--- /dev/null
+++ b/packages/SettingsLib/RestrictedLockUtils/lint-baseline.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.0.0-dev" type="baseline" dependencies="true" variant="all" version="8.0.0-dev">
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 24 (current min is 23): `android.os.UserHandle#of`"
+        errorLine1="        context.startActivityAsUser(intent, UserHandle.of(targetUserId));"
+        errorLine2="                                                       ~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java"
+            line="97"
+            column="56"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 24 (current min is 23): `android.os.UserHandle#of`"
+        errorLine1="        return um.getUserProfiles().contains(UserHandle.of(userId));"
+        errorLine2="                                                        ~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java"
+            line="140"
+            column="57"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 26 (current min is 23): `android.app.admin.DevicePolicyManager#getDeviceOwnerComponentOnAnyUser`"
+        errorLine1="            adminComponent = dpm.getDeviceOwnerComponentOnAnyUser();"
+        errorLine2="                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java"
+            line="75"
+            column="34"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 28 (current min is 23): `android.content.Context#createPackageContextAsUser`"
+        errorLine1="            userContext = context.createPackageContextAsUser(context.getPackageName(), 0, user);"
+        errorLine2="                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java"
+            line="64"
+            column="35"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 29 (current min is 23): `android.app.admin.DevicePolicyManager#getDeviceOwnerUser`"
+        errorLine1="        if (Objects.equals(dpm.getDeviceOwnerUser(), user)) {"
+        errorLine2="                               ~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java"
+            line="74"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 29 (current min is 23): `android.content.Context#startActivityAsUser`"
+        errorLine1="        context.startActivityAsUser(intent, UserHandle.of(targetUserId));"
+        errorLine2="                ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java"
+            line="97"
+            column="17"/>
+    </issue>
+
+</issues>
\ No newline at end of file
diff --git a/packages/SettingsLib/SchedulesProvider/lint-baseline.xml b/packages/SettingsLib/SchedulesProvider/lint-baseline.xml
new file mode 100644
index 0000000..0744710
--- /dev/null
+++ b/packages/SettingsLib/SchedulesProvider/lint-baseline.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.0.0-dev" type="baseline" dependencies="true" variant="all" version="8.0.0-dev">
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 28 (current min is 21): `android.os.SystemProperties#getInt`"
+        errorLine1='        if (SystemProperties.getInt("ro.debuggable", 0) == 1) {'
+        errorLine2="                             ~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/SchedulesProvider/src/com/android/settingslib/schedulesprovider/SchedulesProvider.java"
+            line="118"
+            column="30"/>
+    </issue>
+
+</issues>
\ No newline at end of file
diff --git a/packages/SettingsLib/SearchProvider/lint-baseline.xml b/packages/SettingsLib/SearchProvider/lint-baseline.xml
new file mode 100644
index 0000000..53346e0
--- /dev/null
+++ b/packages/SettingsLib/SearchProvider/lint-baseline.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.0.0-dev" type="baseline" dependencies="true" variant="all" version="8.0.0-dev">
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 23 (current min is 21): `new android.provider.SearchIndexableResource`"
+        errorLine1="            super("
+        errorLine2="            ~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/SearchProvider/src/com/android/settingslib/searchprovider/SettingsXmlIndexProvider.java"
+            line="107"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 23 (current min is 21): `android.provider.SearchIndexableResource`"
+        errorLine1="    public static final class SearchIndexableIntentResource extends SearchIndexableResource {"
+        errorLine2="                                                                    ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/SearchProvider/src/com/android/settingslib/searchprovider/SettingsXmlIndexProvider.java"
+            line="97"
+            column="69"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 23 (current min is 21): `android.provider.SearchIndexablesProvider`"
+        errorLine1="public abstract class SettingsXmlIndexProvider extends SearchIndexablesProvider {"
+        errorLine2="                                                       ~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/SearchProvider/src/com/android/settingslib/searchprovider/SettingsXmlIndexProvider.java"
+            line="34"
+            column="56"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 23 (current min is 21): `android.provider.SearchIndexableData#className`"
+        errorLine1="                    .add(XmlResource.COLUMN_CLASS_NAME, indexableResource.className)"
+        errorLine2="                                                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/SearchProvider/src/com/android/settingslib/searchprovider/SettingsXmlIndexProvider.java"
+            line="52"
+            column="57"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 23 (current min is 21): `android.provider.SearchIndexableData#intentAction`"
+        errorLine1="                    .add(XmlResource.COLUMN_INTENT_ACTION, indexableResource.intentAction)"
+        errorLine2="                                                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/SearchProvider/src/com/android/settingslib/searchprovider/SettingsXmlIndexProvider.java"
+            line="53"
+            column="60"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 23 (current min is 21): `android.provider.SearchIndexableData#intentAction`"
+        errorLine1='                this.intentAction = "android.intent.action.MAIN";'
+        errorLine2="                ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/SearchProvider/src/com/android/settingslib/searchprovider/SettingsXmlIndexProvider.java"
+            line="113"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 23 (current min is 21): `android.provider.SearchIndexableData#intentAction`"
+        errorLine1="                this.intentAction = intentAction;"
+        errorLine2="                ~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/SearchProvider/src/com/android/settingslib/searchprovider/SettingsXmlIndexProvider.java"
+            line="115"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 23 (current min is 21): `android.provider.SearchIndexableData#intentTargetClass`"
+        errorLine1="                            indexableResource.intentTargetClass);"
+        errorLine2="                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/SearchProvider/src/com/android/settingslib/searchprovider/SettingsXmlIndexProvider.java"
+            line="56"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 23 (current min is 21): `android.provider.SearchIndexableData#intentTargetClass`"
+        errorLine1="            this.intentTargetClass = className;"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/SearchProvider/src/com/android/settingslib/searchprovider/SettingsXmlIndexProvider.java"
+            line="117"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 23 (current min is 21): `android.provider.SearchIndexableData#rank`"
+        errorLine1="                    .add(XmlResource.COLUMN_RANK, indexableResource.rank)"
+        errorLine2="                                                  ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/SearchProvider/src/com/android/settingslib/searchprovider/SettingsXmlIndexProvider.java"
+            line="50"
+            column="51"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 23 (current min is 21): `android.provider.SearchIndexableResource#xmlResId`"
+        errorLine1="                    .add(XmlResource.COLUMN_XML_RESID, indexableResource.xmlResId)"
+        errorLine2="                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/SearchProvider/src/com/android/settingslib/searchprovider/SettingsXmlIndexProvider.java"
+            line="51"
+            column="56"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 23 (current min is 21): `android.provider.SearchIndexablesContract#INDEXABLES_XML_RES_COLUMNS`"
+        errorLine1="        final MatrixCursor cursor = new MatrixCursor(INDEXABLES_XML_RES_COLUMNS);"
+        errorLine2="                                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/SearchProvider/src/com/android/settingslib/searchprovider/SettingsXmlIndexProvider.java"
+            line="45"
+            column="54"/>
+    </issue>
+
+</issues>
\ No newline at end of file
diff --git a/packages/SettingsLib/Spa/.idea/codeStyles/Project.xml b/packages/SettingsLib/Spa/.idea/codeStyles/Project.xml
index 940f5c9..78a7408 100644
--- a/packages/SettingsLib/Spa/.idea/codeStyles/Project.xml
+++ b/packages/SettingsLib/Spa/.idea/codeStyles/Project.xml
@@ -1,17 +1,12 @@
 <component name="ProjectCodeStyleConfiguration">
   <code_scheme name="Project" version="173">
     <JetCodeStyleSettings>
-      <option name="PACKAGES_TO_USE_STAR_IMPORTS">
-        <value />
-      </option>
       <option name="PACKAGES_IMPORT_LAYOUT">
         <value>
           <package name="" alias="false" withSubpackages="true" />
           <package name="" alias="true" withSubpackages="true" />
         </value>
       </option>
-      <option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
-      <option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
       <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
     </JetCodeStyleSettings>
     <XML>
diff --git a/packages/SettingsLib/Spa/build.gradle b/packages/SettingsLib/Spa/build.gradle
index 42af999..2071489 100644
--- a/packages/SettingsLib/Spa/build.gradle
+++ b/packages/SettingsLib/Spa/build.gradle
@@ -24,7 +24,7 @@
     }
 }
 plugins {
-    id 'com.android.application' version '7.3.1' apply false
-    id 'com.android.library' version '7.3.1' apply false
+    id 'com.android.application' version '8.0.0-beta03' apply false
+    id 'com.android.library' version '8.0.0-beta03' apply false
     id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
 }
diff --git a/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties b/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties
index bd7e7ff..c3d5431 100644
--- a/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties
+++ b/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties
@@ -16,7 +16,7 @@
 
 #Thu Jul 14 10:36:06 CST 2022
 distributionBase=GRADLE_USER_HOME
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-rc-2-bin.zip
 distributionPath=wrapper/dists
 zipStorePath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
diff --git a/packages/SettingsLib/Spa/spa/build.gradle b/packages/SettingsLib/Spa/spa/build.gradle
index 640aa01..4563b7d 100644
--- a/packages/SettingsLib/Spa/spa/build.gradle
+++ b/packages/SettingsLib/Spa/spa/build.gradle
@@ -48,11 +48,11 @@
         }
     }
     compileOptions {
-        sourceCompatibility JavaVersion.VERSION_11
-        targetCompatibility JavaVersion.VERSION_11
+        sourceCompatibility JavaVersion.VERSION_17
+        targetCompatibility JavaVersion.VERSION_17
     }
     kotlinOptions {
-        jvmTarget = '11'
+        jvmTarget = '17'
         freeCompilerArgs = ["-Xjvm-default=all"]
     }
     buildFeatures {
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPage.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPage.kt
index 724588f..3fdb1d1 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPage.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPage.kt
@@ -77,9 +77,8 @@
         return true
     }
 
-    fun isEnabled(): Boolean {
-        return getPageProvider(sppName)?.isEnabled(arguments) ?: false
-    }
+    fun isEnabled(): Boolean =
+        SpaEnvironment.IS_DEBUG || getPageProvider(sppName)?.isEnabled(arguments) ?: false
 
     fun getTitle(): String {
         return getPageProvider(sppName)?.getTitle(arguments) ?: ""
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SpaEnvironment.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SpaEnvironment.kt
index 02962a5..2d956d5 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SpaEnvironment.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SpaEnvironment.kt
@@ -88,4 +88,13 @@
     open val sliceProviderAuthorities: String? = null
 
     // TODO: add other environment setup here.
+    companion object {
+        /**
+         * Whether debug mode is on or off.
+         *
+         * If set to true, this will also enable all the pages under development (allows browsing
+         * and searching).
+         */
+        const val IS_DEBUG = false
+    }
 }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SpaLogger.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SpaLogger.kt
index 78df0f2..ca88f8d 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SpaLogger.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SpaLogger.kt
@@ -16,6 +16,7 @@
 
 package com.android.settingslib.spa.framework.common
 
+import android.app.settings.SettingsEnums
 import android.os.Bundle
 
 // Defines the category of the log, for quick filter
@@ -31,20 +32,21 @@
 }
 
 // Defines the log events in Spa.
-enum class LogEvent {
+enum class LogEvent(val action: Int) {
     // Page related events.
-    PAGE_ENTER,
-    PAGE_LEAVE,
+    PAGE_ENTER(SettingsEnums.PAGE_VISIBLE),
+    PAGE_LEAVE(SettingsEnums.PAGE_HIDE),
 
     // Entry related events.
-    ENTRY_CLICK,
-    ENTRY_SWITCH,
+    ENTRY_CLICK(SettingsEnums.ACTION_SETTINGS_TILE_CLICK),
+    ENTRY_SWITCH(SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE),
 }
 
 internal const val LOG_DATA_DISPLAY_NAME = "name"
-internal const val LOG_DATA_SESSION_NAME = "session"
 internal const val LOG_DATA_SWITCH_STATUS = "switch"
 
+const val LOG_DATA_SESSION_NAME = "session"
+
 /**
  * The interface of logger in Spa
  */
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/SpaIntent.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/SpaIntent.kt
index 2c3c2e0..d8c35a3 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/SpaIntent.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/SpaIntent.kt
@@ -22,9 +22,11 @@
 import com.android.settingslib.spa.framework.common.SettingsPage
 import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
 
+const val SESSION_UNKNOWN = "unknown"
 const val SESSION_BROWSE = "browse"
 const val SESSION_SEARCH = "search"
 const val SESSION_SLICE = "slice"
+const val SESSION_EXTERNAL = "external"
 
 const val KEY_DESTINATION = "spaActivityDestination"
 const val KEY_HIGHLIGHT_ENTRY = "highlightEntry"
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt
index 4218489b..f6ca0c4 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SearchScaffold.kt
@@ -41,6 +41,7 @@
 import androidx.compose.runtime.getValue
 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.draw.alpha
@@ -72,6 +73,7 @@
     actions: @Composable RowScope.() -> Unit = {},
     content: @Composable (bottomPadding: Dp, searchQuery: State<String>) -> Unit,
 ) {
+    var isSearchMode by rememberSaveable { mutableStateOf(false) }
     val viewModel: SearchScaffoldViewModel = viewModel()
 
     val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
@@ -82,8 +84,11 @@
                 title = title,
                 actions = actions,
                 scrollBehavior = scrollBehavior,
+                isSearchMode = isSearchMode,
+                onSearchModeChange = { isSearchMode = it },
                 searchQuery = viewModel.searchQuery,
-            ) { viewModel.searchQuery = it }
+                onSearchQueryChange = { viewModel.searchQuery = it },
+            )
         },
     ) { paddingValues ->
         Box(
@@ -95,7 +100,7 @@
             content(
                 bottomPadding = paddingValues.calculateBottomPadding(),
                 searchQuery = remember {
-                    derivedStateOf { viewModel.searchQuery?.text ?: "" }
+                    derivedStateOf { if (isSearchMode) viewModel.searchQuery.text else "" }
                 },
             )
         }
@@ -103,7 +108,8 @@
 }
 
 internal class SearchScaffoldViewModel : ViewModel() {
-    var searchQuery: TextFieldValue? by mutableStateOf(null)
+    // Put in view model because TextFieldValue has not default Saver for rememberSaveable.
+    var searchQuery by mutableStateOf(TextFieldValue())
 }
 
 @OptIn(ExperimentalMaterial3Api::class)
@@ -112,14 +118,16 @@
     title: String,
     actions: @Composable RowScope.() -> Unit,
     scrollBehavior: TopAppBarScrollBehavior,
-    searchQuery: TextFieldValue?,
-    onSearchQueryChange: (TextFieldValue?) -> Unit,
+    isSearchMode: Boolean,
+    onSearchModeChange: (Boolean) -> Unit,
+    searchQuery: TextFieldValue,
+    onSearchQueryChange: (TextFieldValue) -> Unit,
 ) {
-    if (searchQuery != null) {
+    if (isSearchMode) {
         SearchTopAppBar(
             query = searchQuery,
             onQueryChange = onSearchQueryChange,
-            onClose = { onSearchQueryChange(null) },
+            onClose = { onSearchModeChange(false) },
             actions = actions,
         )
     } else {
@@ -127,6 +135,7 @@
             SearchAction {
                 scrollBehavior.collapse()
                 onSearchQueryChange(TextFieldValue())
+                onSearchModeChange(true)
             }
             actions()
         }
diff --git a/packages/SettingsLib/Spa/testutils/build.gradle b/packages/SettingsLib/Spa/testutils/build.gradle
index 536829e..e7f7db2 100644
--- a/packages/SettingsLib/Spa/testutils/build.gradle
+++ b/packages/SettingsLib/Spa/testutils/build.gradle
@@ -38,11 +38,11 @@
         }
     }
     compileOptions {
-        sourceCompatibility JavaVersion.VERSION_11
-        targetCompatibility JavaVersion.VERSION_11
+        sourceCompatibility JavaVersion.VERSION_17
+        targetCompatibility JavaVersion.VERSION_17
     }
     kotlinOptions {
-        jvmTarget = '11'
+        jvmTarget = '17'
         freeCompilerArgs = ["-Xjvm-default=all"]
     }
     buildFeatures {
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppStorageSize.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppStorageSize.kt
index 1a3c0ab..47bf85d 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppStorageSize.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppStorageSize.kt
@@ -19,6 +19,7 @@
 import android.content.Context
 import android.content.pm.ApplicationInfo
 import android.text.format.Formatter
+import android.util.Log
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.State
 import androidx.compose.runtime.produceState
@@ -30,18 +31,26 @@
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.withContext
 
+private const val TAG = "AppStorageSize"
+
 @Composable
 fun ApplicationInfo.getStorageSize(): State<String> {
     val context = LocalContext.current
     return produceState(initialValue = stringResource(R.string.summary_placeholder)) {
         withContext(Dispatchers.IO) {
-            value = Formatter.formatFileSize(context, calculateSizeBytes(context))
+            val sizeBytes = calculateSizeBytes(context)
+            value = if (sizeBytes != null) Formatter.formatFileSize(context, sizeBytes) else ""
         }
     }
 }
 
-private fun ApplicationInfo.calculateSizeBytes(context: Context): Long {
+private fun ApplicationInfo.calculateSizeBytes(context: Context): Long? {
     val storageStatsManager = context.storageStatsManager
-    val stats = storageStatsManager.queryStatsForPackage(storageUuid, packageName, userHandle)
-    return stats.codeBytes + stats.dataBytes
+    return try {
+        val stats = storageStatsManager.queryStatsForPackage(storageUuid, packageName, userHandle)
+        stats.codeBytes + stats.dataBytes
+    } catch (e: Exception) {
+        Log.w(TAG, "Failed to query stats: $e")
+        null
+    }
 }
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppStorageSizeTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppStorageSizeTest.kt
index fcacc34..e3af587 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppStorageSizeTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppStorageSizeTest.kt
@@ -20,6 +20,7 @@
 import android.app.usage.StorageStatsManager
 import android.content.Context
 import android.content.pm.ApplicationInfo
+import android.content.pm.PackageManager.NameNotFoundException
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.test.junit4.createComposeRule
@@ -60,9 +61,11 @@
     @Before
     fun setUp() {
         whenever(context.storageStatsManager).thenReturn(storageStatsManager)
-        whenever(storageStatsManager.queryStatsForPackage(
-            app.storageUuid, app.packageName, app.userHandle
-        )).thenReturn(STATS)
+        whenever(
+            storageStatsManager.queryStatsForPackage(
+                app.storageUuid, app.packageName, app.userHandle
+            )
+        ).thenReturn(STATS)
     }
 
     @Test
@@ -78,6 +81,24 @@
         composeTestRule.waitUntil { storageSize.value == "120 B" }
     }
 
+    @Test
+    fun getStorageSize_throwException() {
+        var storageSize = stateOf("Computing")
+        whenever(
+            storageStatsManager.queryStatsForPackage(
+                app.storageUuid, app.packageName, app.userHandle
+            )
+        ).thenThrow(NameNotFoundException())
+
+        composeTestRule.setContent {
+            CompositionLocalProvider(LocalContext provides context) {
+                storageSize = app.getStorageSize()
+            }
+        }
+
+        composeTestRule.waitUntil { storageSize.value == "" }
+    }
+
     companion object {
         private val STATS = StorageStats().apply {
             codeBytes = 100
diff --git a/packages/SettingsLib/Tile/lint-baseline.xml b/packages/SettingsLib/Tile/lint-baseline.xml
index 4df6bd9..326ec0d 100644
--- a/packages/SettingsLib/Tile/lint-baseline.xml
+++ b/packages/SettingsLib/Tile/lint-baseline.xml
@@ -4,7 +4,7 @@
     <issue
         id="NewApi"
         message="Call requires API level 24 (current min is 21): `java.lang.Iterable#forEach`"
-        errorLine1="        controllers.forEach(controller -> {"
+        errorLine1="        controllers.forEach(controller -&gt; {"
         errorLine2="                    ~~~~~~~">
         <location
             file="frameworks/base/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/SwitchesProvider.java"
@@ -14,68 +14,42 @@
 
     <issue
         id="NewApi"
-        message="Call requires API level 29 (current min is 21): `android.os.Parcel#readBoolean`"
-        errorLine1="        final boolean isProviderTile = in.readBoolean();"
-        errorLine2="                                          ~~~~~~~~~~~">
+        message="Call requires API level 23 (current min is 21): `android.graphics.drawable.Icon#createWithResource`">
         <location
             file="frameworks/base/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java"
-            line="83"
-            column="43"/>
+            line="312"/>
     </issue>
 
     <issue
         id="NewApi"
-        message="Call requires API level 29 (current min is 21): `android.os.Parcel#writeBoolean`"
-        errorLine1="        dest.writeBoolean(this instanceof ProviderTile);"
-        errorLine2="             ~~~~~~~~~~~~">
+        message="Call requires API level 23 (current min is 21): `android.graphics.drawable.Icon#setTint`">
         <location
             file="frameworks/base/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java"
-            line="102"
-            column="14"/>
+            line="318"/>
     </issue>
 
     <issue
         id="NewApi"
-        message="Call requires API level 23 (current min is 21): `android.graphics.drawable.Icon#createWithResource`"
-        errorLine1="            final Icon icon = Icon.createWithResource(componentInfo.packageName, iconResId);"
-        errorLine2="                                   ~~~~~~~~~~~~~~~~~~">
+        message="Call requires API level 29 (current min is 21): `android.os.Parcel#readBoolean`">
         <location
             file="frameworks/base/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java"
-            line="314"
-            column="36"/>
+            line="373"/>
     </issue>
 
     <issue
         id="NewApi"
-        message="Call requires API level 23 (current min is 21): `android.graphics.drawable.Icon#setTint`"
-        errorLine1="                icon.setTint(tintColor);"
-        errorLine2="                     ~~~~~~~">
+        message="Call requires API level 29 (current min is 21): `android.os.Parcel#writeBoolean`">
         <location
             file="frameworks/base/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java"
-            line="320"
-            column="22"/>
+            line="108"/>
     </issue>
 
     <issue
         id="NewApi"
-        message="Call requires API level 29 (current min is 21): `android.os.Parcel#readBoolean`"
-        errorLine1="            final boolean isProviderTile = source.readBoolean();"
-        errorLine2="                                                  ~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java"
-            line="364"
-            column="51"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 31 (current min is 21): `android.content.Context#getAttributionSource`"
-        errorLine1="            return provider.call(context.getAttributionSource(),"
-        errorLine2="                                         ~~~~~~~~~~~~~~~~~~~~">
+        message="Call requires API level 31 (current min is 21): `android.content.Context#getAttributionSource`">
         <location
             file="frameworks/base/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java"
-            line="558"
-            column="42"/>
+            line="565"/>
     </issue>
 
-</issues>
+</issues>
\ No newline at end of file
diff --git a/packages/SettingsLib/Utils/lint-baseline.xml b/packages/SettingsLib/Utils/lint-baseline.xml
new file mode 100644
index 0000000..3fcd56c
--- /dev/null
+++ b/packages/SettingsLib/Utils/lint-baseline.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.0.0-dev" type="baseline" dependencies="true" variant="all" version="8.0.0-dev">
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 24 (current min is 21): `android.os.UserHandle#of`"
+        errorLine1="                            mContext.getPackageName(), 0, UserHandle.of(managedUserId)"
+        errorLine2="                                                                     ~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/Utils/src/com/android/settingslib/utils/WorkPolicyUtils.java"
+            line="119"
+            column="70"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 24 (current min is 21): `android.os.UserHandle#of`"
+        errorLine1="                        intent, 0, UserHandle.of(managedUserId));"
+        errorLine2="                                              ~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/Utils/src/com/android/settingslib/utils/WorkPolicyUtils.java"
+            line="150"
+            column="47"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 24 (current min is 21): `android.os.UserHandle#of`"
+        errorLine1="            activityContext.startActivityAsUser(intent, UserHandle.of(userId));"
+        errorLine2="                                                                   ~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/Utils/src/com/android/settingslib/utils/WorkPolicyUtils.java"
+            line="80"
+            column="68"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 24 (current min is 21): `android.os.UserManager#isManagedProfile`"
+        errorLine1="            if (mUserManager.isManagedProfile(id)) {"
+        errorLine2="                             ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/Utils/src/com/android/settingslib/utils/WorkPolicyUtils.java"
+            line="173"
+            column="30"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 24 (current min is 23): `android.os.UserManager#isManagedProfile`"
+        errorLine1="        return context.getSystemService(UserManager.class).isManagedProfile(userId)"
+        errorLine2="                                                           ~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/Utils/src/com/android/settingslib/utils/applications/AppUtils.java"
+            line="62"
+            column="60"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 26 (current min is 21): `android.app.admin.DevicePolicyManager#getDeviceOwnerComponentOnAnyUser`"
+        errorLine1="        return mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser();"
+        errorLine2="                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/Utils/src/com/android/settingslib/utils/WorkPolicyUtils.java"
+            line="163"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 28 (current min is 21): `android.content.Context#createPackageContextAsUser`"
+        errorLine1="                    mContext.createPackageContextAsUser("
+        errorLine2="                             ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/Utils/src/com/android/settingslib/utils/WorkPolicyUtils.java"
+            line="118"
+            column="30"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 29 (current min is 21): `android.content.Context#startActivityAsUser`"
+        errorLine1="            activityContext.startActivityAsUser(intent, UserHandle.of(userId));"
+        errorLine2="                            ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/Utils/src/com/android/settingslib/utils/WorkPolicyUtils.java"
+            line="80"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 29 (current min is 21): `android.content.pm.PackageManager#queryIntentActivitiesAsUser`"
+        errorLine1="                mPackageManager.queryIntentActivitiesAsUser("
+        errorLine2="                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/Utils/src/com/android/settingslib/utils/WorkPolicyUtils.java"
+            line="149"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 30 (current min is 21): `android.os.UserManager#getAllProfiles`"
+        errorLine1="        List&lt;UserHandle&gt; allProfiles = mUserManager.getAllProfiles();"
+        errorLine2="                                                    ~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/Utils/src/com/android/settingslib/utils/WorkPolicyUtils.java"
+            line="170"
+            column="53"/>
+    </issue>
+
+</issues>
\ No newline at end of file
diff --git a/packages/SettingsLib/lint-baseline.xml b/packages/SettingsLib/lint-baseline.xml
index d6ea73d..d6a23fd 100644
--- a/packages/SettingsLib/lint-baseline.xml
+++ b/packages/SettingsLib/lint-baseline.xml
@@ -3,915 +3,202 @@
 
     <issue
         id="NewApi"
-        message="Call requires API level R (current min is 29): `android.telephony.ims.ImsMmTelManager#getRegistrationState`"
-        errorLine1="            imsMmTelManager.getRegistrationState(executors, stateCallback);"
-        errorLine2="                            ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractImsStatusPreferenceController.java"
-            line="116"
-            column="29"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.net.wifi.hotspot2.PasspointConfiguration#getUniqueId`"
-        errorLine1="        mPasspointUniqueId = config.getUniqueId();"
-        errorLine2="                                    ~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java"
-            line="379"
-            column="37"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.net.wifi.hotspot2.PasspointConfiguration#getSubscriptionExpirationTimeMillis`"
-        errorLine1="        mSubscriptionExpirationTimeInMillis = config.getSubscriptionExpirationTimeMillis();"
-        errorLine2="                                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java"
-            line="382"
-            column="54"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.net.wifi.hotspot2.PasspointConfiguration#isOsuProvisioned`"
-        errorLine1="        if (config.isOsuProvisioned()) {"
-        errorLine2="                   ~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java"
-            line="383"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.net.wifi.WifiConfiguration#getKey`"
-        errorLine1="        mPasspointUniqueId = config.getKey();"
-        errorLine2="                                    ~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java"
-            line="400"
-            column="37"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.net.wifi.WifiManager#calculateSignalLevel`"
-        errorLine1="        int difference = wifiManager.calculateSignalLevel(other.mRssi)"
-        errorLine2="                                     ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java"
-            line="481"
-            column="38"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.net.wifi.WifiManager#calculateSignalLevel`"
-        errorLine1="                - wifiManager.calculateSignalLevel(mRssi);"
-        errorLine2="                              ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java"
-            line="482"
-            column="31"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.net.wifi.WifiConfiguration#getKey`"
-        errorLine1="            return getKey(config.getKey());"
-        errorLine2="                                 ~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java"
-            line="707"
-            column="34"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.net.wifi.WifiConfiguration#getKey`"
-        errorLine1="            return (isPasspoint() &amp;&amp; config.getKey().equals(mConfig.getKey()));"
-        errorLine2="                                            ~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java"
-            line="796"
-            column="45"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.net.wifi.WifiConfiguration#getKey`"
-        errorLine1="            return (isPasspoint() &amp;&amp; config.getKey().equals(mConfig.getKey()));"
-        errorLine2="                                                                    ~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java"
-            line="796"
-            column="69"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.net.wifi.WifiManager#calculateSignalLevel`"
-        errorLine1="        return getWifiManager().calculateSignalLevel(mRssi);"
-        errorLine2="                                ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java"
-            line="903"
-            column="33"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.net.wifi.hotspot2.PasspointConfiguration#getUniqueId`"
-        errorLine1="            String uniqueId = passpointConfig.getUniqueId();"
-        errorLine2="                                              ~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java"
-            line="1988"
-            column="47"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.net.wifi.WifiConfiguration#getKey`"
-        errorLine1="                if (TextUtils.equals(config.getKey(), uniqueId)) {"
-        errorLine2="                                            ~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java"
-            line="1992"
-            column="45"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.util.SparseArray#contains`"
-        errorLine1="        return mEntriesMap.contains(userId);"
-        errorLine2="                           ~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java"
-            line="1503"
-            column="28"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.bluetooth.BluetoothDevice#getAlias`"
-        errorLine1="                    + mDevice.getAlias() + &quot;, newProfileState &quot; + newProfileState);"
-        errorLine2="                              ~~~~~~~~">
+        message="Call requires API level 31 (current min is 30): `android.bluetooth.BluetoothDevice#setAlias`">
         <location
             file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java"
-            line="155"
-            column="31"/>
+            line="584"/>
     </issue>
 
     <issue
         id="NewApi"
-        message="Call requires API level R (current min is 29): `android.bluetooth.BluetoothDevice#getAlias`"
-        errorLine1="        final String aliasName = mDevice.getAlias();"
-        errorLine2="                                         ~~~~~~~~">
+        message="Call requires API level 31 (current min is 30): `android.net.wifi.WifiInfo#getSubscriptionId`">
         <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java"
-            line="431"
-            column="42"/>
+            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java"
+            line="248"/>
     </issue>
 
     <issue
         id="NewApi"
-        message="Call requires API level 31 (current min is 29): `android.bluetooth.BluetoothDevice#setAlias`"
-        errorLine1="            mDevice.setAlias(name);"
-        errorLine2="                    ~~~~~~~~">
+        message="Call requires API level 31 (current min is 30): `android.net.wifi.WifiInfo#getSubscriptionId`">
         <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java"
-            line="442"
-            column="21"/>
+            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java"
+            line="278"/>
     </issue>
 
     <issue
         id="NewApi"
-        message="Call requires API level R (current min is 29): `android.bluetooth.BluetoothDevice#getAlias`"
-        errorLine1="        return !TextUtils.isEmpty(mDevice.getAlias());"
-        errorLine2="                                          ~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java"
-            line="489"
-            column="43"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.bluetooth.BluetoothDevice#getAlias`"
-        errorLine1="            Log.d(TAG, &quot;updating profiles for &quot; + mDevice.getAlias());"
-        errorLine2="                                                          ~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java"
-            line="638"
-            column="59"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.bluetooth.BluetoothDevice#getAlias`"
-        errorLine1="        String name = device.getAlias();"
-        errorLine2="                             ~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java"
-            line="171"
-            column="30"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Class requires API level 31 (current min is 29): `android.net.wifi.WifiManager.SubsystemRestartTrackingCallback`"
-        errorLine1="            new SubsystemRestartTrackingCallback() {"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        message="Call requires API level 31 (current min is 30): `android.net.wifi.WifiManager#registerSubsystemRestartTrackingCallback`">
         <location
             file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/connectivity/ConnectivitySubsystemsRecoveryManager.java"
-            line="62"
-            column="17"/>
+            line="201"/>
     </issue>
 
     <issue
         id="NewApi"
-        message="Class requires API level 31 (current min is 29): `android.telephony.TelephonyCallback`"
-        errorLine1="    private class MobileTelephonyCallback extends TelephonyCallback implements"
-        errorLine2="                                                  ~~~~~~~~~~~~~~~~~">
+        message="Call requires API level 31 (current min is 30): `android.net.wifi.WifiManager#unregisterSubsystemRestartTrackingCallback`">
         <location
             file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/connectivity/ConnectivitySubsystemsRecoveryManager.java"
-            line="77"
-            column="51"/>
+            line="208"/>
     </issue>
 
     <issue
         id="NewApi"
-        message="Call requires API level 31 (current min is 29): `android.net.wifi.WifiManager#registerSubsystemRestartTrackingCallback`"
-        errorLine1="        mWifiManager.registerSubsystemRestartTrackingCallback(new HandlerExecutor(mHandler),"
-        errorLine2="                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        message="Call requires API level 31 (current min is 30): `android.os.UserManager#isUserForeground`">
         <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/connectivity/ConnectivitySubsystemsRecoveryManager.java"
-            line="197"
-            column="22"/>
+            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/enterprise/ManagedDeviceActionDisabledByAdminController.java"
+            line="78"/>
     </issue>
 
     <issue
         id="NewApi"
-        message="Call requires API level 31 (current min is 29): `android.net.wifi.WifiManager#unregisterSubsystemRestartTrackingCallback`"
-        errorLine1="        mWifiManager.unregisterSubsystemRestartTrackingCallback("
-        errorLine2="                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/connectivity/ConnectivitySubsystemsRecoveryManager.java"
-            line="202"
-            column="22"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 31 (current min is 29): `android.telephony.TelephonyManager#registerTelephonyCallback`"
-        errorLine1="        mTelephonyManager.registerTelephonyCallback(new HandlerExecutor(mHandler),"
-        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/connectivity/ConnectivitySubsystemsRecoveryManager.java"
-            line="207"
-            column="27"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 31 (current min is 29): `android.telephony.TelephonyManager#unregisterTelephonyCallback`"
-        errorLine1="        mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback);"
-        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/connectivity/ConnectivitySubsystemsRecoveryManager.java"
-            line="212"
-            column="27"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 31 (current min is 29): `android.telephony.TelephonyManager#isDataCapable`"
-        errorLine1="        return getTelephonyManager().isDataCapable()"
-        errorLine2="                                     ~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java"
-            line="236"
-            column="38"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.telephony.TelephonyManager#getSubscriptionId`"
-        errorLine1="        final int mobileDefaultSubId = telephonyManager.getSubscriptionId();"
-        errorLine2="                                                        ~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java"
-            line="41"
-            column="57"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.MediaRoute2Info#getName`"
-        errorLine1="        return mRouteInfo.getName().toString();"
-        errorLine2="                          ~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java"
-            line="51"
-            column="27"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.MediaRoute2Info#getClientPackageName`"
-        errorLine1="        return mRouteInfo.getClientPackageName() != null"
-        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java"
-            line="56"
-            column="27"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.MediaRoute2Info#getFeatures`"
-        errorLine1="        final List&lt;String> features = mRouteInfo.getFeatures();"
-        errorLine2="                                                 ~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java"
-            line="93"
-            column="50"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.MediaRoute2Info#getId`"
-        errorLine1="        if (info != null &amp;&amp; info.getSelectableRoutes().contains(device.mRouteInfo.getId())) {"
-        errorLine2="                                                                                  ~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java"
-            line="131"
-            column="83"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.RoutingSessionInfo#getSelectableRoutes`"
-        errorLine1="        if (info != null &amp;&amp; info.getSelectableRoutes().contains(device.mRouteInfo.getId())) {"
-        errorLine2="                                 ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java"
-            line="131"
-            column="34"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.MediaRoute2Info#getId`"
-        errorLine1="        if (info != null &amp;&amp; info.getSelectedRoutes().contains(device.mRouteInfo.getId())) {"
-        errorLine2="                                                                                ~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java"
-            line="162"
-            column="81"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.RoutingSessionInfo#getSelectedRoutes`"
-        errorLine1="        if (info != null &amp;&amp; info.getSelectedRoutes().contains(device.mRouteInfo.getId())) {"
-        errorLine2="                                 ~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java"
-            line="162"
-            column="34"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.MediaRoute2Info#getName`"
-        errorLine1="                Log.d(TAG, route.getName() + &quot; is deselectable for &quot; + mPackageName);"
-        errorLine2="                                 ~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java"
-            line="238"
-            column="34"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.RoutingSessionInfo#getVolumeMax`"
-        errorLine1="            return info.getVolumeMax();"
-        errorLine2="                        ~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java"
-            line="320"
-            column="25"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.RoutingSessionInfo#getVolume`"
-        errorLine1="            return info.getVolume();"
-        errorLine2="                        ~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java"
-            line="341"
-            column="25"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.RoutingSessionInfo#getName`"
-        errorLine1="            return info.getName();"
-        errorLine2="                        ~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java"
-            line="357"
-            column="25"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.MediaRoute2Info#getName`"
-        errorLine1="                Log.d(TAG, &quot;buildAllRoutes() route : &quot; + route.getName() + &quot;, volume : &quot;"
-        errorLine2="                                                               ~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java"
-            line="408"
-            column="64"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.MediaRoute2Info#getVolume`"
-        errorLine1="                        + route.getVolume() + &quot;, type : &quot; + route.getType());"
-        errorLine2="                                ~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java"
-            line="409"
-            column="33"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.MediaRoute2Info#isSystemRoute`"
-        errorLine1="            if (route.isSystemRoute()) {"
-        errorLine2="                      ~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java"
-            line="411"
-            column="23"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.MediaRoute2Info#getName`"
-        errorLine1="                Log.d(TAG, &quot;buildAvailableRoutes() route : &quot; + route.getName() + &quot;, volume : &quot;"
-        errorLine2="                                                                     ~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java"
-            line="424"
-            column="70"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.MediaRoute2Info#getVolume`"
-        errorLine1="                        + route.getVolume() + &quot;, type : &quot; + route.getType());"
-        errorLine2="                                ~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java"
-            line="425"
-            column="33"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.MediaRoute2Info#getId`"
-        errorLine1="                        &amp;&amp; getRoutingSessionInfo().getSelectedRoutes().contains(route.getId())"
-        errorLine2="                                                                                      ~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java"
-            line="444"
-            column="87"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.RoutingSessionInfo#getSelectedRoutes`"
-        errorLine1="                        &amp;&amp; getRoutingSessionInfo().getSelectedRoutes().contains(route.getId())"
-        errorLine2="                                                   ~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java"
-            line="444"
-            column="52"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.RoutingSessionInfo#getName`"
-        errorLine1="                Log.d(TAG, &quot;onTransferred() oldSession : &quot; + oldSession.getName()"
-        errorLine2="                                                                        ~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java"
-            line="509"
-            column="73"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.RoutingSessionInfo#getName`"
-        errorLine1="                        + &quot;, newSession : &quot; + newSession.getName());"
-        errorLine2="                                                         ~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java"
-            line="510"
-            column="58"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.RoutingSessionInfo#getId`"
-        errorLine1="            if (TextUtils.equals(sessionId, info.getId())) {"
-        errorLine2="                                                 ~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java"
-            line="342"
-            column="50"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.MediaRoute2Info#getVolumeMax`"
-        errorLine1="        return mRouteInfo.getVolumeMax();"
-        errorLine2="                          ~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java"
-            line="221"
-            column="27"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.MediaRoute2Info#getVolume`"
-        errorLine1="        return mRouteInfo.getVolume();"
-        errorLine2="                          ~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java"
-            line="234"
-            column="27"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.MediaRoute2Info#getClientPackageName`"
-        errorLine1="        return mRouteInfo.getClientPackageName();"
-        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java"
-            line="247"
-            column="27"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.MediaRoute2Info#getFeatures`"
-        errorLine1="        return mRouteInfo.getFeatures();"
-        errorLine2="                          ~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java"
-            line="387"
-            column="27"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.MediaRoute2Info#getId`"
-        errorLine1="        return route.getId();"
-        errorLine2="                     ~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/MediaDeviceUtils.java"
-            line="57"
-            column="22"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.telephony.TelephonyDisplayInfo#getOverrideNetworkType`"
-        errorLine1="        if (telephonyDisplayInfo.getOverrideNetworkType()"
-        errorLine2="                                 ~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java"
-            line="42"
-            column="34"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.telephony.TelephonyDisplayInfo#getNetworkType`"
-        errorLine1="            return toIconKey(telephonyDisplayInfo.getNetworkType());"
-        errorLine2="                                                  ~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java"
-            line="44"
-            column="51"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.telephony.TelephonyDisplayInfo#getOverrideNetworkType`"
-        errorLine1="            return toDisplayIconKey(telephonyDisplayInfo.getOverrideNetworkType());"
-        errorLine2="                                                         ~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java"
-            line="46"
-            column="58"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 31 (current min is 29): `android.telephony.TelephonyManager#registerTelephonyCallback`"
-        errorLine1="            mPhone.registerTelephonyCallback(mReceiverHandler::post, mTelephonyCallback);"
-        errorLine2="                   ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java"
-            line="80"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 31 (current min is 29): `android.telephony.TelephonyManager#unregisterTelephonyCallback`"
-        errorLine1="            mPhone.unregisterTelephonyCallback(mTelephonyCallback);"
-        errorLine2="                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java"
-            line="82"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Class requires API level 31 (current min is 29): `android.telephony.TelephonyCallback`"
-        errorLine1="    public class MobileTelephonyCallback extends TelephonyCallback implements"
-        errorLine2="                                                 ~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java"
-            line="109"
-            column="50"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Class requires API level 31 (current min is 29): `android.telephony.TelephonyCallback.ServiceStateListener`"
-        errorLine1="            TelephonyCallback.ServiceStateListener,"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java"
-            line="110"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Class requires API level 31 (current min is 29): `android.telephony.TelephonyCallback.SignalStrengthsListener`"
-        errorLine1="            TelephonyCallback.SignalStrengthsListener,"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java"
-            line="111"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Class requires API level 31 (current min is 29): `android.telephony.TelephonyCallback.DataConnectionStateListener`"
-        errorLine1="            TelephonyCallback.DataConnectionStateListener,"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java"
-            line="112"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Class requires API level 31 (current min is 29): `android.telephony.TelephonyCallback.DataActivityListener`"
-        errorLine1="            TelephonyCallback.DataActivityListener,"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java"
-            line="113"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Class requires API level 31 (current min is 29): `android.telephony.TelephonyCallback.CarrierNetworkListener`"
-        errorLine1="            TelephonyCallback.CarrierNetworkListener,"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java"
-            line="114"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Class requires API level 31 (current min is 29): `android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener`"
-        errorLine1="            TelephonyCallback.ActiveDataSubscriptionIdListener,"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java"
-            line="115"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Class requires API level 31 (current min is 29): `android.telephony.TelephonyCallback.DisplayInfoListener`"
-        errorLine1="            TelephonyCallback.DisplayInfoListener{"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java"
-            line="116"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.telephony.SubscriptionManager#getActiveDataSubscriptionId`"
-        errorLine1="            return SubscriptionManager.getActiveDataSubscriptionId();"
-        errorLine2="                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java"
-            line="207"
-            column="40"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 31 (current min is 29): `com.google.android.collect.Lists#newArrayList`"
-        errorLine1="    private ArrayList&lt;NetworkPolicy> mPolicies = Lists.newArrayList();"
-        errorLine2="                                                       ~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java"
-            line="54"
-            column="56"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.media.MediaRoute2Info#getName`"
-        errorLine1="                name = mRouteInfo.getName();"
-        errorLine2="                                  ~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java"
-            line="71"
-            column="35"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.app.admin.DevicePolicyManager#isOrganizationOwnedDeviceWithManagedProfile`"
-        errorLine1="            if (profileAdmin != null &amp;&amp; dpm.isOrganizationOwnedDeviceWithManagedProfile()) {"
-        errorLine2="                                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java"
-            line="280"
-            column="45"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.content.Context#bindServiceAsUser`"
-        errorLine1="        mContext.bindServiceAsUser(mServiceIntent, mServiceConnection, Context.BIND_AUTO_CREATE,"
-        errorLine2="                 ~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionController.java"
-            line="83"
-            column="18"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `new android.net.NetworkInfo`"
-        errorLine1="            mNetworkInfo = new NetworkInfo("
-        errorLine2="                           ~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java"
-            line="110"
-            column="28"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level R (current min is 29): `android.net.wifi.WifiManager#getMaxSignalLevel`"
-        errorLine1="        int maxSignalLevel = wifiManager.getMaxSignalLevel();"
-        errorLine2="                                         ~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java"
-            line="131"
-            column="42"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 31 (current min is 29): `android.telephony.TelephonyManager#isDataCapable`"
-        errorLine1="        return !context.getSystemService(TelephonyManager.class).isDataCapable();"
-        errorLine2="                                                                 ~~~~~~~~~~~~~">
+        message="Call requires API level 31 (current min is 30): `android.telephony.TelephonyManager#isDataCapable`">
         <location
             file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/Utils.java"
-            line="447"
-            column="66"/>
+            line="498"/>
     </issue>
 
     <issue
         id="NewApi"
-        message="Call requires API level R (current min is 29): `android.net.NetworkRequest.Builder#clearCapabilities`"
-        errorLine1="            .clearCapabilities()"
-        errorLine2="             ~~~~~~~~~~~~~~~~~">
+        message="Call requires API level 31 (current min is 30): `android.telephony.TelephonyManager#isDataCapable`">
         <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java"
-            line="72"
-            column="14"/>
+            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java"
+            line="225"/>
     </issue>
 
     <issue
         id="NewApi"
-        message="Call requires API level 31 (current min is 29): `android.net.wifi.WifiInfo#getSubscriptionId`"
-        errorLine1="                    subId = mWifiInfo.getSubscriptionId();"
-        errorLine2="                                      ~~~~~~~~~~~~~~~~~">
+        message="Call requires API level 31 (current min is 30): `android.telephony.TelephonyManager#registerTelephonyCallback`">
         <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java"
-            line="231"
-            column="39"/>
+            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/connectivity/ConnectivitySubsystemsRecoveryManager.java"
+            line="215"/>
     </issue>
 
     <issue
         id="NewApi"
-        message="Call requires API level 31 (current min is 29): `android.net.wifi.WifiInfo#getSubscriptionId`"
-        errorLine1="                subId = mWifiInfo.getSubscriptionId();"
-        errorLine2="                                  ~~~~~~~~~~~~~~~~~">
+        message="Call requires API level 31 (current min is 30): `android.telephony.TelephonyManager#registerTelephonyCallback`">
         <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java"
-            line="263"
-            column="35"/>
+            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java"
+            line="86"/>
     </issue>
 
     <issue
         id="NewApi"
-        message="Call requires API level R (current min is 29): `android.net.wifi.WifiManager#calculateSignalLevel`"
-        errorLine1="        level = mWifiManager.calculateSignalLevel(rssi);"
-        errorLine2="                             ~~~~~~~~~~~~~~~~~~~~">
+        message="Call requires API level 31 (current min is 30): `android.telephony.TelephonyManager#unregisterTelephonyCallback`">
         <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java"
-            line="279"
-            column="30"/>
+            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/connectivity/ConnectivitySubsystemsRecoveryManager.java"
+            line="222"/>
     </issue>
 
     <issue
         id="NewApi"
-        message="Call requires API level R (current min is 29): `android.net.NetworkRequest.Builder#clearCapabilities`"
-        errorLine1="                .clearCapabilities()"
-        errorLine2="                 ~~~~~~~~~~~~~~~~~">
+        message="Call requires API level 31 (current min is 30): `android.telephony.TelephonyManager#unregisterTelephonyCallback`">
         <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java"
-            line="243"
-            column="18"/>
+            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java"
+            line="88"/>
     </issue>
 
     <issue
         id="NewApi"
-        message="Call requires API level R (current min is 29): `android.net.wifi.WifiInfo#getWifiStandard`"
-        errorLine1="            visibility.append(&quot; standard = &quot;).append(info.getWifiStandard());"
-        errorLine2="                                                          ~~~~~~~~~~~~~~~">
+        message="Call requires API level 34 (current min is 30): `android.os.UserManager#isAdminUser`">
         <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java"
-            line="104"
-            column="59"/>
+            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/development/AbstractEnableAdbPreferenceController.java"
+            line="66"/>
     </issue>
 
     <issue
         id="NewApi"
-        message="Call requires API level S (current min is 29): `android.os.UserManager#isUserForeground`"
-        errorLine1="                .getSystemService(UserManager.class).isUserForeground();"
-        errorLine2="                                                     ~~~~~~~~~~~~~~~~">
+        message="Call requires API level 34 (current min is 30): `android.os.UserManager#isAdminUser`">
         <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/enterprise/ManagedDeviceActionDisabledByAdminController.java"
-            line="120"
-            column="54"/>
+            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/development/DevelopmentSettingsEnabler.java"
+            line="49"/>
     </issue>
 
     <issue
         id="NewApi"
-        message="Call requires API level 31 (current min is 29): `android.os.UserManager#isUserForeground`"
-        errorLine1="                .getSystemService(UserManager.class).isUserForeground();"
-        errorLine2="                                                     ~~~~~~~~~~~~~~~~">
+        message="Call requires API level 34 (current min is 30): `android.os.UserManager#isAdminUser`">
         <location
-            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/enterprise/ManagedDeviceActionDisabledByAdminController.java"
-            line="120"
-            column="54"/>
+            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractSimStatusImeiInfoPreferenceController.java"
+            line="33"/>
     </issue>
 
-</issues>
+    <issue
+        id="NewApi"
+        message="Class requires API level 31 (current min is 30): `android.net.wifi.WifiManager.SubsystemRestartTrackingCallback`">
+        <location
+            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/connectivity/ConnectivitySubsystemsRecoveryManager.java"
+            line="64"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 31 (current min is 30): `android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener`">
+        <location
+            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java"
+            line="125"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 31 (current min is 30): `android.telephony.TelephonyCallback.CarrierNetworkListener`">
+        <location
+            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java"
+            line="124"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 31 (current min is 30): `android.telephony.TelephonyCallback.DataActivityListener`">
+        <location
+            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java"
+            line="123"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 31 (current min is 30): `android.telephony.TelephonyCallback.DataConnectionStateListener`">
+        <location
+            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java"
+            line="122"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 31 (current min is 30): `android.telephony.TelephonyCallback.DisplayInfoListener`">
+        <location
+            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java"
+            line="126"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 31 (current min is 30): `android.telephony.TelephonyCallback.ServiceStateListener`">
+        <location
+            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java"
+            line="120"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 31 (current min is 30): `android.telephony.TelephonyCallback.SignalStrengthsListener`">
+        <location
+            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java"
+            line="121"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 31 (current min is 30): `android.telephony.TelephonyCallback`">
+        <location
+            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/connectivity/ConnectivitySubsystemsRecoveryManager.java"
+            line="79"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 31 (current min is 30): `android.telephony.TelephonyCallback`">
+        <location
+            file="frameworks/base/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java"
+            line="119"/>
+    </issue>
+
+</issues>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/drawable-mcc310-mnc012/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc310-mnc012/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc310-mnc012/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc310-mnc590/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc310-mnc590/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc310-mnc590/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc310-mnc591/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc310-mnc591/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc310-mnc591/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc310-mnc592/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc310-mnc592/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc310-mnc592/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc310-mnc593/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc310-mnc593/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc310-mnc593/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc310-mnc594/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc310-mnc594/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc310-mnc594/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc310-mnc595/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc310-mnc595/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc310-mnc595/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc310-mnc596/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc310-mnc596/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc310-mnc596/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc310-mnc597/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc310-mnc597/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc310-mnc597/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc310-mnc598/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc310-mnc598/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc310-mnc598/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc310-mnc599/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc310-mnc599/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc310-mnc599/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc310-mnc890/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc310-mnc890/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc310-mnc890/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc270/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc270/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc311-mnc270/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc280/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc280/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc311-mnc280/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc281/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc281/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc311-mnc281/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc282/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc282/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc311-mnc282/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc283/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc283/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc311-mnc283/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc284/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc284/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc311-mnc284/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc285/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc285/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc311-mnc285/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc286/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc286/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc311-mnc286/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc287/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc287/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc311-mnc287/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc288/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc288/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc311-mnc288/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc289/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc289/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc311-mnc289/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc480/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc480/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc311-mnc480/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc481/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc481/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc311-mnc481/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc482/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc482/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc311-mnc482/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc483/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc483/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc311-mnc483/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc484/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc484/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc311-mnc484/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc485/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc485/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc311-mnc485/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc486/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc486/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc311-mnc486/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc487/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc487/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc311-mnc487/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc488/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc488/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc311-mnc488/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc489/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc489/ic_5g_plus_mobiledata.xml
deleted file mode 100644
index c1103fe..0000000
--- a/packages/SettingsLib/res/drawable-mcc311-mnc489/ic_5g_plus_mobiledata.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-     Copyright (C) 2023 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:viewportWidth="22"
-    android:viewportHeight="17"
-    android:width="22dp"
-    android:height="17dp">
-  <group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
-      <path android:fillColor="#FF000000"
-            android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
-    </group>
-    <group>
-      <path android:fillColor="#FF000000"
-          android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
-    </group>
-    <path android:fillColor="#FF000000"
-        android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
-  </group>
-</vector>
diff --git a/packages/SettingsLib/res/values-af/arrays.xml b/packages/SettingsLib/res/values-af/arrays.xml
index 1907b3e..28f7c50 100644
--- a/packages/SettingsLib/res/values-af/arrays.xml
+++ b/packages/SettingsLib/res/values-af/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Het gefiltreer geaktiveer"</item>
     <item msgid="2779123106632690576">"Geaktiveer"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Opskrifte is gefiltreer"</item>
-    <item msgid="4818549483446395865">"A2DP-mediapakkette is gefiltreer"</item>
-    <item msgid="8207123990453243311">"RFCOMM-kanaal is gefiltreer"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Gedeaktiveer"</item>
-    <item msgid="5884245882825346396">"Wonder"</item>
-    <item msgid="6569400572915342949">"Opskrif"</item>
-    <item msgid="1239386221416967664">"Volledige filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (verstek)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 31f50e8..3de581e 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -522,7 +522,7 @@
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Wekkers en onthounotas"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Laat toe dat wekkers en onthounotas gestel word"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Wekkers en onthounotas"</string>
-    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Laat hierdie program toe om wekkers te stel en tydsensitiewe handelinge te skeduleer. Dit laat die program op die agtergrond werk, wat meer batterykrag kan gebruik.\n\nAs hierdie toestemming af is, sal bestaande wekkers en tydgegronde geleenthede wat deur hierdie program geskeduleer is, nie werk nie."</string>
+    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Laat hierdie app toe om wekkers te stel en tydsensitiewe handelinge te skeduleer. Dit laat die app op die agtergrond werk, wat meer batterykrag kan gebruik.\n\nAs hierdie toestemming af is, sal bestaande wekkers en tydgegronde geleenthede wat deur hierdie app geskeduleer is, nie werk nie."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"skedule, wekker, onthounota, horlosie"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Skakel aan"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Skakel Moenie steur nie aan"</string>
diff --git a/packages/SettingsLib/res/values-am/arrays.xml b/packages/SettingsLib/res/values-am/arrays.xml
index ad0f1ed..c423d3c 100644
--- a/packages/SettingsLib/res/values-am/arrays.xml
+++ b/packages/SettingsLib/res/values-am/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"ማጣሪያን አንቃ"</item>
     <item msgid="2779123106632690576">"ነቅቷል"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"ራስጌዎች ተጣርተዋል"</item>
-    <item msgid="4818549483446395865">"የA2DP ሚዲያ ፓኬቶች ተጣርተዋል"</item>
-    <item msgid="8207123990453243311">"የRFCOMM ሰርጥ ተጣርቷል"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"ተሰናክሏል"</item>
-    <item msgid="5884245882825346396">"ማጂክ"</item>
-    <item msgid="6569400572915342949">"የራስጌ ጽሑፍ"</item>
-    <item msgid="1239386221416967664">"ሙሉ ማጣሪያ"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ነባሪ)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ar/arrays.xml b/packages/SettingsLib/res/values-ar/arrays.xml
index cede18e..cf46a8f 100644
--- a/packages/SettingsLib/res/values-ar/arrays.xml
+++ b/packages/SettingsLib/res/values-ar/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"تمّ تفعيل التصفية"</item>
     <item msgid="2779123106632690576">"مفعّل"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"العناوين المفلترة"</item>
-    <item msgid="4818549483446395865">"‏حُزم وسائط A2DP مفلترة"</item>
-    <item msgid="8207123990453243311">"‏قناة بروتوكول RFCOMM مفلترة"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"حُزم البيانات غير المفعّلة"</item>
-    <item msgid="5884245882825346396">"سِحري"</item>
-    <item msgid="6569400572915342949">"العنوان"</item>
-    <item msgid="1239386221416967664">"فلترة كاملة"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"‏AVRCP 1.5 (تلقائي)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-as/arrays.xml b/packages/SettingsLib/res/values-as/arrays.xml
index c52d27e2..284ca12 100644
--- a/packages/SettingsLib/res/values-as/arrays.xml
+++ b/packages/SettingsLib/res/values-as/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"সক্ষম কৰাবিলাক ফিল্টাৰ কৰা হৈছে"</item>
     <item msgid="2779123106632690576">"সক্ষম কৰা আছে"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"হেডাৰ ফিল্টাৰ কৰা হৈছে"</item>
-    <item msgid="4818549483446395865">"A2DP মিডিয়াৰ পেকেট ফিল্টাৰ কৰা হৈছে"</item>
-    <item msgid="8207123990453243311">"RFCOMM চেনেল ফিল্টাৰ কৰা হৈছে"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"অক্ষম কৰা আছে"</item>
-    <item msgid="5884245882825346396">"যাদু"</item>
-    <item msgid="6569400572915342949">"হেডাৰ"</item>
-    <item msgid="1239386221416967664">"সম্পূৰ্ণ ফিল্টাৰ"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ডিফ’ল্ট)"</item>
     <item msgid="1637054408779685086">"AVRCP ১.৩"</item>
diff --git a/packages/SettingsLib/res/values-az/arrays.xml b/packages/SettingsLib/res/values-az/arrays.xml
index 9605c51..ff0054b 100644
--- a/packages/SettingsLib/res/values-az/arrays.xml
+++ b/packages/SettingsLib/res/values-az/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filtrləmə aktivdir"</item>
     <item msgid="2779123106632690576">"Aktivdir"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Başlıqlar Filtrlənib"</item>
-    <item msgid="4818549483446395865">"A2DP Media Paketləri Filtrlənib"</item>
-    <item msgid="8207123990453243311">"RFCOMM Kanalı Filtrlənib"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Deaktiv"</item>
-    <item msgid="5884245882825346396">"Sehr"</item>
-    <item msgid="6569400572915342949">"Başlıq"</item>
-    <item msgid="1239386221416967664">"Tam Filtr"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Defolt)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
index 618748b..32071e5 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Omogućeno filtrirano"</item>
     <item msgid="2779123106632690576">"Omogućeno"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Filtrirana zaglavlja"</item>
-    <item msgid="4818549483446395865">"Filtrirani A2DP medijski paketi"</item>
-    <item msgid="8207123990453243311">"Filtrirani RFCOMM kanal"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Onemogućeno"</item>
-    <item msgid="5884245882825346396">"Magija"</item>
-    <item msgid="6569400572915342949">"Zaglavlje"</item>
-    <item msgid="1239386221416967664">"Potpuni filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (podrazumevano)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-be/arrays.xml b/packages/SettingsLib/res/values-be/arrays.xml
index 117f0b4..a60d354 100644
--- a/packages/SettingsLib/res/values-be/arrays.xml
+++ b/packages/SettingsLib/res/values-be/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Уключана з фільтрацыяй"</item>
     <item msgid="2779123106632690576">"Уключана"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Адфільтраваны загалоўкі"</item>
-    <item msgid="4818549483446395865">"Адфільтраваны пакеты мультымедыя A2DP"</item>
-    <item msgid="8207123990453243311">"Адфільтраваны канал RFCOMM"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Адключана"</item>
-    <item msgid="5884245882825346396">"Спецыяльная фраза"</item>
-    <item msgid="6569400572915342949">"Загаловак"</item>
-    <item msgid="1239386221416967664">"Поўная фільтрацыя"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (стандартная)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-bg/arrays.xml b/packages/SettingsLib/res/values-bg/arrays.xml
index cf643c8..d778ca2 100644
--- a/packages/SettingsLib/res/values-bg/arrays.xml
+++ b/packages/SettingsLib/res/values-bg/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Филтрирането е активирано"</item>
     <item msgid="2779123106632690576">"Активирано"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Заглавките са филтрирани"</item>
-    <item msgid="4818549483446395865">"Мултимедийните пакети A2DP са филтрирани"</item>
-    <item msgid="8207123990453243311">"Каналът RFCOMM е филтриран"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Деактивирано"</item>
-    <item msgid="5884245882825346396">"Магия"</item>
-    <item msgid="6569400572915342949">"Заглавка"</item>
-    <item msgid="1239386221416967664">"Пълен филтър"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (основно)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-bn/arrays.xml b/packages/SettingsLib/res/values-bn/arrays.xml
index 1a7652d..dbb738c 100644
--- a/packages/SettingsLib/res/values-bn/arrays.xml
+++ b/packages/SettingsLib/res/values-bn/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"ফিল্টার করা চালু আছে"</item>
     <item msgid="2779123106632690576">"চালু করা আছে"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"হেডার ফিল্টার করা হয়েছে"</item>
-    <item msgid="4818549483446395865">"A2DP মিডিয়া প্যাকেট ফিল্টার করা হয়েছে"</item>
-    <item msgid="8207123990453243311">"RFCOMM চ্যানেল ফিল্টার করা হয়েছে"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"বন্ধ করা আছে"</item>
-    <item msgid="5884245882825346396">"ম্যাজিক"</item>
-    <item msgid="6569400572915342949">"হেডার"</item>
-    <item msgid="1239386221416967664">"সম্পূর্ণ ফিল্টার"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ডিফল্ট)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml
index 2ab1b79..740e704 100644
--- a/packages/SettingsLib/res/values-bs/arrays.xml
+++ b/packages/SettingsLib/res/values-bs/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Omogućeno filtrirano"</item>
     <item msgid="2779123106632690576">"Omogućeno"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Filtrirana zaglavlja"</item>
-    <item msgid="4818549483446395865">"Filtrirani A2DP medijski paketi"</item>
-    <item msgid="8207123990453243311">"Filtrirani RFCOMM kanal"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Onemogućeno"</item>
-    <item msgid="5884245882825346396">"Magija"</item>
-    <item msgid="6569400572915342949">"Zaglavlje"</item>
-    <item msgid="1239386221416967664">"Potpuni filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (zadano)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index e8cabfa..1aa8ff3 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -522,7 +522,7 @@
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmi i podsjetnici"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Dozvoli postavljanje alarma i podsjetnika"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmi i podsjetnici"</string>
-    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Dozvolite ovoj aplikaciji da postavlja alarme i zakazuje vremenski osjetljive radnje. Ovim će se omogućiti aplikaciji da radi u pozadini, čime se može povećati potrošnja baterije.\n\nAko je ovo odobrenje isključeno, postojeći alarmi i događaji zasnovani na vremenu koje je ova aplikacija zakazala neće funkcionirati."</string>
+    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Dozvolite ovoj aplikaciji da postavlja alarme i zakazuje vremenski osjetljive radnje. Ovim će se omogućiti aplikaciji da radi u pozadini, čime se može povećati potrošnja baterije.\n\nAko je ovo odobrenje isključeno, postojeći alarmi i događaji zasnovani na vremenu, a koje je ova aplikacija zakazala, neće funkcionirati."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"raspored, alarm, podsjetnik, sat"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Uključi"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Uključi način rada Ne ometaj"</string>
diff --git a/packages/SettingsLib/res/values-ca/arrays.xml b/packages/SettingsLib/res/values-ca/arrays.xml
index 00a126c..4e437ba 100644
--- a/packages/SettingsLib/res/values-ca/arrays.xml
+++ b/packages/SettingsLib/res/values-ca/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Activat amb filtres"</item>
     <item msgid="2779123106632690576">"Activat"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Capçaleres filtrades"</item>
-    <item msgid="4818549483446395865">"Paquets multimèdia A2DP filtrats"</item>
-    <item msgid="8207123990453243311">"Canal RFCOMM filtrat"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Desactivat"</item>
-    <item msgid="5884245882825346396">"Màgia"</item>
-    <item msgid="6569400572915342949">"Capçalera"</item>
-    <item msgid="1239386221416967664">"Filtre complet"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (predeterminada)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 83b32d4..f14befd 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -522,7 +522,7 @@
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes i recordatoris"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permet la configuració d\'alarmes i recordatoris"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes i recordatoris"</string>
-    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permet que aquesta aplicació configuri alarmes i programi accions. Això permet a l\'aplicació executar-se en segon pla i, per tant, és possible que consumeixi més bateria.\n\nSi aquest permís està desactivat, les alarmes i els esdeveniments que ja hagi programat l\'aplicació no funcionaran."</string>
+    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permet que aquesta aplicació configuri alarmes i programi accions a una hora determinada. Això permet a l\'aplicació executar-se en segon pla i, per tant, és possible que consumeixi més bateria.\n\nSi aquest permís està desactivat, les alarmes i els esdeveniments que ja hagi programat l\'aplicació no funcionaran."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programació, alarma, recordatori, rellotge"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activa"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activa el mode No molestis"</string>
diff --git a/packages/SettingsLib/res/values-cs/arrays.xml b/packages/SettingsLib/res/values-cs/arrays.xml
index a4bd21f..e1a5aef 100644
--- a/packages/SettingsLib/res/values-cs/arrays.xml
+++ b/packages/SettingsLib/res/values-cs/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Povolit filtrované"</item>
     <item msgid="2779123106632690576">"Zapnuto"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Záhlaví filtrována"</item>
-    <item msgid="4818549483446395865">"Mediální balíčky A2DP filtrovány"</item>
-    <item msgid="8207123990453243311">"Kanál RFCOMM filtrován"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Zakázáno"</item>
-    <item msgid="5884245882825346396">"Komplexní hodnocení"</item>
-    <item msgid="6569400572915342949">"Záhlaví"</item>
-    <item msgid="1239386221416967664">"Úplný filtr"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (výchozí)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-da/arrays.xml b/packages/SettingsLib/res/values-da/arrays.xml
index 37da365..03cab20 100644
--- a/packages/SettingsLib/res/values-da/arrays.xml
+++ b/packages/SettingsLib/res/values-da/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filtreret er aktiveret"</item>
     <item msgid="2779123106632690576">"Aktiveret"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Overskrifter filtreret"</item>
-    <item msgid="4818549483446395865">"A2DP-mediepakker filtreret"</item>
-    <item msgid="8207123990453243311">"RFCOMM-kanal filtreret"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Deaktiveret"</item>
-    <item msgid="5884245882825346396">"Magi"</item>
-    <item msgid="6569400572915342949">"Overskrift"</item>
-    <item msgid="1239386221416967664">"Fuldt filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (standard)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-de/arrays.xml b/packages/SettingsLib/res/values-de/arrays.xml
index 2241666..c5dcc10 100644
--- a/packages/SettingsLib/res/values-de/arrays.xml
+++ b/packages/SettingsLib/res/values-de/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filter aktiviert"</item>
     <item msgid="2779123106632690576">"Aktiviert"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Header gefiltert"</item>
-    <item msgid="4818549483446395865">"A2DP-Medienpakete gefiltert"</item>
-    <item msgid="8207123990453243311">"RFCOMM-Kanal gefiltert"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Deaktiviert"</item>
-    <item msgid="5884245882825346396">"Magie"</item>
-    <item msgid="6569400572915342949">"Header"</item>
-    <item msgid="1239386221416967664">"Vollständig gefiltert"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Standard)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-el/arrays.xml b/packages/SettingsLib/res/values-el/arrays.xml
index 1a824c1..6486b3d 100644
--- a/packages/SettingsLib/res/values-el/arrays.xml
+++ b/packages/SettingsLib/res/values-el/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Ενεργοποιήθηκε το φιλτράρισμα"</item>
     <item msgid="2779123106632690576">"Ενεργοποιήθηκε"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Φιλτραρισμένες κεφαλίδες"</item>
-    <item msgid="4818549483446395865">"Φιλτραρισμένα πακέτα μέσων A2DP"</item>
-    <item msgid="8207123990453243311">"Φιλτραρισμένο κανάλι RFCOMM"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Ανενεργό"</item>
-    <item msgid="5884245882825346396">"Μαγεία"</item>
-    <item msgid="6569400572915342949">"Κεφαλίδα"</item>
-    <item msgid="1239386221416967664">"Πλήρες φίλτρο"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Προεπιλογή)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-en-rAU/arrays.xml b/packages/SettingsLib/res/values-en-rAU/arrays.xml
index de63386..9a7390e 100644
--- a/packages/SettingsLib/res/values-en-rAU/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rAU/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Enabled Filtered"</item>
     <item msgid="2779123106632690576">"Enabled"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Headers filtered"</item>
-    <item msgid="4818549483446395865">"A2DP media packets filtered"</item>
-    <item msgid="8207123990453243311">"RFCOMM channel filtered"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Disabled"</item>
-    <item msgid="5884245882825346396">"Magic"</item>
-    <item msgid="6569400572915342949">"Header"</item>
-    <item msgid="1239386221416967664">"Full filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-en-rCA/arrays.xml b/packages/SettingsLib/res/values-en-rCA/arrays.xml
index 0af8b4e..184d210 100644
--- a/packages/SettingsLib/res/values-en-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rCA/arrays.xml
@@ -64,15 +64,15 @@
     <item msgid="2779123106632690576">"Enabled"</item>
   </string-array>
   <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Headers Filtered"</item>
-    <item msgid="4818549483446395865">"A2DP Media Packets Filtered"</item>
-    <item msgid="8207123990453243311">"RFCOMM Channel Filtered"</item>
+    <item msgid="195768089203590086">"Leave only ACL headers"</item>
+    <item msgid="2776218217644557831">"Filter A2DP media packets"</item>
+    <item msgid="8163235976612675092">"Filter RFCOMM channel"</item>
   </string-array>
   <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Disabled"</item>
-    <item msgid="5884245882825346396">"Magic"</item>
-    <item msgid="6569400572915342949">"Header"</item>
-    <item msgid="1239386221416967664">"Full Filter"</item>
+    <item msgid="3961868665260627524">"Disable"</item>
+    <item msgid="2505973306504851132">"Fill with string of characters"</item>
+    <item msgid="5883011000629613855">"Leave only header"</item>
+    <item msgid="1051534112762023603">"Fully remove"</item>
   </string-array>
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
diff --git a/packages/SettingsLib/res/values-en-rGB/arrays.xml b/packages/SettingsLib/res/values-en-rGB/arrays.xml
index de63386..9a7390e 100644
--- a/packages/SettingsLib/res/values-en-rGB/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rGB/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Enabled Filtered"</item>
     <item msgid="2779123106632690576">"Enabled"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Headers filtered"</item>
-    <item msgid="4818549483446395865">"A2DP media packets filtered"</item>
-    <item msgid="8207123990453243311">"RFCOMM channel filtered"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Disabled"</item>
-    <item msgid="5884245882825346396">"Magic"</item>
-    <item msgid="6569400572915342949">"Header"</item>
-    <item msgid="1239386221416967664">"Full filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-en-rIN/arrays.xml b/packages/SettingsLib/res/values-en-rIN/arrays.xml
index de63386..9a7390e 100644
--- a/packages/SettingsLib/res/values-en-rIN/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rIN/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Enabled Filtered"</item>
     <item msgid="2779123106632690576">"Enabled"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Headers filtered"</item>
-    <item msgid="4818549483446395865">"A2DP media packets filtered"</item>
-    <item msgid="8207123990453243311">"RFCOMM channel filtered"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Disabled"</item>
-    <item msgid="5884245882825346396">"Magic"</item>
-    <item msgid="6569400572915342949">"Header"</item>
-    <item msgid="1239386221416967664">"Full filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-en-rXC/arrays.xml b/packages/SettingsLib/res/values-en-rXC/arrays.xml
index 30c9a49..dec70f4 100644
--- a/packages/SettingsLib/res/values-en-rXC/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rXC/arrays.xml
@@ -64,15 +64,15 @@
     <item msgid="2779123106632690576">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‏‎‎‏‎‎‎‏‎‏‏‎‏‏‎‏‏‎‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‎‏‎‏‏‏‏‏‎‏‎‏‏‏‎‎‏‎‎‎‎‎Enabled‎‏‎‎‏‎"</item>
   </string-array>
   <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‎‎‏‏‏‎‏‏‎‏‏‎‏‎‏‎‏‎‎‎‏‎‏‏‏‎‏‏‎‎‎‏‏‎‏‎‏‎‎‏‏‎‎‏‎‏‎‏‎‏‎‎‏‎Headers Filtered‎‏‎‎‏‎"</item>
-    <item msgid="4818549483446395865">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‎‏‏‏‏‎‏‏‏‎‏‏‎‏‎‎‏‏‏‎‎‏‏‎‏‏‎‏‎‏‎‏‏‏‎‏‏‎‏‏‏‎‎‎‏‏‏‏‎‏‏‎‎‏‎A2DP Media Packets Filtered‎‏‎‎‏‎"</item>
-    <item msgid="8207123990453243311">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‎‎‏‎‏‏‎‎‎‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‎‎‏‏‎‏‏‎‏‎‏‏‏‏‎RFCOMM Channel Filtered‎‏‎‎‏‎"</item>
+    <item msgid="195768089203590086">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‎‏‎‏‏‎‏‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‎‏‎‎‎‏‏‎‏‏‏‎‏‎‏‎‏‏‎‎‏‎‎‎‎‏‏‏‏‎‎‎‏‏‎‎Leave only ACL headers‎‏‎‎‏‎"</item>
+    <item msgid="2776218217644557831">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‏‎‎‎‎‏‏‏‎‎‎‏‏‎‏‏‏‏‎‎‎‎‏‎‏‎‎‎‏‎‎‏‏‎‏‎‏‏‎‎‎‎‎‎‎‏‏‎‎‎‎‎‎‏‏‏‎Filter A2DP media packets‎‏‎‎‏‎"</item>
+    <item msgid="8163235976612675092">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‎‏‎‎‎‏‏‏‏‎‏‏‏‏‎‏‎‏‏‏‎‏‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‎‎Filter RFCOMM channel‎‏‎‎‏‎"</item>
   </string-array>
   <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎‏‎‎‎‎‏‎‎‎‎‏‎‏‎‏‏‎‎‏‎‎‏‏‎‏‎‎‏‏‎‎‎‎‏‏‎‎‏‎‏‏‏‎‏‏‎‎‏‏‎Disabled‎‏‎‎‏‎"</item>
-    <item msgid="5884245882825346396">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‎‎‏‎‎‎‎‏‎‏‎‎‏‏‏‎‏‎‎‎‏‎‏‎‎‎‎‏‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‎‏‏‏‎‎‎Magic‎‏‎‎‏‎"</item>
-    <item msgid="6569400572915342949">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‏‎‏‏‎‎‏‏‎‎‏‏‎‎‎‎‎‎‏‏‏‏‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‎‏‎Header‎‏‎‎‏‎"</item>
-    <item msgid="1239386221416967664">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‏‎‎‏‏‎‎‏‏‎‎‏‎‏‏‏‏‎‎‏‏‎‎‏‏‏‎‏‎‏‎‏‏‎‎‎‏‎‎‏‎‎‏‏‎‏‏‎‏‏‏‏‏‎‎‎‎‎Full Filter‎‏‎‎‏‎"</item>
+    <item msgid="3961868665260627524">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‏‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎‏‎‎‎‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‏‏‏‎‎‎‏‎‏‎‏‏‎‎‏‎‎‎‏‎‎‎Disable‎‏‎‎‏‎"</item>
+    <item msgid="2505973306504851132">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‎‏‏‎‎‎‏‏‏‎‎‎‎‎‎‎‏‎‏‏‏‎‎‎‏‏‏‏‎‏‏‏‎‏‏‎‏‎‏‎‏‎‎‏‎‏‏‏‎‏‎‏‏‏‏‎‎‎Fill with string of characters‎‏‎‎‏‎"</item>
+    <item msgid="5883011000629613855">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‎‏‎‎‏‎‏‎‎‏‏‏‎‏‎‏‎‏‎‏‏‏‏‎‎‏‏‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‎‏‎‎‎‏‏‏‏‏‎Leave only header‎‏‎‎‏‎"</item>
+    <item msgid="1051534112762023603">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‏‎‎‏‎‏‏‏‏‏‎‎‏‏‎‎‏‎‏‏‎‏‎‎‎‏‎‎‏‏‎‎‎‏‏‎‎‎‏‎‏‏‎‎‏‏‏‎‏‎‏‏‎‎‏‏‎Fully remove‎‏‎‎‏‎"</item>
   </string-array>
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‎‏‎‏‏‎‏‏‎‎‏‎‏‎‎‎‎‏‏‏‎‏‏‎‏‏‎‎‎‏‎‎‎‎‎‏‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎AVRCP 1.5 (Default)‎‏‎‎‏‎"</item>
diff --git a/packages/SettingsLib/res/values-es-rUS/arrays.xml b/packages/SettingsLib/res/values-es-rUS/arrays.xml
index e2a36c6..771690d 100644
--- a/packages/SettingsLib/res/values-es-rUS/arrays.xml
+++ b/packages/SettingsLib/res/values-es-rUS/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filtrado habilitado"</item>
     <item msgid="2779123106632690576">"Habilitado"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Títulos filtrados"</item>
-    <item msgid="4818549483446395865">"Paquetes de medios A2DP filtrados"</item>
-    <item msgid="8207123990453243311">"Canal RFCOMM filtrado"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Inhabilitada"</item>
-    <item msgid="5884245882825346396">"Automático"</item>
-    <item msgid="6569400572915342949">"Título"</item>
-    <item msgid="1239386221416967664">"Filtro completo"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (predeterminado)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-es/arrays.xml b/packages/SettingsLib/res/values-es/arrays.xml
index b5e035c..e07f9dc 100644
--- a/packages/SettingsLib/res/values-es/arrays.xml
+++ b/packages/SettingsLib/res/values-es/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Habilitado con filtros"</item>
     <item msgid="2779123106632690576">"Habilitado"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Encabezados filtrados"</item>
-    <item msgid="4818549483446395865">"Paquetes de medios A2DP filtrados"</item>
-    <item msgid="8207123990453243311">"Canal RFCOMM filtrado"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Inhabilitado"</item>
-    <item msgid="5884245882825346396">"Mágico"</item>
-    <item msgid="6569400572915342949">"Encabezado"</item>
-    <item msgid="1239386221416967664">"Filtro completo"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (predeterminado)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-et/arrays.xml b/packages/SettingsLib/res/values-et/arrays.xml
index d910a0e..34448a7 100644
--- a/packages/SettingsLib/res/values-et/arrays.xml
+++ b/packages/SettingsLib/res/values-et/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Luba filtreeritud"</item>
     <item msgid="2779123106632690576">"Lubatud"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Filtreeritud päised"</item>
-    <item msgid="4818549483446395865">"Filtreeritud A2DP meediapaketid"</item>
-    <item msgid="8207123990453243311">"Filtreeritud RFCOMM-kanal"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Keelatud"</item>
-    <item msgid="5884245882825346396">"Maagiline"</item>
-    <item msgid="6569400572915342949">"Päis"</item>
-    <item msgid="1239386221416967664">"Täielik filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (vaikeseade)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-eu/arrays.xml b/packages/SettingsLib/res/values-eu/arrays.xml
index 2d3575b..eb678ff 100644
--- a/packages/SettingsLib/res/values-eu/arrays.xml
+++ b/packages/SettingsLib/res/values-eu/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Gaituta baina iragazita"</item>
     <item msgid="2779123106632690576">"Gaituta"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Goiburuan iragazita"</item>
-    <item msgid="4818549483446395865">"A2DP multimedia-paketeak iragazita"</item>
-    <item msgid="8207123990453243311">"RFCOMM kanala iragazita"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Desgaituta"</item>
-    <item msgid="5884245882825346396">"Magia"</item>
-    <item msgid="6569400572915342949">"Goiburua"</item>
-    <item msgid="1239386221416967664">"Iragazki osoa"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (lehenetsia)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 82e0eea..02ab192 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -522,7 +522,7 @@
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmak eta abisuak"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Eman alarmak eta abisuak ezartzeko baimena"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmak eta abisuak"</string>
-    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Eman alarmak ezartzeko eta denbora-muga duten ekintzak programatzeko baimena aplikazioari. Hala, aplikazioak atzeko planoan funtzionatuko du, eta litekeena da bateria gehiago kontsumitzea.\n\nEz baduzu ematen baimen hori, ez dute funtzionatuko aplikazio honen bidez programatutako alarmek eta denbora-muga duten ekintzek."</string>
+    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Eman alarmak ezartzeko eta denbora-muga duten ekintzak programatzeko baimena aplikazioari. Hala, aplikazioak atzeko planoan funtzionatuko du, eta litekeena da bateria gehiago kontsumitzea.\n\nBaimen hori ematen ez baduzu, ez dute funtzionatuko aplikazio honen bidez programatutako alarmek eta denbora-muga duten ekintzek."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programazioa, alarma, abisua, erlojua"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktibatu"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktibatu ez molestatzeko modua"</string>
diff --git a/packages/SettingsLib/res/values-fa/arrays.xml b/packages/SettingsLib/res/values-fa/arrays.xml
index b983bcc..2d9be31 100644
--- a/packages/SettingsLib/res/values-fa/arrays.xml
+++ b/packages/SettingsLib/res/values-fa/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"فیلترشده فعال شده است"</item>
     <item msgid="2779123106632690576">"فعال"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"سرصفحه‌ها فیلتر شد"</item>
-    <item msgid="4818549483446395865">"‏بسته‌های رسانه A2DP فیلتر شد"</item>
-    <item msgid="8207123990453243311">"‏کانال RFCOMM فیلتر شد"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"غیرفعال"</item>
-    <item msgid="5884245882825346396">"جادویی"</item>
-    <item msgid="6569400572915342949">"سرصفحه"</item>
-    <item msgid="1239386221416967664">"فیلتر کامل"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"‏AVRCP نسخه ۱.۵ (پیش‌فرض)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-fi/arrays.xml b/packages/SettingsLib/res/values-fi/arrays.xml
index 9e3bcd2..d6f002f 100644
--- a/packages/SettingsLib/res/values-fi/arrays.xml
+++ b/packages/SettingsLib/res/values-fi/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Suodatus käytössä"</item>
     <item msgid="2779123106632690576">"Päällä"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Otsikot suodatettu"</item>
-    <item msgid="4818549483446395865">"A2DP-mediapaketit suodatettu"</item>
-    <item msgid="8207123990453243311">"RFCOMM-kanava suodatettu"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Ei käytössä"</item>
-    <item msgid="5884245882825346396">"Magic"</item>
-    <item msgid="6569400572915342949">"Otsikko"</item>
-    <item msgid="1239386221416967664">"Täysi suodatus"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (oletus)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-fr-rCA/arrays.xml b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
index 86066b6..6657aa1 100644
--- a/packages/SettingsLib/res/values-fr-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filtres activés"</item>
     <item msgid="2779123106632690576">"Activé"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"En-têtes filtrés"</item>
-    <item msgid="4818549483446395865">"Paquets multimédias A2DP filtrés"</item>
-    <item msgid="8207123990453243311">"Canal RFCOMM filtré"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Désactivé"</item>
-    <item msgid="5884245882825346396">"Magie"</item>
-    <item msgid="6569400572915342949">"En-tête"</item>
-    <item msgid="1239386221416967664">"Filtre intégral"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (par défaut)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-fr/arrays.xml b/packages/SettingsLib/res/values-fr/arrays.xml
index 5f31ff5..869d88a 100644
--- a/packages/SettingsLib/res/values-fr/arrays.xml
+++ b/packages/SettingsLib/res/values-fr/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Activé et filtré"</item>
     <item msgid="2779123106632690576">"Activé"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"En-têtes filtrés"</item>
-    <item msgid="4818549483446395865">"Paquets multimédias A2DP filtrés"</item>
-    <item msgid="8207123990453243311">"Canal RFCOMM filtré"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Désactivé"</item>
-    <item msgid="5884245882825346396">"Magie"</item>
-    <item msgid="6569400572915342949">"En-tête"</item>
-    <item msgid="1239386221416967664">"Filtre complet"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (par défaut)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-gl/arrays.xml b/packages/SettingsLib/res/values-gl/arrays.xml
index 665851d..3cd7b4b 100644
--- a/packages/SettingsLib/res/values-gl/arrays.xml
+++ b/packages/SettingsLib/res/values-gl/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Está activado o filtrado"</item>
     <item msgid="2779123106632690576">"Activada"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Cabeceiras filtradas"</item>
-    <item msgid="4818549483446395865">"A2DP Media Packets filtrados"</item>
-    <item msgid="8207123990453243311">"Canle RFCOMM filtrada"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Desactivado"</item>
-    <item msgid="5884245882825346396">"Maxia"</item>
-    <item msgid="6569400572915342949">"Cabeceira"</item>
-    <item msgid="1239386221416967664">"Filtro completo"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (predeterminado)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-gu/arrays.xml b/packages/SettingsLib/res/values-gu/arrays.xml
index e373952..f559b80 100644
--- a/packages/SettingsLib/res/values-gu/arrays.xml
+++ b/packages/SettingsLib/res/values-gu/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"ફિલ્ટર કરેલ ચાલુ છે"</item>
     <item msgid="2779123106632690576">"ચાલુ છે"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"ફિલ્ટર કરેલા હેડર"</item>
-    <item msgid="4818549483446395865">"ફિલ્ટર કરેલા A2DP મીડિયા પૅકેટ"</item>
-    <item msgid="8207123990453243311">"ફિલ્ટર કરેલી RFCOMM ચૅનલ"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"બંધ કર્યું"</item>
-    <item msgid="5884245882825346396">"જાદુ"</item>
-    <item msgid="6569400572915342949">"હેડર"</item>
-    <item msgid="1239386221416967664">"સંપૂર્ણ ફિલ્ટર"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ડિફૉલ્ટ)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-hi/arrays.xml b/packages/SettingsLib/res/values-hi/arrays.xml
index 356a13c..be88620 100644
--- a/packages/SettingsLib/res/values-hi/arrays.xml
+++ b/packages/SettingsLib/res/values-hi/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"चालू और फ़िल्टर किया गया"</item>
     <item msgid="2779123106632690576">"चालू है"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"हेडर फ़िल्टर किए गए"</item>
-    <item msgid="4818549483446395865">"A2DP मीडिया पैकेट फ़िल्टर किए गए"</item>
-    <item msgid="8207123990453243311">"RFCOMM चैनल फ़िल्टर किए गए"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"बंद है"</item>
-    <item msgid="5884245882825346396">"मैजिक"</item>
-    <item msgid="6569400572915342949">"हेडर"</item>
-    <item msgid="1239386221416967664">"सभी फ़िल्टर"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (डिफ़ॉल्ट)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-hr/arrays.xml b/packages/SettingsLib/res/values-hr/arrays.xml
index 812f8d2..5c73ebb 100644
--- a/packages/SettingsLib/res/values-hr/arrays.xml
+++ b/packages/SettingsLib/res/values-hr/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Omogućeno filtrirano"</item>
     <item msgid="2779123106632690576">"Omogućeno"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Filtrirana zaglavlja"</item>
-    <item msgid="4818549483446395865">"Filtrirani A2DP medijski paketi"</item>
-    <item msgid="8207123990453243311">"Filtrirani RFCOMM kanal"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Onemogućeno"</item>
-    <item msgid="5884245882825346396">"Čarolija"</item>
-    <item msgid="6569400572915342949">"Zaglavlje"</item>
-    <item msgid="1239386221416967664">"Potpuni filtar"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (zadano)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-hu/arrays.xml b/packages/SettingsLib/res/values-hu/arrays.xml
index 9c842f9..500b9fd 100644
--- a/packages/SettingsLib/res/values-hu/arrays.xml
+++ b/packages/SettingsLib/res/values-hu/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Szűrtek engedélyezve"</item>
     <item msgid="2779123106632690576">"Engedélyezve"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Szűrt fejlécek"</item>
-    <item msgid="4818549483446395865">"Szűrt A2DP-médiacsomagok"</item>
-    <item msgid="8207123990453243311">"Szűrt RFCOMM-csatorna"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Kikapcsolva"</item>
-    <item msgid="5884245882825346396">"Mágia"</item>
-    <item msgid="6569400572915342949">"Fejléc"</item>
-    <item msgid="1239386221416967664">"Teljes szűrő"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (alapértelmezett)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-hy/arrays.xml b/packages/SettingsLib/res/values-hy/arrays.xml
index 59351c4..6fd6893 100644
--- a/packages/SettingsLib/res/values-hy/arrays.xml
+++ b/packages/SettingsLib/res/values-hy/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Միացված է զտիչներով"</item>
     <item msgid="2779123106632690576">"Միացված է"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Զտված էջագլուխներ"</item>
-    <item msgid="4818549483446395865">"Զտված A2DP մուլտիմեդիա փաթեթներ"</item>
-    <item msgid="8207123990453243311">"Զտված RFCOMM կապուղի"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Անջատված է"</item>
-    <item msgid="5884245882825346396">"Կախարդանք"</item>
-    <item msgid="6569400572915342949">"Էջագլուխ"</item>
-    <item msgid="1239386221416967664">"Ամբողջական զտիչ"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (կանխադրված)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml
index 06e24b9..8257d0e 100644
--- a/packages/SettingsLib/res/values-in/arrays.xml
+++ b/packages/SettingsLib/res/values-in/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Diaktifkan Difilter"</item>
     <item msgid="2779123106632690576">"Diaktifkan"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Header Difilter"</item>
-    <item msgid="4818549483446395865">"Paket Media A2DP Difilter"</item>
-    <item msgid="8207123990453243311">"Saluran RFCOMM Difilter"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Nonaktif"</item>
-    <item msgid="5884245882825346396">"Magic"</item>
-    <item msgid="6569400572915342949">"Header"</item>
-    <item msgid="1239386221416967664">"Filter Lengkap"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-is/arrays.xml b/packages/SettingsLib/res/values-is/arrays.xml
index a87e760..1b114ee 100644
--- a/packages/SettingsLib/res/values-is/arrays.xml
+++ b/packages/SettingsLib/res/values-is/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Kveikt á síuðu"</item>
     <item msgid="2779123106632690576">"Kveikt"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Síaðar fyrirsagnir"</item>
-    <item msgid="4818549483446395865">"Síaðir A2DP-efnispakkar"</item>
-    <item msgid="8207123990453243311">"Síuð RFCOMM-rás"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Slökkt"</item>
-    <item msgid="5884245882825346396">"Töfrar"</item>
-    <item msgid="6569400572915342949">"Haus"</item>
-    <item msgid="1239386221416967664">"Heildarsía"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (sjálfgefið)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-it/arrays.xml b/packages/SettingsLib/res/values-it/arrays.xml
index 18923b6..50eca93 100644
--- a/packages/SettingsLib/res/values-it/arrays.xml
+++ b/packages/SettingsLib/res/values-it/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filtro attivo"</item>
     <item msgid="2779123106632690576">"Attiva"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Intestazioni filtrate"</item>
-    <item msgid="4818549483446395865">"Pacchetti multimediali A2DP filtrati"</item>
-    <item msgid="8207123990453243311">"Canale RFCOMM filtrato"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Disattivato"</item>
-    <item msgid="5884245882825346396">"Magia"</item>
-    <item msgid="6569400572915342949">"Intestazione"</item>
-    <item msgid="1239386221416967664">"Filtro completo"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (versione predefinita)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-iw/arrays.xml b/packages/SettingsLib/res/values-iw/arrays.xml
index 8e76f2e..02b7751 100644
--- a/packages/SettingsLib/res/values-iw/arrays.xml
+++ b/packages/SettingsLib/res/values-iw/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"המסננים המופעלים"</item>
     <item msgid="2779123106632690576">"מופעל"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"כותרות לאחר סינון"</item>
-    <item msgid="4818549483446395865">"‏מנות מדיה A2DP לאחר סינון"</item>
-    <item msgid="8207123990453243311">"‏ערוצי RFCOMM לאחר סינון"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"בהשבתה"</item>
-    <item msgid="5884245882825346396">"קסם"</item>
-    <item msgid="6569400572915342949">"כותרת"</item>
-    <item msgid="1239386221416967664">"סינון מלא"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"‏AVRCP 1.5 (ברירת המחדל)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ja/arrays.xml b/packages/SettingsLib/res/values-ja/arrays.xml
index 47517fe..869fd997 100644
--- a/packages/SettingsLib/res/values-ja/arrays.xml
+++ b/packages/SettingsLib/res/values-ja/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"有効(フィルタ済み)"</item>
     <item msgid="2779123106632690576">"有効"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"ヘッダーのフィルタ"</item>
-    <item msgid="4818549483446395865">"A2DP メディア パケットのフィルタ"</item>
-    <item msgid="8207123990453243311">"RFCOMM チャネルのフィルタ"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"無効"</item>
-    <item msgid="5884245882825346396">"マジック"</item>
-    <item msgid="6569400572915342949">"ヘッダー"</item>
-    <item msgid="1239386221416967664">"フルフィルタ"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5(デフォルト)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ka/arrays.xml b/packages/SettingsLib/res/values-ka/arrays.xml
index eceaac7..71a283c 100644
--- a/packages/SettingsLib/res/values-ka/arrays.xml
+++ b/packages/SettingsLib/res/values-ka/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"გაფილტრულის ჩართვა"</item>
     <item msgid="2779123106632690576">"ჩართულია"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"გაფილტრული სათაურები"</item>
-    <item msgid="4818549483446395865">"გაფილტრული A2DP მედია პაკეტები"</item>
-    <item msgid="8207123990453243311">"გაფილტრული RFCOMM არხი"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"გათიშული"</item>
-    <item msgid="5884245882825346396">"მაგია"</item>
-    <item msgid="6569400572915342949">"სათაური"</item>
-    <item msgid="1239386221416967664">"სრული ფილტრი"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ნაგულისხმევი)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-kk/arrays.xml b/packages/SettingsLib/res/values-kk/arrays.xml
index 517b116..ab5e107 100644
--- a/packages/SettingsLib/res/values-kk/arrays.xml
+++ b/packages/SettingsLib/res/values-kk/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Сүзгіленгендері қосулы"</item>
     <item msgid="2779123106632690576">"Қосулы"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Сүзілген тақырыптар"</item>
-    <item msgid="4818549483446395865">"Сүзілген A2DP медиапакеттері"</item>
-    <item msgid="8207123990453243311">"Сүзілген RFCOMM арнасы"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Өшірулі"</item>
-    <item msgid="5884245882825346396">"Сиқыр"</item>
-    <item msgid="6569400572915342949">"Тақырып"</item>
-    <item msgid="1239386221416967664">"Толық сүзгі"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (әдепкі)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-km/arrays.xml b/packages/SettingsLib/res/values-km/arrays.xml
index db99329..bfc9834 100644
--- a/packages/SettingsLib/res/values-km/arrays.xml
+++ b/packages/SettingsLib/res/values-km/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"បានបើក​ការត្រង"</item>
     <item msgid="2779123106632690576">"បាន​បើក"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"បានត្រងក្បាលទំព័រ"</item>
-    <item msgid="4818549483446395865">"បានត្រងកញ្ចប់មេឌៀ A2DP"</item>
-    <item msgid="8207123990453243311">"បានត្រងបណ្ដាញ RFCOMM"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"បានបិទ"</item>
-    <item msgid="5884245882825346396">"វេទមន្ត"</item>
-    <item msgid="6569400572915342949">"ក្បាល​ទំព័រ"</item>
-    <item msgid="1239386221416967664">"តម្រងពេញ"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (លំនាំដើម)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-kn/arrays.xml b/packages/SettingsLib/res/values-kn/arrays.xml
index 2bf4ef0..61e2791 100644
--- a/packages/SettingsLib/res/values-kn/arrays.xml
+++ b/packages/SettingsLib/res/values-kn/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"ಫಿಲ್ಟರ್ ಮಾಡುವುದನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</item>
     <item msgid="2779123106632690576">"ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"ಶಿರೋಲೇಖಗಳನ್ನು ಫಿಲ್ಟರ್ ಮಾಡಲಾಗಿದೆ"</item>
-    <item msgid="4818549483446395865">"A2DP ಮೀಡಿಯಾ ಪ್ಯಾಕೆಟ್‌ಗಳನ್ನು ಫಿಲ್ಟರ್‌ ಮಾಡಲಾಗಿದೆ"</item>
-    <item msgid="8207123990453243311">"RFCOMM ಚಾನಲ್ ಫಿಲ್ಟರ್‌ ಮಾಡಲಾಗಿದೆ"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</item>
-    <item msgid="5884245882825346396">"ಮ್ಯಾಜಿಕ್"</item>
-    <item msgid="6569400572915342949">"ಶಿರೋಲೇಖ"</item>
-    <item msgid="1239386221416967664">"ಸಂಪೂರ್ಣ ಫಿಲ್ಟರ್"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ಡೀಫಾಲ್ಟ್)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ko/arrays.xml b/packages/SettingsLib/res/values-ko/arrays.xml
index 1a1469f..b4a035a 100644
--- a/packages/SettingsLib/res/values-ko/arrays.xml
+++ b/packages/SettingsLib/res/values-ko/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"필터링 사용 설정됨"</item>
     <item msgid="2779123106632690576">"사용 설정됨"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"헤더 필터링됨"</item>
-    <item msgid="4818549483446395865">"A2DP 미디어 패킷 필터링됨"</item>
-    <item msgid="8207123990453243311">"RFCOMM 채널 필터링됨"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"사용 안함"</item>
-    <item msgid="5884245882825346396">"매직"</item>
-    <item msgid="6569400572915342949">"헤더"</item>
-    <item msgid="1239386221416967664">"전체 필터"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5(기본값)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ky/arrays.xml b/packages/SettingsLib/res/values-ky/arrays.xml
index f59d4d4..657e63e 100644
--- a/packages/SettingsLib/res/values-ky/arrays.xml
+++ b/packages/SettingsLib/res/values-ky/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Чыпкалар иштетилди"</item>
     <item msgid="2779123106632690576">"Иштетилди"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Жогорку колонтитулдар чыпкаланды"</item>
-    <item msgid="4818549483446395865">"A2DP медиа топтомдор чыпкаланды"</item>
-    <item msgid="8207123990453243311">"RFCOMM каналы чыпкаланды"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Өчүрүлдү"</item>
-    <item msgid="5884245882825346396">"Сыйкырдуу"</item>
-    <item msgid="6569400572915342949">"Жогорку колонтитул"</item>
-    <item msgid="1239386221416967664">"Толук чыпка"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Демейки)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-lo/arrays.xml b/packages/SettingsLib/res/values-lo/arrays.xml
index 4981273..11688d4 100644
--- a/packages/SettingsLib/res/values-lo/arrays.xml
+++ b/packages/SettingsLib/res/values-lo/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"ເປີດການກັ່ນຕອງແລ້ວ"</item>
     <item msgid="2779123106632690576">"ເປີດໃຊ້ແລ້ວ"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"ສ່ວນຫົວຖືກກັ່ນຕອງ"</item>
-    <item msgid="4818549483446395865">"ແພັກເກດສື່ A2DP ຖືກກັ່ນຕອງ"</item>
-    <item msgid="8207123990453243311">"ຊ່ອງ RFCOMM ຖືກກັ່ນຕອງ"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"ປິດການນຳໃຊ້ແລ້ວ"</item>
-    <item msgid="5884245882825346396">"ເວດມົນ"</item>
-    <item msgid="6569400572915342949">"ສ່ວນຫົວ"</item>
-    <item msgid="1239386221416967664">"ການກັ່ນຕອງແບບເຕັມ"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ຄ່າເລີ່ມຕົ້ນ)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-lt/arrays.xml b/packages/SettingsLib/res/values-lt/arrays.xml
index 15e65e8..6718660 100644
--- a/packages/SettingsLib/res/values-lt/arrays.xml
+++ b/packages/SettingsLib/res/values-lt/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Įgalinta filtruota"</item>
     <item msgid="2779123106632690576">"Įgalinta"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Antraštės išfiltruotos"</item>
-    <item msgid="4818549483446395865">"A2DP medijos paketai išfiltruoti"</item>
-    <item msgid="8207123990453243311">"RFCOMM kanalas išfiltruotas"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Išjungta"</item>
-    <item msgid="5884245882825346396">"Magiškoji eilutė"</item>
-    <item msgid="6569400572915342949">"Antraštė"</item>
-    <item msgid="1239386221416967664">"Visi filtrai"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (numatytoji)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-lv/arrays.xml b/packages/SettingsLib/res/values-lv/arrays.xml
index 47531a0..3e1869a 100644
--- a/packages/SettingsLib/res/values-lv/arrays.xml
+++ b/packages/SettingsLib/res/values-lv/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Iespējot filtrētos"</item>
     <item msgid="2779123106632690576">"Iespējots"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Filtrētas galvenes"</item>
-    <item msgid="4818549483446395865">"Filtrētas A2DP multivides paketes"</item>
-    <item msgid="8207123990453243311">"Filtrēts RFCOMM kanāls"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Atspējots"</item>
-    <item msgid="5884245882825346396">"Pielāgotās virknes"</item>
-    <item msgid="6569400572915342949">"Galvene"</item>
-    <item msgid="1239386221416967664">"Visi filtri"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (noklusējums)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-mcc310-mnc590/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc590/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc310-mnc590/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc310-mnc591/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc591/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc310-mnc591/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc310-mnc592/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc592/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc310-mnc592/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc310-mnc593/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc593/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc310-mnc593/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc310-mnc594/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc594/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc310-mnc594/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc310-mnc595/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc595/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc310-mnc595/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc310-mnc596/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc596/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc310-mnc596/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc310-mnc597/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc597/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc310-mnc597/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc310-mnc598/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc598/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc310-mnc598/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc310-mnc599/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc599/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc310-mnc599/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc310-mnc890/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc890/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc310-mnc890/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc270/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc270/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc311-mnc270/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc280/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc280/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc311-mnc280/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc281/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc281/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc311-mnc281/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc282/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc282/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc311-mnc282/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc283/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc283/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc311-mnc283/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc284/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc284/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc311-mnc284/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc285/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc285/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc311-mnc285/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc286/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc286/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc311-mnc286/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc287/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc287/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc311-mnc287/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc288/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc288/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc311-mnc288/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc289/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc289/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc311-mnc289/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc481/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc481/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc311-mnc481/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc482/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc482/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc311-mnc482/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc483/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc483/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc311-mnc483/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc484/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc484/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc311-mnc484/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc485/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc485/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc311-mnc485/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc486/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc486/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc311-mnc486/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc487/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc487/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc311-mnc487/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc488/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc488/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc311-mnc488/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc489/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc489/strings.xml
deleted file mode 100644
index 4cd04d0..0000000
--- a/packages/SettingsLib/res/values-mcc311-mnc489/strings.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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
diff --git a/packages/SettingsLib/res/values-mk/arrays.xml b/packages/SettingsLib/res/values-mk/arrays.xml
index 9d5a5e1..ebf387b 100644
--- a/packages/SettingsLib/res/values-mk/arrays.xml
+++ b/packages/SettingsLib/res/values-mk/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Овозможено е филтрирано"</item>
     <item msgid="2779123106632690576">"Овозможено"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Насловите се филтрирани"</item>
-    <item msgid="4818549483446395865">"A2DP аудиовизуелните пакети се филтрирани"</item>
-    <item msgid="8207123990453243311">"RFCOMM-каналот е филтриран"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Оневозможено"</item>
-    <item msgid="5884245882825346396">"Магија"</item>
-    <item msgid="6569400572915342949">"Заглавие"</item>
-    <item msgid="1239386221416967664">"Целосен филтер"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Стандардна)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ml/arrays.xml b/packages/SettingsLib/res/values-ml/arrays.xml
index f28be85..30adb57 100644
--- a/packages/SettingsLib/res/values-ml/arrays.xml
+++ b/packages/SettingsLib/res/values-ml/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"ഫിൽട്ടറിംഗ് പ്രവർത്തനക്ഷമമാക്കി"</item>
     <item msgid="2779123106632690576">"പ്രവർത്തനക്ഷമമാക്കി"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"ഹെഡ്ഡറുകൾ ഫിൽട്ടർ ചെയ്‌തു"</item>
-    <item msgid="4818549483446395865">"A2DP മീഡിയാ പാക്കറ്റകൾ ഫിൽട്ടർ ചെയ്‌തു"</item>
-    <item msgid="8207123990453243311">"RFCOMM ചാനൽ ഫിൽട്ടർ ചെയ്‌തു"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"പ്രവർത്തനരഹിതമാക്കി"</item>
-    <item msgid="5884245882825346396">"മാജിക്"</item>
-    <item msgid="6569400572915342949">"ഹെഡ്ഡർ"</item>
-    <item msgid="1239386221416967664">"പൂർണ്ണ ഫിൽട്ടർ"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ഡിഫോൾട്ട്)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-mn/arrays.xml b/packages/SettingsLib/res/values-mn/arrays.xml
index d3c344e..d03fcd6 100644
--- a/packages/SettingsLib/res/values-mn/arrays.xml
+++ b/packages/SettingsLib/res/values-mn/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Идэвхжүүлсэн Шүүсэн"</item>
     <item msgid="2779123106632690576">"Идэвхжүүлсэн"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Толгой хэсгийг шүүсэн"</item>
-    <item msgid="4818549483446395865">"A2DP Медиа пакетыг шүүсэн"</item>
-    <item msgid="8207123990453243311">"RFCOMM сувгийг шүүсэн"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Идэвхгүй болгосон"</item>
-    <item msgid="5884245882825346396">"Ид шид"</item>
-    <item msgid="6569400572915342949">"Толгой хэсэг"</item>
-    <item msgid="1239386221416967664">"Бүтэн шүүлтүүр"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Өгөгдмөл)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-mr/arrays.xml b/packages/SettingsLib/res/values-mr/arrays.xml
index 093e36b..68eff75 100644
--- a/packages/SettingsLib/res/values-mr/arrays.xml
+++ b/packages/SettingsLib/res/values-mr/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"फिल्टर केलेले सुरू केले"</item>
     <item msgid="2779123106632690576">"सुरू केले"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"फिल्टर केलेले हेडर"</item>
-    <item msgid="4818549483446395865">"फिल्टर केलेली A2DP मीडिया पॅकेट"</item>
-    <item msgid="8207123990453243311">"फिल्टर केलेली RFCOMM चॅनल"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"बंद केले"</item>
-    <item msgid="5884245882825346396">"मॅजिक"</item>
-    <item msgid="6569400572915342949">"हेडर"</item>
-    <item msgid="1239386221416967664">"पूर्ण फिल्टर"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (डीफॉल्ट)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ms/arrays.xml b/packages/SettingsLib/res/values-ms/arrays.xml
index 1daa579..efdd879 100644
--- a/packages/SettingsLib/res/values-ms/arrays.xml
+++ b/packages/SettingsLib/res/values-ms/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Didayakan Ditapis"</item>
     <item msgid="2779123106632690576">"Didayakan"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Pengepala Ditapis"</item>
-    <item msgid="4818549483446395865">"Paket Media A2DP Ditapis"</item>
-    <item msgid="8207123990453243311">"Saluran RFCOMM Ditapis"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Dilumpuhkan"</item>
-    <item msgid="5884245882825346396">"Magik"</item>
-    <item msgid="6569400572915342949">"Pengepala"</item>
-    <item msgid="1239386221416967664">"Penapis Penuh"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Lalai)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-my/arrays.xml b/packages/SettingsLib/res/values-my/arrays.xml
index dbca299..4d0b792 100644
--- a/packages/SettingsLib/res/values-my/arrays.xml
+++ b/packages/SettingsLib/res/values-my/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"စစ်ထုတ်ထားသည်များကို ဖွင့်ထားသည်"</item>
     <item msgid="2779123106632690576">"ဖွင့်ထားသည်"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"စစ်ထုတ်ထားသော ခေါင်းစီးများ"</item>
-    <item msgid="4818549483446395865">"စစ်ထုတ်ထားသော A2DP မီဒီယာအတွဲများ"</item>
-    <item msgid="8207123990453243311">"စစ်ထုတ်ထားသော RFCOMM ချန်နယ်"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"ပိတ်ထားသည်"</item>
-    <item msgid="5884245882825346396">"ပဉ္စလက်"</item>
-    <item msgid="6569400572915342949">"ခေါင်းစီး"</item>
-    <item msgid="1239386221416967664">"စစ်ထုတ်မှုအပြည့်"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (မူလ)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-nb/arrays.xml b/packages/SettingsLib/res/values-nb/arrays.xml
index 35c4cdd..9293bdad 100644
--- a/packages/SettingsLib/res/values-nb/arrays.xml
+++ b/packages/SettingsLib/res/values-nb/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filtrering er slått på"</item>
     <item msgid="2779123106632690576">"Slått på"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Filtrert topptekst"</item>
-    <item msgid="4818549483446395865">"Filtrerte A2DP-mediepakker"</item>
-    <item msgid="8207123990453243311">"Filtrert RFCOMM-kanal"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Slått av"</item>
-    <item msgid="5884245882825346396">"Magi"</item>
-    <item msgid="6569400572915342949">"Topptekst"</item>
-    <item msgid="1239386221416967664">"Fullt filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (standard)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml
index 76652cd..29a7c60 100644
--- a/packages/SettingsLib/res/values-ne/arrays.xml
+++ b/packages/SettingsLib/res/values-ne/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"फिल्टर सक्षम पारियो"</item>
     <item msgid="2779123106632690576">"सक्षम पारिएको छ"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"हेडरहरू फिल्टर गरिए"</item>
-    <item msgid="4818549483446395865">"A2DP मिडिया प्याकेटहरू फिल्टर गरिए"</item>
-    <item msgid="8207123990453243311">"RFCOMM च्यानल फिल्टर गरियो"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"अफ गरियो"</item>
-    <item msgid="5884245882825346396">"म्याजिक"</item>
-    <item msgid="6569400572915342949">"हेडर"</item>
-    <item msgid="1239386221416967664">"फुल फिल्टर"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP १.५ (डिफल्ट)"</item>
     <item msgid="1637054408779685086">"AVRCP १.३"</item>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index ae7e8b3..831ed2f 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -520,7 +520,7 @@
     <string name="okay" msgid="949938843324579502">"ठिक छ"</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_switch_title" msgid="4939393911531826222">"अलार्म तथा रिमाइन्डर सेट गर्ने अनुमति दिनुहोस्"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"अलार्म तथा रिमाइन्डर"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"यो एपलाई अलार्म सेट गर्ने र समयमै पूरा गर्नु पर्ने कारबाहीहरूको रुटिन बनाउने अनुमति दिनुहोस्। यो अनुमति दिइएको छ भने यो एप ब्याकग्राउन्डमा चल्छ र धेरै ब्याट्री खपत हुन्छ।\n\nयो अनुमति दिइएको छैन भने सेट गरिएका अलार्म बज्दैनन् र यो एपले तय गरेका गतिविधि चल्दैनन्।"</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"समयतालिका, अलार्म, रिमाइन्डर, घडी"</string>
diff --git a/packages/SettingsLib/res/values-nl/arrays.xml b/packages/SettingsLib/res/values-nl/arrays.xml
index 2ecfbd8..460302c 100644
--- a/packages/SettingsLib/res/values-nl/arrays.xml
+++ b/packages/SettingsLib/res/values-nl/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Gefilterd staat aan"</item>
     <item msgid="2779123106632690576">"Aangezet"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Headers gefilterd"</item>
-    <item msgid="4818549483446395865">"A2DP-mediapakketten gefilterd"</item>
-    <item msgid="8207123990453243311">"RFCOMM-kanaal gefilterd"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Uitgezet"</item>
-    <item msgid="5884245882825346396">"Magie"</item>
-    <item msgid="6569400572915342949">"Header"</item>
-    <item msgid="1239386221416967664">"Volledig filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (standaard)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-or/arrays.xml b/packages/SettingsLib/res/values-or/arrays.xml
index 5f48344..439bd72 100644
--- a/packages/SettingsLib/res/values-or/arrays.xml
+++ b/packages/SettingsLib/res/values-or/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"ଫିଲ୍ଟର୍‌କୁ ସକ୍ଷମ କରାଯାଇଛି"</item>
     <item msgid="2779123106632690576">"ସକ୍ଷମ କରାଯାଇଛି"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"ହେଡରଗୁଡ଼ିକୁ ଫିଲ୍ଟର କରାଯାଇଛି"</item>
-    <item msgid="4818549483446395865">"A2DP ମିଡିଆ ପେକେଟ ଫିଲ୍ଟର କରାଯାଇଛି"</item>
-    <item msgid="8207123990453243311">"RFCOMM ଚେନେଲ ଫିଲ୍ଟର କରାଯାଇଛି"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"ଅକ୍ଷମ କରାଯାଇଛି"</item>
-    <item msgid="5884245882825346396">"ମେଜିକ"</item>
-    <item msgid="6569400572915342949">"ହେଡର"</item>
-    <item msgid="1239386221416967664">"ସମ୍ପୂର୍ଣ୍ଣ ଫିଲ୍ଟର"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ଡିଫଲ୍ଟ)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pa/arrays.xml b/packages/SettingsLib/res/values-pa/arrays.xml
index d8b1c7e..f4bfcd1 100644
--- a/packages/SettingsLib/res/values-pa/arrays.xml
+++ b/packages/SettingsLib/res/values-pa/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"ਫਿਲਟਰ ਕੀਤਿਆਂ ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਗਿਆ"</item>
     <item msgid="2779123106632690576">"ਚਾਲੂ"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"ਸਿਰਲੇਖ ਫਿਲਟਰ ਕੀਤੇ ਗਏ"</item>
-    <item msgid="4818549483446395865">"A2DP ਮੀਡੀਆ ਪੈਕੇਟ ਫਿਲਟਰ ਕੀਤੇ ਗਏ"</item>
-    <item msgid="8207123990453243311">"RFCOMM ਚੈਨਲ ਫਿਲਟਰ ਕੀਤੇ ਗਏ"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"ਬੰਦ ਹੈ"</item>
-    <item msgid="5884245882825346396">"ਜਾਦੂ"</item>
-    <item msgid="6569400572915342949">"ਸਿਰਲੇਖ"</item>
-    <item msgid="1239386221416967664">"ਸਭ ਫਿਲਟਰ"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ਪੂਰਵ-ਨਿਰਧਾਰਿਤ)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml
index 9659acb..a305a65 100644
--- a/packages/SettingsLib/res/values-pl/arrays.xml
+++ b/packages/SettingsLib/res/values-pl/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filtrowanie włączone"</item>
     <item msgid="2779123106632690576">"Włączono"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Przefiltrowane nagłówki"</item>
-    <item msgid="4818549483446395865">"Przefiltrowane pakiety multimediów A2DP"</item>
-    <item msgid="8207123990453243311">"Przefiltrowany kanał RFCOMM"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Wyłączono"</item>
-    <item msgid="5884245882825346396">"Magia"</item>
-    <item msgid="6569400572915342949">"Nagłówek"</item>
-    <item msgid="1239386221416967664">"Pełny filtr"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (domyślnie)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 84aa66a..ddff92c 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -522,7 +522,7 @@
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmy i przypomnienia"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Zezwalaj na ustawianie alarmów i przypomnień"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmy i przypomnienia"</string>
-    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Zezwól na ustawianie alarmów i planowanie innych działań, w przypadku których czas jest istotny. Dzięki temu aplikacja będzie mogła działać w tle, co może zwiększyć wykorzystanie baterii.\n\nJeśli nie włączysz tych uprawnień, istniejące alarmy i zaplanowane wydarzenia z tej aplikacji nie będą działać."</string>
+    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Zezwalaj tej aplikacji na ustawianie alarmów i planowanie działań, w przypadku których czas jest istotny. Aplikacja będzie mogła działać w tle, co może zwiększyć wykorzystanie baterii.\n\nJeśli nie włączysz tego uprawnienia, istniejące alarmy i zaplanowane wydarzenia z tej aplikacji nie będą działać."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"harmonogram, alarm, przypomnienie, zegar"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Włącz"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Włącz tryb Nie przeszkadzać"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/arrays.xml b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
index 0bff6c7..eff0922 100644
--- a/packages/SettingsLib/res/values-pt-rBR/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filtro ativado"</item>
     <item msgid="2779123106632690576">"Ativado"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Cabeçalhos filtrados"</item>
-    <item msgid="4818549483446395865">"Pacotes de mídia A2DP filtrados"</item>
-    <item msgid="8207123990453243311">"Canal RFCOMM filtrado"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Desativado"</item>
-    <item msgid="5884245882825346396">"Mágica"</item>
-    <item msgid="6569400572915342949">"Cabeçalho"</item>
-    <item msgid="1239386221416967664">"Filtro completo"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (padrão)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 168207d..3a48c3d 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -522,7 +522,7 @@
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes e lembretes"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Autorizar a definição de alarmes e lembretes"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
-    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações mais imediatas. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
+    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações com hora marcada. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programar, alarme, lembrete, relógio"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ativar"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Ativar o Não perturbe"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/arrays.xml b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
index b134be6..0553aac 100644
--- a/packages/SettingsLib/res/values-pt-rPT/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filtrado ativado"</item>
     <item msgid="2779123106632690576">"Ativado"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Cabeçalhos filtrados"</item>
-    <item msgid="4818549483446395865">"Pacotes de multimédia A2DP filtrados"</item>
-    <item msgid="8207123990453243311">"Canal RFCOMM filtrado"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Desativado"</item>
-    <item msgid="5884245882825346396">"Magia"</item>
-    <item msgid="6569400572915342949">"Cabeçalho"</item>
-    <item msgid="1239386221416967664">"Filtro completo"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (predefinição)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pt/arrays.xml b/packages/SettingsLib/res/values-pt/arrays.xml
index 0bff6c7..eff0922 100644
--- a/packages/SettingsLib/res/values-pt/arrays.xml
+++ b/packages/SettingsLib/res/values-pt/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filtro ativado"</item>
     <item msgid="2779123106632690576">"Ativado"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Cabeçalhos filtrados"</item>
-    <item msgid="4818549483446395865">"Pacotes de mídia A2DP filtrados"</item>
-    <item msgid="8207123990453243311">"Canal RFCOMM filtrado"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Desativado"</item>
-    <item msgid="5884245882825346396">"Mágica"</item>
-    <item msgid="6569400572915342949">"Cabeçalho"</item>
-    <item msgid="1239386221416967664">"Filtro completo"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (padrão)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 168207d..3a48c3d 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -522,7 +522,7 @@
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes e lembretes"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Autorizar a definição de alarmes e lembretes"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
-    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações mais imediatas. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
+    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações com hora marcada. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programar, alarme, lembrete, relógio"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ativar"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Ativar o Não perturbe"</string>
diff --git a/packages/SettingsLib/res/values-ro/arrays.xml b/packages/SettingsLib/res/values-ro/arrays.xml
index 8c7ffb2..303d669 100644
--- a/packages/SettingsLib/res/values-ro/arrays.xml
+++ b/packages/SettingsLib/res/values-ro/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Este activat Filtrat"</item>
     <item msgid="2779123106632690576">"Activat"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Anteturi filtrate"</item>
-    <item msgid="4818549483446395865">"Pachete media A2DP filtrate"</item>
-    <item msgid="8207123990453243311">"Canal RFCOMM filtrat"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Dezactivat"</item>
-    <item msgid="5884245882825346396">"Magie"</item>
-    <item msgid="6569400572915342949">"Antet"</item>
-    <item msgid="1239386221416967664">"Filtru complet"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (prestabilit)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index dba7507..e9afb3d 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -522,7 +522,7 @@
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarme și mementouri"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permite setarea pentru alarme și mementouri"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarme și mementouri"</string>
-    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite acestei aplicații să stabilească alarme și să planifice acțiuni dependente de timp. Astfel, aplicația poate să ruleze în fundal, fapt care ar putea consuma mai multă baterie.\n\nDacă permisiunea este dezactivată, alarmele și evenimentele dependente de timp planificate de aplicație nu vor funcționa."</string>
+    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite acestei aplicații să seteze alarme și să planifice acțiuni care trebuie realizate în timp scurt. Astfel, aplicația poate să ruleze în fundal, ceea ce ar putea crește consumul de baterie.\n\nDacă permisiunea este dezactivată, alarmele și evenimentele dependente de timp planificate de aplicație nu vor funcționa."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programare, alarmă, memento, ceas"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activează"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activează Nu deranja"</string>
diff --git a/packages/SettingsLib/res/values-ru/arrays.xml b/packages/SettingsLib/res/values-ru/arrays.xml
index 1df0435..4772df98 100644
--- a/packages/SettingsLib/res/values-ru/arrays.xml
+++ b/packages/SettingsLib/res/values-ru/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Включены фильтры"</item>
     <item msgid="2779123106632690576">"Включено"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Применен фильтр по заголовкам"</item>
-    <item msgid="4818549483446395865">"Применен фильтр по медиапакетам A2DP"</item>
-    <item msgid="8207123990453243311">"Применен фильтр по каналу RFCOMM"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Отключено"</item>
-    <item msgid="5884245882825346396">"Специальный параметр"</item>
-    <item msgid="6569400572915342949">"Заголовок"</item>
-    <item msgid="1239386221416967664">"Общий фильтр"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (по умолчанию)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 76d163c..16788c3 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -522,7 +522,7 @@
     <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>
-    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Если вы разрешите этому приложению устанавливать будильники и планировать на определенное время действия, оно будет работать в фоновом режиме. В таком случае заряд батареи может расходоваться быстрее.\n\nЕсли отключить эту настройку, текущие будильники и созданные приложением мероприятия перестанут запускаться."</string>
+    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Вы можете разрешить этому приложению устанавливать будильники и планировать запуск действий в определенное время. В этом случае оно будет работать в фоновом режиме и быстрее расходовать заряд батареи.\n\nЕсли отключить это разрешение, текущие будильники и созданные приложением события перестанут запускаться."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"установить, будильник, напоминание, часы"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Включить"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Включите режим \"Не беспокоить\""</string>
diff --git a/packages/SettingsLib/res/values-si/arrays.xml b/packages/SettingsLib/res/values-si/arrays.xml
index b516ce6..8de6a71 100644
--- a/packages/SettingsLib/res/values-si/arrays.xml
+++ b/packages/SettingsLib/res/values-si/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"සබල පෙරහන් කළ"</item>
     <item msgid="2779123106632690576">"සබලයි"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"ශීර්ෂයන් පෙරන ලදි"</item>
-    <item msgid="4818549483446395865">"A2DP මාධ්‍ය පැකට් පෙරන ලදි"</item>
-    <item msgid="8207123990453243311">"RFCOMM නාලිකාව පෙරන ලදි"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"අබලයි"</item>
-    <item msgid="5884245882825346396">"මැජික්"</item>
-    <item msgid="6569400572915342949">"ශීර්ෂකය"</item>
-    <item msgid="1239386221416967664">"පූර්ණ පෙරහන"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (පෙරනිමි)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sk/arrays.xml b/packages/SettingsLib/res/values-sk/arrays.xml
index 35c4518..f15dfb7 100644
--- a/packages/SettingsLib/res/values-sk/arrays.xml
+++ b/packages/SettingsLib/res/values-sk/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Aktivované filtrované"</item>
     <item msgid="2779123106632690576">"Aktivované"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Hlavičky sú filtrované"</item>
-    <item msgid="4818549483446395865">"Balíky A2DP Media sú filtrované"</item>
-    <item msgid="8207123990453243311">"Kanál RFCOMM je filtrovaný"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Deaktivované"</item>
-    <item msgid="5884245882825346396">"Magic"</item>
-    <item msgid="6569400572915342949">"Hlavička"</item>
-    <item msgid="1239386221416967664">"Úplný filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (predvolené)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sl/arrays.xml b/packages/SettingsLib/res/values-sl/arrays.xml
index 12442a4..9ef852c 100644
--- a/packages/SettingsLib/res/values-sl/arrays.xml
+++ b/packages/SettingsLib/res/values-sl/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Omogočeno filtrirano"</item>
     <item msgid="2779123106632690576">"Omogočeno"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Glave so filtrirane"</item>
-    <item msgid="4818549483446395865">"Predstavnostni paketi A2DP so filtrirani"</item>
-    <item msgid="8207123990453243311">"Kanal RFCOMM je filtriran"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Onemogočeno"</item>
-    <item msgid="5884245882825346396">"Čarovnija"</item>
-    <item msgid="6569400572915342949">"Glava"</item>
-    <item msgid="1239386221416967664">"Polni filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (privzeto)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sq/arrays.xml b/packages/SettingsLib/res/values-sq/arrays.xml
index 742a86a..89a316d 100644
--- a/packages/SettingsLib/res/values-sq/arrays.xml
+++ b/packages/SettingsLib/res/values-sq/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Të aktivizuara të filtruara"</item>
     <item msgid="2779123106632690576">"Aktiv"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Titujt e filtruar"</item>
-    <item msgid="4818549483446395865">"Paketat e medias A2DP të filtruara"</item>
-    <item msgid="8207123990453243311">"Kanalet e RFCOMM të filtruara"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Joaktiv"</item>
-    <item msgid="5884245882825346396">"Magji"</item>
-    <item msgid="6569400572915342949">"Titulli"</item>
-    <item msgid="1239386221416967664">"Filtri i plotë"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (I parazgjedhur)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sr/arrays.xml b/packages/SettingsLib/res/values-sr/arrays.xml
index a338142..e76820e 100644
--- a/packages/SettingsLib/res/values-sr/arrays.xml
+++ b/packages/SettingsLib/res/values-sr/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Омогућено филтрирано"</item>
     <item msgid="2779123106632690576">"Омогућено"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Филтрирана заглавља"</item>
-    <item msgid="4818549483446395865">"Филтрирани A2DP медијски пакети"</item>
-    <item msgid="8207123990453243311">"Филтрирани RFCOMM канал"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Онемогућено"</item>
-    <item msgid="5884245882825346396">"Магија"</item>
-    <item msgid="6569400572915342949">"Заглавље"</item>
-    <item msgid="1239386221416967664">"Потпуни филтер"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (подразумевано)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sv/arrays.xml b/packages/SettingsLib/res/values-sv/arrays.xml
index a31c155..391f603 100644
--- a/packages/SettingsLib/res/values-sv/arrays.xml
+++ b/packages/SettingsLib/res/values-sv/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filtrering har aktiverats"</item>
     <item msgid="2779123106632690576">"Aktiverad"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Filtrerade rubriker"</item>
-    <item msgid="4818549483446395865">"Filtrerade A2DP-mediapaket"</item>
-    <item msgid="8207123990453243311">"Filtrerad RFCOMM-kanal"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Inaktiverad"</item>
-    <item msgid="5884245882825346396">"Magi"</item>
-    <item msgid="6569400572915342949">"Rubrik"</item>
-    <item msgid="1239386221416967664">"Fullständigt filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (standard)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sw/arrays.xml b/packages/SettingsLib/res/values-sw/arrays.xml
index 8daf092..1a33b6e4 100644
--- a/packages/SettingsLib/res/values-sw/arrays.xml
+++ b/packages/SettingsLib/res/values-sw/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Vichujio Vilivyowekwa"</item>
     <item msgid="2779123106632690576">"Imewashwa"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Vijajuu Vimechujwa"</item>
-    <item msgid="4818549483446395865">"Kifurushi cha Maelezo cha A2DP Kimechujwa"</item>
-    <item msgid="8207123990453243311">"Kituo cha RFCOMM Kimechujwa"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Kimezimwa"</item>
-    <item msgid="5884245882825346396">"Kiinimacho"</item>
-    <item msgid="6569400572915342949">"Kijajuu"</item>
-    <item msgid="1239386221416967664">"Kichujio Kamili"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Chaguomsingi)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ta/arrays.xml b/packages/SettingsLib/res/values-ta/arrays.xml
index 8f2fe7e..23eb242 100644
--- a/packages/SettingsLib/res/values-ta/arrays.xml
+++ b/packages/SettingsLib/res/values-ta/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"இயக்கப்பட்டு வடிகட்டப்பட்டது"</item>
     <item msgid="2779123106632690576">"இயக்கப்பட்டது"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"வடிகட்டப்பட்ட தலைப்புப்பகுதிகள்"</item>
-    <item msgid="4818549483446395865">"வடிகட்டப்பட்ட A2DP மீடியா பேக்கெட்டுகள்"</item>
-    <item msgid="8207123990453243311">"வடிகட்டப்பட்ட RFCOMM சேனல்"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"முடக்கப்பட்டுள்ளது"</item>
-    <item msgid="5884245882825346396">"மேஜிக்"</item>
-    <item msgid="6569400572915342949">"தலைப்புப்பகுதி"</item>
-    <item msgid="1239386221416967664">"முழு வடிப்பான்"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (இயல்பு)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml
index 4b07f37..0f62c1d 100644
--- a/packages/SettingsLib/res/values-te/arrays.xml
+++ b/packages/SettingsLib/res/values-te/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"ప్రారంభించబడింది ఫిల్టర్ చేయబడింది"</item>
     <item msgid="2779123106632690576">"ప్రారంభించబడింది"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"హెడర్‌లు ఫిల్టర్ చేయబడ్డాయి"</item>
-    <item msgid="4818549483446395865">"A2DP మీడియా ప్యాకెట్‌లు ఫిల్టర్ చేయబడ్డాయి"</item>
-    <item msgid="8207123990453243311">"RFCOMM ఛానెల్ ఫిల్టర్ చేయబడింది"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"డిజేబుల్ చేయబడింది"</item>
-    <item msgid="5884245882825346396">"మ్యాజిక్"</item>
-    <item msgid="6569400572915342949">"హెడర్"</item>
-    <item msgid="1239386221416967664">"పూర్తి ఫిల్టర్"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.4 (ఆటోమేటిక్ సెట్టింగ్)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-th/arrays.xml b/packages/SettingsLib/res/values-th/arrays.xml
index be8dd8b..8d98cdb 100644
--- a/packages/SettingsLib/res/values-th/arrays.xml
+++ b/packages/SettingsLib/res/values-th/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"เปิดใช้รายการที่กรอง"</item>
     <item msgid="2779123106632690576">"เปิดใช้"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"ส่วนหัวที่กรอง"</item>
-    <item msgid="4818549483446395865">"แพ็กเก็ตสื่อ A2DP ที่กรอง"</item>
-    <item msgid="8207123990453243311">"แชแนล RFCOMM ที่กรอง"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"ปิดใช้"</item>
-    <item msgid="5884245882825346396">"Magic"</item>
-    <item msgid="6569400572915342949">"ส่วนหัว"</item>
-    <item msgid="1239386221416967664">"ตัวกรองแบบเต็ม"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ค่าเริ่มต้น)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-tl/arrays.xml b/packages/SettingsLib/res/values-tl/arrays.xml
index 9b4ae0e..ed47d32 100644
--- a/packages/SettingsLib/res/values-tl/arrays.xml
+++ b/packages/SettingsLib/res/values-tl/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Na-enable Na-filter"</item>
     <item msgid="2779123106632690576">"Naka-enable"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Mga Na-filter na Header"</item>
-    <item msgid="4818549483446395865">"Mga Na-filter na A2DP Media Packet"</item>
-    <item msgid="8207123990453243311">"Mga Na-filter na RFCOMM Channel"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Naka-disable"</item>
-    <item msgid="5884245882825346396">"Magic"</item>
-    <item msgid="6569400572915342949">"Header"</item>
-    <item msgid="1239386221416967664">"Kumpletong Filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-tr/arrays.xml b/packages/SettingsLib/res/values-tr/arrays.xml
index 57c9935..45580f5 100644
--- a/packages/SettingsLib/res/values-tr/arrays.xml
+++ b/packages/SettingsLib/res/values-tr/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Etkin Filtrelenmiş"</item>
     <item msgid="2779123106632690576">"Etkin"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Başlıklar Filtrelendi"</item>
-    <item msgid="4818549483446395865">"A2DP Medya Paketleri Filtrelendi"</item>
-    <item msgid="8207123990453243311">"RFCOMM Kanalı Filtrelendi"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Devre dışı"</item>
-    <item msgid="5884245882825346396">"Sihir"</item>
-    <item msgid="6569400572915342949">"Başlık"</item>
-    <item msgid="1239386221416967664">"Tam Filtre"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Varsayılan)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 86d53e7..1f56170 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -520,7 +520,7 @@
     <string name="okay" msgid="949938843324579502">"Tamam"</string>
     <string name="done" msgid="381184316122520313">"Bitti"</string>
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmlar ve hatırlatıcılar"</string>
-    <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Alarm ve hatırlatıcı ayarlanmasına izin ver"</string>
+    <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Alarm ve hatırlatıcı ayarlamasına izin ver"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmlar ve hatırlatıcılar"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Bu uygulamanın alarm kurmasına ve zamana bağlı işlemler programlamasına izin verin. Bu izin, uygulamanın arka planda çalışmasına olanak sağlayarak daha fazla pil harcanmasına neden olabilir.\n\nBu izin verilmezse bu uygulama tarafından programlanmış mevcut alarmlar ve zamana bağlı etkinlikler çalışmaz."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"program, alarm, hatırlatıcı, saat"</string>
diff --git a/packages/SettingsLib/res/values-uk/arrays.xml b/packages/SettingsLib/res/values-uk/arrays.xml
index 53bbb87..f97452c 100644
--- a/packages/SettingsLib/res/values-uk/arrays.xml
+++ b/packages/SettingsLib/res/values-uk/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Увімкнено з фільтром"</item>
     <item msgid="2779123106632690576">"Увімкнено"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Фільтрування за заголовками"</item>
-    <item msgid="4818549483446395865">"Фільтрування за пакетами медіаданих A2DP"</item>
-    <item msgid="8207123990453243311">"Фільтрування за каналом RFCOMM"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Вимкнено"</item>
-    <item msgid="5884245882825346396">"Магія"</item>
-    <item msgid="6569400572915342949">"Заголовок"</item>
-    <item msgid="1239386221416967664">"Повний фільтр"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (за умовчанням)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ur/arrays.xml b/packages/SettingsLib/res/values-ur/arrays.xml
index 5f82062..74af322 100644
--- a/packages/SettingsLib/res/values-ur/arrays.xml
+++ b/packages/SettingsLib/res/values-ur/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"فعال کردہ فلٹر کردہ"</item>
     <item msgid="2779123106632690576">"فعال"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"ہیڈرز فلٹر کئے گئے"</item>
-    <item msgid="4818549483446395865">"‏A2DP میڈیا پیکٹ فلٹر کیے گئے"</item>
-    <item msgid="8207123990453243311">"‏RFCOMM چینل فلٹر کیا گیا"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"غیر فعال"</item>
-    <item msgid="5884245882825346396">"جادو"</item>
-    <item msgid="6569400572915342949">"ہیڈر"</item>
-    <item msgid="1239386221416967664">"مکمل فلٹر"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"‏AVRCP 1.5 (ڈیفالٹ)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-uz/arrays.xml b/packages/SettingsLib/res/values-uz/arrays.xml
index dc7e6cd..3e53ae6 100644
--- a/packages/SettingsLib/res/values-uz/arrays.xml
+++ b/packages/SettingsLib/res/values-uz/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filtrlar yoniq"</item>
     <item msgid="2779123106632690576">"Yoniq"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Sarlavhalar filtrlandi"</item>
-    <item msgid="4818549483446395865">"A2DP media paketlar filtrlandi"</item>
-    <item msgid="8207123990453243311">"RFCOMM kanali filtrlandi"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Faolsizlantirilgan"</item>
-    <item msgid="5884245882825346396">"Sehr"</item>
-    <item msgid="6569400572915342949">"Sarlavha"</item>
-    <item msgid="1239386221416967664">"Toʻliq filtrlash"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (asosiy)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-vi/arrays.xml b/packages/SettingsLib/res/values-vi/arrays.xml
index 18e6c57..649cb5c 100644
--- a/packages/SettingsLib/res/values-vi/arrays.xml
+++ b/packages/SettingsLib/res/values-vi/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Đã bật và lọc"</item>
     <item msgid="2779123106632690576">"Đã bật"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Đã lọc tiêu đề"</item>
-    <item msgid="4818549483446395865">"Đã lọc gói nội dung nghe nhìn A2DP"</item>
-    <item msgid="8207123990453243311">"Đã lọc kênh RFCOMM"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Đã tắt"</item>
-    <item msgid="5884245882825346396">"Ảo thuật"</item>
-    <item msgid="6569400572915342949">"Tiêu đề"</item>
-    <item msgid="1239386221416967664">"Bộ lọc đầy đủ"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Mặc định)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-zh-rCN/arrays.xml b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
index 0d76e6f..13941af 100644
--- a/packages/SettingsLib/res/values-zh-rCN/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"已启用“已过滤”"</item>
     <item msgid="2779123106632690576">"已启用"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"已过滤标题"</item>
-    <item msgid="4818549483446395865">"已过滤 A2DP 媒体数据包"</item>
-    <item msgid="8207123990453243311">"已过滤 RFCOMM 通道"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"已停用"</item>
-    <item msgid="5884245882825346396">"魔术"</item>
-    <item msgid="6569400572915342949">"标题"</item>
-    <item msgid="1239386221416967664">"完整过滤器"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5(默认)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-zh-rHK/arrays.xml b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
index c30e9f7..9b359ed 100644
--- a/packages/SettingsLib/res/values-zh-rHK/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"已啟用篩選"</item>
     <item msgid="2779123106632690576">"已啟用"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"已篩選標題"</item>
-    <item msgid="4818549483446395865">"已篩選 A2DP 媒體封包"</item>
-    <item msgid="8207123990453243311">"已篩選 RFCOMM 頻道"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"已停用"</item>
-    <item msgid="5884245882825346396">"Magic"</item>
-    <item msgid="6569400572915342949">"標題"</item>
-    <item msgid="1239386221416967664">"完整篩選器"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (預設)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-zh-rTW/arrays.xml b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
index c6073f0..00362d8 100644
--- a/packages/SettingsLib/res/values-zh-rTW/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"已啟用篩選結果"</item>
     <item msgid="2779123106632690576">"已啟用"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"已篩選標頭"</item>
-    <item msgid="4818549483446395865">"已篩選 A2DP 媒體封包"</item>
-    <item msgid="8207123990453243311">"已篩選 RFCOMM 管道"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"已停用"</item>
-    <item msgid="5884245882825346396">"按偏好排序"</item>
-    <item msgid="6569400572915342949">"標頭"</item>
-    <item msgid="1239386221416967664">"完整篩選器"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (預設)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 8bfbd7a..588c4f4 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -230,7 +230,7 @@
     <string name="adb_wireless_error" msgid="721958772149779856">"錯誤"</string>
     <string name="adb_wireless_settings" msgid="2295017847215680229">"無線偵錯"</string>
     <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"如要查看並使用可用的裝置,請開啟無線偵錯功能"</string>
-    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"使用 QR 圖碼配對裝置"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"使用 QR code 配對裝置"</string>
     <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"使用 QR code 掃描器配對新裝置"</string>
     <string name="adb_pair_method_code_title" msgid="1122590300445142904">"使用配對碼配對裝置"</string>
     <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"使用六位數的配對碼配對新裝置"</string>
diff --git a/packages/SettingsLib/res/values-zu/arrays.xml b/packages/SettingsLib/res/values-zu/arrays.xml
index 8b23bbb..ac3cb02 100644
--- a/packages/SettingsLib/res/values-zu/arrays.xml
+++ b/packages/SettingsLib/res/values-zu/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Okuhlungiwe okunikwe amandla"</item>
     <item msgid="2779123106632690576">"Kunikwe amandla"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Izihloko Zihlungiwe"</item>
-    <item msgid="4818549483446395865">"I-A2DP Media Packets Ihlungiwe"</item>
-    <item msgid="8207123990453243311">"Isiteshi se-RFCOMM Sihlungiwe"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Kukhutshaziwe"</item>
-    <item msgid="5884245882825346396">"Umlingo"</item>
-    <item msgid="6569400572915342949">"Unhlokweni"</item>
-    <item msgid="1239386221416967664">"Isihlungi Esigcwele"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"I-AVRCP 1.5 (Okuzenzakalelayo)"</item>
     <item msgid="1637054408779685086">"I-AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index 5022960..3e2b800 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -572,7 +572,7 @@
 
     <!-- BatteryMeterView parameters -->
     <array name="batterymeter_color_levels">
-        <item>15</item>
+        <item>20</item>
         <item>100</item>
     </array>
     <array name="batterymeter_color_values">
diff --git a/packages/SettingsLib/res/values/colors.xml b/packages/SettingsLib/res/values/colors.xml
index 6b7e918..67139b5 100644
--- a/packages/SettingsLib/res/values/colors.xml
+++ b/packages/SettingsLib/res/values/colors.xml
@@ -43,4 +43,6 @@
     <color name="qr_focused_corner_line_color">#ff1a73e8</color>
     <color name="qr_background_color">#b3ffffff</color> <!-- 70% white transparency -->
     <!-- End of QR code scanner colors -->
+
+    <color name="batterymeter_saver_color">#FBBC04</color>
 </resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index b92b3d6..ff80f52 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -868,6 +868,11 @@
     <!-- UI debug setting: force right to left layout summary [CHAR LIMIT=100] -->
     <string name="force_rtl_layout_all_locales_summary">Force screen layout direction to RTL for all locales</string>
 
+    <!-- UI debug setting: make navigation bar background color transparent by default [CHAR LIMIT=50] -->
+    <string name="transparent_navigation_bar">Transparent navigation bar</string>
+    <!-- UI debug setting: make navigation bar background color transparent by default summary [CHAR LIMIT=100] -->
+    <string name="transparent_navigation_bar_summary">Make navigation bar background color transparent by default</string>
+
     <!-- UI debug setting: enable or disable window blurs [CHAR LIMIT=50] -->
     <string name="window_blurs">Allow window-level blurs</string>
 
@@ -1648,4 +1653,7 @@
         <item>Move right</item>
         <item>Move up</item>
     </string-array>
+
+    <!-- Formatting states for the scale of font size, in percent. Double "%" is required to represent the symbol "%". [CHAR LIMIT=20] -->
+    <string name="font_scale_percentage"> <xliff:g id="percentage">%1$d</xliff:g> %%</string>
 </resources>
diff --git a/packages/SettingsLib/search/lint-baseline.xml b/packages/SettingsLib/search/lint-baseline.xml
new file mode 100644
index 0000000..7ec512b
--- /dev/null
+++ b/packages/SettingsLib/search/lint-baseline.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.0.0-dev" type="baseline" dependencies="true" variant="all" version="8.0.0-dev">
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 23 (current min is 21): `new android.provider.SearchIndexableData`"
+        errorLine1="        super(context);"
+        errorLine2="        ~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableRaw.java"
+            line="62"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 23 (current min is 21): `android.provider.SearchIndexableData`"
+        errorLine1="public class SearchIndexableRaw extends SearchIndexableData {"
+        errorLine2="                                        ~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="frameworks/base/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableRaw.java"
+            line="29"
+            column="41"/>
+    </issue>
+
+</issues>
\ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/PrimarySwitchPreference.java b/packages/SettingsLib/src/com/android/settingslib/PrimarySwitchPreference.java
index fb06976..3ec5eba 100644
--- a/packages/SettingsLib/src/com/android/settingslib/PrimarySwitchPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/PrimarySwitchPreference.java
@@ -23,6 +23,7 @@
 
 import androidx.annotation.Keep;
 import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
 import androidx.preference.PreferenceViewHolder;
 
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
@@ -132,6 +133,11 @@
         }
     }
 
+    @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+    public boolean isSwitchEnabled() {
+        return mEnableSwitch;
+    }
+
     /**
      * If admin is not null, disables the switch.
      * Otherwise, keep it enabled.
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ServiceListing.java b/packages/SettingsLib/src/com/android/settingslib/applications/ServiceListing.java
index bd9e760..c8bcabf 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ServiceListing.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ServiceListing.java
@@ -35,6 +35,7 @@
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
+import java.util.function.Predicate;
 
 /**
  * Class for managing services matching a given intent and requesting a given permission.
@@ -51,12 +52,13 @@
     private final HashSet<ComponentName> mEnabledServices = new HashSet<>();
     private final List<ServiceInfo> mServices = new ArrayList<>();
     private final List<Callback> mCallbacks = new ArrayList<>();
+    private final Predicate mValidator;
 
     private boolean mListening;
 
     private ServiceListing(Context context, String tag,
             String setting, String intentAction, String permission, String noun,
-            boolean addDeviceLockedFlags) {
+            boolean addDeviceLockedFlags, Predicate validator) {
         mContentResolver = context.getContentResolver();
         mContext = context;
         mTag = tag;
@@ -65,6 +67,7 @@
         mPermission = permission;
         mNoun = noun;
         mAddDeviceLockedFlags = addDeviceLockedFlags;
+        mValidator = validator;
     }
 
     public void addCallback(Callback callback) {
@@ -137,7 +140,6 @@
         final PackageManager pmWrapper = mContext.getPackageManager();
         List<ResolveInfo> installedServices = pmWrapper.queryIntentServicesAsUser(
                 new Intent(mIntentAction), flags, user);
-
         for (ResolveInfo resolveInfo : installedServices) {
             ServiceInfo info = resolveInfo.serviceInfo;
 
@@ -148,6 +150,9 @@
                         + mPermission);
                 continue;
             }
+            if (mValidator != null && !mValidator.test(info)) {
+                continue;
+            }
             mServices.add(info);
         }
         for (Callback callback : mCallbacks) {
@@ -194,6 +199,7 @@
         private String mPermission;
         private String mNoun;
         private boolean mAddDeviceLockedFlags = false;
+        private Predicate mValidator;
 
         public Builder(Context context) {
             mContext = context;
@@ -224,6 +230,11 @@
             return this;
         }
 
+        public Builder setValidator(Predicate<ServiceInfo> validator) {
+            mValidator = validator;
+            return this;
+        }
+
         /**
          * Set to true to add support for both MATCH_DIRECT_BOOT_AWARE and
          * MATCH_DIRECT_BOOT_UNAWARE flags when querying PackageManager. Required to get results
@@ -236,7 +247,7 @@
 
         public ServiceListing build() {
             return new ServiceListing(mContext, mTag, mSetting, mIntentAction, mPermission, mNoun,
-                    mAddDeviceLockedFlags);
+                    mAddDeviceLockedFlags, mValidator);
         }
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 63bb2fe..a3d632c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -210,7 +210,7 @@
 
         synchronized (mProfileLock) {
             if (profile instanceof A2dpProfile || profile instanceof HeadsetProfile
-                    || profile instanceof HearingAidProfile) {
+                    || profile instanceof HearingAidProfile || profile instanceof LeAudioProfile) {
                 setProfileConnectedStatus(profile.getProfileId(), false);
                 switch (newProfileState) {
                     case BluetoothProfile.STATE_CONNECTED:
@@ -228,7 +228,20 @@
                     case BluetoothProfile.STATE_DISCONNECTED:
                         if (mHandler.hasMessages(profile.getProfileId())) {
                             mHandler.removeMessages(profile.getProfileId());
-                            setProfileConnectedStatus(profile.getProfileId(), true);
+                            if (profile.getConnectionPolicy(mDevice) >
+                                BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) {
+                                /*
+                                 * If we received state DISCONNECTED and previous state was
+                                 * CONNECTING and connection policy is FORBIDDEN or UNKNOWN
+                                 * then it's not really a failure to connect.
+                                 *
+                                 * Connection profile is considered as failed when connection
+                                 * policy indicates that profile should be connected
+                                 * but it got disconnected.
+                                 */
+                                Log.w(TAG, "onProfileStateChanged(): Failed to connect profile");
+                                setProfileConnectedStatus(profile.getProfileId(), true);
+                            }
                         }
                         break;
                     default:
@@ -1205,6 +1218,13 @@
     }
 
     private boolean isProfileConnectedFail() {
+        Log.d(TAG, "anonymizedAddress=" + mDevice.getAnonymizedAddress()
+                + " mIsA2dpProfileConnectedFail=" + mIsA2dpProfileConnectedFail
+                + " mIsHearingAidProfileConnectedFail=" + mIsHearingAidProfileConnectedFail
+                + " mIsLeAudioProfileConnectedFail=" + mIsLeAudioProfileConnectedFail
+                + " mIsHeadsetProfileConnectedFail=" + mIsHeadsetProfileConnectedFail
+                + " isConnectedSapDevice()=" + isConnectedSapDevice());
+
         return mIsA2dpProfileConnectedFail || mIsHearingAidProfileConnectedFail
                 || (!isConnectedSapDevice() && mIsHeadsetProfileConnectedFail)
                 || mIsLeAudioProfileConnectedFail;
diff --git a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
index 2614644..688fc72 100644
--- a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
@@ -55,6 +55,7 @@
         public ComponentName settingsComponentName;
         public CharSequence description;
         public Drawable previewImage;
+        public boolean supportsComplications = false;
 
         @Override
         public String toString() {
@@ -175,6 +176,7 @@
             if (dreamMetadata != null) {
                 dreamInfo.settingsComponentName = dreamMetadata.settingsActivity;
                 dreamInfo.previewImage = dreamMetadata.previewImage;
+                dreamInfo.supportsComplications = dreamMetadata.showComplications;
             }
             dreamInfos.add(dreamInfo);
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
index 28353ab..52f3111 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
@@ -169,8 +169,11 @@
      */
     public static boolean maybeShowBatterySaverConfirmation(Context context, Bundle extras) {
         if (Secure.getInt(context.getContentResolver(),
-                Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 0) != 0) {
-            return false; // Already shown.
+                Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 0) != 0
+                && Secure.getInt(context.getContentResolver(),
+                Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, 0) != 0) {
+            // Already shown.
+            return false;
         }
         context.sendBroadcast(
                 getSystemUiBroadcast(ACTION_SHOW_START_SAVER_CONFIRMATION, extras));
@@ -190,8 +193,10 @@
     }
 
     private static void setBatterySaverConfirmationAcknowledged(Context context) {
-        Secure.putIntForUser(context.getContentResolver(), Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1,
-                UserHandle.USER_CURRENT);
+        Secure.putIntForUser(context.getContentResolver(),
+                Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1, UserHandle.USER_CURRENT);
+        Secure.putIntForUser(context.getContentResolver(),
+                Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, 1, UserHandle.USER_CURRENT);
     }
 
     /**
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt b/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
index faea5b2..a03acc3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
@@ -135,7 +135,7 @@
     }
 
     private val errorPaint = Paint(Paint.ANTI_ALIAS_FLAG).also { p ->
-        p.color = Utils.getColorStateListDefaultColor(context, R.color.batterymeter_plus_color)
+        p.color = Utils.getColorStateListDefaultColor(context, R.color.batterymeter_saver_color)
         p.alpha = 255
         p.isDither = true
         p.strokeWidth = 0f
@@ -244,10 +244,11 @@
                 c.drawPath(scaledBolt, fillColorStrokeProtection)
             }
         } else if (powerSaveEnabled) {
-            // If power save is enabled draw the perimeter path with colorError
-            c.drawPath(scaledErrorPerimeter, errorPaint)
+            // If power save is enabled draw the level path with colorError
+            c.drawPath(levelPath, errorPaint)
             // And draw the plus sign on top of the fill
-            c.drawPath(scaledPlus, errorPaint)
+            fillPaint.color = fillColor
+            c.drawPath(scaledPlus, fillPaint)
         }
         c.restore()
     }
@@ -414,7 +415,7 @@
     companion object {
         const val WIDTH = 12f
         const val HEIGHT = 20f
-        private const val CRITICAL_LEVEL = 15
+        private const val CRITICAL_LEVEL = 20
         // On a 12x20 grid, how wide to make the fill protection stroke.
         // Scales when our size changes
         private const val PROTECTION_STROKE_WIDTH = 3f
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
index 6a1cee3..562d20d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
@@ -224,6 +224,9 @@
                     mMetricsLogger.logOnConditionSelected();
                     updateAlarmWarningText(tag.condition);
                 }
+                tag.line1.setStateDescription(
+                        isChecked ? buttonView.getContext().getString(
+                                com.android.internal.R.string.selected) : null);
             }
         });
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java b/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
index 87e97b1..abbdaa7 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
@@ -196,6 +196,9 @@
                 if (isChecked) {
                     tag.rb.setChecked(true);
                 }
+                tag.line1.setStateDescription(
+                        isChecked ? buttonView.getContext().getString(
+                                com.android.internal.R.string.selected) : null);
             }
         });
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/udfps/UdfpsUtils.java b/packages/SettingsLib/src/com/android/settingslib/udfps/UdfpsUtils.java
index dc8a862..31f014c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/udfps/UdfpsUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/udfps/UdfpsUtils.java
@@ -62,16 +62,7 @@
      */
     public Point getTouchInNativeCoordinates(int idx, MotionEvent event,
             UdfpsOverlayParams udfpsOverlayParams) {
-        Point portraitTouch = new Point((int) event.getRawX(idx), (int) event.getRawY(idx));
-        int rot = udfpsOverlayParams.getRotation();
-        if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
-            RotationUtils.rotatePoint(
-                    portraitTouch,
-                    RotationUtils.deltaRotation(rot, Surface.ROTATION_0),
-                    udfpsOverlayParams.getLogicalDisplayWidth(),
-                    udfpsOverlayParams.getLogicalDisplayHeight()
-            );
-        }
+        Point portraitTouch = getPortraitTouch(idx, event, udfpsOverlayParams);
 
         // Scale the coordinates to native resolution.
         float scale = udfpsOverlayParams.getScaleFactor();
@@ -81,13 +72,25 @@
     }
 
     /**
+     * @param idx                The pointer identifier.
+     * @param event              The MotionEvent object containing full information about the event.
+     * @param udfpsOverlayParams The [UdfpsOverlayParams] used.
+     * @return Whether the touch event is within sensor area.
+     */
+    public boolean isWithinSensorArea(int idx, MotionEvent event,
+            UdfpsOverlayParams udfpsOverlayParams) {
+        Point portraitTouch = getPortraitTouch(idx, event, udfpsOverlayParams);
+        return udfpsOverlayParams.getSensorBounds().contains(portraitTouch.x, portraitTouch.y);
+    }
+
+    /**
      * This function computes the angle of touch relative to the sensor and maps the angle to a list
      * of help messages which are announced if accessibility is enabled.
      *
      * @return Whether the announcing string is null
      */
-    public String onTouchOutsideOfSensorArea(boolean touchExplorationEnabled,
-            Context context, int touchX, int touchY, UdfpsOverlayParams udfpsOverlayParams) {
+    public String onTouchOutsideOfSensorArea(boolean touchExplorationEnabled, Context context,
+            int scaledTouchX, int scaledTouchY, UdfpsOverlayParams udfpsOverlayParams) {
         if (!touchExplorationEnabled) {
             return null;
         }
@@ -106,8 +109,8 @@
         String theStr =
                 onTouchOutsideOfSensorAreaImpl(
                         touchHints,
-                        touchX,
-                        touchY,
+                        scaledTouchX,
+                        scaledTouchY,
                         scaledSensorX,
                         scaledSensorY,
                         udfpsOverlayParams.getRotation()
@@ -156,4 +159,22 @@
         }
         return touchHints[index];
     }
+
+    /**
+     * Map the touch to portrait mode if the device is in landscape mode.
+     */
+    private Point getPortraitTouch(int idx, MotionEvent event,
+            UdfpsOverlayParams udfpsOverlayParams) {
+        Point portraitTouch = new Point((int) event.getRawX(idx), (int) event.getRawY(idx));
+        int rot = udfpsOverlayParams.getRotation();
+        if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
+            RotationUtils.rotatePoint(
+                    portraitTouch,
+                    RotationUtils.deltaRotation(rot, Surface.ROTATION_0),
+                    udfpsOverlayParams.getLogicalDisplayWidth(),
+                    udfpsOverlayParams.getLogicalDisplayHeight()
+            );
+        }
+        return portraitTouch;
+    }
 }
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/DeviceStateRotationLockSettingsManagerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/DeviceStateRotationLockSettingsManagerTest.java
index 81006dd..0fa15eb 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/DeviceStateRotationLockSettingsManagerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/DeviceStateRotationLockSettingsManagerTest.java
@@ -33,7 +33,10 @@
 import com.android.internal.R;
 import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager.SettableDeviceState;
 
+import com.google.common.truth.Expect;
+
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -45,6 +48,8 @@
 @RunWith(AndroidJUnit4.class)
 public class DeviceStateRotationLockSettingsManagerTest {
 
+    @Rule public Expect mExpect = Expect.create();
+
     @Mock private Context mMockContext;
     @Mock private Resources mMockResources;
 
@@ -117,4 +122,40 @@
                 new SettableDeviceState(/* deviceState= */ 0, /* isSettable= */ false)
         ).inOrder();
     }
+
+    @Test
+    public void persistedInvalidIgnoredState_returnsDefaults() {
+        when(mMockResources.getStringArray(
+                R.array.config_perDeviceStateRotationLockDefaults)).thenReturn(
+                new String[]{"0:1", "1:0:2", "2:2"});
+        // Here 2 has IGNORED, and in the defaults 1 has IGNORED.
+        persistSettings("0:2:2:0:1:2");
+        DeviceStateRotationLockSettingsManager manager =
+                new DeviceStateRotationLockSettingsManager(mMockContext, mFakeSecureSettings);
+
+        mExpect.that(manager.getRotationLockSetting(0)).isEqualTo(1);
+        mExpect.that(manager.getRotationLockSetting(1)).isEqualTo(2);
+        mExpect.that(manager.getRotationLockSetting(2)).isEqualTo(2);
+    }
+
+    @Test
+    public void persistedValidValues_returnsPersistedValues() {
+        when(mMockResources.getStringArray(
+                R.array.config_perDeviceStateRotationLockDefaults)).thenReturn(
+                new String[]{"0:1", "1:0:2", "2:2"});
+        persistSettings("0:2:1:0:2:1");
+        DeviceStateRotationLockSettingsManager manager =
+                new DeviceStateRotationLockSettingsManager(mMockContext, mFakeSecureSettings);
+
+        mExpect.that(manager.getRotationLockSetting(0)).isEqualTo(2);
+        mExpect.that(manager.getRotationLockSetting(1)).isEqualTo(1);
+        mExpect.that(manager.getRotationLockSetting(2)).isEqualTo(1);
+    }
+
+    private void persistSettings(String value) {
+        mFakeSecureSettings.putStringForUser(
+                Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
+                value,
+                UserHandle.USER_CURRENT);
+    }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java
index f7fd25b..7ff0988 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java
@@ -18,20 +18,35 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyList;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
 import android.provider.Settings;
 
+import androidx.test.core.app.ApplicationProvider;
+
+import com.google.common.collect.ImmutableList;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 
+import java.util.List;
+
 @RunWith(RobolectricTestRunner.class)
 public class ServiceListingTest {
 
@@ -39,10 +54,16 @@
     private static final String TEST_INTENT = "com.example.intent";
 
     private ServiceListing mServiceListing;
+    private Context mContext;
+    private PackageManager mPm;
 
     @Before
     public void setUp() {
-        mServiceListing = new ServiceListing.Builder(RuntimeEnvironment.application)
+        mPm = mock(PackageManager.class);
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        when(mContext.getPackageManager()).thenReturn(mPm);
+
+        mServiceListing = new ServiceListing.Builder(mContext)
                 .setTag("testTag")
                 .setSetting(TEST_SETTING)
                 .setNoun("testNoun")
@@ -52,6 +73,81 @@
     }
 
     @Test
+    public void testValidator() {
+        ServiceInfo s1 = new ServiceInfo();
+        s1.permission = "testPermission";
+        s1.packageName = "pkg";
+        ServiceInfo s2 = new ServiceInfo();
+        s2.permission = "testPermission";
+        s2.packageName = "pkg2";
+        ResolveInfo r1 = new ResolveInfo();
+        r1.serviceInfo = s1;
+        ResolveInfo r2 = new ResolveInfo();
+        r2.serviceInfo = s2;
+
+        when(mPm.queryIntentServicesAsUser(any(), anyInt(), anyInt())).thenReturn(
+                ImmutableList.of(r1, r2));
+
+        mServiceListing = new ServiceListing.Builder(mContext)
+                .setTag("testTag")
+                .setSetting(TEST_SETTING)
+                .setNoun("testNoun")
+                .setIntentAction(TEST_INTENT)
+                .setValidator(info -> {
+                    if (info.packageName.equals("pkg")) {
+                        return true;
+                    }
+                    return false;
+                })
+                .setPermission("testPermission")
+                .build();
+        ServiceListing.Callback callback = mock(ServiceListing.Callback.class);
+        mServiceListing.addCallback(callback);
+        mServiceListing.reload();
+
+        verify(mPm).queryIntentServicesAsUser(any(), anyInt(), anyInt());
+        ArgumentCaptor<List<ServiceInfo>> captor = ArgumentCaptor.forClass(List.class);
+        verify(callback, times(1)).onServicesReloaded(captor.capture());
+
+        assertThat(captor.getValue().size()).isEqualTo(1);
+        assertThat(captor.getValue().get(0)).isEqualTo(s1);
+    }
+
+    @Test
+    public void testNoValidator() {
+        ServiceInfo s1 = new ServiceInfo();
+        s1.permission = "testPermission";
+        s1.packageName = "pkg";
+        ServiceInfo s2 = new ServiceInfo();
+        s2.permission = "testPermission";
+        s2.packageName = "pkg2";
+        ResolveInfo r1 = new ResolveInfo();
+        r1.serviceInfo = s1;
+        ResolveInfo r2 = new ResolveInfo();
+        r2.serviceInfo = s2;
+
+        when(mPm.queryIntentServicesAsUser(any(), anyInt(), anyInt())).thenReturn(
+                ImmutableList.of(r1, r2));
+
+        mServiceListing = new ServiceListing.Builder(mContext)
+                .setTag("testTag")
+                .setSetting(TEST_SETTING)
+                .setNoun("testNoun")
+                .setIntentAction(TEST_INTENT)
+                .setPermission("testPermission")
+                .build();
+        ServiceListing.Callback callback = mock(ServiceListing.Callback.class);
+        mServiceListing.addCallback(callback);
+        mServiceListing.reload();
+
+        verify(mPm).queryIntentServicesAsUser(any(), anyInt(), anyInt());
+        ArgumentCaptor<List<ServiceInfo>> captor = ArgumentCaptor.forClass(List.class);
+        verify(callback, times(1)).onServicesReloaded(captor.capture());
+
+        assertThat(captor.getValue().size()).isEqualTo(2);
+    }
+
+    @Test
     public void testCallback() {
         ServiceListing.Callback callback = mock(ServiceListing.Callback.class);
         mServiceListing.addCallback(callback);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
index 77c19a1..1c179f8 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -97,15 +97,76 @@
         mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
         when(mDevice.getAddress()).thenReturn(DEVICE_ADDRESS);
         when(mHfpProfile.isProfileReady()).thenReturn(true);
+        when(mHfpProfile.getProfileId()).thenReturn(BluetoothProfile.HEADSET);
         when(mA2dpProfile.isProfileReady()).thenReturn(true);
+        when(mA2dpProfile.getProfileId()).thenReturn(BluetoothProfile.A2DP);
         when(mPanProfile.isProfileReady()).thenReturn(true);
+        when(mPanProfile.getProfileId()).thenReturn(BluetoothProfile.PAN);
         when(mHearingAidProfile.isProfileReady()).thenReturn(true);
+        when(mHearingAidProfile.getProfileId()).thenReturn(BluetoothProfile.HEARING_AID);
+        when(mLeAudioProfile.isProfileReady()).thenReturn(true);
+        when(mLeAudioProfile.getProfileId()).thenReturn(BluetoothProfile.LE_AUDIO);
         mCachedDevice = spy(new CachedBluetoothDevice(mContext, mProfileManager, mDevice));
         mSubCachedDevice = spy(new CachedBluetoothDevice(mContext, mProfileManager, mSubDevice));
         doAnswer((invocation) -> mBatteryLevel).when(mCachedDevice).getBatteryLevel();
         doAnswer((invocation) -> mBatteryLevel).when(mSubCachedDevice).getBatteryLevel();
     }
 
+    private void testTransitionFromConnectingToDisconnected(
+        LocalBluetoothProfile connectingProfile, LocalBluetoothProfile connectedProfile,
+        int connectionPolicy, String expectedSummary) {
+        // Arrange:
+        // At least one profile has to be connected
+        updateProfileStatus(connectedProfile, BluetoothProfile.STATE_CONNECTED);
+        // Set profile under test to CONNECTING
+        updateProfileStatus(connectingProfile, BluetoothProfile.STATE_CONNECTING);
+        // Set connection policy
+        when(connectingProfile.getConnectionPolicy(mDevice)).thenReturn(connectionPolicy);
+
+        // Act & Assert:
+        //   Get the expected connection summary.
+        updateProfileStatus(connectingProfile, BluetoothProfile.STATE_DISCONNECTED);
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(expectedSummary);
+    }
+
+    @Test
+    public void onProfileStateChanged_testConnectingToDisconnected_policyAllowed_problem() {
+        String connectTimeoutString = mContext.getString(R.string.profile_connect_timeout_subtext);
+
+        testTransitionFromConnectingToDisconnected(mA2dpProfile, mLeAudioProfile,
+        BluetoothProfile.CONNECTION_POLICY_ALLOWED, connectTimeoutString);
+        testTransitionFromConnectingToDisconnected(mHearingAidProfile, mLeAudioProfile,
+        BluetoothProfile.CONNECTION_POLICY_ALLOWED, connectTimeoutString);
+        testTransitionFromConnectingToDisconnected(mHfpProfile, mLeAudioProfile,
+        BluetoothProfile.CONNECTION_POLICY_ALLOWED, connectTimeoutString);
+        testTransitionFromConnectingToDisconnected(mLeAudioProfile, mA2dpProfile,
+        BluetoothProfile.CONNECTION_POLICY_ALLOWED, connectTimeoutString);
+    }
+
+    @Test
+    public void onProfileStateChanged_testConnectingToDisconnected_policyForbidden_noProblem() {
+        testTransitionFromConnectingToDisconnected(mA2dpProfile, mLeAudioProfile,
+        BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, null);
+        testTransitionFromConnectingToDisconnected(mHearingAidProfile, mLeAudioProfile,
+        BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, null);
+        testTransitionFromConnectingToDisconnected(mHfpProfile, mLeAudioProfile,
+        BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, null);
+        testTransitionFromConnectingToDisconnected(mLeAudioProfile, mA2dpProfile,
+        BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, null);
+    }
+
+    @Test
+    public void onProfileStateChanged_testConnectingToDisconnected_policyUnknown_noProblem() {
+        testTransitionFromConnectingToDisconnected(mA2dpProfile, mLeAudioProfile,
+        BluetoothProfile.CONNECTION_POLICY_UNKNOWN, null);
+        testTransitionFromConnectingToDisconnected(mHearingAidProfile, mLeAudioProfile,
+        BluetoothProfile.CONNECTION_POLICY_UNKNOWN, null);
+        testTransitionFromConnectingToDisconnected(mHfpProfile, mLeAudioProfile,
+        BluetoothProfile.CONNECTION_POLICY_UNKNOWN, null);
+        testTransitionFromConnectingToDisconnected(mLeAudioProfile, mA2dpProfile,
+        BluetoothProfile.CONNECTION_POLICY_UNKNOWN, null);
+    }
+
     @Test
     public void getConnectionSummary_testProfilesInactive_returnPairing() {
         // Arrange:
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
index a15fe9f..ad022a6 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
@@ -69,6 +69,7 @@
     @Test
     public void testSetPowerSaveMode_enable_firstCall_needWarning() {
         Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
+        Secure.putString(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, "null");
         Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
 
         assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, true)).isFalse();
@@ -77,15 +78,18 @@
         verify(mMockPowerManager, times(0)).setPowerSaveModeEnabled(anyBoolean());
 
         // They shouldn't have changed.
+        assertEquals(-1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
         assertEquals(-1,
-                Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+                Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
         assertEquals(-2,
                 Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
     }
 
     @Test
     public void testSetPowerSaveMode_enable_secondCall_needWarning() {
-        Secure.putInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1); // Already acked.
+        // Already acked.
+        Secure.putInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1);
+        Secure.putInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, 1);
         Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
 
         assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, true)).isTrue();
@@ -94,12 +98,17 @@
         verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(true));
 
         assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
-        assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
+        assertEquals(1,
+                Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+        assertEquals(1,
+                Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
     }
 
     @Test
     public void testSetPowerSaveMode_enable_thridCall_needWarning() {
-        Secure.putInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1); // Already acked.
+        // Already acked.
+        Secure.putInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1);
+        Secure.putInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, 1);
         Secure.putInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, 1);
 
         assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, true)).isTrue();
@@ -108,12 +117,16 @@
         verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(true));
 
         assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
-        assertEquals(2, Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
+        assertEquals(1,
+                Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+        assertEquals(2,
+                Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
     }
 
     @Test
     public void testSetPowerSaveMode_enable_firstCall_noWarning() {
         Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
+        Secure.putString(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, "null");
         Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
 
         assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, false)).isTrue();
@@ -122,12 +135,15 @@
         verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(true));
 
         assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+        assertEquals(1,
+                Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
         assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
     }
 
     @Test
     public void testSetPowerSaveMode_disable_firstCall_noWarning() {
         Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
+        Secure.putString(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, "null");
         Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
 
         // When disabling, needFirstTimeWarning doesn't matter.
@@ -137,6 +153,8 @@
         verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(false));
 
         assertEquals(-1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+        assertEquals(-1,
+                Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
         assertEquals(-2,
                 Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
     }
@@ -144,6 +162,7 @@
     @Test
     public void testSetPowerSaveMode_disable_firstCall_needWarning() {
         Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
+        Secure.putString(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, "null");
         Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
 
         // When disabling, needFirstTimeWarning doesn't matter.
@@ -153,6 +172,8 @@
         verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(false));
 
         assertEquals(-1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+        assertEquals(-1,
+                Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
         assertEquals(-2,
                 Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
     }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
index 59d5674..6b81c1a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settingslib.notification;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
@@ -78,6 +80,8 @@
         mController.mForeverId =  Condition.newId(mContext).appendPath("forever").build();
         when(mContext.getString(com.android.internal.R.string.zen_mode_forever))
                 .thenReturn("testSummary");
+        when(mContext.getString(com.android.internal.R.string.selected))
+                .thenReturn("selected");
         NotificationManager.Policy alarmsEnabledPolicy = new NotificationManager.Policy(
                 NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS, 0, 0, 0);
         doReturn(alarmsEnabledPolicy).when(mNotificationManager).getNotificationPolicy();
@@ -190,4 +194,25 @@
         // alarm warning should NOT be null
         assertNotNull(mController.computeAlarmWarningText(null));
     }
+
+    @Test
+    public void testAccessibility() {
+        mController.bindConditions(null);
+        EnableZenModeDialog.ConditionTag forever = mController.getConditionTagAt(
+                ZenDurationDialog.FOREVER_CONDITION_INDEX);
+        EnableZenModeDialog.ConditionTag countdown = mController.getConditionTagAt(
+                ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
+        EnableZenModeDialog.ConditionTag alwaysAsk = mController.getConditionTagAt(
+                ZenDurationDialog.ALWAYS_ASK_CONDITION_INDEX);
+
+        forever.rb.setChecked(true);
+        assertThat(forever.line1.getStateDescription().toString()).isEqualTo("selected");
+        assertThat(countdown.line1.getStateDescription()).isNull();
+        assertThat(alwaysAsk.line1.getStateDescription()).isNull();
+
+        alwaysAsk.rb.setChecked(true);
+        assertThat(forever.line1.getStateDescription()).isNull();
+        assertThat(countdown.line1.getStateDescription()).isNull();
+        assertThat(alwaysAsk.line1.getStateDescription().toString()).isEqualTo("selected");
+    }
 }
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
index 437c0d4..fc45e89 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settingslib.notification;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
@@ -205,4 +207,27 @@
                 ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
         assertEquals(120, tag.countdownZenDuration);
     }
+
+    @Test
+    public void testAccessibility() {
+        Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_DURATION,
+                Settings.Secure.ZEN_DURATION_FOREVER);
+        mController.setupDialog(mBuilder);
+        ZenDurationDialog.ConditionTag forever = mController.getConditionTagAt(
+                ZenDurationDialog.FOREVER_CONDITION_INDEX);
+        ZenDurationDialog.ConditionTag countdown = mController.getConditionTagAt(
+                ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
+        ZenDurationDialog.ConditionTag alwaysAsk = mController.getConditionTagAt(
+                ZenDurationDialog.ALWAYS_ASK_CONDITION_INDEX);
+
+        forever.rb.setChecked(true);
+        assertThat(forever.line1.getStateDescription().toString()).isEqualTo("selected");
+        assertThat(countdown.line1.getStateDescription()).isNull();
+        assertThat(alwaysAsk.line1.getStateDescription()).isNull();
+
+        alwaysAsk.rb.setChecked(true);
+        assertThat(forever.line1.getStateDescription()).isNull();
+        assertThat(countdown.line1.getStateDescription()).isNull();
+        assertThat(alwaysAsk.line1.getStateDescription().toString()).isEqualTo("selected");
+    }
 }
\ No newline at end of file
diff --git a/packages/SettingsProvider/Android.bp b/packages/SettingsProvider/Android.bp
index 1ac20471..346462d 100644
--- a/packages/SettingsProvider/Android.bp
+++ b/packages/SettingsProvider/Android.bp
@@ -48,6 +48,7 @@
         "test/**/*.java",
         "src/android/provider/settings/backup/*",
         "src/android/provider/settings/validators/*",
+        "src/com/android/providers/settings/GenerationRegistry.java",
         "src/com/android/providers/settings/SettingsBackupAgent.java",
         "src/com/android/providers/settings/SettingsState.java",
         "src/com/android/providers/settings/SettingsHelper.java",
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
index 09a1ba2..e50f522 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
@@ -49,6 +49,7 @@
         Settings.Global.CHARGING_SOUNDS_ENABLED,
         Settings.Global.USB_MASS_STORAGE_ENABLED,
         Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
+        Settings.Global.NETWORK_AVOID_BAD_WIFI,
         Settings.Global.WIFI_WAKEUP_ENABLED,
         Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
         Settings.Global.USE_OPEN_WIFI_PACKAGE,
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 210a387..f66fcba 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -142,6 +142,8 @@
         Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION,
         Settings.Secure.VOLUME_HUSH_GESTURE,
         Settings.Secure.MANUAL_RINGER_TOGGLE_COUNT,
+        Settings.Secure.LOW_POWER_WARNING_ACKNOWLEDGED,
+        Settings.Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED,
         Settings.Secure.HUSH_GESTURE_USED,
         Settings.Secure.IN_CALL_NOTIFICATION_ENABLED,
         Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
@@ -237,5 +239,6 @@
         Settings.Secure.HEARING_AID_CALL_ROUTING,
         Settings.Secure.HEARING_AID_MEDIA_ROUTING,
         Settings.Secure.HEARING_AID_SYSTEM_SOUNDS_ROUTING,
+        Settings.Secure.ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED
     };
 }
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
index c9d840a..6a5535d 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
@@ -97,5 +97,8 @@
         Settings.System.TOUCHPAD_NATURAL_SCROLLING,
         Settings.System.TOUCHPAD_TAP_TO_CLICK,
         Settings.System.TOUCHPAD_RIGHT_CLICK_ZONE,
+        Settings.System.CAMERA_FLASH_NOTIFICATION,
+        Settings.System.SCREEN_FLASH_NOTIFICATION,
+        Settings.System.SCREEN_FLASH_NOTIFICATION_COLOR,
     };
 }
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
index e57cf3b..8d07fb6 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
@@ -20,6 +20,9 @@
 import static android.hardware.display.HdrConversionMode.HDR_CONVERSION_PASSTHROUGH;
 import static android.hardware.display.HdrConversionMode.HDR_CONVERSION_SYSTEM;
 import static android.media.AudioFormat.SURROUND_SOUND_ENCODING;
+import static android.net.ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI_AVOID;
+import static android.net.ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI_IGNORE;
+import static android.net.ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI_PROMPT;
 import static android.provider.settings.validators.SettingsValidators.ANY_INTEGER_VALIDATOR;
 import static android.provider.settings.validators.SettingsValidators.ANY_STRING_VALIDATOR;
 import static android.provider.settings.validators.SettingsValidators.BOOLEAN_VALIDATOR;
@@ -103,6 +106,14 @@
         VALIDATORS.put(
                 Global.NETWORK_RECOMMENDATIONS_ENABLED,
                 new DiscreteValueValidator(new String[] {"-1", "0", "1"}));
+        VALIDATORS.put(
+                Global.NETWORK_AVOID_BAD_WIFI,
+                new DiscreteValueValidator(
+                        new String[] {
+                                String.valueOf(NETWORK_AVOID_BAD_WIFI_IGNORE),
+                                String.valueOf(NETWORK_AVOID_BAD_WIFI_PROMPT),
+                                String.valueOf(NETWORK_AVOID_BAD_WIFI_AVOID),
+                        }));
         VALIDATORS.put(Global.WIFI_WAKEUP_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, BOOLEAN_VALIDATOR);
         VALIDATORS.put(
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 39cd24a..558e19f 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -219,6 +219,8 @@
                 COLON_SEPARATED_PACKAGE_LIST_VALIDATOR); // legacy restore setting
         VALIDATORS.put(Secure.HUSH_GESTURE_USED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.MANUAL_RINGER_TOGGLE_COUNT, NON_NEGATIVE_INTEGER_VALIDATOR);
+        VALIDATORS.put(Secure.LOW_POWER_WARNING_ACKNOWLEDGED, BOOLEAN_VALIDATOR);
+        VALIDATORS.put(Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.IN_CALL_NOTIFICATION_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, BOOLEAN_VALIDATOR);
@@ -374,5 +376,6 @@
                 new DiscreteValueValidator(new String[] {"0", "1", "2"}));
         VALIDATORS.put(Secure.HEARING_AID_SYSTEM_SOUNDS_ROUTING,
                 new DiscreteValueValidator(new String[] {"0", "1", "2"}));
+        VALIDATORS.put(Secure.ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED, BOOLEAN_VALIDATOR);
     }
 }
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
index c2a3ada..3fe12b3 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
@@ -16,6 +16,7 @@
 
 package android.provider.settings.validators;
 
+import static android.provider.settings.validators.SettingsValidators.ANY_INTEGER_VALIDATOR;
 import static android.provider.settings.validators.SettingsValidators.ANY_STRING_VALIDATOR;
 import static android.provider.settings.validators.SettingsValidators.BOOLEAN_VALIDATOR;
 import static android.provider.settings.validators.SettingsValidators.COMPONENT_NAME_VALIDATOR;
@@ -215,5 +216,8 @@
         VALIDATORS.put(System.UNREAD_NOTIFICATION_DOT_INDICATOR, BOOLEAN_VALIDATOR);
         VALIDATORS.put(System.AUTO_LAUNCH_MEDIA_CONTROLS, BOOLEAN_VALIDATOR);
         VALIDATORS.put(System.LOCALE_PREFERENCES, ANY_STRING_VALIDATOR);
+        VALIDATORS.put(System.CAMERA_FLASH_NOTIFICATION, BOOLEAN_VALIDATOR);
+        VALIDATORS.put(System.SCREEN_FLASH_NOTIFICATION, BOOLEAN_VALIDATOR);
+        VALIDATORS.put(System.SCREEN_FLASH_NOTIFICATION_COLOR, ANY_INTEGER_VALIDATOR);
     }
 }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java b/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
index 5617331..db6cc1a 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
@@ -16,20 +16,21 @@
 
 package com.android.providers.settings;
 
+import android.annotation.NonNull;
 import android.os.Bundle;
-import android.os.UserManager;
 import android.provider.Settings;
+import android.util.ArrayMap;
 import android.util.MemoryIntArray;
 import android.util.Slog;
-import android.util.SparseIntArray;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 
 import java.io.IOException;
 
 /**
  * This class tracks changes for config/global/secure/system tables
- * on a per user basis and updates a shared memory region which
+ * on a per user basis and updates shared memory regions which
  * client processes can read to determine if their local caches are
  * stale.
  */
@@ -40,138 +41,212 @@
 
     private final Object mLock;
 
+    // Key -> backingStore mapping
     @GuardedBy("mLock")
-    private final SparseIntArray mKeyToIndexMap = new SparseIntArray();
+    private final ArrayMap<Integer, MemoryIntArray> mKeyToBackingStoreMap = new ArrayMap();
+
+    // Key -> (String->Index map) mapping
+    @GuardedBy("mLock")
+    private final ArrayMap<Integer, ArrayMap<String, Integer>> mKeyToIndexMapMap = new ArrayMap<>();
+
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    // Maximum number of backing stores allowed
+    static final int NUM_MAX_BACKING_STORE = 8;
 
     @GuardedBy("mLock")
-    private MemoryIntArray mBackingStore;
+    private int mNumBackingStore = 0;
+
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    // Maximum size of an individual backing store
+    static final int MAX_BACKING_STORE_SIZE = MemoryIntArray.getMaxSize();
+
+    // Use an empty string to track the generation number of all non-predefined, unset settings
+    // The generation number is only increased when a new non-predefined setting is inserted
+    private static final String DEFAULT_MAP_KEY_FOR_UNSET_SETTINGS = "";
 
     public GenerationRegistry(Object lock) {
         mLock = lock;
     }
 
-    public void incrementGeneration(int key) {
+    /**
+     *  Increment the generation number if the setting is already cached in the backing stores.
+     *  Otherwise, do nothing.
+     */
+    public void incrementGeneration(int key, String name) {
+        final boolean isConfig =
+                (SettingsState.getTypeFromKey(key) == SettingsState.SETTINGS_TYPE_CONFIG);
+        // Only store the prefix if the mutated setting is a config
+        final String indexMapKey = isConfig ? (name.split("/")[0] + "/") : name;
+        incrementGenerationInternal(key, indexMapKey);
+    }
+
+    private void incrementGenerationInternal(int key, @NonNull String indexMapKey) {
         synchronized (mLock) {
-            MemoryIntArray backingStore = getBackingStoreLocked();
-            if (backingStore != null) {
-                try {
-                    final int index = getKeyIndexLocked(key, mKeyToIndexMap, backingStore);
-                    if (index >= 0) {
-                        final int generation = backingStore.get(index) + 1;
-                        backingStore.set(index, generation);
-                    }
-                } catch (IOException e) {
-                    Slog.e(LOG_TAG, "Error updating generation id", e);
-                    destroyBackingStore();
+            final MemoryIntArray backingStore = getBackingStoreLocked(key,
+                    /* createIfNotExist= */ false);
+            if (backingStore == null) {
+                return;
+            }
+            try {
+                final int index = getKeyIndexLocked(key, indexMapKey, mKeyToIndexMapMap,
+                        backingStore, /* createIfNotExist= */ false);
+                if (index < 0) {
+                    return;
                 }
+                final int generation = backingStore.get(index) + 1;
+                backingStore.set(index, generation);
+                if (DEBUG) {
+                    Slog.i(LOG_TAG, "Incremented generation for "
+                            + (indexMapKey.isEmpty() ? "unset settings" : "setting:" + indexMapKey)
+                            + " key:" + SettingsState.keyToString(key)
+                            + " at index:" + index);
+                }
+            } catch (IOException e) {
+                Slog.e(LOG_TAG, "Error updating generation id", e);
+                destroyBackingStoreLocked(key);
             }
         }
     }
 
-    public void addGenerationData(Bundle bundle, int key) {
+    // A new, non-predefined setting has been inserted, increment the tracking number for all unset
+    // settings
+    public void incrementGenerationForUnsetSettings(int key) {
+        final boolean isConfig =
+                (SettingsState.getTypeFromKey(key) == SettingsState.SETTINGS_TYPE_CONFIG);
+        if (isConfig) {
+            // No need to track new settings for configs
+            return;
+        }
+        incrementGenerationInternal(key, DEFAULT_MAP_KEY_FOR_UNSET_SETTINGS);
+    }
+
+    /**
+     *  Return the backing store's reference, the index and the current generation number
+     *  of a cached setting. If it was not in the backing store, first create the entry in it before
+     *  returning the result.
+     */
+    public void addGenerationData(Bundle bundle, int key, String indexMapKey) {
         synchronized (mLock) {
-            MemoryIntArray backingStore = getBackingStoreLocked();
+            final MemoryIntArray backingStore = getBackingStoreLocked(key,
+                    /* createIfNotExist= */ true);
+            if (backingStore == null) {
+                // Error accessing existing backing store or no new backing store is available
+                return;
+            }
             try {
-                if (backingStore != null) {
-                    final int index = getKeyIndexLocked(key, mKeyToIndexMap, backingStore);
-                    if (index >= 0) {
-                        bundle.putParcelable(Settings.CALL_METHOD_TRACK_GENERATION_KEY,
-                                backingStore);
-                        bundle.putInt(Settings.CALL_METHOD_GENERATION_INDEX_KEY, index);
-                        bundle.putInt(Settings.CALL_METHOD_GENERATION_KEY,
-                                backingStore.get(index));
-                        if (DEBUG) {
-                            Slog.i(LOG_TAG, "Exported index:" + index + " for key:"
-                                    + SettingsProvider.keyToString(key));
-                        }
-                    }
+                final int index = getKeyIndexLocked(key, indexMapKey, mKeyToIndexMapMap,
+                        backingStore, /* createIfNotExist= */ true);
+                if (index < 0) {
+                    // Should not happen unless having error accessing the backing store
+                    return;
+                }
+                bundle.putParcelable(Settings.CALL_METHOD_TRACK_GENERATION_KEY,
+                        backingStore);
+                bundle.putInt(Settings.CALL_METHOD_GENERATION_INDEX_KEY, index);
+                bundle.putInt(Settings.CALL_METHOD_GENERATION_KEY,
+                        backingStore.get(index));
+                if (DEBUG) {
+                    Slog.i(LOG_TAG, "Exported index:" + index + " for "
+                            + (indexMapKey.isEmpty() ? "unset settings" : "setting:" + indexMapKey)
+                            + " key:" + SettingsState.keyToString(key));
                 }
             } catch (IOException e) {
                 Slog.e(LOG_TAG, "Error adding generation data", e);
-                destroyBackingStore();
+                destroyBackingStoreLocked(key);
             }
         }
     }
 
-    public void onUserRemoved(int userId) {
-        synchronized (mLock) {
-            MemoryIntArray backingStore = getBackingStoreLocked();
-            if (backingStore != null && mKeyToIndexMap.size() > 0) {
-                try {
-                    final int secureKey = SettingsProvider.makeKey(
-                            SettingsProvider.SETTINGS_TYPE_SECURE, userId);
-                    resetSlotForKeyLocked(secureKey, mKeyToIndexMap, backingStore);
+    public void addGenerationDataForUnsetSettings(Bundle bundle, int key) {
+        addGenerationData(bundle, key, /* indexMapKey= */ DEFAULT_MAP_KEY_FOR_UNSET_SETTINGS);
+    }
 
-                    final int systemKey = SettingsProvider.makeKey(
-                            SettingsProvider.SETTINGS_TYPE_SYSTEM, userId);
-                    resetSlotForKeyLocked(systemKey, mKeyToIndexMap, backingStore);
-                } catch (IOException e) {
-                    Slog.e(LOG_TAG, "Error cleaning up for user", e);
-                    destroyBackingStore();
-                }
+    public void onUserRemoved(int userId) {
+        final int secureKey = SettingsState.makeKey(
+                SettingsState.SETTINGS_TYPE_SECURE, userId);
+        final int systemKey = SettingsState.makeKey(
+                SettingsState.SETTINGS_TYPE_SYSTEM, userId);
+        synchronized (mLock) {
+            if (mKeyToIndexMapMap.containsKey(secureKey)) {
+                destroyBackingStoreLocked(secureKey);
+                mKeyToIndexMapMap.remove(secureKey);
+                mNumBackingStore = mNumBackingStore - 1;
+            }
+            if (mKeyToIndexMapMap.containsKey(systemKey)) {
+                destroyBackingStoreLocked(systemKey);
+                mKeyToIndexMapMap.remove(systemKey);
+                mNumBackingStore = mNumBackingStore - 1;
             }
         }
     }
 
     @GuardedBy("mLock")
-    private MemoryIntArray getBackingStoreLocked() {
-        if (mBackingStore == null) {
-            // One for the config table, one for the global table, two for system
-            // and secure tables for a managed profile (managed profile is not
-            // included in the max user count), ten for partially deleted users if
-            // users are quickly removed, and twice max user count for system and
-            // secure.
-            final int size = 1 + 1 + 2 + 10 + 2 * UserManager.getMaxSupportedUsers();
+    private MemoryIntArray getBackingStoreLocked(int key, boolean createIfNotExist) {
+        MemoryIntArray backingStore = mKeyToBackingStoreMap.get(key);
+        if (!createIfNotExist) {
+            return backingStore;
+        }
+        if (backingStore == null) {
             try {
-                mBackingStore = new MemoryIntArray(size);
+                if (mNumBackingStore >= NUM_MAX_BACKING_STORE) {
+                    Slog.e(LOG_TAG, "Error creating backing store - at capacity");
+                    return null;
+                }
+                backingStore = new MemoryIntArray(MAX_BACKING_STORE_SIZE);
+                mKeyToBackingStoreMap.put(key, backingStore);
+                mNumBackingStore += 1;
                 if (DEBUG) {
-                    Slog.e(LOG_TAG, "Created backing store " + mBackingStore);
+                    Slog.e(LOG_TAG, "Created backing store for "
+                            + SettingsState.keyToString(key) + " on user: "
+                            + SettingsState.getUserIdFromKey(key));
                 }
             } catch (IOException e) {
                 Slog.e(LOG_TAG, "Error creating generation tracker", e);
             }
         }
-        return mBackingStore;
+        return backingStore;
     }
 
-    private void destroyBackingStore() {
-        if (mBackingStore != null) {
+    @GuardedBy("mLock")
+    private void destroyBackingStoreLocked(int key) {
+        MemoryIntArray backingStore = mKeyToBackingStoreMap.get(key);
+        if (backingStore != null) {
             try {
-                mBackingStore.close();
+                backingStore.close();
                 if (DEBUG) {
-                    Slog.e(LOG_TAG, "Destroyed backing store " + mBackingStore);
+                    Slog.e(LOG_TAG, "Destroyed backing store " + backingStore);
                 }
             } catch (IOException e) {
                 Slog.e(LOG_TAG, "Cannot close generation memory array", e);
             }
-            mBackingStore = null;
+            mKeyToBackingStoreMap.remove(key);
         }
     }
 
-    private static void resetSlotForKeyLocked(int key, SparseIntArray keyToIndexMap,
-            MemoryIntArray backingStore) throws IOException {
-        final int index = keyToIndexMap.get(key, -1);
-        if (index >= 0) {
-            keyToIndexMap.delete(key);
-            backingStore.set(index, 0);
-            if (DEBUG) {
-                Slog.i(LOG_TAG, "Freed index:" + index + " for key:"
-                        + SettingsProvider.keyToString(key));
+    private static int getKeyIndexLocked(int key, String indexMapKey,
+            ArrayMap<Integer, ArrayMap<String, Integer>> keyToIndexMapMap,
+            MemoryIntArray backingStore, boolean createIfNotExist) throws IOException {
+        ArrayMap<String, Integer> nameToIndexMap = keyToIndexMapMap.get(key);
+        if (nameToIndexMap == null) {
+            if (!createIfNotExist) {
+                return -1;
             }
+            nameToIndexMap = new ArrayMap<>();
+            keyToIndexMapMap.put(key, nameToIndexMap);
         }
-    }
-
-    private static int getKeyIndexLocked(int key, SparseIntArray keyToIndexMap,
-            MemoryIntArray backingStore) throws IOException {
-        int index = keyToIndexMap.get(key, -1);
+        int index = nameToIndexMap.getOrDefault(indexMapKey, -1);
         if (index < 0) {
+            if (!createIfNotExist) {
+                return -1;
+            }
             index = findNextEmptyIndex(backingStore);
             if (index >= 0) {
                 backingStore.set(index, 1);
-                keyToIndexMap.append(key, index);
+                nameToIndexMap.put(indexMapKey, index);
                 if (DEBUG) {
-                    Slog.i(LOG_TAG, "Allocated index:" + index + " for key:"
-                            + SettingsProvider.keyToString(key));
+                    Slog.i(LOG_TAG, "Allocated index:" + index + " for setting:" + indexMapKey
+                            + " of type:" + SettingsState.keyToString(key)
+                            + " on user:" + SettingsState.getUserIdFromKey(key));
                 }
             } else {
                 Slog.e(LOG_TAG, "Could not allocate generation index");
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 574fd5a..11154d1 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -182,6 +182,8 @@
             "visible_pattern_enabled";
     private static final String KEY_LOCK_SETTINGS_POWER_BUTTON_INSTANTLY_LOCKS =
             "power_button_instantly_locks";
+    private static final String KEY_LOCK_SETTINGS_PIN_ENHANCED_PRIVACY =
+            "pin_enhanced_privacy";
 
     // Name of the temporary file we use during full backup/restore.  This is
     // stored in the full-backup tarfile as well, so should not be changed.
@@ -709,6 +711,10 @@
                 out.writeUTF(KEY_LOCK_SETTINGS_POWER_BUTTON_INSTANTLY_LOCKS);
                 out.writeUTF(powerButtonInstantlyLocks ? "1" : "0");
             }
+            if (lockPatternUtils.isPinEnhancedPrivacyEverChosen(userId)) {
+                out.writeUTF(KEY_LOCK_SETTINGS_PIN_ENHANCED_PRIVACY);
+                out.writeUTF(lockPatternUtils.isPinEnhancedPrivacyEnabled(userId) ? "1" : "0");
+            }
             // End marker
             out.writeUTF("");
             out.flush();
@@ -961,6 +967,9 @@
                     case KEY_LOCK_SETTINGS_POWER_BUTTON_INSTANTLY_LOCKS:
                         lockPatternUtils.setPowerButtonInstantlyLocks("1".equals(value), userId);
                         break;
+                    case KEY_LOCK_SETTINGS_PIN_ENHANCED_PRIVACY:
+                        lockPatternUtils.setPinEnhancedPrivacyEnabled("1".equals(value), userId);
+                        break;
                 }
             }
             in.close();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index fb3c313..d49627e 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1852,6 +1852,9 @@
         dumpSetting(s, p,
                 Settings.Secure.HEARING_AID_SYSTEM_SOUNDS_ROUTING,
                 SecureSettingsProto.Accessibility.HEARING_AID_SYSTEM_SOUNDS_ROUTING);
+        dumpSetting(s, p,
+                Settings.Secure.ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED,
+                SecureSettingsProto.Accessibility.ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED);
         p.end(accessibilityToken);
 
         final long adaptiveSleepToken = p.start(SecureSettingsProto.ADAPTIVE_SLEEP);
@@ -2832,6 +2835,15 @@
         dumpSetting(s, p,
                 Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
                 SystemSettingsProto.Notification.VIBRATION_INTENSITY);
+        dumpSetting(s, p,
+                Settings.System.CAMERA_FLASH_NOTIFICATION,
+                SystemSettingsProto.Notification.CAMERA_FLASH_NOTIFICATION);
+        dumpSetting(s, p,
+                Settings.System.SCREEN_FLASH_NOTIFICATION,
+                SystemSettingsProto.Notification.SCREEN_FLASH_NOTIFICATION);
+        dumpSetting(s, p,
+                Settings.System.SCREEN_FLASH_NOTIFICATION_COLOR,
+                SystemSettingsProto.Notification.SCREEN_FLASH_NOTIFICATION_COLOR_GLOBAL);
         // Settings.System.NOTIFICATIONS_USE_RING_VOLUME intentionally excluded since it's deprecated.
         p.end(notificationToken);
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 683c08e..e6408bf 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -35,6 +35,7 @@
 import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
 import static com.android.internal.accessibility.util.AccessibilityUtils.ACCESSIBILITY_MENU_IN_SYSTEM;
 import static com.android.providers.settings.SettingsState.FALLBACK_FILE_SUFFIX;
+import static com.android.providers.settings.SettingsState.makeKey;
 
 import android.Manifest;
 import android.annotation.NonNull;
@@ -375,10 +376,6 @@
     @GuardedBy("mLock")
     private boolean mSyncConfigDisabledUntilReboot;
 
-    public static int makeKey(int type, int userId) {
-        return SettingsState.makeKey(type, userId);
-    }
-
     public static int getTypeFromKey(int key) {
         return SettingsState.getTypeFromKey(key);
     }
@@ -387,9 +384,6 @@
         return SettingsState.getUserIdFromKey(key);
     }
 
-    public static String keyToString(int key) {
-        return SettingsState.keyToString(key);
-    }
     @ChangeId
     @EnabledSince(targetSdkVersion=android.os.Build.VERSION_CODES.S)
     private static final long ENFORCE_READ_PERMISSION_FOR_MULTI_SIM_DATA_CALL = 172670679L;
@@ -428,22 +422,26 @@
         switch (method) {
             case Settings.CALL_METHOD_GET_CONFIG: {
                 Setting setting = getConfigSetting(name);
-                return packageValueForCallResult(setting, isTrackingGeneration(args));
+                return packageValueForCallResult(SETTINGS_TYPE_CONFIG, name, requestingUserId,
+                        setting, isTrackingGeneration(args));
             }
 
             case Settings.CALL_METHOD_GET_GLOBAL: {
                 Setting setting = getGlobalSetting(name);
-                return packageValueForCallResult(setting, isTrackingGeneration(args));
+                return packageValueForCallResult(SETTINGS_TYPE_GLOBAL, name, requestingUserId,
+                        setting, isTrackingGeneration(args));
             }
 
             case Settings.CALL_METHOD_GET_SECURE: {
                 Setting setting = getSecureSetting(name, requestingUserId);
-                return packageValueForCallResult(setting, isTrackingGeneration(args));
+                return packageValueForCallResult(SETTINGS_TYPE_SECURE, name, requestingUserId,
+                        setting, isTrackingGeneration(args));
             }
 
             case Settings.CALL_METHOD_GET_SYSTEM: {
                 Setting setting = getSystemSetting(name, requestingUserId);
-                return packageValueForCallResult(setting, isTrackingGeneration(args));
+                return packageValueForCallResult(SETTINGS_TYPE_SYSTEM, name, requestingUserId,
+                        setting, isTrackingGeneration(args));
             }
 
             case Settings.CALL_METHOD_PUT_CONFIG: {
@@ -553,7 +551,7 @@
 
             case Settings.CALL_METHOD_LIST_CONFIG: {
                 String prefix = getSettingPrefix(args);
-                Bundle result = packageValuesForCallResult(getAllConfigFlags(prefix),
+                Bundle result = packageValuesForCallResult(prefix, getAllConfigFlags(prefix),
                         isTrackingGeneration(args));
                 reportDeviceConfigAccess(prefix);
                 return result;
@@ -1175,7 +1173,7 @@
             Slog.v(LOG_TAG, "setAllConfigSettings for prefix: " + prefix);
         }
 
-        enforceWritePermission(Manifest.permission.WRITE_DEVICE_CONFIG);
+        enforceDeviceConfigWritePermission(getContext(), keyValues.keySet());
         final String callingPackage = resolveCallingPackage();
 
         synchronized (mLock) {
@@ -1194,7 +1192,8 @@
             Slog.v(LOG_TAG, "setSyncDisabledModeConfig(" + syncDisabledMode + ")");
         }
 
-        enforceWritePermission(Manifest.permission.WRITE_DEVICE_CONFIG);
+        enforceHasAtLeastOnePermission(Manifest.permission.WRITE_DEVICE_CONFIG,
+                Manifest.permission.READ_WRITE_SYNC_DISABLED_MODE_CONFIG);
 
         synchronized (mLock) {
             setSyncDisabledModeConfigLocked(syncDisabledMode);
@@ -1206,7 +1205,8 @@
             Slog.v(LOG_TAG, "getSyncDisabledModeConfig");
         }
 
-        enforceWritePermission(Manifest.permission.WRITE_DEVICE_CONFIG);
+        enforceHasAtLeastOnePermission(Manifest.permission.WRITE_DEVICE_CONFIG,
+                Manifest.permission.READ_WRITE_SYNC_DISABLED_MODE_CONFIG);
 
         synchronized (mLock) {
             return getSyncDisabledModeConfigLocked();
@@ -1291,13 +1291,13 @@
 
     private boolean mutateConfigSetting(String name, String value, String prefix,
             boolean makeDefault, int operation, int mode) {
-        enforceWritePermission(Manifest.permission.WRITE_DEVICE_CONFIG);
         final String callingPackage = resolveCallingPackage();
 
         // Perform the mutation.
         synchronized (mLock) {
             switch (operation) {
                 case MUTATION_OPERATION_INSERT: {
+                    enforceDeviceConfigWritePermission(getContext(), Collections.singleton(name));
                     return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_CONFIG,
                             UserHandle.USER_SYSTEM, name, value, null, makeDefault, true,
                             callingPackage, false, null,
@@ -1305,11 +1305,14 @@
                 }
 
                 case MUTATION_OPERATION_DELETE: {
+                    enforceDeviceConfigWritePermission(getContext(), Collections.singleton(name));
                     return mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_CONFIG,
                             UserHandle.USER_SYSTEM, name, false, null);
                 }
 
                 case MUTATION_OPERATION_RESET: {
+                    enforceDeviceConfigWritePermission(getContext(),
+                            getAllConfigFlags(prefix).keySet());
                     mSettingsRegistry.resetSettingsLocked(SETTINGS_TYPE_CONFIG,
                             UserHandle.USER_SYSTEM, callingPackage, mode, null, prefix);
                 } return true;
@@ -1319,6 +1322,7 @@
         return false;
     }
 
+    @NonNull
     private HashMap<String, String> getAllConfigFlags(@Nullable String prefix) {
         if (DEBUG) {
             Slog.v(LOG_TAG, "getAllConfigFlags() for " + prefix);
@@ -1465,7 +1469,7 @@
             boolean makeDefault, int requestingUserId, int operation, boolean forceNotify,
             int mode, boolean overrideableByRestore) {
         // Make sure the caller can change the settings - treated as secure.
-        enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS);
+        enforceHasAtLeastOnePermission(Manifest.permission.WRITE_SECURE_SETTINGS);
 
         // Resolve the userId on whose behalf the call is made.
         final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
@@ -1753,7 +1757,7 @@
             boolean makeDefault, int requestingUserId, int operation, boolean forceNotify,
             int mode, boolean overrideableByRestore) {
         // Make sure the caller can change the settings.
-        enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS);
+        enforceHasAtLeastOnePermission(Manifest.permission.WRITE_SECURE_SETTINGS);
 
         // Resolve the userId on whose behalf the call is made.
         final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
@@ -2278,11 +2282,57 @@
         }
     }
 
-    private void enforceWritePermission(String permission) {
-        if (getContext().checkCallingOrSelfPermission(permission)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Permission denial: writing to settings requires:"
-                    + permission);
+    private void enforceHasAtLeastOnePermission(String ...permissions) {
+        for (String permission : permissions) {
+            if (getContext().checkCallingOrSelfPermission(permission)
+                    == PackageManager.PERMISSION_GRANTED) {
+                return;
+            }
+        }
+        throw new SecurityException("Permission denial, must have one of: "
+            + Arrays.toString(permissions));
+    }
+
+    /**
+     * Throws an exception if write permissions are not granted for {@code flags}.
+     * <p>
+     * Write permissions are granted if the calling UID is root, or the
+     * WRITE_DEVICE_CONFIG permission is granted, or the WRITE_DEVICE_CONFIG_ALLOWLIST
+     * permission is granted and each flag in {@code flags} is allowlisted in {@code
+     * WRITABLE_FLAG_ALLOWLIST_FLAG}.
+     *
+     * @param context the {@link Context} this is called in
+     * @param flags a list of flags to check, each one of the form 'namespace/flagName'
+     *
+     * @throws SecurityException if the above criteria are not met.
+     * @hide
+     */
+    private void enforceDeviceConfigWritePermission(
+            @NonNull Context context,
+            @NonNull Set<String> flags) {
+        boolean hasAllowlistPermission =
+                context.checkCallingOrSelfPermission(
+                Manifest.permission.ALLOWLISTED_WRITE_DEVICE_CONFIG)
+                == PackageManager.PERMISSION_GRANTED;
+        boolean hasWritePermission =
+                context.checkCallingOrSelfPermission(
+                Manifest.permission.WRITE_DEVICE_CONFIG)
+                == PackageManager.PERMISSION_GRANTED;
+        boolean isRoot = Binder.getCallingUid() == Process.ROOT_UID;
+
+        if (isRoot || hasWritePermission) {
+            return;
+        } else if (hasAllowlistPermission) {
+            for (String flag : flags) {
+                if (!DeviceConfig.getAdbWritableFlags().contains(flag)) {
+                    throw new SecurityException("Permission denial for flag '"
+                        + flag
+                        + "'; allowlist permission granted, but must add flag to the allowlist.");
+                }
+            }
+        } else {
+            throw new SecurityException("Permission denial to mutate flag, must have root, "
+                + "WRITE_DEVICE_CONFIG, or ALLOWLISTED_WRITE_DEVICE_CONFIG");
         }
     }
 
@@ -2316,7 +2366,8 @@
                 "get/set setting for user", null);
     }
 
-    private Bundle packageValueForCallResult(Setting setting, boolean trackingGeneration) {
+    private Bundle packageValueForCallResult(int type, @NonNull String name, int userId,
+            @Nullable Setting setting, boolean trackingGeneration) {
         if (!trackingGeneration) {
             if (setting == null || setting.isNull()) {
                 return NULL_SETTING_BUNDLE;
@@ -2325,24 +2376,47 @@
         }
         Bundle result = new Bundle();
         result.putString(Settings.NameValueTable.VALUE,
-                !setting.isNull() ? setting.getValue() : null);
+                (setting != null && !setting.isNull()) ? setting.getValue() : null);
 
-        mSettingsRegistry.mGenerationRegistry.addGenerationData(result, setting.getKey());
+        synchronized (mLock) {
+            if ((setting != null && !setting.isNull()) || isSettingPreDefined(name, type)) {
+                // Individual generation tracking for predefined settings even if they are unset
+                mSettingsRegistry.mGenerationRegistry.addGenerationData(result,
+                        SettingsState.makeKey(type, userId), name);
+            } else {
+                // All non-predefined, unset settings are tracked using the same generation number
+                mSettingsRegistry.mGenerationRegistry.addGenerationDataForUnsetSettings(result,
+                        SettingsState.makeKey(type, userId));
+            }
+        }
         return result;
     }
 
-    private Bundle packageValuesForCallResult(HashMap<String, String> keyValues,
-            boolean trackingGeneration) {
+    private boolean isSettingPreDefined(String name, int type) {
+        if (type == SETTINGS_TYPE_GLOBAL) {
+            return sAllGlobalSettings.contains(name);
+        } else if (type == SETTINGS_TYPE_SECURE) {
+            return sAllSecureSettings.contains(name);
+        } else if (type == SETTINGS_TYPE_SYSTEM) {
+            return sAllSystemSettings.contains(name);
+        } else {
+            // Consider all config settings predefined because they are used by system apps only
+            return type == SETTINGS_TYPE_CONFIG;
+        }
+    }
+
+    private Bundle packageValuesForCallResult(String prefix,
+            @NonNull HashMap<String, String> keyValues, boolean trackingGeneration) {
         Bundle result = new Bundle();
         result.putSerializable(Settings.NameValueTable.VALUE, keyValues);
         if (trackingGeneration) {
             synchronized (mLock) {
+                // Track generation even if namespace is empty because this is for system apps only
                 mSettingsRegistry.mGenerationRegistry.addGenerationData(result,
-                        mSettingsRegistry.getSettingsLocked(
-                                SETTINGS_TYPE_CONFIG, UserHandle.USER_SYSTEM).mKey);
+                        SettingsState.makeKey(SETTINGS_TYPE_CONFIG, UserHandle.USER_SYSTEM),
+                        prefix);
             }
         }
-
         return result;
     }
 
@@ -3033,10 +3107,15 @@
             final int key = makeKey(type, userId);
 
             boolean success = false;
+            boolean wasUnsetNonPredefinedSetting = false;
             SettingsState settingsState = peekSettingsStateLocked(key);
             if (settingsState != null) {
+                if (!isSettingPreDefined(name, type) && !settingsState.hasSetting(name)) {
+                    wasUnsetNonPredefinedSetting = true;
+                }
                 success = settingsState.insertSettingLocked(name, value,
-                        tag, makeDefault, forceNonSystemPackage, packageName, overrideableByRestore);
+                        tag, makeDefault, forceNonSystemPackage, packageName,
+                        overrideableByRestore);
             }
 
             if (success && criticalSettings != null && criticalSettings.contains(name)) {
@@ -3045,6 +3124,11 @@
 
             if (forceNotify || success) {
                 notifyForSettingsChange(key, name);
+                if (wasUnsetNonPredefinedSetting) {
+                    // Increment the generation number for all non-predefined, unset settings,
+                    // because a new non-predefined setting has been inserted
+                    mGenerationRegistry.incrementGenerationForUnsetSettings(key);
+                }
             }
             if (success) {
                 logSettingChanged(userId, name, type, CHANGE_TYPE_INSERT);
@@ -3449,7 +3533,7 @@
 
         private void notifyForSettingsChange(int key, String name) {
             // Increment the generation first, so observers always see the new value
-            mGenerationRegistry.incrementGeneration(key);
+            mGenerationRegistry.incrementGeneration(key, name);
 
             if (isGlobalSettingsKey(key) || isConfigSettingsKey(key)) {
                 final long token = Binder.clearCallingIdentity();
@@ -3487,7 +3571,7 @@
                 List<String> changedSettings) {
 
             // Increment the generation first, so observers always see the new value
-            mGenerationRegistry.incrementGeneration(key);
+            mGenerationRegistry.incrementGeneration(key, prefix);
 
             StringBuilder stringBuilder = new StringBuilder(prefix);
             for (int i = 0; i < changedSettings.size(); ++i) {
@@ -3513,7 +3597,7 @@
                     if (profileId != userId) {
                         final int key = makeKey(type, profileId);
                         // Increment the generation first, so observers always see the new value
-                        mGenerationRegistry.incrementGeneration(key);
+                        mGenerationRegistry.incrementGeneration(key, name);
                         mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED,
                                 profileId, 0, uri).sendToTarget();
                     }
@@ -3676,7 +3760,7 @@
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 214;
+            private static final int SETTINGS_VERSION = 215;
 
             private final int mUserId;
 
@@ -5631,6 +5715,49 @@
                     currentVersion = 214;
                 }
 
+                if (currentVersion == 214) {
+                    // Version 214: Set a default value for Credential Manager service.
+
+                    final SettingsState secureSettings = getSecureSettingsLocked(userId);
+                    final Setting currentSetting = secureSettings
+                            .getSettingLocked(Settings.Secure.CREDENTIAL_SERVICE);
+                    if (currentSetting.isNull()) {
+                        final int resourceId =
+                            com.android.internal.R.string.config_defaultCredentialProviderService;
+                        final Resources resources = getContext().getResources();
+                        // If the config has not be defined we might get an exception. We also get
+                        // values from both the string array type and the single string in case the
+                        // OEM uses the wrong one.
+                        final List<String> providers = new ArrayList<>();
+                        try {
+                            providers.addAll(Arrays.asList(resources.getStringArray(resourceId)));
+                        } catch (Resources.NotFoundException e) {
+                            Slog.w(LOG_TAG,
+                                "Get default array Cred Provider not found: " + e.toString());
+                        }
+                        try {
+                            final String storedValue = resources.getString(resourceId);
+                            if (!TextUtils.isEmpty(storedValue)) {
+                                providers.add(storedValue);
+                            }
+                        } catch (Resources.NotFoundException e) {
+                            Slog.w(LOG_TAG,
+                                "Get default Cred Provider not found: " + e.toString());
+                        }
+
+                        if (!providers.isEmpty()) {
+                            final String defaultValue = String.join(":", providers);
+                            Slog.d(LOG_TAG, "Setting [" + defaultValue + "] as CredMan Service "
+                                    + "for user " + userId);
+                            secureSettings.insertSettingOverrideableByRestoreLocked(
+                                    Settings.Secure.CREDENTIAL_SERVICE, defaultValue, null, true,
+                                    SettingsState.SYSTEM_PACKAGE_NAME);
+                        }
+                    }
+
+                    currentVersion = 215;
+                }
+
                 // vXXX: Add new settings above this point.
 
                 if (currentVersion != newVersion) {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index c388826..4d8705f 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -759,6 +759,12 @@
         mPackageToMemoryUsage.put(packageName, newSize);
     }
 
+    public boolean hasSetting(String name) {
+        synchronized (mLock) {
+            return hasSettingLocked(name);
+        }
+    }
+
     @GuardedBy("mLock")
     private boolean hasSettingLocked(String name) {
         return mSettings.indexOfKey(name) >= 0;
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index c0176d5..1f14723 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -322,6 +322,7 @@
                     Settings.Global.LOW_BATTERY_SOUND,
                     Settings.Global.LOW_BATTERY_SOUND_TIMEOUT,
                     Settings.Global.LOW_POWER_MODE,
+                    Settings.Global.EXTRA_LOW_POWER_MODE,
                     Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX,
                     Settings.Global.LOW_POWER_MODE_STICKY,
                     Settings.Global.LOW_POWER_MODE_SUGGESTION_PARAMS,
@@ -371,7 +372,6 @@
                     Settings.Global.NETPOLICY_QUOTA_FRAC_JOBS,
                     Settings.Global.NETPOLICY_QUOTA_FRAC_MULTIPATH,
                     Settings.Global.NETPOLICY_OVERRIDE_ENABLED,
-                    Settings.Global.NETWORK_AVOID_BAD_WIFI,
                     Settings.Global.NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES,
                     Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE,
                     Settings.Global.NETWORK_WATCHLIST_LAST_REPORT_TIME,
@@ -800,7 +800,6 @@
                  Settings.Secure.PARENTAL_CONTROL_REDIRECT_URL,
                  Settings.Secure.BLUETOOTH_ON_WHILE_DRIVING,
                  Settings.Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT,
-                 Settings.Secure.LOW_POWER_WARNING_ACKNOWLEDGED,
                  Settings.Secure.SUPPRESS_AUTO_BATTERY_SAVER_SUGGESTION,
                  Settings.Secure.PACKAGES_TO_CLEAR_DATA_BEFORE_FULL_RESTORE,
                  Settings.Secure.FLASHLIGHT_AVAILABLE,
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/GenerationRegistryTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/GenerationRegistryTest.java
new file mode 100644
index 0000000..6ec8146
--- /dev/null
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/GenerationRegistryTest.java
@@ -0,0 +1,197 @@
+/*
+ * 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.providers.settings;
+
+import static android.provider.Settings.CALL_METHOD_GENERATION_INDEX_KEY;
+import static android.provider.Settings.CALL_METHOD_GENERATION_KEY;
+import static android.provider.Settings.CALL_METHOD_TRACK_GENERATION_KEY;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Bundle;
+import android.util.MemoryIntArray;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+
+@RunWith(AndroidJUnit4.class)
+public class GenerationRegistryTest {
+    @Test
+    public void testGenerationsWithRegularSetting() throws IOException {
+        final GenerationRegistry generationRegistry = new GenerationRegistry(new Object());
+        final int secureKey = SettingsState.makeKey(SettingsState.SETTINGS_TYPE_SECURE, 0);
+        final String testSecureSetting = "test_secure_setting";
+        Bundle b = new Bundle();
+        // IncrementGeneration should have no effect on a non-cached setting.
+        generationRegistry.incrementGeneration(secureKey, testSecureSetting);
+        generationRegistry.incrementGeneration(secureKey, testSecureSetting);
+        generationRegistry.incrementGeneration(secureKey, testSecureSetting);
+        generationRegistry.addGenerationData(b, secureKey, testSecureSetting);
+        // Default index is 0 and generation is only 1 despite early calls of incrementGeneration
+        checkBundle(b, 0, 1, false);
+
+        generationRegistry.incrementGeneration(secureKey, testSecureSetting);
+        generationRegistry.addGenerationData(b, secureKey, testSecureSetting);
+        // Index is still 0 and generation is now 2; also check direct array access
+        assertThat(getArray(b).get(0)).isEqualTo(2);
+
+        final int systemKey = SettingsState.makeKey(SettingsState.SETTINGS_TYPE_SYSTEM, 0);
+        final String testSystemSetting = "test_system_setting";
+        generationRegistry.addGenerationData(b, systemKey, testSystemSetting);
+        // Default index is 0 and generation is 1 for another backingStore (system)
+        checkBundle(b, 0, 1, false);
+
+        final String testSystemSetting2 = "test_system_setting2";
+        generationRegistry.addGenerationData(b, systemKey, testSystemSetting2);
+        // Second system setting index is 1 and default generation is 1
+        checkBundle(b, 1, 1, false);
+
+        generationRegistry.incrementGeneration(systemKey, testSystemSetting);
+        generationRegistry.incrementGeneration(systemKey, testSystemSetting);
+        generationRegistry.addGenerationData(b, systemKey, testSystemSetting);
+        // First system setting generation now incremented to 3
+        checkBundle(b, 0, 3, false);
+
+        final int systemKey2 = SettingsState.makeKey(SettingsState.SETTINGS_TYPE_SYSTEM, 10);
+        generationRegistry.addGenerationData(b, systemKey2, testSystemSetting);
+        // User 10 has a new set of backingStores
+        checkBundle(b, 0, 1, false);
+
+        // Check user removal
+        generationRegistry.onUserRemoved(10);
+        generationRegistry.incrementGeneration(systemKey2, testSystemSetting);
+
+        // Removed user should not affect existing caches
+        generationRegistry.addGenerationData(b, secureKey, testSecureSetting);
+        assertThat(getArray(b).get(0)).isEqualTo(2);
+
+        // IncrementGeneration should have no effect for a non-cached user
+        b.clear();
+        checkBundle(b, -1, -1, true);
+        // AddGeneration should create new backing store for the non-cached user
+        generationRegistry.addGenerationData(b, systemKey2, testSystemSetting);
+        checkBundle(b, 0, 1, false);
+    }
+
+    @Test
+    public void testGenerationsWithConfigSetting() throws IOException {
+        final GenerationRegistry generationRegistry = new GenerationRegistry(new Object());
+        final String prefix = "test_namespace/";
+        final int configKey = SettingsState.makeKey(SettingsState.SETTINGS_TYPE_CONFIG, 0);
+
+        Bundle b = new Bundle();
+        generationRegistry.addGenerationData(b, configKey, prefix);
+        checkBundle(b, 0, 1, false);
+
+        final String setting = "test_namespace/test_setting";
+        // Check that the generation of the prefix is incremented correctly
+        generationRegistry.incrementGeneration(configKey, setting);
+        generationRegistry.addGenerationData(b, configKey, prefix);
+        checkBundle(b, 0, 2, false);
+    }
+
+    @Test
+    public void testMaxNumBackingStores() throws IOException {
+        final GenerationRegistry generationRegistry = new GenerationRegistry(new Object());
+        final String testSecureSetting = "test_secure_setting";
+        Bundle b = new Bundle();
+        for (int i = 0; i < GenerationRegistry.NUM_MAX_BACKING_STORE; i++) {
+            b.clear();
+            final int key = SettingsState.makeKey(SettingsState.SETTINGS_TYPE_SECURE, i);
+            generationRegistry.addGenerationData(b, key, testSecureSetting);
+            checkBundle(b, 0, 1, false);
+        }
+        b.clear();
+        final int key = SettingsState.makeKey(SettingsState.SETTINGS_TYPE_SECURE,
+                GenerationRegistry.NUM_MAX_BACKING_STORE + 1);
+        generationRegistry.addGenerationData(b, key, testSecureSetting);
+        // Should fail to add generation because the number of backing stores has reached limit
+        checkBundle(b, -1, -1, true);
+        // Remove one user should free up a backing store
+        generationRegistry.onUserRemoved(0);
+        generationRegistry.addGenerationData(b, key, testSecureSetting);
+        checkBundle(b, 0, 1, false);
+    }
+
+    @Test
+    public void testMaxSizeBackingStore() throws IOException {
+        final GenerationRegistry generationRegistry = new GenerationRegistry(new Object());
+        final int secureKey = SettingsState.makeKey(SettingsState.SETTINGS_TYPE_SECURE, 0);
+        final String testSecureSetting = "test_secure_setting";
+        Bundle b = new Bundle();
+        for (int i = 0; i < GenerationRegistry.MAX_BACKING_STORE_SIZE; i++) {
+            generationRegistry.addGenerationData(b, secureKey, testSecureSetting + i);
+            checkBundle(b, i, 1, false);
+        }
+        b.clear();
+        generationRegistry.addGenerationData(b, secureKey, testSecureSetting);
+        // Should fail to increase index because the number of entries in the backing store has
+        // reached the limit
+        checkBundle(b, -1, -1, true);
+        // Shouldn't affect other cached entries
+        generationRegistry.addGenerationData(b, secureKey, testSecureSetting + "0");
+        checkBundle(b, 0, 1, false);
+    }
+
+    @Test
+    public void testUnsetSettings() throws IOException {
+        final GenerationRegistry generationRegistry = new GenerationRegistry(new Object());
+        final int secureKey = SettingsState.makeKey(SettingsState.SETTINGS_TYPE_SECURE, 0);
+        final String testSecureSetting = "test_secure_setting";
+        Bundle b = new Bundle();
+        generationRegistry.addGenerationData(b, secureKey, testSecureSetting);
+        checkBundle(b, 0, 1, false);
+        generationRegistry.addGenerationDataForUnsetSettings(b, secureKey);
+        checkBundle(b, 1, 1, false);
+        generationRegistry.addGenerationDataForUnsetSettings(b, secureKey);
+        // Test that unset settings always have the same index
+        checkBundle(b, 1, 1, false);
+        generationRegistry.incrementGenerationForUnsetSettings(secureKey);
+        // Test that the generation number of the unset settings have increased
+        generationRegistry.addGenerationDataForUnsetSettings(b, secureKey);
+        checkBundle(b, 1, 2, false);
+    }
+
+
+    private void checkBundle(Bundle b, int expectedIndex, int expectedGeneration, boolean isNull)
+            throws IOException {
+        final MemoryIntArray array = getArray(b);
+        if (isNull) {
+            assertThat(array).isNull();
+        } else {
+            assertThat(array).isNotNull();
+        }
+        final int index = b.getInt(
+                CALL_METHOD_GENERATION_INDEX_KEY, -1);
+        assertThat(index).isEqualTo(expectedIndex);
+        final int generation = b.getInt(CALL_METHOD_GENERATION_KEY, -1);
+        assertThat(generation).isEqualTo(expectedGeneration);
+        if (!isNull) {
+            // Read into the result array with the result index should match the result generation
+            assertThat(array.get(index)).isEqualTo(generation);
+        }
+    }
+
+    private MemoryIntArray getArray(Bundle b) {
+        return b.getParcelable(
+                CALL_METHOD_TRACK_GENERATION_KEY, android.util.MemoryIntArray.class);
+    }
+}
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 90bec42..4c48f0e 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -148,6 +148,8 @@
     <uses-permission android:name="android.permission.LOCATION_BYPASS" />
     <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
     <uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" />
+    <uses-permission android:name="android.permission.ALLOWLISTED_WRITE_DEVICE_CONFIG" />
+    <uses-permission android:name="android.permission.READ_WRITE_SYNC_DISABLED_MODE_CONFIG" />
     <uses-permission android:name="android.permission.MONITOR_DEVICE_CONFIG_ACCESS" />
     <uses-permission android:name="android.permission.BROADCAST_STICKY" />
     <uses-permission android:name="android.permission.MANAGE_ACCESSIBILITY" />
@@ -721,6 +723,7 @@
     <!-- Permission required for CTS test - CtsTelephonyTestCases -->
     <uses-permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE" />
     <uses-permission android:name="android.permission.MODIFY_CELL_BROADCASTS" />
+    <uses-permission android:name="android.permission.SATELLITE_COMMUNICATION" />
 
     <!-- Permission required for CTS test - CtsPersistentDataBlockManagerTestCases -->
     <uses-permission android:name="android.permission.ACCESS_PDB_STATE" />
@@ -825,6 +828,8 @@
     <!-- Permission required for CTS test - CtsTelephonyProviderTestCases -->
     <uses-permission android:name="android.permission.WRITE_APN_SETTINGS" />
 
+    <uses-permission android:name="android.permission.LOG_FOREGROUND_RESOURCE_USE"/>
+
     <application android:label="@string/app_label"
                 android:theme="@android:style/Theme.DeviceDefault.DayNight"
                 android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 9d46961..b236ac5 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -449,6 +449,7 @@
                 enabled: true,
                 optimize: true,
                 shrink: true,
+                shrink_resources: true,
                 proguard_compatibility: false,
                 proguard_flags_files: ["proguard.flags"],
             },
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 4e18222..1136c11 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -181,8 +181,8 @@
     <!-- Doze mode temp whitelisting for notification dispatching. -->
     <uses-permission android:name="android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST" />
 
-    <!-- Tag user-initiated PendingIntent invocations as "interactive" when appropriate -->
-    <uses-permission android:name="android.permission.COMPONENT_OPTION_INTERACTIVE" />
+    <!-- Adjust delivery policies for broadcast intents -->
+    <uses-permission android:name="android.permission.BROADCAST_OPTION_INTERACTIVE" />
 
     <!-- Listen for keyboard attachment / detachment -->
     <uses-permission android:name="android.permission.TABLET_MODE" />
@@ -341,6 +341,8 @@
 
     <uses-permission android:name="android.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS" />
 
+    <uses-permission android:name="android.permission.MONITOR_KEYBOARD_BACKLIGHT" />
+
     <protected-broadcast android:name="com.android.settingslib.action.REGISTER_SLICE_RECEIVER" />
     <protected-broadcast android:name="com.android.settingslib.action.UNREGISTER_SLICE_RECEIVER" />
     <protected-broadcast android:name="com.android.settings.flashlight.action.FLASHLIGHT_CHANGED" />
@@ -419,7 +421,7 @@
                  android:permission="com.android.systemui.permission.SELF"
                  android:exported="false" />
 
-        <activity android:name=".screenshot.AppClipsTrampolineActivity"
+        <activity android:name=".screenshot.appclips.AppClipsTrampolineActivity"
             android:theme="@style/AppClipsTrampolineActivity"
             android:label="@string/screenshot_preview_description"
             android:permission="android.permission.LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE"
@@ -430,7 +432,7 @@
             </intent-filter>
         </activity>
 
-        <activity android:name=".screenshot.AppClipsActivity"
+        <activity android:name=".screenshot.appclips.AppClipsActivity"
             android:theme="@style/AppClipsActivity"
             android:process=":appclips.screenshot"
             android:label="@string/screenshot_preview_description"
@@ -965,6 +967,7 @@
             android:enabled="false"
             android:exported="true"
             android:excludeFromRecents="true"
+            android:resizeableActivity="false"
             android:theme="@android:style/Theme.NoDisplay"
             android:label="@string/note_task_button_label"
             android:icon="@drawable/ic_note_task_shortcut_widget">
@@ -979,6 +982,7 @@
             android:name=".notetask.shortcut.LaunchNoteTaskActivity"
             android:exported="true"
             android:excludeFromRecents="true"
+            android:resizeableActivity="false"
             android:theme="@android:style/Theme.NoDisplay" />
         <!-- endregion -->
 
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
index 140c10d..f358417 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
+++ b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
@@ -18,6 +18,15 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
+// This filegroup is used by menu tests.
+filegroup {
+    name: "AccessibilityMenuSource",
+    srcs: [
+        "src/**/AccessibilityMenuService.java",
+        "src/**/A11yMenuShortcut.java",
+    ],
+}
+
 android_app {
     name: "AccessibilityMenu",
 
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/AndroidManifest.xml b/packages/SystemUI/accessibility/accessibilitymenu/AndroidManifest.xml
index ca84265..440c6e5 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/AndroidManifest.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/AndroidManifest.xml
@@ -58,5 +58,8 @@
         <intent>
             <action android:name="android.intent.action.VOICE_COMMAND" />
         </intent>
+        <!--intent>
+            <action android:name="android.settings.ACCESSIBILITY_SETTINGS" />
+        </intent-->
     </queries>
 </manifest>
\ No newline at end of file
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable-night/a11ymenu_intro.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable-night/a11ymenu_intro.xml
new file mode 100644
index 0000000..b2a0b32
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable-night/a11ymenu_intro.xml
@@ -0,0 +1,90 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="412dp"
+    android:height="300dp"
+    android:viewportWidth="412"
+    android:viewportHeight="300">
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M383.9,300H28.1c-15.5,0 -28.1,-12.6 -28.1,-28.1V28.1C0,12.6 12.6,0 28.1,0H383.9c15.5,0 28.1,12.6 28.1,28.1v243.8c0,15.5 -12.6,28.1 -28.1,28.1Z"/>
+  <path
+      android:pathData="M106.4,0h195.3c2,0 3.6,0.2 3.6,0.4V31.2c0,0.2 -1.6,0.4 -3.6,0.4H106.4c-2,0 -3.6,-0.2 -3.6,-0.4V0.4c0,-0.2 1.6,-0.4 3.6,-0.4Z"
+      android:fillColor="#3b4043"/>
+  <path
+      android:pathData="M303.7,238.9H104.5v1h98.4v29.5h1v-29.5h99.8v-1Z"
+      android:fillColor="#3b4043"/>
+  <path
+      android:pathData="M153.7,258.3l0.7,-0.7 -2.7,-2.7h5.9v-1h-5.9l2.7,-2.7 -0.7,-0.7 -3.9,3.9 3.9,3.9Z"
+      android:fillColor="#3b4043"
+      android:fillType="evenOdd"/>
+  <path
+      android:pathData="M253.5,250.4l-0.7,0.7 2.7,2.7h-5.9v1h5.9l-2.7,2.7 0.7,0.7 3.9,-3.9 -3.9,-3.9Z"
+      android:fillColor="#7f868c"
+      android:fillType="evenOdd"/>
+  <path
+      android:pathData="M119.3,273h169.8c10.2,0 18.5,-8.3 18.5,-18.5V73.7c2,0 3.7,-1.7 3.7,-3.7V33.1c0,-2 -1.7,-3.7 -3.7,-3.7V0h-3.7V254.5c0,8.1 -6.6,14.8 -14.8,14.8H119.3c-8.1,0 -14.8,-6.6 -14.8,-14.8V0h-3.7V254.5c0,10.2 8.3,18.5 18.5,18.5Z"
+      android:fillColor="#80868b"/>
+  <path
+      android:pathData="M141.86,52.23h0c9.77,0 17.7,7.92 17.7,17.7h0c0,9.77 -7.92,17.7 -17.7,17.7h0c-9.77,0 -17.7,-7.92 -17.7,-17.7h0c0,-9.77 7.92,-17.7 17.7,-17.7Z"
+      android:fillColor="#2197f3"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M141.86,81.15l-2.93,-2.93h-4.39c-0.39,0 -0.73,-0.15 -1.02,-0.44 -0.29,-0.29 -0.44,-0.63 -0.44,-1.02v-14.63c0,-0.39 0.15,-0.73 0.44,-1.02 0.29,-0.29 0.63,-0.44 1.02,-0.44h14.63c0.39,0 0.73,0.15 1.02,0.44 0.29,0.29 0.44,0.63 0.44,1.02v14.63c0,0.39 -0.15,0.73 -0.44,1.02 -0.29,0.29 -0.63,0.44 -1.02,0.44h-4.39l-2.93,2.93ZM141.88,74l1.37,-3.12 3.12,-1.37 -3.12,-1.37 -1.37,-3.12 -1.39,3.12 -3.1,1.37 3.1,1.37 1.39,3.12Z"/>
+  <path
+      android:pathData="M270.14,52.23h0c9.77,0 17.7,7.92 17.7,17.7h0c0,9.77 -7.92,17.7 -17.7,17.7h0c-9.77,0 -17.7,-7.92 -17.7,-17.7h0c0,-9.77 7.92,-17.7 17.7,-17.7Z"
+      android:fillColor="#dbdce0"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M269.25,62.01h1.77v8.74h-1.77v-8.74ZM274.01,65.22l1.22,-1.22c1.66,1.44 2.76,3.54 2.76,5.97 0,4.31 -3.54,7.85 -7.85,7.85s-7.85,-3.54 -7.85,-7.85c0,-2.43 1.11,-4.53 2.76,-5.97l1.22,1.22c-1.33,1.11 -2.21,2.88 -2.21,4.76 0,3.43 2.76,6.19 6.19,6.19 3.43,0 6.19,-2.76 6.19,-6.19 -0.11,-1.99 -1.11,-3.65 -2.43,-4.76Z"
+      android:fillType="evenOdd"/>
+  <path
+      android:pathData="M207.03,52.23h0c9.77,0 17.7,7.92 17.7,17.7h0c0,9.77 -7.92,17.7 -17.7,17.7h0c-9.77,0 -17.7,-7.92 -17.7,-17.7h0c0,-9.77 7.92,-17.7 17.7,-17.7Z"
+      android:fillColor="#d9affd"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M207.03,62.6c-0.44,0 -0.81,-0.16 -1.13,-0.47 -0.31,-0.31 -0.47,-0.69 -0.47,-1.13s0.16,-0.81 0.47,-1.13c0.31,-0.31 0.69,-0.47 1.13,-0.47s0.81,0.16 1.13,0.47c0.31,0.31 0.47,0.69 0.47,1.13s-0.16,0.81 -0.47,1.13 -0.69,0.47 -1.13,0.47ZM204.75,76.06v-10.83c-0.92,-0.07 -1.85,-0.18 -2.78,-0.32 -0.94,-0.14 -1.8,-0.31 -2.61,-0.52l0.33,-1.31c1.17,0.29 2.37,0.5 3.61,0.64 1.23,0.13 2.48,0.2 3.74,0.2s2.5,-0.07 3.74,-0.2c1.23,-0.13 2.44,-0.34 3.61,-0.64l0.33,1.31c-0.8,0.2 -1.67,0.38 -2.61,0.52 -0.94,0.14 -1.86,0.24 -2.78,0.32v10.83h-1.31v-5.35h-1.93v5.35h-1.31ZM203.45,80.44c-0.25,0 -0.45,-0.08 -0.6,-0.23 -0.15,-0.15 -0.23,-0.35 -0.23,-0.6 0,-0.25 0.08,-0.45 0.23,-0.6 0.15,-0.15 0.35,-0.23 0.6,-0.23s0.45,0.08 0.6,0.23c0.15,0.15 0.23,0.35 0.23,0.6 0,0.25 -0.08,0.45 -0.23,0.6 -0.15,0.15 -0.35,0.23 -0.6,0.23ZM207.05,80.44c-0.25,0 -0.45,-0.08 -0.6,-0.23 -0.15,-0.15 -0.23,-0.35 -0.23,-0.6 0,-0.25 0.08,-0.45 0.23,-0.6 0.15,-0.15 0.35,-0.23 0.6,-0.23s0.45,0.08 0.6,0.23c0.15,0.15 0.23,0.35 0.23,0.6 0,0.25 -0.08,0.45 -0.23,0.6 -0.15,0.15 -0.35,0.23 -0.6,0.23ZM210.64,80.44c-0.25,0 -0.45,-0.08 -0.6,-0.23 -0.15,-0.15 -0.23,-0.35 -0.23,-0.6 0,-0.25 0.08,-0.45 0.23,-0.6 0.15,-0.15 0.35,-0.23 0.6,-0.23s0.45,0.08 0.6,0.23c0.15,0.15 0.23,0.35 0.23,0.6 0,0.25 -0.08,0.45 -0.23,0.6 -0.15,0.15 -0.35,0.23 -0.6,0.23Z"/>
+  <path
+      android:pathData="M141.86,180.81h0c9.77,0 17.7,7.92 17.7,17.7h0c0,9.77 -7.92,17.7 -17.7,17.7h0c-9.77,0 -17.7,-7.92 -17.7,-17.7h0c0,-9.77 7.92,-17.7 17.7,-17.7Z"
+      android:fillColor="#fdd663"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M141.88,209.09l-3.16,-3.06h-4.35v-4.35l-3.13,-3.13 3.13,-3.13v-4.35h4.35l3.16,-3.13 3.11,3.13h4.35v4.35l3.13,3.13 -3.13,3.13v4.35h-4.35l-3.11,3.06ZM141.88,203.08c-1.26,0 -2.34,-0.44 -3.23,-1.33 -0.89,-0.89 -1.33,-1.96 -1.33,-3.23s0.44,-2.34 1.33,-3.23c0.89,-0.89 1.96,-1.33 3.23,-1.33 1.26,0 2.34,0.44 3.23,1.33 0.89,0.89 1.33,1.96 1.33,3.23s-0.44,2.34 -1.33,3.23c-0.89,0.89 -1.96,1.33 -3.23,1.33ZM141.88,201.68c0.89,0 1.64,-0.3 2.24,-0.91 0.61,-0.61 0.91,-1.36 0.91,-2.24 -0,-0.89 -0.3,-1.64 -0.91,-2.24 -0.61,-0.61 -1.36,-0.91 -2.24,-0.91 -0.89,0 -1.64,0.3 -2.24,0.91 -0.61,0.61 -0.91,1.36 -0.91,2.24s0.3,1.64 0.91,2.24c0.61,0.61 1.36,0.91 2.24,0.91ZM141.88,207.12l2.53,-2.5h3.53v-3.53l2.55,-2.55 -2.55,-2.55v-3.53h-3.53l-2.53,-2.55 -2.57,2.55h-3.53v3.53l-2.55,2.55 2.55,2.55v3.53h3.51l2.6,2.5Z"/>
+  <path
+      android:pathData="M207.03,180.82h0c9.77,0 17.7,7.92 17.7,17.7h0c0,9.77 -7.92,17.7 -17.7,17.7h0c-9.77,0 -17.7,-7.92 -17.7,-17.7h0c0,-9.77 7.92,-17.7 17.7,-17.7Z"
+      android:fillColor="#fdd663"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M207.05,209.09l-3.16,-3.06h-4.35v-4.35l-3.13,-3.13 3.13,-3.13v-4.35h4.35l3.16,-3.13 3.11,3.13h4.35v4.35l3.13,3.13 -3.13,3.13v4.35h-4.35l-3.11,3.06ZM207.05,203.08c1.26,0 2.34,-0.44 3.23,-1.33 0.89,-0.89 1.33,-1.96 1.33,-3.23s-0.44,-2.34 -1.33,-3.23c-0.89,-0.89 -1.96,-1.33 -3.23,-1.33 -1.26,0 -2.34,0.44 -3.23,1.33 -0.89,0.89 -1.33,1.96 -1.33,3.23s0.44,2.34 1.33,3.23c0.89,0.89 1.96,1.33 3.23,1.33ZM207.05,201.68c0.89,0 1.64,-0.3 2.24,-0.91 0.61,-0.61 0.91,-1.36 0.91,-2.24 -0,-0.89 -0.3,-1.64 -0.91,-2.24 -0.61,-0.61 -1.36,-0.91 -2.24,-0.91 -0.89,0 -1.64,0.3 -2.24,0.91 -0.61,0.61 -0.91,1.36 -0.91,2.24s0.3,1.64 0.91,2.24c0.61,0.61 1.36,0.91 2.24,0.91ZM207.05,207.13l2.53,-2.5h3.53v-3.53l2.55,-2.55 -2.55,-2.55v-3.53h-3.53l-2.53,-2.55 -2.57,2.55h-3.53v3.53l-2.55,2.55 2.55,2.55v3.53h3.51l2.6,2.5ZM207.05,201.68c0.89,0 1.64,-0.3 2.24,-0.91 0.61,-0.61 0.91,-1.36 0.91,-2.24 -0,-0.89 -0.3,-1.64 -0.91,-2.24 -0.61,-0.61 -1.36,-0.91 -2.24,-0.91 -0.89,0 -1.64,0.3 -2.24,0.91 -0.61,0.61 -0.91,1.36 -0.91,2.24s0.3,1.64 0.91,2.24c0.61,0.61 1.36,0.91 2.24,0.91Z"/>
+  <path
+      android:pathData="M270.14,180.81h0c9.77,0 17.7,7.92 17.7,17.7h0c0,9.77 -7.92,17.7 -17.7,17.7h0c-9.77,0 -17.7,-7.92 -17.7,-17.7h0c0,-9.77 7.92,-17.7 17.7,-17.7Z"
+      android:fillColor="#84e39f"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M263.92,207.44c-0.4,0 -0.74,-0.14 -1.02,-0.42s-0.42,-0.62 -0.42,-1.02v-10.37c0,-0.4 0.14,-0.74 0.42,-1.02s0.62,-0.42 1.02,-0.42h1.67v-2.29c0,-1.26 0.44,-2.33 1.33,-3.22 0.88,-0.88 1.96,-1.33 3.22,-1.33s2.33,0.44 3.22,1.33c0.88,0.88 1.33,1.96 1.33,3.22v2.29h1.67c0.4,0 0.74,0.14 1.02,0.42s0.42,0.62 0.42,1.02v10.37c0,0.4 -0.14,0.74 -0.42,1.02s-0.62,0.42 -1.02,0.42h-12.43ZM263.92,206.01h12.43v-10.37h-12.43v10.37ZM270.14,202.66c0.51,0 0.94,-0.18 1.3,-0.53s0.54,-0.77 0.54,-1.27c0,-0.48 -0.18,-0.91 -0.54,-1.3s-0.79,-0.59 -1.3,-0.59 -0.94,0.2 -1.3,0.59c-0.36,0.39 -0.54,0.82 -0.54,1.3 0,0.49 0.18,0.92 0.54,1.27s0.79,0.53 1.3,0.53ZM267.03,194.2h6.22v-2.29c0,-0.86 -0.3,-1.59 -0.91,-2.2 -0.61,-0.61 -1.34,-0.91 -2.2,-0.91s-1.59,0.3 -2.2,0.91 -0.91,1.34 -0.91,2.2v2.29ZM263.92,206.01v0Z"/>
+  <path
+      android:pathData="M207.03,116.5h0c9.77,0 17.7,7.92 17.7,17.7h0c0,9.77 -7.92,17.7 -17.7,17.7h0c-9.77,0 -17.7,-7.92 -17.7,-17.7h0c0,-9.77 7.92,-17.7 17.7,-17.7Z"
+      android:fillColor="#7ae2d4"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M209.17,143.6v-1.66c1.73,-0.5 3.15,-1.46 4.25,-2.88 1.1,-1.42 1.65,-3.03 1.65,-4.84 0,-1.8 -0.54,-3.42 -1.63,-4.85s-2.51,-2.38 -4.26,-2.87v-1.66c2.22,0.5 4.02,1.62 5.41,3.36 1.39,1.74 2.09,3.75 2.09,6.02s-0.7,4.27 -2.09,6.02c-1.39,1.74 -3.2,2.86 -5.41,3.36ZM197.38,137.46v-6.43h4.29l5.36,-5.36v17.15l-5.36,-5.36h-4.29ZM208.63,138.75v-9.03c0.98,0.3 1.76,0.88 2.34,1.71 0.58,0.84 0.87,1.78 0.87,2.81 0,1.02 -0.29,1.95 -0.88,2.79s-1.37,1.41 -2.33,1.71ZM205.42,129.75l-3.03,2.89h-3.4v3.22h3.4l3.03,2.92v-9.03Z"/>
+  <path
+      android:pathData="M270.14,116.54h0c9.77,0 17.7,7.92 17.7,17.7h0c0,9.77 -7.92,17.7 -17.7,17.7h0c-9.77,0 -17.7,-7.92 -17.7,-17.7h0c0,-9.77 7.92,-17.7 17.7,-17.7Z"
+      android:fillColor="#efa5de"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M275.08,127.12h-9.89v14.23h9.89v-14.23Z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M263.88,129.91h-3.56v8.76h3.56v-8.76Z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M279.96,129.91h-3.56v8.76h3.56v-8.76Z"/>
+  <path
+      android:pathData="M267.04,128.82h6.21v10.83h-6.21z"
+      android:fillColor="#efa5de"/>
+  <path
+      android:pathData="M141.86,116.5h0c9.77,0 17.7,7.92 17.7,17.7h0c0,9.77 -7.92,17.7 -17.7,17.7h0c-9.77,0 -17.7,-7.92 -17.7,-17.7h0c0,-9.77 7.92,-17.7 17.7,-17.7Z"
+      android:fillColor="#7ae2d4"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M134.62,137.44v-6.43h4.29l5.36,-5.36v17.16l-5.36,-5.36h-4.29ZM145.88,138.73v-9.03c0.97,0.3 1.74,0.88 2.33,1.72 0.59,0.84 0.88,1.78 0.88,2.81 0,1.05 -0.29,1.99 -0.88,2.81s-1.37,1.39 -2.33,1.69ZM142.66,129.72l-3.03,2.9h-3.4v3.22h3.4l3.03,2.92v-9.03Z"/>
+</vector>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable-sw600dp-night/a11ymenu_intro.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable-sw600dp-night/a11ymenu_intro.xml
index 7a4fbb2..cb2e974 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable-sw600dp-night/a11ymenu_intro.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable-sw600dp-night/a11ymenu_intro.xml
@@ -3,274 +3,104 @@
     android:height="300dp"
     android:viewportWidth="412"
     android:viewportHeight="300">
-  <group>
-    <clip-path
-        android:pathData="M62.23,50.19L349.77,50.19A16,16 0,0 1,365.77 66.19L365.77,236.14A16,16 0,0 1,349.77 252.14L62.23,252.14A16,16 0,0 1,46.23 236.14L46.23,66.19A16,16 0,0 1,62.23 50.19z"/>
-    <path
-        android:pathData="M62.23,50.19L349.77,50.19A16,16 0,0 1,365.77 66.19L365.77,236.14A16,16 0,0 1,349.77 252.14L62.23,252.14A16,16 0,0 1,46.23 236.14L46.23,66.19A16,16 0,0 1,62.23 50.19z"
-        android:fillColor="#3B4043"/>
-    <path
-        android:pathData="M46.23,52.14h160v200h-160z"
-        android:fillColor="#000000"/>
-    <path
-        android:pathData="M86.21,240.04L86.91,239.34L84.21,236.64H90.11V235.64H84.21L86.91,232.94L86.21,232.24L82.31,236.14L86.21,240.04Z"
-        android:fillColor="#3B4043"
-        android:fillType="evenOdd"/>
-    <path
-        android:pathData="M125.71,220.14V252.14H127.71V220.14H125.71Z"
-        android:fillColor="#3B4043"/>
-    <path
-        android:pathData="M166.21,232.24L165.51,232.94L168.21,235.64H162.31V236.64H168.21L165.51,239.34L166.21,240.04L170.11,236.14L166.21,232.24Z"
-        android:fillColor="#7F868C"
-        android:fillType="evenOdd"/>
-    <path
-        android:pathData="M46.71,221.14H206.71V219.14H46.71V221.14Z"
-        android:fillColor="#3B4043"/>
-    <path
-        android:pathData="M78.71,120.5L78.71,120.5A16,16 0,0 1,94.71 136.5L94.71,136.5A16,16 0,0 1,78.71 152.5L78.71,152.5A16,16 0,0 1,62.71 136.5L62.71,136.5A16,16 0,0 1,78.71 120.5z"
-        android:fillColor="#327969"/>
-    <group>
-      <clip-path
-          android:pathData="M73.36,138.95V134.15H76.56L80.56,130.15V142.85L76.56,138.85H73.36V138.95ZM82.06,133.35C83.26,133.95 84.06,135.15 84.06,136.55C84.06,137.95 83.26,139.15 82.06,139.75V133.35Z"
-          android:fillType="evenOdd"/>
-      <path
-          android:pathData="M88.36,127.05H69.36V146.05H88.36V127.05Z"
-          android:fillColor="#000000"/>
-    </group>
-    <path
-        android:pathData="M78.71,172.5L78.71,172.5A16,16 0,0 1,94.71 188.5L94.71,188.5A16,16 0,0 1,78.71 204.5L78.71,204.5A16,16 0,0 1,62.71 188.5L62.71,188.5A16,16 0,0 1,78.71 172.5z"
-        android:fillColor="#DE9834"/>
-    <path
-        android:pathData="M87.66,188.5L85.06,191.1V194.8H81.36L78.76,197.4L76.16,194.8H72.36V191.1L69.76,188.5L72.36,185.9V182.2H76.06L78.66,179.6L81.26,182.2H84.96V185.9L87.66,188.5ZM73.96,188.5C73.96,191.1 76.06,193.3 78.76,193.3C81.36,193.3 83.56,191.2 83.56,188.5C83.56,185.8 81.46,183.7 78.76,183.7C76.06,183.7 73.96,185.8 73.96,188.5Z"
-        android:fillColor="#000000"
-        android:fillType="evenOdd"/>
-    <path
-        android:pathData="M80.66,187.9H76.66V189.4H80.66V187.9Z"
-        android:fillColor="#000000"/>
-    <path
-        android:pathData="M126.71,120.5L126.71,120.5A16,16 0,0 1,142.71 136.5L142.71,136.5A16,16 0,0 1,126.71 152.5L126.71,152.5A16,16 0,0 1,110.71 136.5L110.71,136.5A16,16 0,0 1,126.71 120.5z"
-        android:fillColor="#327969"/>
-    <path
-        android:pathData="M128.31,131.1V129.5C131.51,130.2 133.91,133.1 133.91,136.5C133.91,139.9 131.51,142.7 128.31,143.5V141.9C130.61,141.2 132.31,139.1 132.31,136.6C132.31,134.1 130.61,131.8 128.31,131.1ZM130.31,136.4C130.31,135 129.51,133.8 128.31,133.2V139.6C129.41,139 130.31,137.8 130.31,136.4Z"
-        android:fillColor="#8B3737"
-        android:fillType="evenOdd"/>
-    <path
-        android:pathData="M126.72,142.79V130.13L122.71,134.08H119.5V138.78H122.71L126.72,142.79Z"
-        android:fillColor="#8B3737"/>
-    <group>
-      <clip-path
-          android:pathData="M126.72,142.79V130.13L122.71,134.08H119.5V138.78H122.71L126.72,142.79Z"/>
-      <clip-path
-          android:pathData="M128.31,131.1V129.5C131.51,130.2 133.91,133.1 133.91,136.5C133.91,139.9 131.51,142.7 128.31,143.5V141.9C130.61,141.2 132.31,139.1 132.31,136.6C132.31,134.1 130.61,131.8 128.31,131.1ZM130.31,136.4C130.31,135 129.51,133.8 128.31,133.2V139.6C129.41,139 130.31,137.8 130.31,136.4Z"
-          android:fillType="evenOdd"/>
-      <path
-          android:pathData="M128.31,131.1H78.31V168.15L113.75,178.94L128.31,131.1ZM128.31,129.5L138.99,80.66L78.31,67.38V129.5H128.31ZM128.31,143.5H78.31V207.54L140.44,192.01L128.31,143.5ZM128.31,141.9L113.75,94.07L78.31,104.86V141.9H128.31ZM128.31,133.2L150.67,88.48L78.31,52.3V133.2H128.31ZM128.31,139.6H78.31V223.83L152.25,183.5L128.31,139.6ZM126.72,130.13H176.73V10.79L91.66,94.5L126.72,130.13ZM126.72,142.79L91.37,178.15L176.73,263.5V142.79H126.72ZM122.71,138.78L158.07,103.43L143.43,88.78H122.71V138.78ZM119.5,138.78H69.5V188.78H119.5V138.78ZM119.5,134.08V84.08H69.5V134.08H119.5ZM122.71,134.08V184.08H143.19L157.78,169.72L122.71,134.08ZM178.31,131.1V129.5H78.31V131.1H178.31ZM117.63,178.35C98.03,174.06 83.91,156.76 83.91,136.5H183.91C183.91,109.44 164.99,86.34 138.99,80.66L117.63,178.35ZM83.91,136.5C83.91,115.15 98.93,99.31 116.18,94.99L140.44,192.01C164.09,186.1 183.91,164.66 183.91,136.5H83.91ZM178.31,143.5V141.9H78.31V143.5H178.31ZM142.87,189.74C164.72,183.09 182.31,162.64 182.31,136.6H82.31C82.31,115.57 96.5,99.32 113.75,94.07L142.87,189.74ZM182.31,136.6C182.31,112.64 166.74,90.53 142.87,83.27L113.75,178.94C94.48,173.07 82.31,155.56 82.31,136.6H182.31ZM180.31,136.4C180.31,115.04 167.88,97.08 150.67,88.48L105.95,177.92C91.14,170.52 80.31,154.96 80.31,136.4H180.31ZM78.31,133.2V139.6H178.31V133.2H78.31ZM152.25,183.5C166.09,175.95 180.31,159.6 180.31,136.4H80.31C80.31,116 92.73,102.06 104.37,95.71L152.25,183.5ZM76.72,130.13V142.79H176.73V130.13H76.72ZM162.08,107.44L158.07,103.43L87.36,174.14L91.37,178.15L162.08,107.44ZM122.71,88.78H119.5V188.78H122.71V88.78ZM169.5,138.78V134.08H69.5V138.78H169.5ZM119.5,184.08H122.71V84.08H119.5V184.08ZM157.78,169.72L161.79,165.77L91.66,94.5L87.65,98.44L157.78,169.72Z"
-          android:fillColor="#000000"/>
-    </group>
-    <path
-        android:pathData="M78.71,68.5L78.71,68.5A16,16 0,0 1,94.71 84.5L94.71,84.5A16,16 0,0 1,78.71 100.5L78.71,100.5A16,16 0,0 1,62.71 84.5L62.71,84.5A16,16 0,0 1,78.71 68.5z"
-        android:fillColor="#3B4043"/>
-    <path
-        android:pathData="M86.26,82.15C86.92,82.15 87.46,81.61 87.46,80.95C87.46,80.29 86.92,79.75 86.26,79.75C85.6,79.75 85.06,80.29 85.06,80.95C85.06,81.61 85.6,82.15 86.26,82.15Z"
-        android:fillColor="#34A853"/>
-    <path
-        android:pathData="M82.66,86.15C83.99,86.15 85.06,85.08 85.06,83.75C85.06,82.43 83.99,81.35 82.66,81.35C81.34,81.35 80.26,82.43 80.26,83.75C80.26,85.08 81.34,86.15 82.66,86.15Z"
-        android:fillColor="#EA4335"/>
-    <path
-        android:pathData="M82.66,92.45C84.21,92.45 85.46,91.2 85.46,89.65C85.46,88.11 84.21,86.85 82.66,86.85C81.11,86.85 79.86,88.11 79.86,89.65C79.86,91.2 81.11,92.45 82.66,92.45Z"
-        android:fillColor="#FBBC04"/>
-    <path
-        android:pathData="M74.76,86.15C77.41,86.15 79.56,84 79.56,81.35C79.56,78.7 77.41,76.55 74.76,76.55C72.11,76.55 69.96,78.7 69.96,81.35C69.96,84 72.11,86.15 74.76,86.15Z"
-        android:fillColor="#4285F4"/>
-    <path
-        android:pathData="M174.71,120.5L174.71,120.5A16,16 0,0 1,190.71 136.5L190.71,136.5A16,16 0,0 1,174.71 152.5L174.71,152.5A16,16 0,0 1,158.71 136.5L158.71,136.5A16,16 0,0 1,174.71 120.5z"
-        android:fillColor="#9F3EBF"/>
-    <path
-        android:pathData="M178.53,130.5H171.03V142.2H178.53V130.5Z"
-        android:fillColor="#000000"/>
-    <path
-        android:pathData="M170.23,132.8H167.53V140H170.23V132.8Z"
-        android:fillColor="#000000"/>
-    <path
-        android:pathData="M182.23,132.8H179.53V140H182.23V132.8Z"
-        android:fillColor="#000000"/>
-    <path
-        android:pathData="M126.71,172.5L126.71,172.5A16,16 0,0 1,142.71 188.5L142.71,188.5A16,16 0,0 1,126.71 204.5L126.71,204.5A16,16 0,0 1,110.71 188.5L110.71,188.5A16,16 0,0 1,126.71 172.5z"
-        android:fillColor="#DE9834"/>
-    <path
-        android:pathData="M135.71,188.5L133.11,191.1V194.8H129.31L126.71,197.4L124.11,194.8H120.31V191.1L117.71,188.5L120.31,185.9V182.2H124.01L126.61,179.6L129.21,182.2H132.91V185.9L135.71,188.5ZM121.91,188.5C121.91,191.1 124.01,193.3 126.71,193.3C129.31,193.3 131.51,191.2 131.51,188.5C131.51,185.8 129.41,183.7 126.71,183.7C124.11,183.7 121.91,185.8 121.91,188.5Z"
-        android:fillColor="#000000"
-        android:fillType="evenOdd"/>
-    <path
-        android:pathData="M127.21,187.9V186.4H126.21V187.9H124.71V188.9H126.21V190.4H127.21V188.9H128.71V187.9H127.21Z"
-        android:fillColor="#000000"
-        android:fillType="evenOdd"/>
-    <path
-        android:pathData="M126.71,68.5L126.71,68.5A16,16 0,0 1,142.71 84.5L142.71,84.5A16,16 0,0 1,126.71 100.5L126.71,100.5A16,16 0,0 1,110.71 84.5L110.71,84.5A16,16 0,0 1,126.71 68.5z"
-        android:fillColor="#521BBF"/>
-    <path
-        android:pathData="M128.36,78.51C128.36,79.31 127.66,80.01 126.76,80.01C125.86,80.01 125.16,79.31 125.16,78.51C125.16,77.71 125.86,77.01 126.76,77.01C127.66,76.91 128.36,77.61 128.36,78.51ZM126.76,80.71C128.96,80.71 131.46,80.51 133.46,79.91L133.86,81.41C132.36,81.81 130.66,82.01 129.06,82.21V92.01H127.46V87.51H125.86V92.01H124.36V82.21C122.76,82.11 121.06,81.81 119.56,81.41L119.96,79.91C122.06,80.51 124.46,80.71 126.76,80.71Z"
-        android:fillColor="#000000"
-        android:fillType="evenOdd"/>
-    <path
-        android:pathData="M174.71,172.5L174.71,172.5A16,16 0,0 1,190.71 188.5L190.71,188.5A16,16 0,0 1,174.71 204.5L174.71,204.5A16,16 0,0 1,158.71 188.5L158.71,188.5A16,16 0,0 1,174.71 172.5z"
-        android:fillColor="#438947"/>
-    <path
-        android:pathData="M179.11,185.95H178.41V184.45C178.41,182.45 176.81,180.75 174.71,180.75C172.61,180.75 171.01,182.35 171.01,184.45V185.95H170.31C169.51,185.95 168.81,186.65 168.81,187.45V194.75C168.81,195.55 169.51,196.25 170.31,196.25H179.11C179.91,196.25 180.61,195.55 180.61,194.75V187.45C180.61,186.65 179.91,185.95 179.11,185.95ZM174.71,192.55C173.91,192.55 173.21,191.85 173.21,191.05C173.21,190.25 173.91,189.55 174.71,189.55C175.51,189.55 176.21,190.25 176.21,191.05C176.21,191.95 175.51,192.55 174.71,192.55ZM172.41,185.95H176.91V184.45C176.91,183.15 175.91,182.15 174.61,182.15C173.31,182.15 172.31,183.15 172.31,184.45V185.95H172.41Z"
-        android:fillColor="#000000"
-        android:fillType="evenOdd"/>
-    <path
-        android:pathData="M174.71,68.5L174.71,68.5A16,16 0,0 1,190.71 84.5L190.71,84.5A16,16 0,0 1,174.71 100.5L174.71,100.5A16,16 0,0 1,158.71 84.5L158.71,84.5A16,16 0,0 1,174.71 68.5z"
-        android:fillColor="#80868B"/>
-    <path
-        android:pathData="M173.91,77.35H175.51V85.25H173.91V77.35ZM178.21,80.25L179.31,79.15C180.81,80.45 181.81,82.35 181.81,84.55C181.81,88.45 178.61,91.65 174.71,91.65C170.81,91.65 167.61,88.45 167.61,84.55C167.61,82.35 168.61,80.45 170.11,79.15L171.21,80.25C170.01,81.25 169.21,82.85 169.21,84.55C169.21,87.65 171.71,90.15 174.81,90.15C177.91,90.15 180.41,87.65 180.41,84.55C180.31,82.75 179.41,81.25 178.21,80.25Z"
-        android:fillColor="#000000"
-        android:fillType="evenOdd"/>
-  </group>
   <path
-      android:pathData="M62.23,51.69L349.77,51.69A14.5,14.5 0,0 1,364.27 66.19L364.27,236.14A14.5,14.5 0,0 1,349.77 250.64L62.23,250.64A14.5,14.5 0,0 1,47.73 236.14L47.73,66.19A14.5,14.5 0,0 1,62.23 51.69z"
-      android:strokeWidth="3"
+      android:fillColor="#FF000000"
+      android:pathData="M199.88,53.03l-2.73,-2.73h-4.09c-0.36,0 -0.68,-0.14 -0.95,-0.41 -0.27,-0.27 -0.41,-0.59 -0.41,-0.95v-13.64c0,-0.36 0.14,-0.68 0.41,-0.95 0.27,-0.27 0.59,-0.41 0.95,-0.41h13.64c0.36,0 0.68,0.14 0.95,0.41 0.27,0.27 0.41,0.59 0.41,0.95v13.64c0,0.36 -0.14,0.68 -0.41,0.95 -0.27,0.27 -0.59,0.41 -0.95,0.41h-4.09l-2.73,2.73ZM199.9,46.37l1.27,-2.91 2.91,-1.27 -2.91,-1.27 -1.27,-2.91 -1.3,2.91 -2.89,1.27 2.89,1.27 1.3,2.91Z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M384.18,300H27.82c-15.29,0 -27.82,-12.83 -27.82,-28.48V28.48C0,12.83 12.53,0 27.82,0H384.29c15.18,0 27.71,12.83 27.71,28.48v243.15c0,15.54 -12.53,28.37 -27.82,28.37Z"/>
+  <path
+      android:pathData="M207.19,52.65h151.18c4.14,0 7.51,3.36 7.51,7.51V243.15c0,4.14 -3.36,7.51 -7.51,7.51H207.19V52.65h0Z"
+      android:fillColor="#5f6368"/>
+  <path
+      android:pathData="M368.24,143.47L368.24,60.55c0,-5.67 -4.59,-10.26 -10.26,-10.26L54.02,50.29c-5.67,0 -10.26,4.59 -10.26,10.26L43.76,242.76c0,5.67 4.59,10.26 10.26,10.26L357.98,253.02c5.67,0 10.26,-4.59 10.26,-10.26v-99.29ZM365.88,243.14c0,4.15 -3.75,7.52 -7.9,7.52L54.02,250.66c-4.15,0 -7.9,-3.37 -7.9,-7.52L46.12,60.55c0,-4.15 3.75,-7.9 7.9,-7.9L357.98,52.65c4.15,0 7.9,3.75 7.9,7.9L365.88,243.14Z"
+      android:fillColor="#80868b"/>
+  <path
+      android:pathData="M319.83,50.29c-0,-1.28 -1.04,-2.31 -2.31,-2.31h-23.11c-1.28,0 -2.31,1.03 -2.31,2.31h27.74Z"
+      android:fillColor="#80868b"/>
+  <path
+      android:pathData="M344.42,50.29c-0,-1.28 -1.03,-2.31 -2.31,-2.31h-9.25c-1.28,0 -2.31,1.03 -2.31,2.31h13.87Z"
+      android:fillColor="#80868b"/>
+  <path
+      android:pathData="M86.06,240.43l0.7,-0.7 -2.7,-2.7h5.9v-1h-5.9l2.7,-2.7 -0.7,-0.7 -3.9,3.9 3.9,3.9Z"
+      android:fillColor="#5f6368"
+      android:fillType="evenOdd"/>
+  <path
+      android:pathData="M166.93,232.89l-0.7,0.7 2.7,2.7h-5.9v1h5.9l-2.7,2.7 0.7,0.7 3.9,-3.9 -3.9,-3.9Z"
+      android:fillColor="#7f868c"
+      android:fillType="evenOdd"/>
+  <path
+      android:strokeWidth="1"
+      android:pathData="M46.12,222.93L207.19,222.93"
       android:fillColor="#00000000"
-      android:strokeColor="#7F868C"/>
+      android:strokeColor="#5f6368"/>
   <path
-      android:pathData="M311.45,50.35C311.45,48.98 312.56,47.87 313.92,47.87L322.84,47.87C324.2,47.87 325.32,48.98 325.32,50.35L319.37,51.34L311.45,50.35Z"
-      android:fillColor="#7F868C"/>
-  <path
-      android:pathData="M263.59,50.35C263.59,48.98 264.7,47.87 266.06,47.87L287.85,47.87C289.22,47.87 290.33,48.98 290.33,50.35L277.45,51.34L263.59,50.35Z"
-      android:fillColor="#7F868C"/>
-  <group>
-    <clip-path
-        android:pathData="M62,50.32L349.54,50.32A16,16 0,0 1,365.54 66.32L365.54,236.27A16,16 0,0 1,349.54 252.27L62,252.27A16,16 0,0 1,46 236.27L46,66.32A16,16 0,0 1,62 50.32z"/>
-    <path
-        android:pathData="M62,50.32L349.54,50.32A16,16 0,0 1,365.54 66.32L365.54,236.27A16,16 0,0 1,349.54 252.27L62,252.27A16,16 0,0 1,46 236.27L46,66.32A16,16 0,0 1,62 50.32z"
-        android:fillColor="#3B4043"/>
-    <path
-        android:pathData="M46,52.27h160v200h-160z"
-        android:fillColor="#000000"/>
-    <path
-        android:pathData="M85.98,240.17L86.68,239.47L83.98,236.77H89.88V235.77H83.98L86.68,233.07L85.98,232.37L82.08,236.27L85.98,240.17Z"
-        android:fillColor="#3B4043"
-        android:fillType="evenOdd"/>
-    <path
-        android:pathData="M125.48,220.27V252.27H127.48V220.27H125.48Z"
-        android:fillColor="#3B4043"/>
-    <path
-        android:pathData="M165.98,232.37L165.28,233.07L167.98,235.77H162.08V236.77H167.98L165.28,239.47L165.98,240.17L169.88,236.27L165.98,232.37Z"
-        android:fillColor="#7F868C"
-        android:fillType="evenOdd"/>
-    <path
-        android:pathData="M46.48,221.27H206.48V219.27H46.48V221.27Z"
-        android:fillColor="#3B4043"/>
-    <path
-        android:pathData="M78.48,120.64L78.48,120.64A16,16 0,0 1,94.48 136.64L94.48,136.64A16,16 0,0 1,78.48 152.64L78.48,152.64A16,16 0,0 1,62.48 136.64L62.48,136.64A16,16 0,0 1,78.48 120.64z"
-        android:fillColor="#7AE2D4"/>
-    <group>
-      <clip-path
-          android:pathData="M73.13,139.09V134.29H76.33L80.33,130.29V142.99L76.33,138.99H73.13V139.09ZM81.83,133.49C83.03,134.09 83.83,135.29 83.83,136.69C83.83,138.09 83.03,139.29 81.83,139.89V133.49Z"
-          android:fillType="evenOdd"/>
-      <path
-          android:pathData="M88.13,127.19H69.13V146.19H88.13V127.19Z"
-          android:fillColor="#000000"/>
-    </group>
-    <path
-        android:pathData="M78.48,172.64L78.48,172.64A16,16 0,0 1,94.48 188.64L94.48,188.64A16,16 0,0 1,78.48 204.64L78.48,204.64A16,16 0,0 1,62.48 188.64L62.48,188.64A16,16 0,0 1,78.48 172.64z"
-        android:fillColor="#FDD663"/>
-    <path
-        android:pathData="M87.43,188.64L84.83,191.24V194.94H81.13L78.53,197.54L75.93,194.94H72.13V191.24L69.53,188.64L72.13,186.04V182.34H75.83L78.43,179.74L81.03,182.34H84.73V186.04L87.43,188.64ZM73.73,188.64C73.73,191.24 75.83,193.44 78.53,193.44C81.13,193.44 83.33,191.34 83.33,188.64C83.33,185.94 81.23,183.84 78.53,183.84C75.83,183.84 73.73,185.94 73.73,188.64Z"
-        android:fillColor="#000000"
-        android:fillType="evenOdd"/>
-    <path
-        android:pathData="M80.43,188.04H76.43V189.54H80.43V188.04Z"
-        android:fillColor="#000000"/>
-    <path
-        android:pathData="M126.48,120.64L126.48,120.64A16,16 0,0 1,142.48 136.64L142.48,136.64A16,16 0,0 1,126.48 152.64L126.48,152.64A16,16 0,0 1,110.48 136.64L110.48,136.64A16,16 0,0 1,126.48 120.64z"
-        android:fillColor="#7AE2D4"/>
-    <path
-        android:pathData="M128.08,131.24V129.64C131.28,130.34 133.68,133.24 133.68,136.64C133.68,140.04 131.28,142.84 128.08,143.64V142.04C130.38,141.34 132.08,139.24 132.08,136.74C132.08,134.24 130.38,131.94 128.08,131.24ZM130.08,136.54C130.08,135.14 129.28,133.94 128.08,133.34V139.74C129.18,139.14 130.08,137.94 130.08,136.54Z"
-        android:fillColor="#000000"
-        android:fillType="evenOdd"/>
-    <path
-        android:pathData="M126.49,142.93V130.27L122.49,134.21H119.27V138.92H122.49L126.49,142.93Z"
-        android:fillColor="#000000"/>
-    <group>
-      <clip-path
-          android:pathData="M126.49,142.93V130.27L122.49,134.21H119.27V138.92H122.49L126.49,142.93Z"/>
-      <clip-path
-          android:pathData="M128.08,131.24V129.64C131.28,130.34 133.68,133.24 133.68,136.64C133.68,140.04 131.28,142.84 128.08,143.64V142.04C130.38,141.34 132.08,139.24 132.08,136.74C132.08,134.24 130.38,131.94 128.08,131.24ZM130.08,136.54C130.08,135.14 129.28,133.94 128.08,133.34V139.74C129.18,139.14 130.08,137.94 130.08,136.54Z"
-          android:fillType="evenOdd"/>
-      <path
-          android:pathData="M128.08,131.24H78.08V168.28L113.52,179.07L128.08,131.24ZM128.08,129.64L138.76,80.79L78.08,67.52V129.64H128.08ZM128.08,143.64H78.08V207.68L140.21,192.14L128.08,143.64ZM128.08,142.04L113.52,94.2L78.08,104.99V142.04H128.08ZM128.08,133.34L150.44,88.62L78.08,52.44V133.34H128.08ZM128.08,139.74H78.08V223.96L152.02,183.63L128.08,139.74ZM126.49,130.27H176.49V10.92L91.43,94.63L126.49,130.27ZM126.49,142.93L91.14,178.28L176.49,263.64V142.93H126.49ZM122.49,138.92L157.84,103.56L143.2,88.92H122.49V138.92ZM119.27,138.92H69.27V188.92H119.27V138.92ZM119.27,134.21V84.22H69.27V134.21H119.27ZM122.49,134.21V184.21H142.96L157.55,169.85L122.49,134.21ZM178.08,131.24V129.64H78.08V131.24H178.08ZM117.39,178.48C97.8,174.2 83.68,156.9 83.68,136.64H183.68C183.68,109.57 164.76,86.48 138.76,80.79L117.39,178.48ZM83.68,136.64C83.68,115.28 98.7,99.44 115.95,95.13L140.21,192.14C163.86,186.23 183.68,164.79 183.68,136.64H83.68ZM178.08,143.64V142.04H78.08V143.64H178.08ZM142.64,189.87C164.49,183.22 182.08,162.77 182.08,136.74H82.08C82.08,115.7 96.27,99.45 113.52,94.2L142.64,189.87ZM182.08,136.74C182.08,112.78 166.51,90.67 142.64,83.4L113.52,179.07C94.25,173.2 82.08,155.69 82.08,136.74H182.08ZM180.08,136.54C180.08,115.18 167.65,97.22 150.44,88.62L105.72,178.06C90.91,170.65 80.08,155.1 80.08,136.54H180.08ZM78.08,133.34V139.74H178.08V133.34H78.08ZM152.02,183.63C165.86,176.08 180.08,159.73 180.08,136.54H80.08C80.08,116.14 92.5,102.19 104.14,95.84L152.02,183.63ZM76.49,130.27V142.93H176.49V130.27H76.49ZM161.85,107.57L157.84,103.56L87.13,174.27L91.14,178.28L161.85,107.57ZM122.49,88.92H119.27V188.92H122.49V88.92ZM169.27,138.92V134.21H69.27V138.92H169.27ZM119.27,184.21H122.49V84.22H119.27V184.21ZM157.55,169.85L161.56,165.91L91.43,94.63L87.42,98.58L157.55,169.85Z"
-          android:fillColor="#000000"/>
-    </group>
-    <path
-        android:pathData="M78.48,68.64L78.48,68.64A16,16 0,0 1,94.48 84.64L94.48,84.64A16,16 0,0 1,78.48 100.64L78.48,100.64A16,16 0,0 1,62.48 84.64L62.48,84.64A16,16 0,0 1,78.48 68.64z"
-        android:fillColor="#3B4043"/>
-    <path
-        android:pathData="M86.03,82.29C86.69,82.29 87.23,81.75 87.23,81.09C87.23,80.42 86.69,79.89 86.03,79.89C85.37,79.89 84.83,80.42 84.83,81.09C84.83,81.75 85.37,82.29 86.03,82.29Z"
-        android:fillColor="#34A853"/>
-    <path
-        android:pathData="M82.43,86.29C83.76,86.29 84.83,85.21 84.83,83.89C84.83,82.56 83.76,81.49 82.43,81.49C81.11,81.49 80.03,82.56 80.03,83.89C80.03,85.21 81.11,86.29 82.43,86.29Z"
-        android:fillColor="#EA4335"/>
-    <path
-        android:pathData="M82.43,92.59C83.98,92.59 85.23,91.33 85.23,89.79C85.23,88.24 83.98,86.99 82.43,86.99C80.88,86.99 79.63,88.24 79.63,89.79C79.63,91.33 80.88,92.59 82.43,92.59Z"
-        android:fillColor="#FBBC04"/>
-    <path
-        android:pathData="M74.53,86.29C77.18,86.29 79.33,84.14 79.33,81.49C79.33,78.84 77.18,76.69 74.53,76.69C71.88,76.69 69.73,78.84 69.73,81.49C69.73,84.14 71.88,86.29 74.53,86.29Z"
-        android:fillColor="#4285F4"/>
-    <path
-        android:pathData="M174.48,120.64L174.48,120.64A16,16 0,0 1,190.48 136.64L190.48,136.64A16,16 0,0 1,174.48 152.64L174.48,152.64A16,16 0,0 1,158.48 136.64L158.48,136.64A16,16 0,0 1,174.48 120.64z"
-        android:fillColor="#EFA5DE"/>
-    <path
-        android:pathData="M178.3,130.64H170.8V142.34H178.3V130.64Z"
-        android:fillColor="#000000"/>
-    <path
-        android:pathData="M170,132.94H167.3V140.14H170V132.94Z"
-        android:fillColor="#000000"/>
-    <path
-        android:pathData="M182,132.94H179.3V140.14H182V132.94Z"
-        android:fillColor="#000000"/>
-    <path
-        android:pathData="M126.48,172.64L126.48,172.64A16,16 0,0 1,142.48 188.64L142.48,188.64A16,16 0,0 1,126.48 204.64L126.48,204.64A16,16 0,0 1,110.48 188.64L110.48,188.64A16,16 0,0 1,126.48 172.64z"
-        android:fillColor="#FDD663"/>
-    <path
-        android:pathData="M135.48,188.64L132.88,191.24V194.94H129.08L126.48,197.54L123.88,194.94H120.08V191.24L117.48,188.64L120.08,186.04V182.34H123.78L126.38,179.74L128.98,182.34H132.68V186.04L135.48,188.64ZM121.68,188.64C121.68,191.24 123.78,193.44 126.48,193.44C129.08,193.44 131.28,191.34 131.28,188.64C131.28,185.94 129.18,183.84 126.48,183.84C123.88,183.84 121.68,185.94 121.68,188.64Z"
-        android:fillColor="#000000"
-        android:fillType="evenOdd"/>
-    <path
-        android:pathData="M126.98,188.04V186.54H125.98V188.04H124.48V189.04H125.98V190.54H126.98V189.04H128.48V188.04H126.98Z"
-        android:fillColor="#000000"
-        android:fillType="evenOdd"/>
-    <path
-        android:pathData="M126.48,68.64L126.48,68.64A16,16 0,0 1,142.48 84.64L142.48,84.64A16,16 0,0 1,126.48 100.64L126.48,100.64A16,16 0,0 1,110.48 84.64L110.48,84.64A16,16 0,0 1,126.48 68.64z"
-        android:fillColor="#D9AFFD"/>
-    <path
-        android:pathData="M128.13,78.64C128.13,79.44 127.43,80.14 126.53,80.14C125.63,80.14 124.93,79.44 124.93,78.64C124.93,77.84 125.63,77.14 126.53,77.14C127.43,77.04 128.13,77.74 128.13,78.64ZM126.53,80.84C128.73,80.84 131.23,80.64 133.23,80.04L133.63,81.54C132.13,81.94 130.43,82.14 128.83,82.34V92.14H127.23V87.64H125.63V92.14H124.13V82.34C122.53,82.24 120.83,81.94 119.33,81.54L119.73,80.04C121.83,80.64 124.23,80.84 126.53,80.84Z"
-        android:fillColor="#000000"
-        android:fillType="evenOdd"/>
-    <path
-        android:pathData="M174.48,172.64L174.48,172.64A16,16 0,0 1,190.48 188.64L190.48,188.64A16,16 0,0 1,174.48 204.64L174.48,204.64A16,16 0,0 1,158.48 188.64L158.48,188.64A16,16 0,0 1,174.48 172.64z"
-        android:fillColor="#84E39F"/>
-    <path
-        android:pathData="M178.88,186.09H178.18V184.59C178.18,182.59 176.58,180.89 174.48,180.89C172.38,180.89 170.78,182.49 170.78,184.59V186.09H170.08C169.28,186.09 168.58,186.79 168.58,187.59V194.89C168.58,195.69 169.28,196.39 170.08,196.39H178.88C179.68,196.39 180.38,195.69 180.38,194.89V187.59C180.38,186.79 179.68,186.09 178.88,186.09ZM174.48,192.69C173.68,192.69 172.98,191.99 172.98,191.19C172.98,190.39 173.68,189.69 174.48,189.69C175.28,189.69 175.98,190.39 175.98,191.19C175.98,192.09 175.28,192.69 174.48,192.69ZM172.18,186.09H176.68V184.59C176.68,183.29 175.68,182.29 174.38,182.29C173.08,182.29 172.08,183.29 172.08,184.59V186.09H172.18Z"
-        android:fillColor="#000000"
-        android:fillType="evenOdd"/>
-    <path
-        android:pathData="M174.48,68.64L174.48,68.64A16,16 0,0 1,190.48 84.64L190.48,84.64A16,16 0,0 1,174.48 100.64L174.48,100.64A16,16 0,0 1,158.48 84.64L158.48,84.64A16,16 0,0 1,174.48 68.64z"
-        android:fillColor="#DBDCE0"/>
-    <path
-        android:pathData="M173.68,77.49H175.28V85.39H173.68V77.49ZM177.98,80.39L179.08,79.29C180.58,80.59 181.58,82.49 181.58,84.69C181.58,88.59 178.38,91.79 174.48,91.79C170.58,91.79 167.38,88.59 167.38,84.69C167.38,82.49 168.38,80.59 169.88,79.29L170.98,80.39C169.78,81.39 168.98,82.99 168.98,84.69C168.98,87.79 171.48,90.29 174.58,90.29C177.68,90.29 180.18,87.79 180.18,84.69C180.08,82.89 179.18,81.39 177.98,80.39Z"
-        android:fillColor="#000000"
-        android:fillType="evenOdd"/>
-  </group>
-  <path
-      android:pathData="M62,51.82L349.54,51.82A14.5,14.5 0,0 1,364.04 66.32L364.04,236.27A14.5,14.5 0,0 1,349.54 250.77L62,250.77A14.5,14.5 0,0 1,47.5 236.27L47.5,66.32A14.5,14.5 0,0 1,62 51.82z"
-      android:strokeWidth="3"
+      android:strokeWidth="1"
+      android:pathData="M126.66,222.93L126.66,250.66"
       android:fillColor="#00000000"
-      android:strokeColor="#7F868C"/>
+      android:strokeColor="#5f6368"/>
   <path
-      android:pathData="M311.22,50.49C311.22,49.11 312.33,48 313.7,48L322.61,48C323.98,48 325.08,49.11 325.08,50.49L319.14,51.48L311.22,50.49Z"
-      android:fillColor="#7F868C"/>
+      android:pathData="M78.55,70.3h0c8.84,0 16,7.16 16,16h0c0,8.84 -7.16,16 -16,16h0c-8.84,0 -16,-7.16 -16,-16h0c0,-8.84 7.16,-16 16,-16Z"
+      android:fillColor="#2197f3"/>
   <path
-      android:pathData="M263.36,50.49C263.36,49.11 264.47,48 265.83,48L287.62,48C288.99,48 290.1,49.11 290.1,50.49L277.22,51.48L263.36,50.49Z"
-      android:fillColor="#7F868C"/>
+      android:pathData="M78.55,174.3h0c8.83,0 16,7.16 16,16h0c0,8.83 -7.16,16 -16,16h0c-8.83,0 -16,-7.16 -16,-16h0c0,-8.83 7.16,-16 16,-16Z"
+      android:fillColor="#fdd663"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M78.57,199.86l-2.85,-2.77h-3.93v-3.93l-2.83,-2.83 2.83,-2.83v-3.93h3.93l2.85,-2.83 2.81,2.83h3.93v3.93l2.83,2.83 -2.83,2.83v3.93h-3.93l-2.81,2.77ZM78.57,194.43c-1.14,0 -2.11,-0.4 -2.92,-1.2 -0.8,-0.8 -1.2,-1.78 -1.2,-2.92s0.4,-2.11 1.2,-2.92c0.8,-0.8 1.78,-1.2 2.92,-1.2 1.14,0 2.11,0.4 2.92,1.2 0.8,0.8 1.2,1.78 1.2,2.92s-0.4,2.11 -1.2,2.92c-0.8,0.8 -1.78,1.2 -2.92,1.2ZM78.57,193.16c0.8,0 1.48,-0.27 2.03,-0.82 0.55,-0.55 0.82,-1.23 0.82,-2.03 -0,-0.8 -0.27,-1.48 -0.82,-2.03 -0.55,-0.55 -1.23,-0.82 -2.03,-0.82 -0.8,0 -1.48,0.27 -2.03,0.82 -0.55,0.55 -0.82,1.23 -0.82,2.03s0.27,1.48 0.82,2.03c0.55,0.55 1.23,0.82 2.03,0.82ZM78.57,198.09l2.28,-2.26h3.19v-3.19l2.3,-2.3 -2.3,-2.3v-3.19h-3.19l-2.28,-2.3 -2.32,2.3h-3.19v3.19l-2.3,2.3 2.3,2.3v3.19h3.17l2.35,2.26Z"/>
+  <path
+      android:pathData="M126.55,174.31h0c8.83,0 16,7.16 16,16h0c0,8.83 -7.16,16 -16,16h0c-8.83,0 -16,-7.16 -16,-16h0c0,-8.83 7.16,-16 16,-16Z"
+      android:fillColor="#fdd663"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M126.58,199.87l-2.85,-2.77h-3.93v-3.93l-2.83,-2.83 2.83,-2.83v-3.93h3.93l2.85,-2.83 2.81,2.83h3.93v3.93l2.83,2.83 -2.83,2.83v3.93h-3.93l-2.81,2.77ZM126.58,194.44c1.14,0 2.11,-0.4 2.92,-1.2 0.8,-0.8 1.2,-1.78 1.2,-2.92s-0.4,-2.11 -1.2,-2.92c-0.8,-0.8 -1.78,-1.2 -2.92,-1.2 -1.14,0 -2.11,0.4 -2.92,1.2 -0.8,0.8 -1.2,1.78 -1.2,2.92s0.4,2.11 1.2,2.92c0.8,0.8 1.78,1.2 2.92,1.2ZM126.58,193.17c0.8,0 1.48,-0.27 2.03,-0.82 0.55,-0.55 0.82,-1.23 0.82,-2.03 -0,-0.8 -0.27,-1.48 -0.82,-2.03 -0.55,-0.55 -1.23,-0.82 -2.03,-0.82 -0.8,0 -1.48,0.27 -2.03,0.82 -0.55,0.55 -0.82,1.23 -0.82,2.03s0.27,1.48 0.82,2.03c0.55,0.55 1.23,0.82 2.03,0.82ZM126.58,198.09l2.28,-2.26h3.19v-3.19l2.3,-2.3 -2.3,-2.3v-3.19h-3.19l-2.28,-2.3 -2.32,2.3h-3.19v3.19l-2.3,2.3 2.3,2.3v3.19h3.17l2.35,2.26ZM126.58,193.17c0.8,0 1.48,-0.27 2.03,-0.82 0.55,-0.55 0.82,-1.23 0.82,-2.03 -0,-0.8 -0.27,-1.48 -0.82,-2.03 -0.55,-0.55 -1.23,-0.82 -2.03,-0.82 -0.8,0 -1.48,0.27 -2.03,0.82 -0.55,0.55 -0.82,1.23 -0.82,2.03s0.27,1.48 0.82,2.03c0.55,0.55 1.23,0.82 2.03,0.82Z"/>
+  <path
+      android:pathData="M174.56,174.3h0c8.83,0 16,7.16 16,16h0c0,8.83 -7.16,16 -16,16h0c-8.83,0 -16,-7.16 -16,-16h0c0,-8.83 7.16,-16 16,-16Z"
+      android:fillColor="#84e39f"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M168.94,198.37c-0.36,0 -0.67,-0.13 -0.92,-0.38s-0.38,-0.56 -0.38,-0.92v-9.38c0,-0.36 0.13,-0.67 0.38,-0.92s0.56,-0.38 0.92,-0.38h1.51v-2.07c0,-1.14 0.4,-2.11 1.2,-2.91 0.8,-0.8 1.77,-1.2 2.91,-1.2s2.11,0.4 2.91,1.2c0.8,0.8 1.2,1.77 1.2,2.91v2.07h1.51c0.36,0 0.67,0.13 0.92,0.38s0.38,0.56 0.38,0.92v9.38c0,0.36 -0.13,0.67 -0.38,0.92s-0.56,0.38 -0.92,0.38h-11.24ZM168.94,197.08h11.24v-9.38h-11.24v9.38ZM174.56,194.05c0.46,0 0.85,-0.16 1.18,-0.48s0.49,-0.7 0.49,-1.15c0,-0.43 -0.16,-0.82 -0.49,-1.18s-0.72,-0.53 -1.18,-0.53 -0.85,0.18 -1.18,0.53c-0.32,0.35 -0.49,0.75 -0.49,1.18 0,0.45 0.16,0.83 0.49,1.15s0.72,0.48 1.18,0.48ZM171.75,186.4h5.62v-2.07c0,-0.78 -0.27,-1.44 -0.82,-1.99 -0.55,-0.55 -1.21,-0.82 -1.99,-0.82s-1.44,0.27 -1.99,0.82 -0.82,1.21 -0.82,1.99v2.07ZM168.94,197.08v0Z"/>
+  <path
+      android:pathData="M174.56,70.24h0c8.87,0 16.06,7.19 16.06,16.06h0c0,8.87 -7.19,16.06 -16.06,16.06h0c-8.87,0 -16.06,-7.19 -16.06,-16.06h0c0,-8.87 7.19,-16.06 16.06,-16.06Z"
+      android:fillColor="#dbdce0"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M173.75,79.12h1.61v7.93h-1.61v-7.93ZM178.07,82.03l1.1,-1.1c1.51,1.31 2.51,3.21 2.51,5.42 0,3.92 -3.21,7.13 -7.13,7.13s-7.13,-3.21 -7.13,-7.13c0,-2.21 1,-4.12 2.51,-5.42l1.1,1.1c-1.2,1 -2.01,2.61 -2.01,4.32 0,3.11 2.51,5.62 5.62,5.62 3.11,0 5.62,-2.51 5.62,-5.62 -0.1,-1.81 -1,-3.31 -2.21,-4.32Z"
+      android:fillType="evenOdd"/>
+  <path
+      android:pathData="M126.55,70.24h0c8.87,0 16.06,7.19 16.06,16.06h0c0,8.87 -7.19,16.06 -16.06,16.06h0c-8.87,0 -16.06,-7.19 -16.06,-16.06h0c0,-8.87 7.19,-16.06 16.06,-16.06Z"
+      android:fillColor="#d9affd"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M126.55,79.66c-0.4,0 -0.74,-0.14 -1.02,-0.43 -0.29,-0.29 -0.43,-0.63 -0.43,-1.02s0.14,-0.74 0.43,-1.02c0.29,-0.29 0.63,-0.43 1.02,-0.43s0.74,0.14 1.02,0.43c0.29,0.29 0.43,0.63 0.43,1.02s-0.14,0.74 -0.43,1.02 -0.63,0.43 -1.02,0.43ZM124.49,91.87v-9.83c-0.84,-0.07 -1.68,-0.16 -2.53,-0.29 -0.85,-0.13 -1.64,-0.28 -2.37,-0.47l0.3,-1.19c1.06,0.27 2.15,0.46 3.27,0.58 1.12,0.12 2.25,0.18 3.39,0.18s2.27,-0.06 3.39,-0.18c1.12,-0.12 2.21,-0.31 3.27,-0.58l0.3,1.19c-0.73,0.19 -1.52,0.34 -2.37,0.47 -0.85,0.13 -1.69,0.22 -2.53,0.29v9.83h-1.19v-4.85h-1.75v4.85h-1.19ZM123.31,95.85c-0.23,0 -0.41,-0.07 -0.55,-0.21 -0.14,-0.14 -0.21,-0.32 -0.21,-0.55 0,-0.23 0.07,-0.41 0.21,-0.55 0.14,-0.14 0.32,-0.21 0.55,-0.21s0.41,0.07 0.55,0.21c0.14,0.14 0.21,0.32 0.21,0.55 0,0.23 -0.07,0.41 -0.21,0.55 -0.14,0.14 -0.32,0.21 -0.55,0.21ZM126.57,95.85c-0.23,0 -0.41,-0.07 -0.55,-0.21 -0.14,-0.14 -0.21,-0.32 -0.21,-0.55 0,-0.23 0.07,-0.41 0.21,-0.55 0.14,-0.14 0.32,-0.21 0.55,-0.21s0.41,0.07 0.55,0.21c0.14,0.14 0.21,0.32 0.21,0.55 0,0.23 -0.07,0.41 -0.21,0.55 -0.14,0.14 -0.32,0.21 -0.55,0.21ZM129.84,95.85c-0.23,0 -0.41,-0.07 -0.55,-0.21 -0.14,-0.14 -0.21,-0.32 -0.21,-0.55 0,-0.23 0.07,-0.41 0.21,-0.55 0.14,-0.14 0.32,-0.21 0.55,-0.21s0.41,0.07 0.55,0.21c0.14,0.14 0.21,0.32 0.21,0.55 0,0.23 -0.07,0.41 -0.21,0.55 -0.14,0.14 -0.32,0.21 -0.55,0.21Z"/>
+  <path
+      android:pathData="M126.55,122.3h0c8.83,0 15.99,7.16 15.99,15.99h0c0,8.83 -7.16,15.99 -15.99,15.99h0c-8.83,0 -15.99,-7.16 -15.99,-15.99h0c0,-8.83 7.16,-15.99 15.99,-15.99Z"
+      android:fillColor="#7ae2d4"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M128.49,146.78v-1.5c1.57,-0.45 2.84,-1.32 3.84,-2.6 0.99,-1.28 1.49,-2.74 1.49,-4.37 0,-1.63 -0.49,-3.09 -1.48,-4.38s-2.27,-2.15 -3.85,-2.59v-1.5c2,0.45 3.63,1.46 4.89,3.04 1.26,1.57 1.89,3.39 1.89,5.43s-0.63,3.86 -1.89,5.43c-1.26,1.57 -2.89,2.59 -4.89,3.04ZM117.84,141.24v-5.81h3.87l4.84,-4.84v15.49l-4.84,-4.84h-3.87ZM128.01,142.4v-8.16c0.89,0.27 1.59,0.79 2.12,1.55 0.52,0.76 0.79,1.61 0.79,2.54 0,0.92 -0.27,1.76 -0.8,2.52s-1.23,1.28 -2.11,1.55ZM125.1,134.26l-2.74,2.61h-3.07v2.91h3.07l2.74,2.64v-8.16Z"/>
+  <path
+      android:pathData="M174.56,122.33h0c8.83,0 15.99,7.16 15.99,15.99h0c0,8.83 -7.16,15.99 -15.99,15.99h0c-8.83,0 -15.99,-7.16 -15.99,-15.99h0c0,-8.83 7.16,-15.99 15.99,-15.99Z"
+      android:fillColor="#efa5de"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M179.02,131.89h-8.93v12.86h8.93v-12.86Z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M168.9,134.41h-3.22v7.91h3.22v-7.91Z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M183.43,134.41h-3.22v7.91h3.22v-7.91Z"/>
+  <path
+      android:pathData="M171.75,133.42h5.61v9.78h-5.61z"
+      android:fillColor="#efa5de"/>
+  <path
+      android:pathData="M78.55,122.3h0c8.83,0 15.99,7.16 15.99,15.99h0c0,8.83 -7.16,15.99 -15.99,15.99h0c-8.83,0 -15.99,-7.16 -15.99,-15.99h0c0,-8.83 7.16,-15.99 15.99,-15.99Z"
+      android:fillColor="#7ae2d4"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M72.01,141.21v-5.81h3.88l4.84,-4.84v15.5l-4.84,-4.84h-3.88ZM82.18,142.38v-8.16c0.87,0.27 1.57,0.79 2.11,1.55 0.53,0.76 0.8,1.61 0.8,2.54 0,0.95 -0.27,1.8 -0.8,2.54 -0.53,0.74 -1.24,1.25 -2.11,1.53ZM79.28,134.24l-2.74,2.62h-3.08v2.91h3.08l2.74,2.64v-8.16Z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M78.73,96.45l-2.73,-2.73h-4.09c-0.36,0 -0.68,-0.14 -0.95,-0.41 -0.27,-0.27 -0.41,-0.59 -0.41,-0.95v-13.64c0,-0.36 0.14,-0.68 0.41,-0.95 0.27,-0.27 0.59,-0.41 0.95,-0.41h13.64c0.36,0 0.68,0.14 0.95,0.41 0.27,0.27 0.41,0.59 0.41,0.95v13.64c0,0.36 -0.14,0.68 -0.41,0.95 -0.27,0.27 -0.59,0.41 -0.95,0.41h-4.09l-2.73,2.73ZM78.75,89.79l1.27,-2.91 2.91,-1.27 -2.91,-1.27 -1.27,-2.91 -1.3,2.91 -2.89,1.27 2.89,1.27 1.3,2.91Z"/>
 </vector>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable-sw600dp/a11ymenu_intro.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable-sw600dp/a11ymenu_intro.xml
index f0fbc48..aba9581 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable-sw600dp/a11ymenu_intro.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable-sw600dp/a11ymenu_intro.xml
@@ -3,139 +3,101 @@
     android:height="300dp"
     android:viewportWidth="412"
     android:viewportHeight="300">
-  <group>
-    <clip-path
-        android:pathData="M62.23,50.19L349.77,50.19A16,16 0,0 1,365.77 66.19L365.77,236.14A16,16 0,0 1,349.77 252.14L62.23,252.14A16,16 0,0 1,46.23 236.14L46.23,66.19A16,16 0,0 1,62.23 50.19z"/>
-    <path
-        android:pathData="M62.23,50.19L349.77,50.19A16,16 0,0 1,365.77 66.19L365.77,236.14A16,16 0,0 1,349.77 252.14L62.23,252.14A16,16 0,0 1,46.23 236.14L46.23,66.19A16,16 0,0 1,62.23 50.19z"
-        android:fillColor="#E8EAED"/>
-    <path
-        android:pathData="M46.23,52.14h160v200h-160z"
-        android:fillColor="#ffffff"/>
-    <path
-        android:pathData="M86.21,240.04L86.91,239.34L84.21,236.64H90.11V235.64H84.21L86.91,232.94L86.21,232.24L82.31,236.14L86.21,240.04Z"
-        android:fillColor="#E8EAED"
-        android:fillType="evenOdd"/>
-    <path
-        android:pathData="M125.71,220.14V252.14H127.71V220.14H125.71Z"
-        android:fillColor="#E8EAED"/>
-    <path
-        android:pathData="M166.21,232.24L165.51,232.94L168.21,235.64H162.31V236.64H168.21L165.51,239.34L166.21,240.04L170.11,236.14L166.21,232.24Z"
-        android:fillColor="#7F868C"
-        android:fillType="evenOdd"/>
-    <path
-        android:pathData="M46.71,221.14H206.71V219.14H46.71V221.14Z"
-        android:fillColor="#E8EAED"/>
-    <path
-        android:pathData="M78.71,120.5L78.71,120.5A16,16 0,0 1,94.71 136.5L94.71,136.5A16,16 0,0 1,78.71 152.5L78.71,152.5A16,16 0,0 1,62.71 136.5L62.71,136.5A16,16 0,0 1,78.71 120.5z"
-        android:fillColor="#327969"/>
-    <group>
-      <clip-path
-          android:pathData="M73.36,138.95V134.15H76.56L80.56,130.15V142.85L76.56,138.85H73.36V138.95ZM82.06,133.35C83.26,133.95 84.06,135.15 84.06,136.55C84.06,137.95 83.26,139.15 82.06,139.75V133.35Z"
-          android:fillType="evenOdd"/>
-      <path
-          android:pathData="M88.36,127.05H69.36V146.05H88.36V127.05Z"
-          android:fillColor="#ffffff"/>
-    </group>
-    <path
-        android:pathData="M78.71,172.5L78.71,172.5A16,16 0,0 1,94.71 188.5L94.71,188.5A16,16 0,0 1,78.71 204.5L78.71,204.5A16,16 0,0 1,62.71 188.5L62.71,188.5A16,16 0,0 1,78.71 172.5z"
-        android:fillColor="#DE9834"/>
-    <path
-        android:pathData="M87.66,188.5L85.06,191.1V194.8H81.36L78.76,197.4L76.16,194.8H72.36V191.1L69.76,188.5L72.36,185.9V182.2H76.06L78.66,179.6L81.26,182.2H84.96V185.9L87.66,188.5ZM73.96,188.5C73.96,191.1 76.06,193.3 78.76,193.3C81.36,193.3 83.56,191.2 83.56,188.5C83.56,185.8 81.46,183.7 78.76,183.7C76.06,183.7 73.96,185.8 73.96,188.5Z"
-        android:fillColor="#ffffff"
-        android:fillType="evenOdd"/>
-    <path
-        android:pathData="M80.66,187.9H76.66V189.4H80.66V187.9Z"
-        android:fillColor="#ffffff"/>
-    <path
-        android:pathData="M126.71,120.5L126.71,120.5A16,16 0,0 1,142.71 136.5L142.71,136.5A16,16 0,0 1,126.71 152.5L126.71,152.5A16,16 0,0 1,110.71 136.5L110.71,136.5A16,16 0,0 1,126.71 120.5z"
-        android:fillColor="#327969"/>
-    <path
-        android:pathData="M128.31,131.1V129.5C131.51,130.2 133.91,133.1 133.91,136.5C133.91,139.9 131.51,142.7 128.31,143.5V141.9C130.61,141.2 132.31,139.1 132.31,136.6C132.31,134.1 130.61,131.8 128.31,131.1ZM130.31,136.4C130.31,135 129.51,133.8 128.31,133.2V139.6C129.41,139 130.31,137.8 130.31,136.4Z"
-        android:fillColor="#ffffff"
-        android:fillType="evenOdd"/>
-    <path
-        android:pathData="M126.72,142.79V130.13L122.71,134.08H119.5V138.78H122.71L126.72,142.79Z"
-        android:fillColor="#ffffff"/>
-    <group>
-      <clip-path
-          android:pathData="M126.72,142.79V130.13L122.71,134.08H119.5V138.78H122.71L126.72,142.79Z"/>
-      <clip-path
-          android:pathData="M128.31,131.1V129.5C131.51,130.2 133.91,133.1 133.91,136.5C133.91,139.9 131.51,142.7 128.31,143.5V141.9C130.61,141.2 132.31,139.1 132.31,136.6C132.31,134.1 130.61,131.8 128.31,131.1ZM130.31,136.4C130.31,135 129.51,133.8 128.31,133.2V139.6C129.41,139 130.31,137.8 130.31,136.4Z"
-          android:fillType="evenOdd"/>
-      <path
-          android:pathData="M128.31,131.1H78.31V168.15L113.75,178.94L128.31,131.1ZM128.31,129.5L138.99,80.66L78.31,67.38V129.5H128.31ZM128.31,143.5H78.31V207.54L140.44,192.01L128.31,143.5ZM128.31,141.9L113.75,94.07L78.31,104.86V141.9H128.31ZM128.31,133.2L150.67,88.48L78.31,52.3V133.2H128.31ZM128.31,139.6H78.31V223.83L152.25,183.5L128.31,139.6ZM126.72,130.13H176.73V10.79L91.66,94.5L126.72,130.13ZM126.72,142.79L91.37,178.15L176.73,263.5V142.79H126.72ZM122.71,138.78L158.07,103.43L143.43,88.78H122.71V138.78ZM119.5,138.78H69.5V188.78H119.5V138.78ZM119.5,134.08V84.08H69.5V134.08H119.5ZM122.71,134.08V184.08H143.19L157.78,169.72L122.71,134.08ZM178.31,131.1V129.5H78.31V131.1H178.31ZM117.63,178.35C98.03,174.06 83.91,156.76 83.91,136.5H183.91C183.91,109.44 164.99,86.34 138.99,80.66L117.63,178.35ZM83.91,136.5C83.91,115.15 98.93,99.31 116.18,94.99L140.44,192.01C164.09,186.1 183.91,164.66 183.91,136.5H83.91ZM178.31,143.5V141.9H78.31V143.5H178.31ZM142.87,189.74C164.72,183.09 182.31,162.64 182.31,136.6H82.31C82.31,115.57 96.5,99.32 113.75,94.07L142.87,189.74ZM182.31,136.6C182.31,112.64 166.74,90.53 142.87,83.27L113.75,178.94C94.48,173.07 82.31,155.56 82.31,136.6H182.31ZM180.31,136.4C180.31,115.04 167.88,97.08 150.67,88.48L105.95,177.92C91.14,170.52 80.31,154.96 80.31,136.4H180.31ZM78.31,133.2V139.6H178.31V133.2H78.31ZM152.25,183.5C166.09,175.95 180.31,159.6 180.31,136.4H80.31C80.31,116 92.73,102.06 104.37,95.71L152.25,183.5ZM76.72,130.13V142.79H176.73V130.13H76.72ZM162.08,107.44L158.07,103.43L87.36,174.14L91.37,178.15L162.08,107.44ZM122.71,88.78H119.5V188.78H122.71V88.78ZM169.5,138.78V134.08H69.5V138.78H169.5ZM119.5,184.08H122.71V84.08H119.5V184.08ZM157.78,169.72L161.79,165.77L91.66,94.5L87.65,98.44L157.78,169.72Z"
-          android:fillColor="#ffffff"/>
-    </group>
-    <path
-        android:pathData="M78.71,68.5L78.71,68.5A16,16 0,0 1,94.71 84.5L94.71,84.5A16,16 0,0 1,78.71 100.5L78.71,100.5A16,16 0,0 1,62.71 84.5L62.71,84.5A16,16 0,0 1,78.71 68.5z"
-        android:fillColor="#E8EAED"/>
-    <path
-        android:pathData="M86.26,82.15C86.92,82.15 87.46,81.61 87.46,80.95C87.46,80.29 86.92,79.75 86.26,79.75C85.6,79.75 85.06,80.29 85.06,80.95C85.06,81.61 85.6,82.15 86.26,82.15Z"
-        android:fillColor="#34A853"/>
-    <path
-        android:pathData="M82.66,86.15C83.99,86.15 85.06,85.08 85.06,83.75C85.06,82.43 83.99,81.35 82.66,81.35C81.34,81.35 80.26,82.43 80.26,83.75C80.26,85.08 81.34,86.15 82.66,86.15Z"
-        android:fillColor="#EA4335"/>
-    <path
-        android:pathData="M82.66,92.45C84.21,92.45 85.46,91.2 85.46,89.65C85.46,88.11 84.21,86.85 82.66,86.85C81.11,86.85 79.86,88.11 79.86,89.65C79.86,91.2 81.11,92.45 82.66,92.45Z"
-        android:fillColor="#FBBC04"/>
-    <path
-        android:pathData="M74.76,86.15C77.41,86.15 79.56,84 79.56,81.35C79.56,78.7 77.41,76.55 74.76,76.55C72.11,76.55 69.96,78.7 69.96,81.35C69.96,84 72.11,86.15 74.76,86.15Z"
-        android:fillColor="#4285F4"/>
-    <path
-        android:pathData="M174.71,120.5L174.71,120.5A16,16 0,0 1,190.71 136.5L190.71,136.5A16,16 0,0 1,174.71 152.5L174.71,152.5A16,16 0,0 1,158.71 136.5L158.71,136.5A16,16 0,0 1,174.71 120.5z"
-        android:fillColor="#9F3EBF"/>
-    <path
-        android:pathData="M178.53,130.5H171.03V142.2H178.53V130.5Z"
-        android:fillColor="#ffffff"/>
-    <path
-        android:pathData="M170.23,132.8H167.53V140H170.23V132.8Z"
-        android:fillColor="#ffffff"/>
-    <path
-        android:pathData="M182.23,132.8H179.53V140H182.23V132.8Z"
-        android:fillColor="#ffffff"/>
-    <path
-        android:pathData="M126.71,172.5L126.71,172.5A16,16 0,0 1,142.71 188.5L142.71,188.5A16,16 0,0 1,126.71 204.5L126.71,204.5A16,16 0,0 1,110.71 188.5L110.71,188.5A16,16 0,0 1,126.71 172.5z"
-        android:fillColor="#DE9834"/>
-    <path
-        android:pathData="M135.71,188.5L133.11,191.1V194.8H129.31L126.71,197.4L124.11,194.8H120.31V191.1L117.71,188.5L120.31,185.9V182.2H124.01L126.61,179.6L129.21,182.2H132.91V185.9L135.71,188.5ZM121.91,188.5C121.91,191.1 124.01,193.3 126.71,193.3C129.31,193.3 131.51,191.2 131.51,188.5C131.51,185.8 129.41,183.7 126.71,183.7C124.11,183.7 121.91,185.8 121.91,188.5Z"
-        android:fillColor="#ffffff"
-        android:fillType="evenOdd"/>
-    <path
-        android:pathData="M127.21,187.9V186.4H126.21V187.9H124.71V188.9H126.21V190.4H127.21V188.9H128.71V187.9H127.21Z"
-        android:fillColor="#ffffff"
-        android:fillType="evenOdd"/>
-    <path
-        android:pathData="M126.71,68.5L126.71,68.5A16,16 0,0 1,142.71 84.5L142.71,84.5A16,16 0,0 1,126.71 100.5L126.71,100.5A16,16 0,0 1,110.71 84.5L110.71,84.5A16,16 0,0 1,126.71 68.5z"
-        android:fillColor="#521BBF"/>
-    <path
-        android:pathData="M128.36,78.51C128.36,79.31 127.66,80.01 126.76,80.01C125.86,80.01 125.16,79.31 125.16,78.51C125.16,77.71 125.86,77.01 126.76,77.01C127.66,76.91 128.36,77.61 128.36,78.51ZM126.76,80.71C128.96,80.71 131.46,80.51 133.46,79.91L133.86,81.41C132.36,81.81 130.66,82.01 129.06,82.21V92.01H127.46V87.51H125.86V92.01H124.36V82.21C122.76,82.11 121.06,81.81 119.56,81.41L119.96,79.91C122.06,80.51 124.46,80.71 126.76,80.71Z"
-        android:fillColor="#ffffff"
-        android:fillType="evenOdd"/>
-    <path
-        android:pathData="M174.71,172.5L174.71,172.5A16,16 0,0 1,190.71 188.5L190.71,188.5A16,16 0,0 1,174.71 204.5L174.71,204.5A16,16 0,0 1,158.71 188.5L158.71,188.5A16,16 0,0 1,174.71 172.5z"
-        android:fillColor="#438947"/>
-    <path
-        android:pathData="M179.11,185.95H178.41V184.45C178.41,182.45 176.81,180.75 174.71,180.75C172.61,180.75 171.01,182.35 171.01,184.45V185.95H170.31C169.51,185.95 168.81,186.65 168.81,187.45V194.75C168.81,195.55 169.51,196.25 170.31,196.25H179.11C179.91,196.25 180.61,195.55 180.61,194.75V187.45C180.61,186.65 179.91,185.95 179.11,185.95ZM174.71,192.55C173.91,192.55 173.21,191.85 173.21,191.05C173.21,190.25 173.91,189.55 174.71,189.55C175.51,189.55 176.21,190.25 176.21,191.05C176.21,191.95 175.51,192.55 174.71,192.55ZM172.41,185.95H176.91V184.45C176.91,183.15 175.91,182.15 174.61,182.15C173.31,182.15 172.31,183.15 172.31,184.45V185.95H172.41Z"
-        android:fillColor="#ffffff"
-        android:fillType="evenOdd"/>
-    <path
-        android:pathData="M174.71,68.5L174.71,68.5A16,16 0,0 1,190.71 84.5L190.71,84.5A16,16 0,0 1,174.71 100.5L174.71,100.5A16,16 0,0 1,158.71 84.5L158.71,84.5A16,16 0,0 1,174.71 68.5z"
-        android:fillColor="#80868B"/>
-    <path
-        android:pathData="M173.91,77.35H175.51V85.25H173.91V77.35ZM178.21,80.25L179.31,79.15C180.81,80.45 181.81,82.35 181.81,84.55C181.81,88.45 178.61,91.65 174.71,91.65C170.81,91.65 167.61,88.45 167.61,84.55C167.61,82.35 168.61,80.45 170.11,79.15L171.21,80.25C170.01,81.25 169.21,82.85 169.21,84.55C169.21,87.65 171.71,90.15 174.81,90.15C177.91,90.15 180.41,87.65 180.41,84.55C180.31,82.75 179.41,81.25 178.21,80.25Z"
-        android:fillColor="#ffffff"
-        android:fillType="evenOdd"/>
-  </group>
   <path
-      android:pathData="M62.23,51.69L349.77,51.69A14.5,14.5 0,0 1,364.27 66.19L364.27,236.14A14.5,14.5 0,0 1,349.77 250.64L62.23,250.64A14.5,14.5 0,0 1,47.73 236.14L47.73,66.19A14.5,14.5 0,0 1,62.23 51.69z"
-      android:strokeWidth="3"
+      android:pathData="M384.18,300H27.82c-15.29,0 -27.82,-12.83 -27.82,-28.48V28.48C0,12.83 12.53,0 27.82,0H384.29c15.18,0 27.71,12.83 27.71,28.48v243.15c0,15.54 -12.53,28.37 -27.82,28.37Z"
+      android:fillColor="#fff"/>
+  <path
+      android:pathData="M78.71,69.91h0c8.84,0 16,7.16 16,16h0c0,8.84 -7.16,16 -16,16h0c-8.84,0 -16,-7.16 -16,-16h0c0,-8.84 7.16,-16 16,-16Z"
+      android:fillColor="#2197f3"/>
+  <path
+      android:pathData="M207.35,52.26h151.18c4.14,0 7.51,3.36 7.51,7.51V242.76c0,4.14 -3.36,7.51 -7.51,7.51H207.35V52.26h0Z"
+      android:fillColor="#e8eaed"/>
+  <path
+      android:pathData="M368.4,143.08L368.4,60.16c0,-5.67 -4.59,-10.26 -10.26,-10.26L54.17,49.9c-5.67,0 -10.26,4.59 -10.26,10.26L43.91,242.37c0,5.67 4.59,10.26 10.26,10.26L358.14,252.63c5.67,0 10.26,-4.59 10.26,-10.26v-99.29ZM366.04,242.75c0,4.15 -3.75,7.52 -7.9,7.52L54.17,250.27c-4.15,0 -7.9,-3.37 -7.9,-7.52L46.27,60.16c0,-4.15 3.75,-7.9 7.9,-7.9L358.14,52.26c4.15,0 7.9,3.75 7.9,7.9L366.04,242.75Z"
+      android:fillColor="#dadce0"/>
+  <path
+      android:pathData="M319.98,49.9c-0,-1.28 -1.04,-2.31 -2.31,-2.31h-23.11c-1.28,0 -2.31,1.03 -2.31,2.31h27.74Z"
+      android:fillColor="#dadce0"/>
+  <path
+      android:pathData="M344.57,49.9c-0,-1.28 -1.03,-2.31 -2.31,-2.31h-9.25c-1.28,0 -2.31,1.03 -2.31,2.31h13.87Z"
+      android:fillColor="#dadce0"/>
+  <path
+      android:pathData="M86.21,240.04l0.7,-0.7 -2.7,-2.7h5.9v-1h-5.9l2.7,-2.7 -0.7,-0.7 -3.9,3.9 3.9,3.9Z"
+      android:fillColor="#e8eaed"
+      android:fillType="evenOdd"/>
+  <path
+      android:pathData="M167.08,232.5l-0.7,0.7 2.7,2.7h-5.9v1h5.9l-2.7,2.7 0.7,0.7 3.9,-3.9 -3.9,-3.9Z"
+      android:fillColor="#7f868c"
+      android:fillType="evenOdd"/>
+  <path
+      android:strokeWidth="1"
+      android:pathData="M46.27,222.54L207.35,222.54"
       android:fillColor="#00000000"
-      android:strokeColor="#DADCE0"/>
+      android:strokeColor="#e8eaed"/>
   <path
-      android:pathData="M311.45,50.35C311.45,48.98 312.56,47.87 313.92,47.87L322.84,47.87C324.2,47.87 325.32,48.98 325.32,50.35L319.37,51.34L311.45,50.35Z"
-      android:fillColor="#DADCE0"/>
+      android:strokeWidth="1"
+      android:pathData="M126.81,222.54L126.81,250.27"
+      android:fillColor="#00000000"
+      android:strokeColor="#e8eaed"/>
   <path
-      android:pathData="M263.59,50.35C263.59,48.98 264.7,47.87 266.06,47.87L287.85,47.87C289.22,47.87 290.33,48.98 290.33,50.35L277.45,51.34L263.59,50.35Z"
-      android:fillColor="#DADCE0"/>
+      android:pathData="M78.71,173.91h0c8.83,0 16,7.16 16,16h0c0,8.83 -7.16,16 -16,16h0c-8.83,0 -16,-7.16 -16,-16h0c0,-8.83 7.16,-16 16,-16Z"
+      android:fillColor="#de9834"/>
+  <path
+      android:pathData="M78.73,199.47l-2.85,-2.77h-3.93v-3.93l-2.83,-2.83 2.83,-2.83v-3.93h3.93l2.85,-2.83 2.81,2.83h3.93v3.93l2.83,2.83 -2.83,2.83v3.93h-3.93l-2.81,2.77ZM78.73,194.04c-1.14,0 -2.11,-0.4 -2.92,-1.2 -0.8,-0.8 -1.2,-1.78 -1.2,-2.92s0.4,-2.11 1.2,-2.92c0.8,-0.8 1.78,-1.2 2.92,-1.2 1.14,0 2.11,0.4 2.92,1.2 0.8,0.8 1.2,1.78 1.2,2.92s-0.4,2.11 -1.2,2.92c-0.8,0.8 -1.78,1.2 -2.92,1.2ZM78.73,192.77c0.8,0 1.48,-0.27 2.03,-0.82 0.55,-0.55 0.82,-1.23 0.82,-2.03 -0,-0.8 -0.27,-1.48 -0.82,-2.03 -0.55,-0.55 -1.23,-0.82 -2.03,-0.82 -0.8,0 -1.48,0.27 -2.03,0.82 -0.55,0.55 -0.82,1.23 -0.82,2.03s0.27,1.48 0.82,2.03c0.55,0.55 1.23,0.82 2.03,0.82ZM78.73,197.7l2.28,-2.26h3.19v-3.19l2.3,-2.3 -2.3,-2.3v-3.19h-3.19l-2.28,-2.3 -2.32,2.3h-3.19v3.19l-2.3,2.3 2.3,2.3v3.19h3.17l2.35,2.26Z"
+      android:fillColor="#fff"/>
+  <path
+      android:pathData="M126.71,173.92h0c8.83,0 16,7.16 16,16h0c0,8.83 -7.16,16 -16,16h0c-8.83,0 -16,-7.16 -16,-16h0c0,-8.83 7.16,-16 16,-16Z"
+      android:fillColor="#de9834"/>
+  <path
+      android:pathData="M126.73,199.48l-2.85,-2.77h-3.93v-3.93l-2.83,-2.83 2.83,-2.83v-3.93h3.93l2.85,-2.83 2.81,2.83h3.93v3.93l2.83,2.83 -2.83,2.83v3.93h-3.93l-2.81,2.77ZM126.73,194.04c1.14,0 2.11,-0.4 2.92,-1.2 0.8,-0.8 1.2,-1.78 1.2,-2.92s-0.4,-2.11 -1.2,-2.92c-0.8,-0.8 -1.78,-1.2 -2.92,-1.2 -1.14,0 -2.11,0.4 -2.92,1.2 -0.8,0.8 -1.2,1.78 -1.2,2.92s0.4,2.11 1.2,2.92c0.8,0.8 1.78,1.2 2.92,1.2ZM126.73,192.78c0.8,0 1.48,-0.27 2.03,-0.82 0.55,-0.55 0.82,-1.23 0.82,-2.03 -0,-0.8 -0.27,-1.48 -0.82,-2.03 -0.55,-0.55 -1.23,-0.82 -2.03,-0.82 -0.8,0 -1.48,0.27 -2.03,0.82 -0.55,0.55 -0.82,1.23 -0.82,2.03s0.27,1.48 0.82,2.03c0.55,0.55 1.23,0.82 2.03,0.82ZM126.73,197.7l2.28,-2.26h3.19v-3.19l2.3,-2.3 -2.3,-2.3v-3.19h-3.19l-2.28,-2.3 -2.32,2.3h-3.19v3.19l-2.3,2.3 2.3,2.3v3.19h3.17l2.35,2.26ZM126.73,192.78c0.8,0 1.48,-0.27 2.03,-0.82 0.55,-0.55 0.82,-1.23 0.82,-2.03 -0,-0.8 -0.27,-1.48 -0.82,-2.03 -0.55,-0.55 -1.23,-0.82 -2.03,-0.82 -0.8,0 -1.48,0.27 -2.03,0.82 -0.55,0.55 -0.82,1.23 -0.82,2.03s0.27,1.48 0.82,2.03c0.55,0.55 1.23,0.82 2.03,0.82Z"
+      android:fillColor="#fff"/>
+  <path
+      android:pathData="M174.71,173.91h0c8.83,0 16,7.16 16,16h0c0,8.83 -7.16,16 -16,16h0c-8.83,0 -16,-7.16 -16,-16h0c0,-8.83 7.16,-16 16,-16Z"
+      android:fillColor="#438947"/>
+  <path
+      android:pathData="M169.09,197.98c-0.36,0 -0.67,-0.13 -0.92,-0.38s-0.38,-0.56 -0.38,-0.92v-9.38c0,-0.36 0.13,-0.67 0.38,-0.92s0.56,-0.38 0.92,-0.38h1.51v-2.07c0,-1.14 0.4,-2.11 1.2,-2.91 0.8,-0.8 1.77,-1.2 2.91,-1.2s2.11,0.4 2.91,1.2c0.8,0.8 1.2,1.77 1.2,2.91v2.07h1.51c0.36,0 0.67,0.13 0.92,0.38s0.38,0.56 0.38,0.92v9.38c0,0.36 -0.13,0.67 -0.38,0.92s-0.56,0.38 -0.92,0.38h-11.24ZM169.09,196.68h11.24v-9.38h-11.24v9.38ZM174.71,193.66c0.46,0 0.85,-0.16 1.18,-0.48s0.49,-0.7 0.49,-1.15c0,-0.43 -0.16,-0.82 -0.49,-1.18s-0.72,-0.53 -1.18,-0.53 -0.85,0.18 -1.18,0.53c-0.32,0.35 -0.49,0.75 -0.49,1.18 0,0.45 0.16,0.83 0.49,1.15s0.72,0.48 1.18,0.48ZM171.9,186.01h5.62v-2.07c0,-0.78 -0.27,-1.44 -0.82,-1.99 -0.55,-0.55 -1.21,-0.82 -1.99,-0.82s-1.44,0.27 -1.99,0.82 -0.82,1.21 -0.82,1.99v2.07ZM169.09,196.68v0Z"
+      android:fillColor="#fff"/>
+  <path
+      android:pathData="M174.71,69.85h0c8.87,0 16.06,7.19 16.06,16.06h0c0,8.87 -7.19,16.06 -16.06,16.06h0c-8.87,0 -16.06,-7.19 -16.06,-16.06h0c0,-8.87 7.19,-16.06 16.06,-16.06Z"
+      android:fillColor="#80868b"/>
+  <path
+      android:pathData="M173.91,78.73h1.61v7.93h-1.61v-7.93ZM178.22,81.64l1.1,-1.1c1.51,1.31 2.51,3.21 2.51,5.42 0,3.92 -3.21,7.13 -7.13,7.13s-7.13,-3.21 -7.13,-7.13c0,-2.21 1,-4.12 2.51,-5.42l1.1,1.1c-1.2,1 -2.01,2.61 -2.01,4.32 0,3.11 2.51,5.62 5.62,5.62 3.11,0 5.62,-2.51 5.62,-5.62 -0.1,-1.81 -1,-3.31 -2.21,-4.32Z"
+      android:fillColor="#fff"
+      android:fillType="evenOdd"/>
+  <path
+      android:pathData="M126.71,69.85h0c8.87,0 16.06,7.19 16.06,16.06h0c0,8.87 -7.19,16.06 -16.06,16.06h0c-8.87,0 -16.06,-7.19 -16.06,-16.06h0c0,-8.87 7.19,-16.06 16.06,-16.06Z"
+      android:fillColor="#521bbf"/>
+  <path
+      android:pathData="M126.71,79.26c-0.4,0 -0.74,-0.14 -1.02,-0.43 -0.29,-0.29 -0.43,-0.63 -0.43,-1.02s0.14,-0.74 0.43,-1.02c0.29,-0.29 0.63,-0.43 1.02,-0.43s0.74,0.14 1.02,0.43c0.29,0.29 0.43,0.63 0.43,1.02s-0.14,0.74 -0.43,1.02 -0.63,0.43 -1.02,0.43ZM124.64,91.48v-9.83c-0.84,-0.07 -1.68,-0.16 -2.53,-0.29 -0.85,-0.13 -1.64,-0.28 -2.37,-0.47l0.3,-1.19c1.06,0.27 2.15,0.46 3.27,0.58 1.12,0.12 2.25,0.18 3.39,0.18s2.27,-0.06 3.39,-0.18c1.12,-0.12 2.21,-0.31 3.27,-0.58l0.3,1.19c-0.73,0.19 -1.52,0.34 -2.37,0.47 -0.85,0.13 -1.69,0.22 -2.53,0.29v9.83h-1.19v-4.85h-1.75v4.85h-1.19ZM123.47,95.46c-0.23,0 -0.41,-0.07 -0.55,-0.21 -0.14,-0.14 -0.21,-0.32 -0.21,-0.55 0,-0.23 0.07,-0.41 0.21,-0.55 0.14,-0.14 0.32,-0.21 0.55,-0.21s0.41,0.07 0.55,0.21c0.14,0.14 0.21,0.32 0.21,0.55 0,0.23 -0.07,0.41 -0.21,0.55 -0.14,0.14 -0.32,0.21 -0.55,0.21ZM126.73,95.46c-0.23,0 -0.41,-0.07 -0.55,-0.21 -0.14,-0.14 -0.21,-0.32 -0.21,-0.55 0,-0.23 0.07,-0.41 0.21,-0.55 0.14,-0.14 0.32,-0.21 0.55,-0.21s0.41,0.07 0.55,0.21c0.14,0.14 0.21,0.32 0.21,0.55 0,0.23 -0.07,0.41 -0.21,0.55 -0.14,0.14 -0.32,0.21 -0.55,0.21ZM129.99,95.46c-0.23,0 -0.41,-0.07 -0.55,-0.21 -0.14,-0.14 -0.21,-0.32 -0.21,-0.55 0,-0.23 0.07,-0.41 0.21,-0.55 0.14,-0.14 0.32,-0.21 0.55,-0.21s0.41,0.07 0.55,0.21c0.14,0.14 0.21,0.32 0.21,0.55 0,0.23 -0.07,0.41 -0.21,0.55 -0.14,0.14 -0.32,0.21 -0.55,0.21Z"
+      android:fillColor="#fff"/>
+  <path
+      android:pathData="M126.71,121.91h0c8.83,0 15.99,7.16 15.99,15.99h0c0,8.83 -7.16,15.99 -15.99,15.99h0c-8.83,0 -15.99,-7.16 -15.99,-15.99h0c0,-8.83 7.16,-15.99 15.99,-15.99Z"
+      android:fillColor="#327969"/>
+  <path
+      android:pathData="M128.65,146.39v-1.5c1.57,-0.45 2.84,-1.32 3.84,-2.6 0.99,-1.28 1.49,-2.74 1.49,-4.37 0,-1.63 -0.49,-3.09 -1.48,-4.38s-2.27,-2.15 -3.85,-2.59v-1.5c2,0.45 3.63,1.46 4.89,3.04 1.26,1.57 1.89,3.39 1.89,5.43s-0.63,3.86 -1.89,5.43c-1.26,1.57 -2.89,2.59 -4.89,3.04ZM117.99,140.84v-5.81h3.87l4.84,-4.84v15.49l-4.84,-4.84h-3.87ZM128.16,142.01v-8.16c0.89,0.27 1.59,0.79 2.12,1.55 0.52,0.76 0.79,1.61 0.79,2.54 0,0.92 -0.27,1.76 -0.8,2.52s-1.23,1.28 -2.11,1.55ZM125.26,133.87l-2.74,2.61h-3.07v2.91h3.07l2.74,2.64v-8.16Z"
+      android:fillColor="#fff"/>
+  <path
+      android:pathData="M174.71,121.94h0c8.83,0 15.99,7.16 15.99,15.99h0c0,8.83 -7.16,15.99 -15.99,15.99h0c-8.83,0 -15.99,-7.16 -15.99,-15.99h0c0,-8.83 7.16,-15.99 15.99,-15.99Z"
+      android:fillColor="#9f3ebf"/>
+  <path
+      android:pathData="M179.18,131.5h-8.93v12.86h8.93v-12.86Z"
+      android:fillColor="#fff"/>
+  <path
+      android:pathData="M169.05,134.02h-3.22v7.91h3.22v-7.91Z"
+      android:fillColor="#fff"/>
+  <path
+      android:pathData="M183.58,134.02h-3.22v7.91h3.22v-7.91Z"
+      android:fillColor="#fff"/>
+  <path
+      android:pathData="M171.91,133.03h5.61v9.78h-5.61z"
+      android:fillColor="#9f3ebf"/>
+  <path
+      android:pathData="M78.71,121.91h0c8.83,0 15.99,7.16 15.99,15.99h0c0,8.83 -7.16,15.99 -15.99,15.99h0c-8.83,0 -15.99,-7.16 -15.99,-15.99h0c0,-8.83 7.16,-15.99 15.99,-15.99Z"
+      android:fillColor="#327969"/>
+  <path
+      android:pathData="M72.17,140.82v-5.81h3.88l4.84,-4.84v15.5l-4.84,-4.84h-3.88ZM82.34,141.98v-8.16c0.87,0.27 1.57,0.79 2.11,1.55 0.53,0.76 0.8,1.61 0.8,2.54 0,0.95 -0.27,1.8 -0.8,2.54 -0.53,0.74 -1.24,1.25 -2.11,1.53ZM79.43,133.85l-2.74,2.62h-3.08v2.91h3.08l2.74,2.64v-8.16Z"
+      android:fillColor="#fff"/>
+  <path
+      android:pathData="M78.73,96.45l-2.73,-2.73h-4.09c-0.36,0 -0.68,-0.14 -0.95,-0.41 -0.27,-0.27 -0.41,-0.59 -0.41,-0.95v-13.64c0,-0.36 0.14,-0.68 0.41,-0.95 0.27,-0.27 0.59,-0.41 0.95,-0.41h13.64c0.36,0 0.68,0.14 0.95,0.41 0.27,0.27 0.41,0.59 0.41,0.95v13.64c0,0.36 -0.14,0.68 -0.41,0.95 -0.27,0.27 -0.59,0.41 -0.95,0.41h-4.09l-2.73,2.73ZM78.75,89.79l1.27,-2.91 2.91,-1.27 -2.91,-1.27 -1.27,-2.91 -1.3,2.91 -2.89,1.27 2.89,1.27 1.3,2.91Z"
+      android:fillColor="#fff"/>
 </vector>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/a11ymenu_intro.png b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/a11ymenu_intro.png
deleted file mode 100644
index 6149ee4..0000000
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/a11ymenu_intro.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/a11ymenu_intro.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/a11ymenu_intro.xml
new file mode 100644
index 0000000..a5a0535
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/a11ymenu_intro.xml
@@ -0,0 +1,90 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="412dp"
+    android:height="299.24dp"
+    android:viewportWidth="412"
+    android:viewportHeight="299.24">
+  <path
+      android:pathData="M383.9,299.24H28.1c-15.5,0 -28.1,-12.57 -28.1,-28.03V28.03C0,12.57 12.6,0 28.1,0H383.9c15.5,0 28.1,12.57 28.1,28.03v243.18c0,15.46 -12.6,28.03 -28.1,28.03Z"
+      android:fillColor="#fff"/>
+  <path
+      android:pathData="M106.4,0h195.3c2,0 3.6,0.2 3.6,0.4V31.2c0,0.2 -1.6,0.4 -3.6,0.4H106.4c-2,0 -3.6,-0.2 -3.6,-0.4V0.4c0,-0.2 1.6,-0.4 3.6,-0.4Z"
+      android:fillColor="#e8eaed"/>
+  <path
+      android:pathData="M303.7,238.9H104.5v1h98.4v29.5h1v-29.5h99.8v-1Z"
+      android:fillColor="#e8eaed"/>
+  <path
+      android:pathData="M153.7,258.3l0.7,-0.7 -2.7,-2.7h5.9v-1h-5.9l2.7,-2.7 -0.7,-0.7 -3.9,3.9 3.9,3.9Z"
+      android:fillColor="#e8eaed"
+      android:fillType="evenOdd"/>
+  <path
+      android:pathData="M253.5,250.4l-0.7,0.7 2.7,2.7h-5.9v1h5.9l-2.7,2.7 0.7,0.7 3.9,-3.9 -3.9,-3.9Z"
+      android:fillColor="#7f868c"
+      android:fillType="evenOdd"/>
+  <path
+      android:pathData="M119.3,273h169.8c10.2,0 18.5,-8.3 18.5,-18.5V73.7c2,0 3.7,-1.7 3.7,-3.7V33.1c0,-2 -1.7,-3.7 -3.7,-3.7V0h-3.7V254.5c0,8.1 -6.6,14.8 -14.8,14.8H119.3c-8.1,0 -14.8,-6.6 -14.8,-14.8V0h-3.7V254.5c0,10.2 8.3,18.5 18.5,18.5Z"
+      android:fillColor="#dadce0"/>
+  <path
+      android:pathData="M141.86,52.23h0c9.77,0 17.7,7.92 17.7,17.7h0c0,9.77 -7.92,17.7 -17.7,17.7h0c-9.77,0 -17.7,-7.92 -17.7,-17.7h0c0,-9.77 7.92,-17.7 17.7,-17.7Z"
+      android:fillColor="#2197f3"/>
+  <path
+      android:pathData="M270.14,52.23h0c9.77,0 17.7,7.92 17.7,17.7h0c0,9.77 -7.92,17.7 -17.7,17.7h0c-9.77,0 -17.7,-7.92 -17.7,-17.7h0c0,-9.77 7.92,-17.7 17.7,-17.7Z"
+      android:fillColor="#80868b"/>
+  <path
+      android:pathData="M269.25,62.01h1.77v8.74h-1.77v-8.74ZM274.01,65.22l1.22,-1.22c1.66,1.44 2.76,3.54 2.76,5.97 0,4.31 -3.54,7.85 -7.85,7.85s-7.85,-3.54 -7.85,-7.85c0,-2.43 1.11,-4.53 2.76,-5.97l1.22,1.22c-1.33,1.11 -2.21,2.88 -2.21,4.76 0,3.43 2.76,6.19 6.19,6.19 3.43,0 6.19,-2.76 6.19,-6.19 -0.11,-1.99 -1.11,-3.65 -2.43,-4.76Z"
+      android:fillColor="#fff"
+      android:fillType="evenOdd"/>
+  <path
+      android:pathData="M207.03,52.23h0c9.77,0 17.7,7.92 17.7,17.7h0c0,9.77 -7.92,17.7 -17.7,17.7h0c-9.77,0 -17.7,-7.92 -17.7,-17.7h0c0,-9.77 7.92,-17.7 17.7,-17.7Z"
+      android:fillColor="#521bbf"/>
+  <path
+      android:pathData="M207.03,62.6c-0.44,0 -0.81,-0.16 -1.13,-0.47 -0.31,-0.31 -0.47,-0.69 -0.47,-1.13s0.16,-0.81 0.47,-1.13c0.31,-0.31 0.69,-0.47 1.13,-0.47s0.81,0.16 1.13,0.47c0.31,0.31 0.47,0.69 0.47,1.13s-0.16,0.81 -0.47,1.13 -0.69,0.47 -1.13,0.47ZM204.75,76.06v-10.83c-0.92,-0.07 -1.85,-0.18 -2.78,-0.32 -0.94,-0.14 -1.8,-0.31 -2.61,-0.52l0.33,-1.31c1.17,0.29 2.37,0.5 3.61,0.64 1.23,0.13 2.48,0.2 3.74,0.2s2.5,-0.07 3.74,-0.2c1.23,-0.13 2.44,-0.34 3.61,-0.64l0.33,1.31c-0.8,0.2 -1.67,0.38 -2.61,0.52 -0.94,0.14 -1.86,0.24 -2.78,0.32v10.83h-1.31v-5.35h-1.93v5.35h-1.31ZM203.45,80.44c-0.25,0 -0.45,-0.08 -0.6,-0.23 -0.15,-0.15 -0.23,-0.35 -0.23,-0.6 0,-0.25 0.08,-0.45 0.23,-0.6 0.15,-0.15 0.35,-0.23 0.6,-0.23s0.45,0.08 0.6,0.23c0.15,0.15 0.23,0.35 0.23,0.6 0,0.25 -0.08,0.45 -0.23,0.6 -0.15,0.15 -0.35,0.23 -0.6,0.23ZM207.05,80.44c-0.25,0 -0.45,-0.08 -0.6,-0.23 -0.15,-0.15 -0.23,-0.35 -0.23,-0.6 0,-0.25 0.08,-0.45 0.23,-0.6 0.15,-0.15 0.35,-0.23 0.6,-0.23s0.45,0.08 0.6,0.23c0.15,0.15 0.23,0.35 0.23,0.6 0,0.25 -0.08,0.45 -0.23,0.6 -0.15,0.15 -0.35,0.23 -0.6,0.23ZM210.64,80.44c-0.25,0 -0.45,-0.08 -0.6,-0.23 -0.15,-0.15 -0.23,-0.35 -0.23,-0.6 0,-0.25 0.08,-0.45 0.23,-0.6 0.15,-0.15 0.35,-0.23 0.6,-0.23s0.45,0.08 0.6,0.23c0.15,0.15 0.23,0.35 0.23,0.6 0,0.25 -0.08,0.45 -0.23,0.6 -0.15,0.15 -0.35,0.23 -0.6,0.23Z"
+      android:fillColor="#fff"/>
+  <path
+      android:pathData="M141.86,180.81h0c9.77,0 17.7,7.92 17.7,17.7h0c0,9.77 -7.92,17.7 -17.7,17.7h0c-9.77,0 -17.7,-7.92 -17.7,-17.7h0c0,-9.77 7.92,-17.7 17.7,-17.7Z"
+      android:fillColor="#de9834"/>
+  <path
+      android:pathData="M141.88,209.09l-3.16,-3.06h-4.35v-4.35l-3.13,-3.13 3.13,-3.13v-4.35h4.35l3.16,-3.13 3.11,3.13h4.35v4.35l3.13,3.13 -3.13,3.13v4.35h-4.35l-3.11,3.06ZM141.88,203.08c-1.26,0 -2.34,-0.44 -3.23,-1.33 -0.89,-0.89 -1.33,-1.96 -1.33,-3.23s0.44,-2.34 1.33,-3.23c0.89,-0.89 1.96,-1.33 3.23,-1.33 1.26,0 2.34,0.44 3.23,1.33 0.89,0.89 1.33,1.96 1.33,3.23s-0.44,2.34 -1.33,3.23c-0.89,0.89 -1.96,1.33 -3.23,1.33ZM141.88,201.68c0.89,0 1.64,-0.3 2.24,-0.91 0.61,-0.61 0.91,-1.36 0.91,-2.24 -0,-0.89 -0.3,-1.64 -0.91,-2.24 -0.61,-0.61 -1.36,-0.91 -2.24,-0.91 -0.89,0 -1.64,0.3 -2.24,0.91 -0.61,0.61 -0.91,1.36 -0.91,2.24s0.3,1.64 0.91,2.24c0.61,0.61 1.36,0.91 2.24,0.91ZM141.88,207.12l2.53,-2.5h3.53v-3.53l2.55,-2.55 -2.55,-2.55v-3.53h-3.53l-2.53,-2.55 -2.57,2.55h-3.53v3.53l-2.55,2.55 2.55,2.55v3.53h3.51l2.6,2.5Z"
+      android:fillColor="#fff"/>
+  <path
+      android:pathData="M207.03,180.82h0c9.77,0 17.7,7.92 17.7,17.7h0c0,9.77 -7.92,17.7 -17.7,17.7h0c-9.77,0 -17.7,-7.92 -17.7,-17.7h0c0,-9.77 7.92,-17.7 17.7,-17.7Z"
+      android:fillColor="#de9834"/>
+  <path
+      android:pathData="M207.05,209.09l-3.16,-3.06h-4.35v-4.35l-3.13,-3.13 3.13,-3.13v-4.35h4.35l3.16,-3.13 3.11,3.13h4.35v4.35l3.13,3.13 -3.13,3.13v4.35h-4.35l-3.11,3.06ZM207.05,203.08c1.26,0 2.34,-0.44 3.23,-1.33 0.89,-0.89 1.33,-1.96 1.33,-3.23s-0.44,-2.34 -1.33,-3.23c-0.89,-0.89 -1.96,-1.33 -3.23,-1.33 -1.26,0 -2.34,0.44 -3.23,1.33 -0.89,0.89 -1.33,1.96 -1.33,3.23s0.44,2.34 1.33,3.23c0.89,0.89 1.96,1.33 3.23,1.33ZM207.05,201.68c0.89,0 1.64,-0.3 2.24,-0.91 0.61,-0.61 0.91,-1.36 0.91,-2.24 -0,-0.89 -0.3,-1.64 -0.91,-2.24 -0.61,-0.61 -1.36,-0.91 -2.24,-0.91 -0.89,0 -1.64,0.3 -2.24,0.91 -0.61,0.61 -0.91,1.36 -0.91,2.24s0.3,1.64 0.91,2.24c0.61,0.61 1.36,0.91 2.24,0.91ZM207.05,207.13l2.53,-2.5h3.53v-3.53l2.55,-2.55 -2.55,-2.55v-3.53h-3.53l-2.53,-2.55 -2.57,2.55h-3.53v3.53l-2.55,2.55 2.55,2.55v3.53h3.51l2.6,2.5ZM207.05,201.68c0.89,0 1.64,-0.3 2.24,-0.91 0.61,-0.61 0.91,-1.36 0.91,-2.24 -0,-0.89 -0.3,-1.64 -0.91,-2.24 -0.61,-0.61 -1.36,-0.91 -2.24,-0.91 -0.89,0 -1.64,0.3 -2.24,0.91 -0.61,0.61 -0.91,1.36 -0.91,2.24s0.3,1.64 0.91,2.24c0.61,0.61 1.36,0.91 2.24,0.91Z"
+      android:fillColor="#fff"/>
+  <path
+      android:pathData="M270.14,180.81h0c9.77,0 17.7,7.92 17.7,17.7h0c0,9.77 -7.92,17.7 -17.7,17.7h0c-9.77,0 -17.7,-7.92 -17.7,-17.7h0c0,-9.77 7.92,-17.7 17.7,-17.7Z"
+      android:fillColor="#438947"/>
+  <path
+      android:pathData="M263.92,207.44c-0.4,0 -0.74,-0.14 -1.02,-0.42s-0.42,-0.62 -0.42,-1.02v-10.37c0,-0.4 0.14,-0.74 0.42,-1.02s0.62,-0.42 1.02,-0.42h1.67v-2.29c0,-1.26 0.44,-2.33 1.33,-3.22 0.88,-0.88 1.96,-1.33 3.22,-1.33s2.33,0.44 3.22,1.33c0.88,0.88 1.33,1.96 1.33,3.22v2.29h1.67c0.4,0 0.74,0.14 1.02,0.42s0.42,0.62 0.42,1.02v10.37c0,0.4 -0.14,0.74 -0.42,1.02s-0.62,0.42 -1.02,0.42h-12.43ZM263.92,206.01h12.43v-10.37h-12.43v10.37ZM270.14,202.66c0.51,0 0.94,-0.18 1.3,-0.53s0.54,-0.77 0.54,-1.27c0,-0.48 -0.18,-0.91 -0.54,-1.3s-0.79,-0.59 -1.3,-0.59 -0.94,0.2 -1.3,0.59c-0.36,0.39 -0.54,0.82 -0.54,1.3 0,0.49 0.18,0.92 0.54,1.27s0.79,0.53 1.3,0.53ZM267.03,194.2h6.22v-2.29c0,-0.86 -0.3,-1.59 -0.91,-2.2 -0.61,-0.61 -1.34,-0.91 -2.2,-0.91s-1.59,0.3 -2.2,0.91 -0.91,1.34 -0.91,2.2v2.29ZM263.92,206.01v0Z"
+      android:fillColor="#fff"/>
+  <path
+      android:pathData="M207.03,116.5h0c9.77,0 17.7,7.92 17.7,17.7h0c0,9.77 -7.92,17.7 -17.7,17.7h0c-9.77,0 -17.7,-7.92 -17.7,-17.7h0c0,-9.77 7.92,-17.7 17.7,-17.7Z"
+      android:fillColor="#327969"/>
+  <path
+      android:pathData="M209.17,143.6v-1.66c1.73,-0.5 3.15,-1.46 4.25,-2.88 1.1,-1.42 1.65,-3.03 1.65,-4.84 0,-1.8 -0.54,-3.42 -1.63,-4.85s-2.51,-2.38 -4.26,-2.87v-1.66c2.22,0.5 4.02,1.62 5.41,3.36 1.39,1.74 2.09,3.75 2.09,6.02s-0.7,4.27 -2.09,6.02c-1.39,1.74 -3.2,2.86 -5.41,3.36ZM197.38,137.46v-6.43h4.29l5.36,-5.36v17.15l-5.36,-5.36h-4.29ZM208.63,138.75v-9.03c0.98,0.3 1.76,0.88 2.34,1.71 0.58,0.84 0.87,1.78 0.87,2.81 0,1.02 -0.29,1.95 -0.88,2.79s-1.37,1.41 -2.33,1.71ZM205.42,129.75l-3.03,2.89h-3.4v3.22h3.4l3.03,2.92v-9.03Z"
+      android:fillColor="#fff"/>
+  <path
+      android:pathData="M270.14,116.54h0c9.77,0 17.7,7.92 17.7,17.7h0c0,9.77 -7.92,17.7 -17.7,17.7h0c-9.77,0 -17.7,-7.92 -17.7,-17.7h0c0,-9.77 7.92,-17.7 17.7,-17.7Z"
+      android:fillColor="#9f3ebf"/>
+  <path
+      android:pathData="M275.08,127.12h-9.89v14.23h9.89v-14.23Z"
+      android:fillColor="#fff"/>
+  <path
+      android:pathData="M263.88,129.91h-3.56v8.76h3.56v-8.76Z"
+      android:fillColor="#fff"/>
+  <path
+      android:pathData="M279.96,129.91h-3.56v8.76h3.56v-8.76Z"
+      android:fillColor="#fff"/>
+  <path
+      android:pathData="M267.04,128.82h6.21v10.83h-6.21z"
+      android:fillColor="#9f3ebf"/>
+  <path
+      android:pathData="M141.86,116.5h0c9.77,0 17.7,7.92 17.7,17.7h0c0,9.77 -7.92,17.7 -17.7,17.7h0c-9.77,0 -17.7,-7.92 -17.7,-17.7h0c0,-9.77 7.92,-17.7 17.7,-17.7Z"
+      android:fillColor="#327969"/>
+  <path
+      android:pathData="M134.62,137.44v-6.43h4.29l5.36,-5.36v17.16l-5.36,-5.36h-4.29ZM145.88,138.73v-9.03c0.97,0.3 1.74,0.88 2.33,1.72 0.59,0.84 0.88,1.78 0.88,2.81 0,1.05 -0.29,1.99 -0.88,2.81s-1.37,1.39 -2.33,1.69ZM142.66,129.72l-3.03,2.9h-3.4v3.22h3.4l3.03,2.92v-9.03Z"
+      android:fillColor="#fff"/>
+  <path
+      android:pathData="M141.86,81.15l-2.93,-2.93h-4.39c-0.39,0 -0.73,-0.15 -1.02,-0.44 -0.29,-0.29 -0.44,-0.63 -0.44,-1.02v-14.63c0,-0.39 0.15,-0.73 0.44,-1.02 0.29,-0.29 0.63,-0.44 1.02,-0.44h14.63c0.39,0 0.73,0.15 1.02,0.44 0.29,0.29 0.44,0.63 0.44,1.02v14.63c0,0.39 -0.15,0.73 -0.44,1.02 -0.29,0.29 -0.63,0.44 -1.02,0.44h-4.39l-2.93,2.93ZM141.88,74l1.37,-3.12 3.12,-1.37 -3.12,-1.37 -1.37,-3.12 -1.39,3.12 -3.1,1.37 3.1,1.37 1.39,3.12Z"
+      android:fillColor="#fff"/>
+</vector>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_assistant_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_assistant_24dp.xml
new file mode 100644
index 0000000..9c3417f
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_assistant_24dp.xml
@@ -0,0 +1,10 @@
+<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="@color/colorControlNormal">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M19,2L5,2c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h4l3,3 3,-3h4c1.1,0 2,-0.9 2,-2L21,4c0,-1.1 -0.9,-2 -2,-2zM13.88,12.88L12,17l-1.88,-4.12L6,11l4.12,-1.88L12,5l1.88,4.12L18,11l-4.12,1.88z"/>
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_assistant_32dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_assistant_32dp.xml
deleted file mode 100644
index ebeebf8..0000000
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_assistant_32dp.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<vector android:height="32dp"
-    android:viewportHeight="192.0" android:viewportWidth="192.0"
-    android:width="32dp" xmlns:android="http://schemas.android.com/apk/res/android">
-    <path android:fillColor="#34A853" android:pathData="M172,60m-12,0a12,12 0,1 1,24 0a12,12 0,1 1,-24 0"/>
-    <path android:fillColor="#EA4335" android:pathData="M136,88m-24,0a24,24 0,1 1,48 0a24,24 0,1 1,-48 0"/>
-    <path android:fillColor="#FBBC05" android:pathData="M136,148m-28,0a28,28 0,1 1,56 0a28,28 0,1 1,-56 0"/>
-    <path android:fillColor="#4285F4" android:pathData="M56,64m-48,0a48,48 0,1 1,96 0a48,48 0,1 1,-96 0"/>
-</vector>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_item.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_item.xml
index 39e5a8c..a902c5b 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_item.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_item.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/shortcutItem"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:paddingTop="@dimen/grid_item_padding"
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-night/colors.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-night/colors.xml
index a600ec6..fbf2b07 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-night/colors.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-night/colors.xml
@@ -9,7 +9,7 @@
   <color name="volume_color">#7ae3d4</color>
   <color name="notifications_color">#f496ac</color>
   <color name="screenshot_color">#adcbff</color>
-  <color name="assistant_color">#F1F3F4</color>
+  <color name="assistant_color">#adcbff</color>
   <color name="brightness_color">#fdd663</color>
 
   <color name="ripple_material_color">#10FFFFFF</color>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values/colors.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values/colors.xml
index c1494f9..d81d0d5 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values/colors.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values/colors.xml
@@ -9,7 +9,7 @@
   <color name="volume_color">#01A2A0</color>
   <color name="notifications_color">#F15B8D</color>
   <color name="screenshot_color">#26459C</color>
-  <color name="assistant_color">#F1F3F4</color>
+  <color name="assistant_color">#2196F3</color>
   <color name="brightness_color">#E59810</color>
   <color name="colorAccent">#1a73e8</color>
 
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values/strings.xml
index 30fd017..0747ef0 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values/strings.xml
@@ -10,7 +10,7 @@
   <!-- String defining the label for the assistant button -->
   <string name="assistant_label">Assistant</string>
   <!-- String defining utterance for the assistant button for screen readers -->
-  <string name="assistant_utterance">Google Assistant</string>
+  <string name="assistant_utterance">Assistant</string>
   <!-- String defining the label for the accessibility settings button -->
   <string name="a11y_settings_label">Accessibility Settings</string>
   <!-- String defining the label for the volume button -->
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java
index c1f2aa8..96ea5b4 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.accessibility.accessibilitymenu;
 
+import android.Manifest;
 import android.accessibilityservice.AccessibilityButtonController;
 import android.accessibilityservice.AccessibilityService;
 import android.content.BroadcastReceiver;
@@ -34,6 +35,7 @@
 import android.os.Looper;
 import android.os.SystemClock;
 import android.provider.Settings;
+import android.util.Log;
 import android.view.Display;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -51,8 +53,14 @@
 /** @hide */
 public class AccessibilityMenuService extends AccessibilityService
         implements View.OnTouchListener {
-    private static final String TAG = "A11yMenuService";
 
+    public static final String PACKAGE_NAME = AccessibilityMenuService.class.getPackageName();
+    public static final String INTENT_TOGGLE_MENU = ".toggle_menu";
+    public static final String INTENT_HIDE_MENU = ".hide_menu";
+    public static final String INTENT_GLOBAL_ACTION = ".global_action";
+    public static final String INTENT_GLOBAL_ACTION_EXTRA = "GLOBAL_ACTION";
+
+    private static final String TAG = "A11yMenuService";
     private static final long BUFFER_MILLISECONDS_TO_PREVENT_UPDATE_FAILURE = 100L;
 
     private static final int BRIGHTNESS_UP_INCREMENT_GAMMA =
@@ -74,7 +82,8 @@
 
     // TODO(b/136716947): Support multi-display once a11y framework side is ready.
     private DisplayManager mDisplayManager;
-    final DisplayManager.DisplayListener mDisplayListener = new DisplayManager.DisplayListener() {
+    private final DisplayManager.DisplayListener mDisplayListener =
+            new DisplayManager.DisplayListener() {
         int mRotation;
 
         @Override
@@ -95,13 +104,20 @@
         }
     };
 
-    final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+    private final BroadcastReceiver mHideMenuReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
             mA11yMenuLayout.hideMenu();
         }
     };
 
+    private final BroadcastReceiver mToggleMenuReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            mA11yMenuLayout.toggleVisibility();
+        }
+    };
+
     /**
      * Update a11y menu layout when large button setting is changed.
      */
@@ -172,7 +188,19 @@
     protected void onServiceConnected() {
         mA11yMenuLayout = new A11yMenuOverlayLayout(this);
 
-        registerReceiver(mBroadcastReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
+        IntentFilter hideMenuFilter = new IntentFilter();
+        hideMenuFilter.addAction(Intent.ACTION_SCREEN_OFF);
+        hideMenuFilter.addAction(PACKAGE_NAME + INTENT_HIDE_MENU);
+
+        // Including WRITE_SECURE_SETTINGS enforces that we only listen to apps
+        // with the restricted WRITE_SECURE_SETTINGS permission who broadcast this intent.
+        registerReceiver(mHideMenuReceiver, hideMenuFilter,
+                Manifest.permission.WRITE_SECURE_SETTINGS, null,
+                Context.RECEIVER_EXPORTED);
+        registerReceiver(mToggleMenuReceiver,
+                new IntentFilter(PACKAGE_NAME + INTENT_TOGGLE_MENU),
+                Manifest.permission.WRITE_SECURE_SETTINGS, null,
+                Context.RECEIVER_EXPORTED);
 
         mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
         mPrefs.registerOnSharedPreferenceChangeListener(mSharedPreferenceChangeListener);
@@ -206,6 +234,22 @@
     }
 
     /**
+     * Performs global action and broadcasts an intent indicating the action was performed.
+     * This is unnecessary for any current functionality, but is used for testing.
+     * Refer to {@code performGlobalAction()}.
+     *
+     * @param globalAction Global action to be performed.
+     * @return {@code true} if successful, {@code false} otherwise.
+     */
+    private boolean performGlobalActionInternal(int globalAction) {
+        Intent intent = new Intent(PACKAGE_NAME + INTENT_GLOBAL_ACTION);
+        intent.putExtra(INTENT_GLOBAL_ACTION_EXTRA, globalAction);
+        sendBroadcast(intent);
+        Log.i("A11yMenuService", "Broadcasting global action " + globalAction);
+        return performGlobalAction(globalAction);
+    }
+
+    /**
      * Handles click events of shortcuts.
      *
      * @param view the shortcut button being clicked.
@@ -224,17 +268,17 @@
                     new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS),
                     Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
         } else if (viewTag == ShortcutId.ID_POWER_VALUE.ordinal()) {
-            performGlobalAction(GLOBAL_ACTION_POWER_DIALOG);
+            performGlobalActionInternal(GLOBAL_ACTION_POWER_DIALOG);
         } else if (viewTag == ShortcutId.ID_RECENT_VALUE.ordinal()) {
-            performGlobalAction(GLOBAL_ACTION_RECENTS);
+            performGlobalActionInternal(GLOBAL_ACTION_RECENTS);
         } else if (viewTag == ShortcutId.ID_LOCKSCREEN_VALUE.ordinal()) {
-            performGlobalAction(GLOBAL_ACTION_LOCK_SCREEN);
+            performGlobalActionInternal(GLOBAL_ACTION_LOCK_SCREEN);
         } else if (viewTag == ShortcutId.ID_QUICKSETTING_VALUE.ordinal()) {
-            performGlobalAction(GLOBAL_ACTION_QUICK_SETTINGS);
+            performGlobalActionInternal(GLOBAL_ACTION_QUICK_SETTINGS);
         } else if (viewTag == ShortcutId.ID_NOTIFICATION_VALUE.ordinal()) {
-            performGlobalAction(GLOBAL_ACTION_NOTIFICATIONS);
+            performGlobalActionInternal(GLOBAL_ACTION_NOTIFICATIONS);
         } else if (viewTag == ShortcutId.ID_SCREENSHOT_VALUE.ordinal()) {
-            performGlobalAction(GLOBAL_ACTION_TAKE_SCREENSHOT);
+            performGlobalActionInternal(GLOBAL_ACTION_TAKE_SCREENSHOT);
         } else if (viewTag == ShortcutId.ID_BRIGHTNESS_UP_VALUE.ordinal()) {
             adjustBrightness(BRIGHTNESS_UP_INCREMENT_GAMMA);
             return;
@@ -260,7 +304,8 @@
      * @param increment The increment amount in gamma-space
      */
     private void adjustBrightness(int increment) {
-        BrightnessInfo info = getDisplay().getBrightnessInfo();
+        Display display = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
+        BrightnessInfo info = display.getBrightnessInfo();
         int gamma = BrightnessUtils.convertLinearToGammaFloat(
                 info.brightness,
                 info.brightnessMinimum,
@@ -275,7 +320,7 @@
                 info.brightnessMinimum,
                 info.brightnessMaximum
         );
-        mDisplayManager.setBrightness(getDisplayId(), brightness);
+        mDisplayManager.setBrightness(display.getDisplayId(), brightness);
         mA11yMenuLayout.showSnackbar(
                 getString(R.string.brightness_percentage_label,
                         (gamma / (BrightnessUtils.GAMMA_SPACE_MAX / 100))));
@@ -310,7 +355,8 @@
 
     @Override
     public boolean onUnbind(Intent intent) {
-        unregisterReceiver(mBroadcastReceiver);
+        unregisterReceiver(mHideMenuReceiver);
+        unregisterReceiver(mToggleMenuReceiver);
         mPrefs.unregisterOnSharedPreferenceChangeListener(mSharedPreferenceChangeListener);
         sInitialized = false;
         return super.onUnbind(intent);
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/model/A11yMenuShortcut.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/model/A11yMenuShortcut.java
index b6328f0..66a2fae 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/model/A11yMenuShortcut.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/model/A11yMenuShortcut.java
@@ -54,7 +54,7 @@
     /** Map stores all shortcut resource IDs that is in matching order of defined shortcut. */
     private static final Map<ShortcutId, int[]> sShortcutResource = new HashMap<>() {{
             put(ShortcutId.ID_ASSISTANT_VALUE, new int[] {
-                    R.drawable.ic_logo_assistant_32dp,
+                    R.drawable.ic_logo_a11y_assistant_24dp,
                     R.color.assistant_color,
                     R.string.assistant_utterance,
                     R.string.assistant_label,
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java
index 6f0fe37..6ae65cb 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java
@@ -21,6 +21,7 @@
 import android.view.TouchDelegate;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.BaseAdapter;
 import android.widget.ImageButton;
 import android.widget.TextView;
@@ -146,6 +147,15 @@
 
             shortcutIconButton.setBackground(
                     mShortcutDrawableUtils.createAdaptiveIconDrawable(shortcutItem.imageColor));
+
+            shortcutIconButton.setAccessibilityDelegate(new View.AccessibilityDelegate() {
+                @Override
+                public void onInitializeAccessibilityNodeInfo(
+                        View host, AccessibilityNodeInfo info) {
+                    super.onInitializeAccessibilityNodeInfo(host, info);
+                    info.setUniqueId(host.getTag().toString());
+                }
+            });
         }
     }
 }
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp b/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp
new file mode 100644
index 0000000..1757dda
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp
@@ -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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test {
+    name: "AccessibilityMenuServiceTests",
+    certificate: "platform",
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    static_libs: [
+        "androidx.test.core",
+        "androidx.test.runner",
+        "androidx.test.ext.junit",
+        "compatibility-device-util-axt",
+        "platform-test-annotations",
+        "truth-prebuilt",
+    ],
+    srcs: [
+        "src/**/*.java",
+        ":AccessibilityMenuSource",
+    ],
+    platform_apis: true,
+    test_suites: ["device-tests"],
+    instrumentation_for: "AccessibilityMenu",
+}
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/tests/AndroidManifest.xml b/packages/SystemUI/accessibility/accessibilitymenu/tests/AndroidManifest.xml
new file mode 100644
index 0000000..2be9245
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/tests/AndroidManifest.xml
@@ -0,0 +1,43 @@
+<?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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    package="com.android.systemui.accessibility.accessibilitymenu.tests">
+
+    <!-- Needed to write to Settings.Secure to enable and disable the service under test. -->
+    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+    <uses-permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS"/>
+
+    <application android:debuggable="true">
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.systemui.accessibility.accessibilitymenu.tests"
+        android:label="AccessibilityMenu Test Cases">
+    </instrumentation>
+
+    <queries>
+        <intent>
+            <action android:name="android.intent.action.VIEW" />
+            <category android:name="android.intent.category.BROWSABLE" />
+            <data android:scheme="https" />
+        </intent>
+        <intent>
+            <action android:name="android.intent.action.VOICE_COMMAND" />
+        </intent>
+    </queries>
+</manifest>
\ No newline at end of file
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/tests/AndroidTest.xml b/packages/SystemUI/accessibility/accessibilitymenu/tests/AndroidTest.xml
new file mode 100644
index 0000000..39bee53
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/tests/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<configuration description="Runs AccessibilityMenu Test Cases.">
+    <option name="test-tag" value="AccessibilityMenuServiceTests" />
+
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="AccessibilityMenuServiceTests.apk" />
+        <option name="aapt-version" value="AAPT2" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="com.android.systemui.accessibility.accessibilitymenu.tests" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/tests/TEST_MAPPING b/packages/SystemUI/accessibility/accessibilitymenu/tests/TEST_MAPPING
new file mode 100644
index 0000000..2bd52b5
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/tests/TEST_MAPPING
@@ -0,0 +1,15 @@
+{
+  "presubmit": [
+    {
+      "name": "AccessibilityMenuServiceTests",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java b/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java
new file mode 100644
index 0000000..0e89dcd
--- /dev/null
+++ b/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java
@@ -0,0 +1,378 @@
+/*
+ * 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.accessibilitymenu.tests;
+
+import static android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_LOCK_SCREEN;
+import static android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS;
+import static android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_POWER_DIALOG;
+import static android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS;
+import static android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_RECENTS;
+import static android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT;
+
+import static com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService.INTENT_GLOBAL_ACTION;
+import static com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService.INTENT_GLOBAL_ACTION_EXTRA;
+import static com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService.INTENT_HIDE_MENU;
+import static com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService.INTENT_TOGGLE_MENU;
+import static com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService.PACKAGE_NAME;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.app.Instrumentation;
+import android.app.UiAutomation;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.display.BrightnessInfo;
+import android.hardware.display.DisplayManager;
+import android.media.AudioManager;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.TestUtils;
+import com.android.systemui.accessibility.accessibilitymenu.model.A11yMenuShortcut.ShortcutId;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+@RunWith(AndroidJUnit4.class)
+public class AccessibilityMenuServiceTest {
+    private static final String TAG = "A11yMenuServiceTest";
+    private static final int CLICK_ID = AccessibilityNodeInfo.ACTION_CLICK;
+
+    private static final int TIMEOUT_SERVICE_STATUS_CHANGE_S = 5;
+    private static final int TIMEOUT_UI_CHANGE_S = 10;
+    private static final int NO_GLOBAL_ACTION = -1;
+    private static final String INPUT_KEYEVENT_KEYCODE_BACK = "input keyevent KEYCODE_BACK";
+
+    private static Instrumentation sInstrumentation;
+    private static UiAutomation sUiAutomation;
+    private static AtomicInteger sLastGlobalAction;
+
+    private static AccessibilityManager sAccessibilityManager;
+
+    @BeforeClass
+    public static void classSetup() throws Throwable {
+        final String serviceName = PACKAGE_NAME + "/.AccessibilityMenuService";
+        sInstrumentation = InstrumentationRegistry.getInstrumentation();
+        sUiAutomation = sInstrumentation.getUiAutomation(
+                UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES);
+        final Context context = sInstrumentation.getTargetContext();
+        sAccessibilityManager = context.getSystemService(AccessibilityManager.class);
+
+        // Disable all a11yServices if any are active.
+        if (!sAccessibilityManager.getEnabledAccessibilityServiceList(
+                AccessibilityServiceInfo.FEEDBACK_ALL_MASK).isEmpty()) {
+            Settings.Secure.putString(context.getContentResolver(),
+                    Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, "");
+            TestUtils.waitUntil("Failed to disable all services",
+                    TIMEOUT_SERVICE_STATUS_CHANGE_S,
+                    () -> sAccessibilityManager.getEnabledAccessibilityServiceList(
+                            AccessibilityServiceInfo.FEEDBACK_ALL_MASK).isEmpty());
+        }
+
+        // Enable a11yMenu service.
+        Settings.Secure.putString(context.getContentResolver(),
+                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, serviceName);
+
+        TestUtils.waitUntil("Failed to enable service",
+                TIMEOUT_SERVICE_STATUS_CHANGE_S,
+                () -> sAccessibilityManager.getEnabledAccessibilityServiceList(
+                        AccessibilityServiceInfo.FEEDBACK_ALL_MASK).stream().filter(
+                                info -> info.getId().contains(serviceName)).count() == 1);
+
+        sLastGlobalAction = new AtomicInteger(NO_GLOBAL_ACTION);
+        context.registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                Log.i(TAG, "Received global action intent.");
+                sLastGlobalAction.set(
+                        intent.getIntExtra(INTENT_GLOBAL_ACTION_EXTRA, NO_GLOBAL_ACTION));
+            }},
+                new IntentFilter(PACKAGE_NAME + INTENT_GLOBAL_ACTION),
+                null, null, Context.RECEIVER_EXPORTED);
+    }
+
+    @AfterClass
+    public static void classTeardown() throws Throwable {
+        Settings.Secure.putString(sInstrumentation.getTargetContext().getContentResolver(),
+                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, "");
+    }
+
+    @Before
+    public void setup() throws Throwable {
+        openMenu();
+    }
+
+    @After
+    public void tearDown() throws Throwable {
+        closeMenu();
+        sLastGlobalAction.set(NO_GLOBAL_ACTION);
+    }
+
+    private static boolean isMenuVisible() {
+        AccessibilityNodeInfo root = sUiAutomation.getRootInActiveWindow();
+        return root != null && root.getPackageName().toString().equals(PACKAGE_NAME);
+    }
+
+    private static void openMenu() throws Throwable {
+        Intent intent = new Intent(PACKAGE_NAME + INTENT_TOGGLE_MENU);
+        sInstrumentation.getContext().sendBroadcast(intent);
+
+        TestUtils.waitUntil("Timed out before menu could appear.",
+                TIMEOUT_UI_CHANGE_S,
+                () -> {
+                    if (isMenuVisible()) {
+                        return true;
+                    } else {
+                        sInstrumentation.getContext().sendBroadcast(intent);
+                        return false;
+                    }
+                });
+    }
+
+    private static void closeMenu() throws Throwable {
+        if (!isMenuVisible()) {
+            return;
+        }
+        Intent intent = new Intent(PACKAGE_NAME + INTENT_HIDE_MENU);
+        sInstrumentation.getContext().sendBroadcast(intent);
+        TestUtils.waitUntil("Timed out before menu could close.",
+                TIMEOUT_UI_CHANGE_S, () -> !isMenuVisible());
+    }
+
+    /**
+     * Provides list of all present shortcut buttons.
+     * @return List of shortcut buttons.
+     */
+    private List<AccessibilityNodeInfo> getGridButtonList() {
+        return sUiAutomation.getRootInActiveWindow()
+                        .findAccessibilityNodeInfosByViewId(PACKAGE_NAME + ":id/shortcutIconBtn");
+    }
+
+    /**
+     * Returns the first button whose uniqueID matches the provided text.
+     * @param buttons List of buttons.
+     * @param text Text to match button's uniqueID to.
+     * @return Button whose uniqueID matches text, {@code null} otherwise.
+     */
+    private AccessibilityNodeInfo findGridButtonInfo(
+            List<AccessibilityNodeInfo> buttons, String text) {
+        for (AccessibilityNodeInfo button: buttons) {
+            if (button.getUniqueId().equals(text)) {
+                return button;
+            }
+        }
+        return null;
+    }
+
+    @Test
+    public void testAdjustBrightness() throws Throwable {
+        Context context = sInstrumentation.getTargetContext();
+        DisplayManager displayManager = context.getSystemService(
+                DisplayManager.class);
+        float resetBrightness = displayManager.getBrightness(context.getDisplayId());
+
+        List<AccessibilityNodeInfo> buttons = getGridButtonList();
+        AccessibilityNodeInfo brightnessUpButton = findGridButtonInfo(buttons,
+                String.valueOf(ShortcutId.ID_BRIGHTNESS_UP_VALUE.ordinal()));
+        AccessibilityNodeInfo brightnessDownButton = findGridButtonInfo(buttons,
+                String.valueOf(ShortcutId.ID_BRIGHTNESS_DOWN_VALUE.ordinal()));
+
+        BrightnessInfo brightnessInfo = displayManager.getDisplay(
+                context.getDisplayId()).getBrightnessInfo();
+
+        try {
+            displayManager.setBrightness(context.getDisplayId(), brightnessInfo.brightnessMinimum);
+            TestUtils.waitUntil("Could not change to minimum brightness",
+                    TIMEOUT_UI_CHANGE_S,
+                    () -> displayManager.getBrightness(context.getDisplayId())
+                            == brightnessInfo.brightnessMinimum);
+            brightnessUpButton.performAction(CLICK_ID);
+            TestUtils.waitUntil("Did not detect an increase in brightness.",
+                    TIMEOUT_UI_CHANGE_S,
+                    () -> displayManager.getBrightness(context.getDisplayId())
+                            > brightnessInfo.brightnessMinimum);
+
+            displayManager.setBrightness(context.getDisplayId(), brightnessInfo.brightnessMaximum);
+            TestUtils.waitUntil("Could not change to maximum brightness",
+                    TIMEOUT_UI_CHANGE_S,
+                    () -> displayManager.getBrightness(context.getDisplayId())
+                            == brightnessInfo.brightnessMaximum);
+            brightnessDownButton.performAction(CLICK_ID);
+            TestUtils.waitUntil("Did not detect a decrease in brightness.",
+                    TIMEOUT_UI_CHANGE_S,
+                    () -> displayManager.getBrightness(context.getDisplayId())
+                            < brightnessInfo.brightnessMaximum);
+        } finally {
+            displayManager.setBrightness(context.getDisplayId(), resetBrightness);
+        }
+    }
+
+    @Test
+    public void testAdjustVolume() throws Throwable {
+        Context context = sInstrumentation.getTargetContext();
+        AudioManager audioManager = context.getSystemService(AudioManager.class);
+        int resetVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
+
+        List<AccessibilityNodeInfo> buttons = getGridButtonList();
+        AccessibilityNodeInfo volumeUpButton = findGridButtonInfo(buttons,
+                String.valueOf(ShortcutId.ID_VOLUME_UP_VALUE.ordinal()));
+        AccessibilityNodeInfo volumeDownButton = findGridButtonInfo(buttons,
+                String.valueOf(ShortcutId.ID_VOLUME_DOWN_VALUE.ordinal()));
+
+        try {
+            int min = audioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC);
+            audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, min,
+                    AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
+            TestUtils.waitUntil("Could not change audio stream to minimum volume.",
+                    TIMEOUT_UI_CHANGE_S,
+                    () -> audioManager.getStreamVolume(AudioManager.STREAM_MUSIC) == min);
+            volumeUpButton.performAction(CLICK_ID);
+            TestUtils.waitUntil("Did not detect an increase in volume.",
+                    TIMEOUT_UI_CHANGE_S,
+                    () -> audioManager.getStreamVolume(AudioManager.STREAM_MUSIC) > min);
+
+            int max = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+            audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, max,
+                    AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
+            TestUtils.waitUntil("Could not change audio stream to maximum volume.",
+                    TIMEOUT_UI_CHANGE_S,
+                    () -> audioManager.getStreamVolume(AudioManager.STREAM_MUSIC) == max);
+            volumeDownButton.performAction(CLICK_ID);
+            TestUtils.waitUntil("Did not detect a decrease in volume.",
+                    TIMEOUT_UI_CHANGE_S,
+                    () -> audioManager.getStreamVolume(AudioManager.STREAM_MUSIC) < max);
+        } finally {
+            audioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
+                    resetVolume, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
+        }
+    }
+
+    @Test
+    public void testAssistantButton_opensVoiceAssistant() throws Throwable {
+        AccessibilityNodeInfo assistantButton = findGridButtonInfo(getGridButtonList(),
+                String.valueOf(ShortcutId.ID_ASSISTANT_VALUE.ordinal()));
+        Intent expectedIntent = new Intent(Intent.ACTION_VOICE_COMMAND);
+        String expectedPackage = expectedIntent.resolveActivity(
+                sInstrumentation.getContext().getPackageManager()).getPackageName();
+
+        sUiAutomation.executeAndWaitForEvent(
+                () -> assistantButton.performAction(CLICK_ID),
+                (event) -> expectedPackage.contains(event.getPackageName()),
+                TIMEOUT_UI_CHANGE_S * 1000
+        );
+    }
+
+    @Test
+    public void testAccessibilitySettingsButton_opensAccessibilitySettings() throws Throwable {
+        AccessibilityNodeInfo settingsButton = findGridButtonInfo(getGridButtonList(),
+                String.valueOf(ShortcutId.ID_A11YSETTING_VALUE.ordinal()));
+        Intent expectedIntent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
+        String expectedPackage = expectedIntent.resolveActivity(
+                sInstrumentation.getContext().getPackageManager()).getPackageName();
+
+        sUiAutomation.executeAndWaitForEvent(
+                () -> settingsButton.performAction(CLICK_ID),
+                (event) -> expectedPackage.contains(event.getPackageName()),
+                TIMEOUT_UI_CHANGE_S * 1000
+        );
+    }
+
+    @Test
+    public void testPowerButton_performsGlobalAction() throws Throwable {
+        AccessibilityNodeInfo button = findGridButtonInfo(getGridButtonList(),
+                String.valueOf(ShortcutId.ID_POWER_VALUE.ordinal()));
+
+        button.performAction(CLICK_ID);
+        TestUtils.waitUntil("Did not detect Power action being performed.",
+                TIMEOUT_UI_CHANGE_S,
+                () -> sLastGlobalAction.compareAndSet(
+                        GLOBAL_ACTION_POWER_DIALOG, NO_GLOBAL_ACTION));
+    }
+
+    @Test
+    public void testRecentButton_performsGlobalAction() throws Throwable {
+        AccessibilityNodeInfo button = findGridButtonInfo(getGridButtonList(),
+                String.valueOf(ShortcutId.ID_RECENT_VALUE.ordinal()));
+
+        button.performAction(CLICK_ID);
+        TestUtils.waitUntil("Did not detect Recents action being performed.",
+                TIMEOUT_UI_CHANGE_S,
+                () -> sLastGlobalAction.compareAndSet(
+                        GLOBAL_ACTION_RECENTS, NO_GLOBAL_ACTION));
+    }
+
+    @Test
+    public void testLockButton_performsGlobalAction() throws Throwable {
+        AccessibilityNodeInfo button = findGridButtonInfo(getGridButtonList(),
+                String.valueOf(ShortcutId.ID_LOCKSCREEN_VALUE.ordinal()));
+
+        button.performAction(CLICK_ID);
+        TestUtils.waitUntil("Did not detect Lock action being performed.",
+                TIMEOUT_UI_CHANGE_S,
+                () -> sLastGlobalAction.compareAndSet(
+                        GLOBAL_ACTION_LOCK_SCREEN, NO_GLOBAL_ACTION));
+    }
+
+    @Test
+    public void testQuickSettingsButton_performsGlobalAction() throws Throwable {
+        AccessibilityNodeInfo button = findGridButtonInfo(getGridButtonList(),
+                String.valueOf(ShortcutId.ID_QUICKSETTING_VALUE.ordinal()));
+
+        button.performAction(CLICK_ID);
+        TestUtils.waitUntil("Did not detect Quick Settings action being performed.",
+                TIMEOUT_UI_CHANGE_S,
+                () -> sLastGlobalAction.compareAndSet(
+                        GLOBAL_ACTION_QUICK_SETTINGS, NO_GLOBAL_ACTION));
+    }
+
+    @Test
+    public void testNotificationsButton_performsGlobalAction() throws Throwable {
+        AccessibilityNodeInfo button = findGridButtonInfo(getGridButtonList(),
+                String.valueOf(ShortcutId.ID_NOTIFICATION_VALUE.ordinal()));
+
+        button.performAction(CLICK_ID);
+        TestUtils.waitUntil("Did not detect Notifications action being performed.",
+                TIMEOUT_UI_CHANGE_S,
+                () -> sLastGlobalAction.compareAndSet(
+                        GLOBAL_ACTION_NOTIFICATIONS, NO_GLOBAL_ACTION));
+    }
+
+    @Test
+    public void testScreenshotButton_performsGlobalAction() throws Throwable {
+        AccessibilityNodeInfo button = findGridButtonInfo(getGridButtonList(),
+                String.valueOf(ShortcutId.ID_SCREENSHOT_VALUE.ordinal()));
+
+        button.performAction(CLICK_ID);
+        TestUtils.waitUntil("Did not detect Screenshot action being performed.",
+                TIMEOUT_UI_CHANGE_S,
+                () -> sLastGlobalAction.compareAndSet(
+                        GLOBAL_ACTION_TAKE_SCREENSHOT, NO_GLOBAL_ACTION));
+    }
+}
diff --git a/packages/SystemUI/animation/.gitignore b/packages/SystemUI/animation/.gitignore
new file mode 100644
index 0000000..f9a33db
--- /dev/null
+++ b/packages/SystemUI/animation/.gitignore
@@ -0,0 +1,9 @@
+.idea/
+.gradle/
+gradle/
+build/
+gradlew*
+local.properties
+*.iml
+android.properties
+buildSrc
\ No newline at end of file
diff --git a/packages/SystemUI/animation/build.gradle b/packages/SystemUI/animation/build.gradle
new file mode 100644
index 0000000..939455f
--- /dev/null
+++ b/packages/SystemUI/animation/build.gradle
@@ -0,0 +1,37 @@
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+
+// TODO: Pull out surfaceeffects outside of src and have separate build files there.
+android {
+    sourceSets {
+        main {
+            java.srcDirs = ["${SYS_UI_DIR}/animation/src/com/android/systemui/surfaceeffects/"]
+            manifest.srcFile "${SYS_UI_DIR}/animation/AndroidManifest.xml"
+        }
+    }
+
+    compileSdk 33
+
+    defaultConfig {
+        minSdk 33
+        targetSdk 33
+    }
+
+    lintOptions {
+        abortOnError false
+    }
+    tasks.lint.enabled = false
+    tasks.withType(JavaCompile) {
+        options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
+    }
+    kotlinOptions {
+        jvmTarget = '1.8'
+        freeCompilerArgs = ["-Xjvm-default=all"]
+    }
+}
+
+dependencies {
+    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0"
+    implementation 'androidx.core:core-animation:1.0.0-alpha02'
+    implementation 'androidx.core:core-ktx:1.9.0'
+}
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 17a94b86..296c2ae 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
@@ -419,7 +419,7 @@
         internal val delegate: AnimationDelegate
 
         init {
-            delegate = AnimationDelegate(controller, callback, launchAnimator, listener)
+            delegate = AnimationDelegate(controller, callback, listener, launchAnimator)
         }
 
         @BinderThread
@@ -446,10 +446,10 @@
     constructor(
         private val controller: Controller,
         private val callback: Callback,
-        /** The animator to use to animate the window launch. */
-        private val launchAnimator: LaunchAnimator = DEFAULT_LAUNCH_ANIMATOR,
         /** Listener for animation lifecycle events. */
-        private val listener: Listener? = null
+        private val listener: Listener? = null,
+        /** The animator to use to animate the window launch. */
+        private val launchAnimator: LaunchAnimator = DEFAULT_LAUNCH_ANIMATOR
     ) : RemoteAnimationDelegate<IRemoteAnimationFinishedCallback> {
         private val launchContainer = controller.launchContainer
         private val context = launchContainer.context
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt
index 40a5e97..c49a487 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt
@@ -26,7 +26,7 @@
      * currently not attached or visible).
      *
      * @param cujType the CUJ type from the [com.android.internal.jank.InteractionJankMonitor]
-     * associated to the launch that will use this controller.
+     *   associated to the launch that will use this controller.
      */
     fun activityLaunchController(cujType: Int? = null): ActivityLaunchAnimator.Controller?
 
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt
index 2903288..f0a8211 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt
@@ -19,14 +19,15 @@
 import android.graphics.fonts.Font
 import android.graphics.fonts.FontVariationAxis
 import android.util.MathUtils
+import android.util.MathUtils.abs
+import java.lang.Float.max
+import java.lang.Float.min
 
 private const val TAG_WGHT = "wght"
 private const val TAG_ITAL = "ital"
 
-private const val FONT_WEIGHT_MAX = 1000f
-private const val FONT_WEIGHT_MIN = 0f
-private const val FONT_WEIGHT_ANIMATION_STEP = 10f
 private const val FONT_WEIGHT_DEFAULT_VALUE = 400f
+private const val FONT_WEIGHT_ANIMATION_FRAME_COUNT = 100
 
 private const val FONT_ITALIC_MAX = 1f
 private const val FONT_ITALIC_MIN = 0f
@@ -118,14 +119,17 @@
             lerp(startAxes, endAxes) { tag, startValue, endValue ->
                 when (tag) {
                     // TODO: Good to parse 'fvar' table for retrieving default value.
-                    TAG_WGHT ->
-                        adjustWeight(
+                    TAG_WGHT -> {
+                        adaptiveAdjustWeight(
                             MathUtils.lerp(
                                 startValue ?: FONT_WEIGHT_DEFAULT_VALUE,
                                 endValue ?: FONT_WEIGHT_DEFAULT_VALUE,
                                 progress
-                            )
+                            ),
+                            startValue ?: FONT_WEIGHT_DEFAULT_VALUE,
+                            endValue ?: FONT_WEIGHT_DEFAULT_VALUE,
                         )
+                    }
                     TAG_ITAL ->
                         adjustItalic(
                             MathUtils.lerp(
@@ -205,10 +209,14 @@
         return result
     }
 
-    // For the performance reasons, we animate weight with FONT_WEIGHT_ANIMATION_STEP. This helps
+    // For the performance reasons, we animate weight with adaptive step. This helps
     // Cache hit ratio in the Skia glyph cache.
-    private fun adjustWeight(value: Float) =
-        coerceInWithStep(value, FONT_WEIGHT_MIN, FONT_WEIGHT_MAX, FONT_WEIGHT_ANIMATION_STEP)
+    // The reason we don't use fix step is because the range of weight axis is not normalized,
+    // some are from 50 to 100, others are from 0 to 1000, so we cannot give a constant proper step
+    private fun adaptiveAdjustWeight(value: Float, start: Float, end: Float): Float {
+        val step = max(abs(end - start) / FONT_WEIGHT_ANIMATION_FRAME_COUNT, 1F)
+        return coerceInWithStep(value, min(start, end), max(start, end), step)
+    }
 
     // For the performance reasons, we animate italic with FONT_ITALIC_ANIMATION_STEP. This helps
     // Cache hit ratio in the Skia glyph cache.
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt
index 9668066..3417ffd 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt
@@ -75,7 +75,7 @@
          * - Get the associated [Context].
          * - Compute whether we are expanding fully above the launch container.
          * - Get to overlay to which we initially put the window background layer, until the opening
-         * window is made visible (see [openingWindowSyncView]).
+         *   window is made visible (see [openingWindowSyncView]).
          *
          * This container can be changed to force this [Controller] to animate the expanding view
          * inside a different location, for instance to ensure correct layering during the
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
index b98b9221..ed8e705 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
@@ -24,7 +24,7 @@
      * Set whether this view should block/postpone all calls to [View.setVisibility]. This ensures
      * that this view:
      * - remains invisible during the launch animation given that it is ghosted and already drawn
-     * somewhere else.
+     *   somewhere else.
      * - remains invisible as long as a dialog expanded from it is shown.
      * - restores its expected visibility once the dialog expanded from it is dismissed.
      *
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt
index 0e2d23b..03e1e66 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt
@@ -59,12 +59,14 @@
             // changes should be ordered top-to-bottom in z
             val mode = change.mode
 
+            var rootIdx = info.findRootIndex(change.endDisplayId)
+            if (rootIdx < 0) rootIdx = 0
             // Launcher animates leaf tasks directly, so always reparent all task leashes to root.
-            t.reparent(leash, info.rootLeash)
+            t.reparent(leash, info.getRoot(rootIdx).leash)
             t.setPosition(
                 leash,
-                (change.startAbsBounds.left - info.rootOffset.x).toFloat(),
-                (change.startAbsBounds.top - info.rootOffset.y).toFloat()
+                (change.startAbsBounds.left - info.getRoot(rootIdx).offset.x).toFloat(),
+                (change.startAbsBounds.top - info.getRoot(rootIdx).offset.y).toFloat()
             )
             t.show(leash)
             // Put all the OPEN/SHOW on top
@@ -114,8 +116,11 @@
                     .setName(change.leash.toString() + "_transition-leash")
                     .setContainerLayer()
                     .setParent(
-                        if (change.parent == null) info.rootLeash
-                        else info.getChange(change.parent!!)!!.leash
+                        if (change.parent == null) {
+                            var rootIdx = info.findRootIndex(change.endDisplayId)
+                            if (rootIdx < 0) rootIdx = 0
+                            info.getRoot(rootIdx).leash
+                        } else info.getChange(change.parent!!)!!.leash
                     )
                     .build()
             // Copied Transitions setup code (which expects bottom-to-top order, so we swap here)
@@ -182,9 +187,9 @@
          * Represents a TransitionInfo object as an array of old-style targets
          *
          * @param wallpapers If true, this will return wallpaper targets; otherwise it returns
-         * non-wallpaper targets.
+         *   non-wallpaper targets.
          * @param leashMap Temporary map of change leash -> launcher leash. Is an output, so should
-         * be populated by this function. If null, it is ignored.
+         *   be populated by this function. If null, it is ignored.
          */
         fun wrapTargets(
             info: TransitionInfo,
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ShadeInterpolation.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ShadeInterpolation.kt
index a96f893..b89a8b0 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ShadeInterpolation.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ShadeInterpolation.kt
@@ -6,6 +6,7 @@
 
     /**
      * Interpolate alpha for notification background scrim during shade expansion.
+     *
      * @param fraction Shade expansion fraction
      */
     @JvmStatic
@@ -16,6 +17,7 @@
 
     /**
      * Interpolate alpha for shade content during shade expansion.
+     *
      * @param fraction Shade expansion fraction
      */
     @JvmStatic
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
index a08b598..7fe94d3 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
@@ -190,6 +190,7 @@
      * @param textSize an optional font size.
      * @param colors an optional colors array that must be the same size as numLines passed to
      *               the TextInterpolator
+     * @param strokeWidth an optional paint stroke width
      * @param animate an optional boolean indicating true for showing style transition as animation,
      *                false for immediate style transition. True by default.
      * @param duration an optional animation duration in milliseconds. This is ignored if animate is
@@ -201,6 +202,7 @@
         weight: Int = -1,
         textSize: Float = -1f,
         color: Int? = null,
+        strokeWidth: Float = -1f,
         animate: Boolean = true,
         duration: Long = -1L,
         interpolator: TimeInterpolator? = null,
@@ -254,6 +256,9 @@
         if (color != null) {
             textInterpolator.targetPaint.color = color
         }
+        if (strokeWidth >= 0F) {
+            textInterpolator.targetPaint.strokeWidth = strokeWidth
+        }
         textInterpolator.onTargetPaintModified()
 
         if (animate) {
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
index 341784e..3eb7fd8 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
@@ -161,7 +161,6 @@
      * This API is useful to continue animation from the middle of the state. For example, if you
      * animate weight from 200 to 400, then if you want to move back to 200 at the half of the
      * animation, it will look like
-     *
      * <pre> <code>
      * ```
      *     val interp = TextInterpolator(layout)
@@ -474,6 +473,7 @@
         // TODO(172943390): Add other interpolation or support custom interpolator.
         out.textSize = MathUtils.lerp(from.textSize, to.textSize, progress)
         out.color = ColorUtils.blendARGB(from.color, to.color, progress)
+        out.strokeWidth = MathUtils.lerp(from.strokeWidth, to.strokeWidth, progress)
     }
 
     // Shape the text and stores the result to out argument.
@@ -497,7 +497,9 @@
                 count,
                 layout.textDirectionHeuristic,
                 paint
-            ) { _, _, glyphs, _ -> runs.add(glyphs) }
+            ) { _, _, glyphs, _ ->
+                runs.add(glyphs)
+            }
             out.add(runs)
 
             if (lineNo > 0) {
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
index 052888b..b5b6037 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
@@ -25,7 +25,6 @@
 
 /**
  * Shader class that renders an expanding ripple effect. The ripple contains three elements:
- *
  * 1. an expanding filled [RippleShape] that appears in the beginning and quickly fades away
  * 2. an expanding ring that appears throughout the effect
  * 3. an expanding ring-shaped area that reveals noise over #2.
@@ -317,6 +316,7 @@
      * Parameters used for fade in and outs of the ripple.
      *
      * <p>Note that all the fade in/ outs are "linear" progression.
+     *
      * ```
      *          (opacity)
      *          1
@@ -331,6 +331,7 @@
      *               fadeIn        fadeOut
      *               Start & End   Start & End
      * ```
+     *
      * <p>If no fade in/ out is needed, set [fadeInStart] and [fadeInEnd] to 0; [fadeOutStart] and
      * [fadeOutEnd] to 1.
      */
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/ShaderUtilLibrary.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/ShaderUtilLibrary.kt
index d78e0c1..280e7ed9 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/ShaderUtilLibrary.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/ShaderUtilLibrary.kt
@@ -53,6 +53,19 @@
                                 cos(p.y * 0.01 + time * 0.005931)) * distort_amount_xy;
             }
 
+            // Perceived luminosity (L′), not absolute luminosity.
+            half getLuminosity(vec3 c) {
+                return 0.3 * c.r + 0.59 * c.g + 0.11 * c.b;
+            }
+
+            // Creates a luminosity mask and clamp to the legal range.
+            vec3 maskLuminosity(vec3 dest, float lum) {
+                dest.rgb *= vec3(lum);
+                // Clip back into the legal range
+                dest = clamp(dest, vec3(0.), vec3(1.0));
+                return dest;
+            }
+
             // Return range [-1, 1].
             vec3 hash(vec3 p) {
                 p = fract(p * vec3(.3456, .1234, .9876));
@@ -62,14 +75,14 @@
             }
 
             // Skew factors (non-uniform).
-            const float SKEW = 0.3333333;  // 1/3
-            const float UNSKEW = 0.1666667;  // 1/6
+            const half SKEW = 0.3333333;  // 1/3
+            const half UNSKEW = 0.1666667;  // 1/6
 
             // Return range roughly [-1,1].
             // It's because the hash function (that returns a random gradient vector) returns
             // different magnitude of vectors. Noise doesn't have to be in the precise range thus
             // skipped normalize.
-            float simplex3d(vec3 p) {
+            half simplex3d(vec3 p) {
                 // Skew the input coordinate, so that we get squashed cubical grid
                 vec3 s = floor(p + (p.x + p.y + p.z) * SKEW);
 
@@ -143,6 +156,22 @@
                 // Should multiply by the possible max contribution to adjust the range in [-1,1].
                 return dot(vec4(32.), nc);
             }
+
+            // Random rotations.
+            // The way you create fractal noise is layering simplex noise with some rotation.
+            // To make random cloud looking noise, the rotations should not align. (Otherwise it
+            // creates patterned noise).
+            // Below rotations only rotate in one axis.
+            const mat3 rot1 = mat3(1.0, 0. ,0., 0., 0.15, -0.98, 0., 0.98, 0.15);
+            const mat3 rot2 = mat3(-0.95, 0. ,-0.3, 0., 1., 0., 0.3, 0., -0.95);
+            const mat3 rot3 = mat3(1.0, 0. ,0., 0., -0.44, -0.89, 0., 0.89, -0.44);
+
+            // Octave = 4
+            // Divide each coefficient by 3 to produce more grainy noise.
+            half simplex3d_fractal(vec3 mat) {
+                return 0.675 * simplex3d(mat * rot1) + 0.225 * simplex3d(2.0 * mat * rot2)
+                        + 0.075 * simplex3d(4.0 * mat * rot3) + 0.025 * simplex3d(8.0 * mat);
+            }
             """
     }
 }
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
index 79bc2f4..89871fa7 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
@@ -30,12 +30,14 @@
      * Noise move speed variables.
      *
      * Its sign determines the direction; magnitude determines the speed. <ul>
+     *
      * ```
      *     <li> [noiseMoveSpeedX] positive: right to left; negative: left to right.
      *     <li> [noiseMoveSpeedY] positive: bottom to top; negative: top to bottom.
      *     <li> [noiseMoveSpeedZ] its sign doesn't matter much, as it moves in Z direction. Use it
      *     to add turbulence in place.
      * ```
+     *
      * </ul>
      */
     val noiseMoveSpeedX: Float = 0f,
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt
index 7456c43..0e22667 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt
@@ -19,8 +19,13 @@
 import com.android.systemui.surfaceeffects.shaderutil.ShaderUtilLibrary
 import java.lang.Float.max
 
-/** Shader that renders turbulence simplex noise, with no octave. */
-class TurbulenceNoiseShader : RuntimeShader(TURBULENCE_NOISE_SHADER) {
+/**
+ * Shader that renders turbulence simplex noise, by default no octave.
+ *
+ * @param useFractal whether to use fractal noise (4 octaves).
+ */
+class TurbulenceNoiseShader(useFractal: Boolean = false) :
+    RuntimeShader(if (useFractal) FRACTAL_NOISE_SHADER else SIMPLEX_NOISE_SHADER) {
     // language=AGSL
     companion object {
         private const val UNIFORMS =
@@ -35,21 +40,7 @@
             layout(color) uniform vec4 in_backgroundColor;
         """
 
-        private const val SHADER_LIB =
-            """
-            float getLuminosity(vec3 c) {
-                return 0.3*c.r + 0.59*c.g + 0.11*c.b;
-            }
-
-            vec3 maskLuminosity(vec3 dest, float lum) {
-                dest.rgb *= vec3(lum);
-                // Clip back into the legal range
-                dest = clamp(dest, vec3(0.), vec3(1.0));
-                return dest;
-            }
-        """
-
-        private const val MAIN_SHADER =
+        private const val SIMPLEX_SHADER =
             """
             vec4 main(vec2 p) {
                 vec2 uv = p / in_size.xy;
@@ -71,8 +62,26 @@
             }
         """
 
-        private const val TURBULENCE_NOISE_SHADER =
-            ShaderUtilLibrary.SHADER_LIB + UNIFORMS + SHADER_LIB + MAIN_SHADER
+        private const val FRACTAL_SHADER =
+            """
+            vec4 main(vec2 p) {
+                vec2 uv = p / in_size.xy;
+                uv.x *= in_aspectRatio;
+
+                vec3 noiseP = vec3(uv + in_noiseMove.xy, in_noiseMove.z) * in_gridNum;
+                float luma = simplex3d_fractal(noiseP) * in_opacity;
+                vec3 mask = maskLuminosity(in_color.rgb, luma);
+                vec3 color = in_backgroundColor.rgb + mask * 0.6;
+
+                // Skip dithering.
+                return vec4(color * in_color.a, in_color.a);
+            }
+        """
+
+        private const val SIMPLEX_NOISE_SHADER =
+            ShaderUtilLibrary.SHADER_LIB + UNIFORMS + SIMPLEX_SHADER
+        private const val FRACTAL_NOISE_SHADER =
+            ShaderUtilLibrary.SHADER_LIB + UNIFORMS + FRACTAL_SHADER
     }
 
     /** Sets the number of grid for generating noise. */
diff --git a/packages/SystemUI/animation/src/com/android/systemui/util/AnimatorExtensions.kt b/packages/SystemUI/animation/src/com/android/systemui/util/AnimatorExtensions.kt
new file mode 100644
index 0000000..35dbb89
--- /dev/null
+++ b/packages/SystemUI/animation/src/com/android/systemui/util/AnimatorExtensions.kt
@@ -0,0 +1,80 @@
+/*
+ * 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
+
+import androidx.core.animation.Animator
+
+/**
+ * Add an action which will be invoked when the animation has ended.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ * @see Animator.end
+ */
+inline fun Animator.doOnEnd(
+    crossinline action: (animator: Animator) -> Unit
+): Animator.AnimatorListener = addListener(onEnd = action)
+
+/**
+ * Add an action which will be invoked when the animation has started.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ * @see Animator.start
+ */
+inline fun Animator.doOnStart(
+    crossinline action: (animator: Animator) -> Unit
+): Animator.AnimatorListener = addListener(onStart = action)
+
+/**
+ * Add an action which will be invoked when the animation has been cancelled.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ * @see Animator.cancel
+ */
+inline fun Animator.doOnCancel(
+    crossinline action: (animator: Animator) -> Unit
+): Animator.AnimatorListener = addListener(onCancel = action)
+
+/**
+ * Add an action which will be invoked when the animation has repeated.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ */
+inline fun Animator.doOnRepeat(
+    crossinline action: (animator: Animator) -> Unit
+): Animator.AnimatorListener = addListener(onRepeat = action)
+
+/**
+ * Add a listener to this Animator using the provided actions.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ */
+inline fun Animator.addListener(
+    crossinline onEnd: (animator: Animator) -> Unit = {},
+    crossinline onStart: (animator: Animator) -> Unit = {},
+    crossinline onCancel: (animator: Animator) -> Unit = {},
+    crossinline onRepeat: (animator: Animator) -> Unit = {}
+): Animator.AnimatorListener {
+    val listener =
+        object : Animator.AnimatorListener {
+            override fun onAnimationRepeat(animator: Animator) = onRepeat(animator)
+            override fun onAnimationEnd(animator: Animator) = onEnd(animator)
+            override fun onAnimationCancel(animator: Animator) = onCancel(animator)
+            override fun onAnimationStart(animator: Animator) = onStart(animator)
+        }
+    addListener(listener)
+    return listener
+}
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DemotingTestWithoutBugDetector.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DemotingTestWithoutBugDetector.kt
new file mode 100644
index 0000000..459a38e
--- /dev/null
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DemotingTestWithoutBugDetector.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.internal.systemui.lint
+
+import com.android.tools.lint.client.api.UElementHandler
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import com.android.tools.lint.detector.api.SourceCodeScanner
+import java.util.regex.Pattern
+import org.jetbrains.uast.UAnnotation
+import org.jetbrains.uast.UElement
+
+class DemotingTestWithoutBugDetector : Detector(), SourceCodeScanner {
+    override fun getApplicableUastTypes(): List<Class<out UElement>> {
+        return listOf(UAnnotation::class.java)
+    }
+
+    override fun createUastHandler(context: JavaContext): UElementHandler {
+        return object : UElementHandler() {
+            override fun visitAnnotation(node: UAnnotation) {
+                // Annotations having int bugId field
+                if (node.qualifiedName in DEMOTING_ANNOTATION_BUG_ID) {
+                    val bugId = node.findAttributeValue("bugId")!!.evaluate() as Int
+                    if (bugId <= 0) {
+                        val location = context.getLocation(node)
+                        val message = "Please attach a bug id to track demoted test"
+                        context.report(ISSUE, node, location, message)
+                    }
+                }
+                // @Ignore has a String field for reason
+                if (node.qualifiedName == DEMOTING_ANNOTATION_IGNORE) {
+                    val reason = node.findAttributeValue("value")!!.evaluate() as String
+                    val bugPattern = Pattern.compile("b/\\d+")
+                    if (!bugPattern.matcher(reason).find()) {
+                        val location = context.getLocation(node)
+                        val message = "Please attach a bug (e.g. b/123) to track demoted test"
+                        context.report(ISSUE, node, location, message)
+                    }
+                }
+            }
+        }
+    }
+
+    companion object {
+        val DEMOTING_ANNOTATION_BUG_ID =
+            listOf(
+                "androidx.test.filters.FlakyTest",
+                "android.platform.test.annotations.FlakyTest",
+                "android.platform.test.rule.PlatinumRule.Platinum",
+            )
+
+        const val DEMOTING_ANNOTATION_IGNORE = "org.junit.Ignore"
+
+        @JvmField
+        val ISSUE: Issue =
+            Issue.create(
+                id = "DemotingTestWithoutBug",
+                briefDescription = "Demoting a test without attaching a bug.",
+                explanation =
+                    """
+                    Annotations (`@FlakyTest`) demote tests to an unmonitored \
+                    test suite. Please set the `bugId` field in such annotations to track \
+                    the test status.
+                    """,
+                category = Category.TESTING,
+                priority = 8,
+                severity = Severity.WARNING,
+                implementation =
+                    Implementation(
+                        DemotingTestWithoutBugDetector::class.java,
+                        Scope.JAVA_FILE_SCOPE
+                    )
+            )
+    }
+}
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DumpableNotRegisteredDetector.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DumpableNotRegisteredDetector.kt
new file mode 100644
index 0000000..30e2a25
--- /dev/null
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DumpableNotRegisteredDetector.kt
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.systemui.lint
+
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Context
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Location
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import com.android.tools.lint.detector.api.SourceCodeScanner
+import com.intellij.psi.PsiMethod
+import org.jetbrains.uast.UCallExpression
+import org.jetbrains.uast.UClass
+
+/**
+ * Checks if any class has implemented the `Dumpable` interface but has not registered itself with
+ * the `DumpManager`.
+ */
+@Suppress("UnstableApiUsage")
+class DumpableNotRegisteredDetector : Detector(), SourceCodeScanner {
+
+    private var isDumpable: Boolean = false
+    private var isCoreStartable: Boolean = false
+    private var hasRegisterCall: Boolean = false
+    private var classLocation: Location? = null
+
+    override fun beforeCheckFile(context: Context) {
+        isDumpable = false
+        isCoreStartable = false
+        hasRegisterCall = false
+        classLocation = null
+    }
+
+    override fun applicableSuperClasses(): List<String> {
+        return listOf(DUMPABLE_CLASS_NAME)
+    }
+
+    override fun getApplicableMethodNames(): List<String> {
+        return listOf("registerDumpable", "registerNormalDumpable", "registerCriticalDumpable")
+    }
+
+    override fun visitClass(context: JavaContext, declaration: UClass) {
+        if (declaration.isInterface || context.evaluator.isAbstract(declaration)) {
+            // Don't require interfaces or abstract classes to call `register` (assume the full
+            // implementations will call it). This also means that we correctly don't warn for the
+            // `Dumpable` interface itself.
+            return
+        }
+
+        classLocation = context.getNameLocation(declaration)
+
+        val superTypeClassNames = declaration.superTypes.mapNotNull { it.resolve()?.qualifiedName }
+        isDumpable = superTypeClassNames.contains(DUMPABLE_CLASS_NAME)
+        isCoreStartable = superTypeClassNames.contains(CORE_STARTABLE_CLASS_NAME)
+    }
+
+    override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) {
+        if (context.evaluator.isMemberInSubClassOf(method, DUMP_MANAGER_CLASS_NAME)) {
+            hasRegisterCall = true
+        }
+    }
+
+    override fun afterCheckFile(context: Context) {
+        if (!isDumpable) {
+            return
+        }
+        if (isDumpable && isCoreStartable) {
+            // CoreStartables will be automatically registered, so classes that implement
+            // CoreStartable do not need a `register` call.
+            return
+        }
+
+        if (!hasRegisterCall) {
+            context.report(
+                issue = ISSUE,
+                location = classLocation!!,
+                message =
+                    "Any class implementing `Dumpable` must call " +
+                        "`DumpManager.registerNormalDumpable` or " +
+                        "`DumpManager.registerCriticalDumpable`",
+            )
+        }
+    }
+
+    companion object {
+        @JvmField
+        val ISSUE: Issue =
+            Issue.create(
+                id = "DumpableNotRegistered",
+                briefDescription = "Dumpable not registered with DumpManager.",
+                explanation =
+                    """
+                    This class has implemented the `Dumpable` interface, but it has not registered \
+                    itself with the `DumpManager`. This means that the class will never actually \
+                    be dumped. Please call `DumpManager.registerNormalDumpable` or \
+                    `DumpManager.registerCriticalDumpable` in the class's constructor or \
+                    initialization method.""",
+                category = Category.CORRECTNESS,
+                priority = 8,
+                severity = Severity.WARNING,
+                implementation =
+                    Implementation(DumpableNotRegisteredDetector::class.java, Scope.JAVA_FILE_SCOPE)
+            )
+
+        private const val DUMPABLE_CLASS_NAME = "com.android.systemui.Dumpable"
+        private const val CORE_STARTABLE_CLASS_NAME = "com.android.systemui.CoreStartable"
+        private const val DUMP_MANAGER_CLASS_NAME = "com.android.systemui.dump.DumpManager"
+    }
+}
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
index 254a6fb..387b67d 100644
--- a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
@@ -32,13 +32,15 @@
                 BindServiceOnMainThreadDetector.ISSUE,
                 BroadcastSentViaContextDetector.ISSUE,
                 CleanArchitectureDependencyViolationDetector.ISSUE,
+                DumpableNotRegisteredDetector.ISSUE,
                 SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY,
                 SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY,
                 NonInjectedMainThreadDetector.ISSUE,
                 RegisterReceiverViaContextDetector.ISSUE,
                 SoftwareBitmapDetector.ISSUE,
                 NonInjectedServiceDetector.ISSUE,
-                StaticSettingsProviderDetector.ISSUE
+                StaticSettingsProviderDetector.ISSUE,
+                DemotingTestWithoutBugDetector.ISSUE
             )
 
     override val api: Int
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt
index a4b59fd..a5f832a 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt
@@ -64,7 +64,8 @@
                         class BadClass(
                             private val viewModel: ViewModel,
                         )
-                    """.trimIndent()
+                    """
+                        .trimIndent()
                 )
             )
             .issues(
@@ -98,7 +99,8 @@
                         class BadClass(
                             private val repository: Repository,
                         )
-                    """.trimIndent()
+                    """
+                        .trimIndent()
                 )
             )
             .issues(
@@ -136,7 +138,8 @@
                             private val interactor: Interactor,
                             private val viewmodel: ViewModel,
                         )
-                    """.trimIndent()
+                    """
+                        .trimIndent()
                 )
             )
             .issues(
@@ -176,7 +179,8 @@
                         class BadClass(
                             private val interactor: Interactor,
                         )
-                    """.trimIndent()
+                    """
+                        .trimIndent()
                 )
             )
             .issues(
@@ -207,7 +211,8 @@
                     data class Model(
                         private val name: String,
                     )
-                """.trimIndent()
+                """
+                    .trimIndent()
             )
         private val REPOSITORY_FILE =
             TestFiles.kotlin(
@@ -228,7 +233,8 @@
                             return models
                         }
                     }
-                """.trimIndent()
+                """
+                    .trimIndent()
             )
         private val INTERACTOR_FILE =
             TestFiles.kotlin(
@@ -245,7 +251,8 @@
                             return repository.getModels()
                         }
                     }
-                """.trimIndent()
+                """
+                    .trimIndent()
             )
         private val VIEW_MODEL_FILE =
             TestFiles.kotlin(
@@ -262,7 +269,8 @@
                             return interactor.getModels().map { model -> model.name }
                         }
                     }
-                """.trimIndent()
+                """
+                    .trimIndent()
             )
         private val NON_CLEAN_ARCHITECTURE_FILE =
             TestFiles.kotlin(
@@ -282,7 +290,8 @@
                             )
                         }
                     }
-                """.trimIndent()
+                """
+                    .trimIndent()
             )
         private val LEGITIMATE_FILES =
             arrayOf(
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DemotingTestWithoutBugDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DemotingTestWithoutBugDetectorTest.kt
new file mode 100644
index 0000000..63eb263
--- /dev/null
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DemotingTestWithoutBugDetectorTest.kt
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.systemui.lint
+
+import com.android.tools.lint.checks.infrastructure.TestFile
+import com.android.tools.lint.checks.infrastructure.TestFiles
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+import org.junit.Test
+
+class DemotingTestWithoutBugDetectorTest : SystemUILintDetectorTest() {
+
+    override fun getDetector(): Detector = DemotingTestWithoutBugDetector()
+    override fun getIssues(): List<Issue> = listOf(DemotingTestWithoutBugDetector.ISSUE)
+
+    @Test
+    fun testMarkFlaky_withBugId() {
+        lint()
+            .files(
+                TestFiles.java(
+                        """
+                        package test.pkg;
+                        import androidx.test.filters.FlakyTest;
+
+                        @FlakyTest(bugId = 123)
+                        public class TestClass {
+                            public void testCase() {}
+                        }
+                    """
+                    )
+                    .indented(),
+                *stubs
+            )
+            .issues(DemotingTestWithoutBugDetector.ISSUE)
+            .run()
+            .expectClean()
+
+        lint()
+            .files(
+                TestFiles.java(
+                        """
+                        package test.pkg;
+                        import android.platform.test.annotations.FlakyTest;
+
+                        @FlakyTest(bugId = 123)
+                        public class TestClass {
+                            public void testCase() {}
+                        }
+                    """
+                    )
+                    .indented(),
+                *stubs
+            )
+            .issues(DemotingTestWithoutBugDetector.ISSUE)
+            .run()
+            .expectClean()
+    }
+
+    @Test
+    fun testMarkFlaky_withoutBugId() {
+        lint()
+            .files(
+                TestFiles.java(
+                        """
+                        package test.pkg;
+                        import androidx.test.filters.FlakyTest;
+
+                        @FlakyTest
+                        public class TestClass {
+                            public void testCase() {}
+                        }
+                    """
+                    )
+                    .indented(),
+                *stubs
+            )
+            .issues(DemotingTestWithoutBugDetector.ISSUE)
+            .run()
+            .expect(
+                """
+                src/test/pkg/TestClass.java:4: Warning: Please attach a bug id to track demoted test [DemotingTestWithoutBug]
+                @FlakyTest
+                ~~~~~~~~~~
+                0 errors, 1 warnings
+                """
+            )
+
+        lint()
+            .files(
+                TestFiles.java(
+                        """
+                        package test.pkg;
+                        import android.platform.test.annotations.FlakyTest;
+
+                        @FlakyTest
+                        public class TestClass {
+                            public void testCase() {}
+                        }
+                    """
+                    )
+                    .indented(),
+                *stubs
+            )
+            .issues(DemotingTestWithoutBugDetector.ISSUE)
+            .run()
+            .expect(
+                """
+                src/test/pkg/TestClass.java:4: Warning: Please attach a bug id to track demoted test [DemotingTestWithoutBug]
+                @FlakyTest
+                ~~~~~~~~~~
+                0 errors, 1 warnings
+                """
+            )
+    }
+
+    @Test
+    fun testExcludeDevices_withBugId() {
+        lint()
+            .files(
+                TestFiles.java(
+                        """
+                        package test.pkg;
+                        import android.platform.test.rule.PlatinumRule.Platinum;
+
+                        @Platinum(devices = "foo,bar", bugId = 123)
+                        public class TestClass {
+                            public void testCase() {}
+                        }
+                    """
+                    )
+                    .indented(),
+                *stubs
+            )
+            .issues(DemotingTestWithoutBugDetector.ISSUE)
+            .run()
+            .expectClean()
+    }
+
+    @Test
+    fun testExcludeDevices_withoutBugId() {
+        lint()
+            .files(
+                TestFiles.java(
+                        """
+                        package test.pkg;
+                        import android.platform.test.rule.PlatinumRule.Platinum;
+
+                        @Platinum(devices = "foo,bar")
+                        public class TestClass {
+                            public void testCase() {}
+                        }
+                    """
+                    )
+                    .indented(),
+                *stubs
+            )
+            .issues(DemotingTestWithoutBugDetector.ISSUE)
+            .run()
+            .expect(
+                """
+                src/test/pkg/TestClass.java:4: Warning: Please attach a bug id to track demoted test [DemotingTestWithoutBug]
+                @Platinum(devices = "foo,bar")
+                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+                0 errors, 1 warnings
+                """
+            )
+    }
+
+    @Test
+    fun testIgnore_withBug() {
+        lint()
+            .files(
+                TestFiles.java(
+                        """
+                        package test.pkg;
+                        import org.junit.Ignore;
+
+                        @Ignore("Blocked by b/123.")
+                        public class TestClass {
+                            public void testCase() {}
+                        }
+                    """
+                    )
+                    .indented(),
+                *stubs
+            )
+            .issues(DemotingTestWithoutBugDetector.ISSUE)
+            .run()
+            .expectClean()
+    }
+
+    @Test
+    fun testIgnore_withoutBug() {
+        lint()
+            .files(
+                TestFiles.java(
+                        """
+                        package test.pkg;
+                        import org.junit.Ignore;
+
+                        @Ignore
+                        public class TestClass {
+                            public void testCase() {}
+                        }
+                    """
+                    )
+                    .indented(),
+                *stubs
+            )
+            .issues(DemotingTestWithoutBugDetector.ISSUE)
+            .run()
+            .expect(
+                """
+                src/test/pkg/TestClass.java:4: Warning: Please attach a bug (e.g. b/123) to track demoted test [DemotingTestWithoutBug]
+                @Ignore
+                ~~~~~~~
+                0 errors, 1 warnings
+                """
+            )
+
+        lint()
+            .files(
+                TestFiles.java(
+                        """
+                        package test.pkg;
+                        import org.junit.Ignore;
+
+                        @Ignore("Not ready")
+                        public class TestClass {
+                            public void testCase() {}
+                        }
+                    """
+                    )
+                    .indented(),
+                *stubs
+            )
+            .issues(DemotingTestWithoutBugDetector.ISSUE)
+            .run()
+            .expect(
+                """
+                src/test/pkg/TestClass.java:4: Warning: Please attach a bug (e.g. b/123) to track demoted test [DemotingTestWithoutBug]
+                @Ignore("Not ready")
+                ~~~~~~~~~~~~~~~~~~~~
+                0 errors, 1 warnings
+                """
+            )
+    }
+
+    private val filtersFlakyTestStub: TestFile =
+        java(
+            """
+        package androidx.test.filters;
+
+        public @interface FlakyTest {
+            int bugId() default -1;
+        }
+        """
+        )
+    private val annotationsFlakyTestStub: TestFile =
+        java(
+            """
+        package android.platform.test.annotations;
+
+        public @interface FlakyTest {
+            int bugId() default -1;
+        }
+        """
+        )
+    private val annotationsPlatinumStub: TestFile =
+        java(
+            """
+        package android.platform.test.rule;
+
+        public class PlatinumRule {
+            public @interface Platinum {
+                String devices();
+                int bugId() default -1;
+            }
+        }
+        """
+        )
+    private val annotationsIgnoreStub: TestFile =
+        java(
+            """
+        package org.junit;
+
+        public @interface Ignore {
+            String value() default "";
+        }
+        """
+        )
+    private val stubs =
+        arrayOf(
+            filtersFlakyTestStub,
+            annotationsFlakyTestStub,
+            annotationsPlatinumStub,
+            annotationsIgnoreStub
+        )
+}
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DumpableNotRegisteredDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DumpableNotRegisteredDetectorTest.kt
new file mode 100644
index 0000000..3d6cbc7
--- /dev/null
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DumpableNotRegisteredDetectorTest.kt
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.systemui.lint
+
+import com.android.tools.lint.checks.infrastructure.TestFiles
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+import org.junit.Test
+
+@Suppress("UnstableApiUsage")
+class DumpableNotRegisteredDetectorTest : SystemUILintDetectorTest() {
+    override fun getDetector(): Detector = DumpableNotRegisteredDetector()
+
+    override fun getIssues(): List<Issue> = listOf(DumpableNotRegisteredDetector.ISSUE)
+
+    @Test
+    fun classIsNotDumpable_noViolation() {
+        lint()
+            .files(
+                TestFiles.java(
+                    """
+                    package test.pkg;
+
+                    class SomeClass() {
+                    }
+                """.trimIndent()
+                ),
+                *stubs,
+            )
+            .issues(DumpableNotRegisteredDetector.ISSUE)
+            .run()
+            .expectClean()
+    }
+
+    @Test
+    fun classIsDumpable_andRegisterIsCalled_noViolation() {
+        lint()
+            .files(
+                TestFiles.java(
+                    """
+                    package test.pkg;
+
+                    import com.android.systemui.Dumpable;
+                    import com.android.systemui.dump.DumpManager;
+
+                    public class SomeClass implements Dumpable {
+                        SomeClass(DumpManager dumpManager) {
+                            dumpManager.registerDumpable(this);
+                        }
+
+                        @Override
+                        void dump(PrintWriter pw, String[] args) {
+                            pw.println("testDump");
+                        }
+                    }
+                """.trimIndent()
+                ),
+                *stubs,
+            )
+            .issues(DumpableNotRegisteredDetector.ISSUE)
+            .run()
+            .expectClean()
+    }
+
+    @Test
+    fun classIsDumpable_andRegisterNormalIsCalled_noViolation() {
+        lint()
+            .files(
+                TestFiles.java(
+                    """
+                    package test.pkg;
+
+                    import com.android.systemui.Dumpable;
+                    import com.android.systemui.dump.DumpManager;
+
+                    public class SomeClass implements Dumpable {
+                        SomeClass(DumpManager dumpManager) {
+                            dumpManager.registerNormalDumpable(this);
+                        }
+
+                        @Override
+                        void dump(PrintWriter pw, String[] args) {
+                            pw.println("testDump");
+                        }
+                    }
+                """.trimIndent()
+                ),
+                *stubs,
+            )
+            .issues(DumpableNotRegisteredDetector.ISSUE)
+            .run()
+            .expectClean()
+    }
+
+    @Test
+    fun classIsDumpable_andRegisterCriticalIsCalled_noViolation() {
+        lint()
+            .files(
+                TestFiles.java(
+                    """
+                    package test.pkg;
+
+                    import com.android.systemui.Dumpable;
+                    import com.android.systemui.dump.DumpManager;
+
+                    public class SomeClass implements Dumpable {
+                        SomeClass(DumpManager dumpManager) {
+                            dumpManager.registerCriticalDumpable(this);
+                        }
+
+                        @Override
+                        void dump(PrintWriter pw, String[] args) {
+                            pw.println("testDump");
+                        }
+                    }
+                """.trimIndent()
+                ),
+                *stubs,
+            )
+            .issues(DumpableNotRegisteredDetector.ISSUE)
+            .run()
+            .expectClean()
+    }
+
+    @Test
+    fun classIsDumpable_noRegister_violation() {
+        lint()
+            .files(
+                TestFiles.java(
+                        """
+                    package test.pkg;
+
+                    import com.android.systemui.Dumpable;
+
+                    public class SomeClass implements Dumpable {
+                        @Override
+                        public void dump() {
+                        }
+                    }
+                """
+                    )
+                    .indented(),
+                *stubs,
+            )
+            .issues(DumpableNotRegisteredDetector.ISSUE)
+            .run()
+            .expect(
+                ("""
+                src/test/pkg/SomeClass.java:5: Warning: Any class implementing Dumpable must call DumpManager.registerNormalDumpable or DumpManager.registerCriticalDumpable [DumpableNotRegistered]
+                public class SomeClass implements Dumpable {
+                             ~~~~~~~~~
+                0 errors, 1 warnings
+                """)
+                    .trimIndent()
+            )
+    }
+
+    @Test
+    fun classIsDumpable_usesNotDumpManagerMethod_violation() {
+        lint()
+            .files(
+                TestFiles.java(
+                        """
+                    package test.pkg;
+
+                    import com.android.systemui.Dumpable;
+                    import com.android.systemui.OtherRegistrationObject;
+
+                    public class SomeClass implements Dumpable {
+                        public SomeClass(OtherRegistrationObject otherRegistrationObject) {
+                            otherRegistrationObject.registerDumpable(this);
+                        }
+                        @Override
+                        public void dump() {
+                        }
+                    }
+                """
+                    )
+                    .indented(),
+                *stubs,
+            )
+            .issues(DumpableNotRegisteredDetector.ISSUE)
+            .run()
+            .expect(
+                ("""
+                src/test/pkg/SomeClass.java:6: Warning: Any class implementing Dumpable must call DumpManager.registerNormalDumpable or DumpManager.registerCriticalDumpable [DumpableNotRegistered]
+                public class SomeClass implements Dumpable {
+                             ~~~~~~~~~
+                0 errors, 1 warnings
+                """)
+                    .trimIndent()
+            )
+    }
+
+    @Test
+    fun classIsDumpableAndCoreStartable_noRegister_noViolation() {
+        lint()
+            .files(
+                TestFiles.java(
+                        """
+                    package test.pkg;
+
+                    import com.android.systemui.Dumpable;
+                    import com.android.systemui.CoreStartable;
+
+                    public class SomeClass implements Dumpable, CoreStartable {
+                        @Override
+                        public void start() {
+                        }
+
+                        @Override
+                        public void dump() {
+                        }
+                    }
+                """
+                    )
+                    .indented(),
+                *stubs,
+            )
+            .issues(DumpableNotRegisteredDetector.ISSUE)
+            .run()
+            .expectClean()
+    }
+
+    @Test
+    fun classIsAbstract_noRegister_noViolation() {
+        lint()
+            .files(
+                TestFiles.java(
+                        """
+                    package test.pkg;
+
+                    import com.android.systemui.Dumpable;
+
+                    public abstract class SomeClass implements Dumpable {
+                        void abstractMethodHere();
+
+                        @Override
+                        public void dump() {
+                        }
+                    }
+                """
+                    )
+                    .indented(),
+                *stubs,
+            )
+            .issues(DumpableNotRegisteredDetector.ISSUE)
+            .run()
+            .expectClean()
+    }
+
+    companion object {
+        private val DUMPABLE_STUB =
+            TestFiles.java(
+                    """
+                    package com.android.systemui;
+
+                    import com.android.systemui.dump.DumpManager;
+                    import java.io.PrintWriter;
+
+                    public interface Dumpable {
+                        void dump();
+                    }
+                """
+                )
+                .indented()
+
+        private val DUMP_MANAGER_STUB =
+            TestFiles.java(
+                    """
+                    package com.android.systemui.dump;
+
+                    public interface DumpManager {
+                        void registerDumpable(Dumpable module);
+                        void registerNormalDumpable(Dumpable module);
+                        void registerCriticalDumpable(Dumpable module);
+                    }
+                """
+                )
+                .indented()
+
+        private val OTHER_REGISTRATION_OBJECT_STUB =
+            TestFiles.java(
+                    """
+                    package com.android.systemui;
+
+                    public interface OtherRegistrationObject {
+                        void registerDumpable(Dumpable module);
+                    }
+                """
+                )
+                .indented()
+
+        private val CORE_STARTABLE_STUB =
+            TestFiles.java(
+                    """
+                    package com.android.systemui;
+
+                    public interface CoreStartable {
+                        void start();
+                    }
+                """
+                )
+                .indented()
+
+        private val stubs =
+            arrayOf(
+                DUMPABLE_STUB,
+                DUMP_MANAGER_STUB,
+                OTHER_REGISTRATION_OBJECT_STUB,
+                CORE_STARTABLE_STUB,
+            )
+    }
+}
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/SystemUiController.kt b/packages/SystemUI/compose/core/src/com/android/compose/SystemUiController.kt
index a02954a..08ab146 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/SystemUiController.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/SystemUiController.kt
@@ -78,11 +78,10 @@
      * Set the status bar color.
      *
      * @param color The **desired** [Color] to set. This may require modification if running on an
-     * API level that only supports white status bar icons.
+     *   API level that only supports white status bar icons.
      * @param darkIcons Whether dark status bar icons would be preferable.
      * @param transformColorForLightContent A lambda which will be invoked to transform [color] if
-     * dark icons were requested but are not available. Defaults to applying a black scrim.
-     *
+     *   dark icons were requested but are not available. Defaults to applying a black scrim.
      * @see statusBarDarkContentEnabled
      */
     fun setStatusBarColor(
@@ -95,16 +94,15 @@
      * Set the navigation bar color.
      *
      * @param color The **desired** [Color] to set. This may require modification if running on an
-     * API level that only supports white navigation bar icons. Additionally this will be ignored
-     * and [Color.Transparent] will be used on API 29+ where gesture navigation is preferred or the
-     * system UI automatically applies background protection in other navigation modes.
+     *   API level that only supports white navigation bar icons. Additionally this will be ignored
+     *   and [Color.Transparent] will be used on API 29+ where gesture navigation is preferred or
+     *   the system UI automatically applies background protection in other navigation modes.
      * @param darkIcons Whether dark navigation bar icons would be preferable.
      * @param navigationBarContrastEnforced Whether the system should ensure that the navigation bar
-     * has enough contrast when a fully transparent background is requested. Only supported on API
-     * 29+.
+     *   has enough contrast when a fully transparent background is requested. Only supported on API
+     *   29+.
      * @param transformColorForLightContent A lambda which will be invoked to transform [color] if
-     * dark icons were requested but are not available. Defaults to applying a black scrim.
-     *
+     *   dark icons were requested but are not available. Defaults to applying a black scrim.
      * @see navigationBarDarkContentEnabled
      * @see navigationBarContrastEnforced
      */
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt b/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
index cfc38df..d4a81f9 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
@@ -255,7 +255,9 @@
                     .onGloballyPositioned {
                         controller.boundsInComposeViewRoot.value = it.boundsInRoot()
                     }
-            ) { wrappedContent(controller.expandable) }
+            ) {
+                wrappedContent(controller.expandable)
+            }
         }
         else -> {
             val clickModifier =
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt b/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt
index edb10c7d..767756e 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt
@@ -156,9 +156,9 @@
      * Create a [LaunchAnimator.Controller] that is going to be used to drive an activity or dialog
      * animation. This controller will:
      * 1. Compute the start/end animation state using [boundsInComposeViewRoot] and the location of
-     * composeViewRoot on the screen.
+     *    composeViewRoot on the screen.
      * 2. Update [animatorState] with the current animation state if we are animating, or null
-     * otherwise.
+     *    otherwise.
      */
     private fun launchController(): LaunchAnimator.Controller {
         return object : LaunchAnimator.Controller {
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/pager/Pager.kt b/packages/SystemUI/compose/core/src/com/android/compose/pager/Pager.kt
index eb9d625..a80a1f9 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/pager/Pager.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/pager/Pager.kt
@@ -86,21 +86,20 @@
 /**
  * A horizontally scrolling layout that allows users to flip between items to the left and right.
  *
- * @sample com.google.accompanist.sample.pager.HorizontalPagerSample
- *
  * @param count the number of pages.
  * @param modifier the modifier to apply to this layout.
  * @param state the state object to be used to control or observe the pager's state.
  * @param reverseLayout reverse the direction of scrolling and layout, when `true` items will be
- * composed from the end to the start and [PagerState.currentPage] == 0 will mean the first item is
- * located at the end.
+ *   composed from the end to the start and [PagerState.currentPage] == 0 will mean the first item
+ *   is located at the end.
  * @param itemSpacing horizontal spacing to add between items.
  * @param flingBehavior logic describing fling behavior.
  * @param key the scroll position will be maintained based on the key, which means if you add/remove
- * items before the current visible item the item with the given key will be kept as the first
- * visible one.
+ *   items before the current visible item the item with the given key will be kept as the first
+ *   visible one.
  * @param content a block which describes the content. Inside this block you can reference
- * [PagerScope.currentPage] and other properties in [PagerScope].
+ *   [PagerScope.currentPage] and other properties in [PagerScope].
+ * @sample com.google.accompanist.sample.pager.HorizontalPagerSample
  */
 @ExperimentalPagerApi
 @Composable
@@ -134,21 +133,20 @@
 /**
  * A vertically scrolling layout that allows users to flip between items to the top and bottom.
  *
- * @sample com.google.accompanist.sample.pager.VerticalPagerSample
- *
  * @param count the number of pages.
  * @param modifier the modifier to apply to this layout.
  * @param state the state object to be used to control or observe the pager's state.
  * @param reverseLayout reverse the direction of scrolling and layout, when `true` items will be
- * composed from the bottom to the top and [PagerState.currentPage] == 0 will mean the first item is
- * located at the bottom.
+ *   composed from the bottom to the top and [PagerState.currentPage] == 0 will mean the first item
+ *   is located at the bottom.
  * @param itemSpacing vertical spacing to add between items.
  * @param flingBehavior logic describing fling behavior.
  * @param key the scroll position will be maintained based on the key, which means if you add/remove
- * items before the current visible item the item with the given key will be kept as the first
- * visible one.
+ *   items before the current visible item the item with the given key will be kept as the first
+ *   visible one.
  * @param content a block which describes the content. Inside this block you can reference
- * [PagerScope.currentPage] and other properties in [PagerScope].
+ *   [PagerScope.currentPage] and other properties in [PagerScope].
+ * @sample com.google.accompanist.sample.pager.VerticalPagerSample
  */
 @ExperimentalPagerApi
 @Composable
@@ -246,7 +244,9 @@
                         // Constraint the content to be <= than the size of the pager.
                         .fillParentMaxHeight()
                         .wrapContentSize()
-                ) { pagerScope.content(page) }
+                ) {
+                    pagerScope.content(page)
+                }
             }
         }
     } else {
@@ -272,7 +272,9 @@
                         // Constraint the content to be <= than the size of the pager.
                         .fillParentMaxWidth()
                         .wrapContentSize()
-                ) { pagerScope.content(page) }
+                ) {
+                    pagerScope.content(page)
+                }
             }
         }
     }
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/pager/PagerState.kt b/packages/SystemUI/compose/core/src/com/android/compose/pager/PagerState.kt
index 2e6ae78..1822a68 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/pager/PagerState.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/pager/PagerState.kt
@@ -198,7 +198,7 @@
      *
      * @param page the page to animate to. Must be between 0 and [pageCount] (inclusive).
      * @param pageOffset the percentage of the page width to offset, from the start of [page]. Must
-     * be in the range 0f..1f.
+     *   be in the range 0f..1f.
      */
     suspend fun animateScrollToPage(
         @IntRange(from = 0) page: Int,
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/pager/SnappingFlingBehavior.kt b/packages/SystemUI/compose/core/src/com/android/compose/pager/SnappingFlingBehavior.kt
index 23122de..9814029 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/pager/SnappingFlingBehavior.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/pager/SnappingFlingBehavior.kt
@@ -44,11 +44,11 @@
 /**
  * Create and remember a snapping [FlingBehavior] to be used with [LazyListState].
  *
- * TODO: move this to a new module and make it public
- *
  * @param lazyListState The [LazyListState] to update.
  * @param decayAnimationSpec The decay animation spec to use for decayed flings.
  * @param snapAnimationSpec The animation spec to use when snapping.
+ *
+ * TODO: move this to a new module and make it public
  */
 @Composable
 internal fun rememberSnappingFlingBehavior(
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/swipeable/Swipeable.kt b/packages/SystemUI/compose/core/src/com/android/compose/swipeable/Swipeable.kt
new file mode 100644
index 0000000..946e779
--- /dev/null
+++ b/packages/SystemUI/compose/core/src/com/android/compose/swipeable/Swipeable.kt
@@ -0,0 +1,849 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.compose.swipeable
+
+import androidx.compose.animation.core.Animatable
+import androidx.compose.animation.core.AnimationSpec
+import androidx.compose.animation.core.SpringSpec
+import androidx.compose.foundation.gestures.DraggableState
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.gestures.draggable
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
+import androidx.compose.runtime.Immutable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.Stable
+import androidx.compose.runtime.State
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.saveable.Saver
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
+import androidx.compose.runtime.snapshotFlow
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.composed
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
+import androidx.compose.ui.input.nestedscroll.NestedScrollSource
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.platform.debugInspectorInfo
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.Velocity
+import androidx.compose.ui.unit.dp
+import com.android.compose.swipeable.SwipeableDefaults.AnimationSpec
+import com.android.compose.swipeable.SwipeableDefaults.StandardResistanceFactor
+import com.android.compose.swipeable.SwipeableDefaults.VelocityThreshold
+import com.android.compose.swipeable.SwipeableDefaults.resistanceConfig
+import com.android.compose.ui.util.lerp
+import kotlin.math.PI
+import kotlin.math.abs
+import kotlin.math.sign
+import kotlin.math.sin
+import kotlinx.coroutines.CancellationException
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.take
+import kotlinx.coroutines.launch
+
+/**
+ * State of the [swipeable] modifier.
+ *
+ * This contains necessary information about any ongoing swipe or animation and provides methods to
+ * change the state either immediately or by starting an animation. To create and remember a
+ * [SwipeableState] with the default animation clock, use [rememberSwipeableState].
+ *
+ * @param initialValue The initial value of the state.
+ * @param animationSpec The default animation that will be used to animate to a new state.
+ * @param confirmStateChange Optional callback invoked to confirm or veto a pending state change.
+ *
+ * TODO(b/272311106): this is a fork from material. Unfork it when Swipeable.kt reaches material3.
+ */
+@Stable
+open class SwipeableState<T>(
+    initialValue: T,
+    internal val animationSpec: AnimationSpec<Float> = AnimationSpec,
+    internal val confirmStateChange: (newValue: T) -> Boolean = { true }
+) {
+    /**
+     * The current value of the state.
+     *
+     * If no swipe or animation is in progress, this corresponds to the anchor at which the
+     * [swipeable] is currently settled. If a swipe or animation is in progress, this corresponds
+     * the last anchor at which the [swipeable] was settled before the swipe or animation started.
+     */
+    var currentValue: T by mutableStateOf(initialValue)
+        private set
+
+    /** Whether the state is currently animating. */
+    var isAnimationRunning: Boolean by mutableStateOf(false)
+        private set
+
+    /**
+     * The current position (in pixels) of the [swipeable].
+     *
+     * You should use this state to offset your content accordingly. The recommended way is to use
+     * `Modifier.offsetPx`. This includes the resistance by default, if resistance is enabled.
+     */
+    val offset: State<Float>
+        get() = offsetState
+
+    /** The amount by which the [swipeable] has been swiped past its bounds. */
+    val overflow: State<Float>
+        get() = overflowState
+
+    // Use `Float.NaN` as a placeholder while the state is uninitialised.
+    private val offsetState = mutableStateOf(0f)
+    private val overflowState = mutableStateOf(0f)
+
+    // the source of truth for the "real"(non ui) position
+    // basically position in bounds + overflow
+    private val absoluteOffset = mutableStateOf(0f)
+
+    // current animation target, if animating, otherwise null
+    private val animationTarget = mutableStateOf<Float?>(null)
+
+    internal var anchors by mutableStateOf(emptyMap<Float, T>())
+
+    private val latestNonEmptyAnchorsFlow: Flow<Map<Float, T>> =
+        snapshotFlow { anchors }.filter { it.isNotEmpty() }.take(1)
+
+    internal var minBound = Float.NEGATIVE_INFINITY
+    internal var maxBound = Float.POSITIVE_INFINITY
+
+    internal fun ensureInit(newAnchors: Map<Float, T>) {
+        if (anchors.isEmpty()) {
+            // need to do initial synchronization synchronously :(
+            val initialOffset = newAnchors.getOffset(currentValue)
+            requireNotNull(initialOffset) { "The initial value must have an associated anchor." }
+            offsetState.value = initialOffset
+            absoluteOffset.value = initialOffset
+        }
+    }
+
+    internal suspend fun processNewAnchors(oldAnchors: Map<Float, T>, newAnchors: Map<Float, T>) {
+        if (oldAnchors.isEmpty()) {
+            // If this is the first time that we receive anchors, then we need to initialise
+            // the state so we snap to the offset associated to the initial value.
+            minBound = newAnchors.keys.minOrNull()!!
+            maxBound = newAnchors.keys.maxOrNull()!!
+            val initialOffset = newAnchors.getOffset(currentValue)
+            requireNotNull(initialOffset) { "The initial value must have an associated anchor." }
+            snapInternalToOffset(initialOffset)
+        } else if (newAnchors != oldAnchors) {
+            // If we have received new anchors, then the offset of the current value might
+            // have changed, so we need to animate to the new offset. If the current value
+            // has been removed from the anchors then we animate to the closest anchor
+            // instead. Note that this stops any ongoing animation.
+            minBound = Float.NEGATIVE_INFINITY
+            maxBound = Float.POSITIVE_INFINITY
+            val animationTargetValue = animationTarget.value
+            // if we're in the animation already, let's find it a new home
+            val targetOffset =
+                if (animationTargetValue != null) {
+                    // first, try to map old state to the new state
+                    val oldState = oldAnchors[animationTargetValue]
+                    val newState = newAnchors.getOffset(oldState)
+                    // return new state if exists, or find the closes one among new anchors
+                    newState ?: newAnchors.keys.minByOrNull { abs(it - animationTargetValue) }!!
+                } else {
+                    // we're not animating, proceed by finding the new anchors for an old value
+                    val actualOldValue = oldAnchors[offset.value]
+                    val value = if (actualOldValue == currentValue) currentValue else actualOldValue
+                    newAnchors.getOffset(value)
+                        ?: newAnchors.keys.minByOrNull { abs(it - offset.value) }!!
+                }
+            try {
+                animateInternalToOffset(targetOffset, animationSpec)
+            } catch (c: CancellationException) {
+                // If the animation was interrupted for any reason, snap as a last resort.
+                snapInternalToOffset(targetOffset)
+            } finally {
+                currentValue = newAnchors.getValue(targetOffset)
+                minBound = newAnchors.keys.minOrNull()!!
+                maxBound = newAnchors.keys.maxOrNull()!!
+            }
+        }
+    }
+
+    internal var thresholds: (Float, Float) -> Float by mutableStateOf({ _, _ -> 0f })
+
+    internal var velocityThreshold by mutableStateOf(0f)
+
+    internal var resistance: ResistanceConfig? by mutableStateOf(null)
+
+    internal val draggableState = DraggableState {
+        val newAbsolute = absoluteOffset.value + it
+        val clamped = newAbsolute.coerceIn(minBound, maxBound)
+        val overflow = newAbsolute - clamped
+        val resistanceDelta = resistance?.computeResistance(overflow) ?: 0f
+        offsetState.value = clamped + resistanceDelta
+        overflowState.value = overflow
+        absoluteOffset.value = newAbsolute
+    }
+
+    private suspend fun snapInternalToOffset(target: Float) {
+        draggableState.drag { dragBy(target - absoluteOffset.value) }
+    }
+
+    private suspend fun animateInternalToOffset(target: Float, spec: AnimationSpec<Float>) {
+        draggableState.drag {
+            var prevValue = absoluteOffset.value
+            animationTarget.value = target
+            isAnimationRunning = true
+            try {
+                Animatable(prevValue).animateTo(target, spec) {
+                    dragBy(this.value - prevValue)
+                    prevValue = this.value
+                }
+            } finally {
+                animationTarget.value = null
+                isAnimationRunning = false
+            }
+        }
+    }
+
+    /**
+     * The target value of the state.
+     *
+     * If a swipe is in progress, this is the value that the [swipeable] would animate to if the
+     * swipe finished. If an animation is running, this is the target value of that animation.
+     * Finally, if no swipe or animation is in progress, this is the same as the [currentValue].
+     */
+    val targetValue: T
+        get() {
+            // TODO(calintat): Track current velocity (b/149549482) and use that here.
+            val target =
+                animationTarget.value
+                    ?: computeTarget(
+                        offset = offset.value,
+                        lastValue = anchors.getOffset(currentValue) ?: offset.value,
+                        anchors = anchors.keys,
+                        thresholds = thresholds,
+                        velocity = 0f,
+                        velocityThreshold = Float.POSITIVE_INFINITY
+                    )
+            return anchors[target] ?: currentValue
+        }
+
+    /**
+     * Information about the ongoing swipe or animation, if any. See [SwipeProgress] for details.
+     *
+     * If no swipe or animation is in progress, this returns `SwipeProgress(value, value, 1f)`.
+     */
+    val progress: SwipeProgress<T>
+        get() {
+            val bounds = findBounds(offset.value, anchors.keys)
+            val from: T
+            val to: T
+            val fraction: Float
+            when (bounds.size) {
+                0 -> {
+                    from = currentValue
+                    to = currentValue
+                    fraction = 1f
+                }
+                1 -> {
+                    from = anchors.getValue(bounds[0])
+                    to = anchors.getValue(bounds[0])
+                    fraction = 1f
+                }
+                else -> {
+                    val (a, b) =
+                        if (direction > 0f) {
+                            bounds[0] to bounds[1]
+                        } else {
+                            bounds[1] to bounds[0]
+                        }
+                    from = anchors.getValue(a)
+                    to = anchors.getValue(b)
+                    fraction = (offset.value - a) / (b - a)
+                }
+            }
+            return SwipeProgress(from, to, fraction)
+        }
+
+    /**
+     * The direction in which the [swipeable] is moving, relative to the current [currentValue].
+     *
+     * This will be either 1f if it is is moving from left to right or top to bottom, -1f if it is
+     * moving from right to left or bottom to top, or 0f if no swipe or animation is in progress.
+     */
+    val direction: Float
+        get() = anchors.getOffset(currentValue)?.let { sign(offset.value - it) } ?: 0f
+
+    /**
+     * Set the state without any animation and suspend until it's set
+     *
+     * @param targetValue The new target value to set [currentValue] to.
+     */
+    suspend fun snapTo(targetValue: T) {
+        latestNonEmptyAnchorsFlow.collect { anchors ->
+            val targetOffset = anchors.getOffset(targetValue)
+            requireNotNull(targetOffset) { "The target value must have an associated anchor." }
+            snapInternalToOffset(targetOffset)
+            currentValue = targetValue
+        }
+    }
+
+    /**
+     * Set the state to the target value by starting an animation.
+     *
+     * @param targetValue The new value to animate to.
+     * @param anim The animation that will be used to animate to the new value.
+     */
+    suspend fun animateTo(targetValue: T, anim: AnimationSpec<Float> = animationSpec) {
+        latestNonEmptyAnchorsFlow.collect { anchors ->
+            try {
+                val targetOffset = anchors.getOffset(targetValue)
+                requireNotNull(targetOffset) { "The target value must have an associated anchor." }
+                animateInternalToOffset(targetOffset, anim)
+            } finally {
+                val endOffset = absoluteOffset.value
+                val endValue =
+                    anchors
+                        // fighting rounding error once again, anchor should be as close as 0.5
+                        // pixels
+                        .filterKeys { anchorOffset -> abs(anchorOffset - endOffset) < 0.5f }
+                        .values
+                        .firstOrNull()
+                        ?: currentValue
+                currentValue = endValue
+            }
+        }
+    }
+
+    /**
+     * Perform fling with settling to one of the anchors which is determined by the given
+     * [velocity]. Fling with settling [swipeable] will always consume all the velocity provided
+     * since it will settle at the anchor.
+     *
+     * In general cases, [swipeable] flings by itself when being swiped. This method is to be used
+     * for nested scroll logic that wraps the [swipeable]. In nested scroll developer may want to
+     * trigger settling fling when the child scroll container reaches the bound.
+     *
+     * @param velocity velocity to fling and settle with
+     * @return the reason fling ended
+     */
+    suspend fun performFling(velocity: Float) {
+        latestNonEmptyAnchorsFlow.collect { anchors ->
+            val lastAnchor = anchors.getOffset(currentValue)!!
+            val targetValue =
+                computeTarget(
+                    offset = offset.value,
+                    lastValue = lastAnchor,
+                    anchors = anchors.keys,
+                    thresholds = thresholds,
+                    velocity = velocity,
+                    velocityThreshold = velocityThreshold
+                )
+            val targetState = anchors[targetValue]
+            if (targetState != null && confirmStateChange(targetState)) animateTo(targetState)
+            // If the user vetoed the state change, rollback to the previous state.
+            else animateInternalToOffset(lastAnchor, animationSpec)
+        }
+    }
+
+    /**
+     * Force [swipeable] to consume drag delta provided from outside of the regular [swipeable]
+     * gesture flow.
+     *
+     * Note: This method performs generic drag and it won't settle to any particular anchor, *
+     * leaving swipeable in between anchors. When done dragging, [performFling] must be called as
+     * well to ensure swipeable will settle at the anchor.
+     *
+     * In general cases, [swipeable] drags by itself when being swiped. This method is to be used
+     * for nested scroll logic that wraps the [swipeable]. In nested scroll developer may want to
+     * force drag when the child scroll container reaches the bound.
+     *
+     * @param delta delta in pixels to drag by
+     * @return the amount of [delta] consumed
+     */
+    fun performDrag(delta: Float): Float {
+        val potentiallyConsumed = absoluteOffset.value + delta
+        val clamped = potentiallyConsumed.coerceIn(minBound, maxBound)
+        val deltaToConsume = clamped - absoluteOffset.value
+        if (abs(deltaToConsume) > 0) {
+            draggableState.dispatchRawDelta(deltaToConsume)
+        }
+        return deltaToConsume
+    }
+
+    companion object {
+        /** The default [Saver] implementation for [SwipeableState]. */
+        fun <T : Any> Saver(
+            animationSpec: AnimationSpec<Float>,
+            confirmStateChange: (T) -> Boolean
+        ) =
+            Saver<SwipeableState<T>, T>(
+                save = { it.currentValue },
+                restore = { SwipeableState(it, animationSpec, confirmStateChange) }
+            )
+    }
+}
+
+/**
+ * Collects information about the ongoing swipe or animation in [swipeable].
+ *
+ * To access this information, use [SwipeableState.progress].
+ *
+ * @param from The state corresponding to the anchor we are moving away from.
+ * @param to The state corresponding to the anchor we are moving towards.
+ * @param fraction The fraction that the current position represents between [from] and [to]. Must
+ *   be between `0` and `1`.
+ */
+@Immutable
+class SwipeProgress<T>(
+    val from: T,
+    val to: T,
+    /*@FloatRange(from = 0.0, to = 1.0)*/
+    val fraction: Float
+) {
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other !is SwipeProgress<*>) return false
+
+        if (from != other.from) return false
+        if (to != other.to) return false
+        if (fraction != other.fraction) return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = from?.hashCode() ?: 0
+        result = 31 * result + (to?.hashCode() ?: 0)
+        result = 31 * result + fraction.hashCode()
+        return result
+    }
+
+    override fun toString(): String {
+        return "SwipeProgress(from=$from, to=$to, fraction=$fraction)"
+    }
+}
+
+/**
+ * Create and [remember] a [SwipeableState] with the default animation clock.
+ *
+ * @param initialValue The initial value of the state.
+ * @param animationSpec The default animation that will be used to animate to a new state.
+ * @param confirmStateChange Optional callback invoked to confirm or veto a pending state change.
+ */
+@Composable
+fun <T : Any> rememberSwipeableState(
+    initialValue: T,
+    animationSpec: AnimationSpec<Float> = AnimationSpec,
+    confirmStateChange: (newValue: T) -> Boolean = { true }
+): SwipeableState<T> {
+    return rememberSaveable(
+        saver =
+            SwipeableState.Saver(
+                animationSpec = animationSpec,
+                confirmStateChange = confirmStateChange
+            )
+    ) {
+        SwipeableState(
+            initialValue = initialValue,
+            animationSpec = animationSpec,
+            confirmStateChange = confirmStateChange
+        )
+    }
+}
+
+/**
+ * Create and [remember] a [SwipeableState] which is kept in sync with another state, i.e.:
+ * 1. Whenever the [value] changes, the [SwipeableState] will be animated to that new value.
+ * 2. Whenever the value of the [SwipeableState] changes (e.g. after a swipe), the owner of the
+ *    [value] will be notified to update their state to the new value of the [SwipeableState] by
+ *    invoking [onValueChange]. If the owner does not update their state to the provided value for
+ *    some reason, then the [SwipeableState] will perform a rollback to the previous, correct value.
+ */
+@Composable
+internal fun <T : Any> rememberSwipeableStateFor(
+    value: T,
+    onValueChange: (T) -> Unit,
+    animationSpec: AnimationSpec<Float> = AnimationSpec
+): SwipeableState<T> {
+    val swipeableState = remember {
+        SwipeableState(
+            initialValue = value,
+            animationSpec = animationSpec,
+            confirmStateChange = { true }
+        )
+    }
+    val forceAnimationCheck = remember { mutableStateOf(false) }
+    LaunchedEffect(value, forceAnimationCheck.value) {
+        if (value != swipeableState.currentValue) {
+            swipeableState.animateTo(value)
+        }
+    }
+    DisposableEffect(swipeableState.currentValue) {
+        if (value != swipeableState.currentValue) {
+            onValueChange(swipeableState.currentValue)
+            forceAnimationCheck.value = !forceAnimationCheck.value
+        }
+        onDispose {}
+    }
+    return swipeableState
+}
+
+/**
+ * Enable swipe gestures between a set of predefined states.
+ *
+ * To use this, you must provide a map of anchors (in pixels) to states (of type [T]). Note that
+ * this map cannot be empty and cannot have two anchors mapped to the same state.
+ *
+ * When a swipe is detected, the offset of the [SwipeableState] will be updated with the swipe
+ * delta. You should use this offset to move your content accordingly (see `Modifier.offsetPx`).
+ * When the swipe ends, the offset will be animated to one of the anchors and when that anchor is
+ * reached, the value of the [SwipeableState] will also be updated to the state corresponding to the
+ * new anchor. The target anchor is calculated based on the provided positional [thresholds].
+ *
+ * Swiping is constrained between the minimum and maximum anchors. If the user attempts to swipe
+ * past these bounds, a resistance effect will be applied by default. The amount of resistance at
+ * each edge is specified by the [resistance] config. To disable all resistance, set it to `null`.
+ *
+ * For an example of a [swipeable] with three states, see:
+ *
+ * @param T The type of the state.
+ * @param state The state of the [swipeable].
+ * @param anchors Pairs of anchors and states, used to map anchors to states and vice versa.
+ * @param thresholds Specifies where the thresholds between the states are. The thresholds will be
+ *   used to determine which state to animate to when swiping stops. This is represented as a lambda
+ *   that takes two states and returns the threshold between them in the form of a
+ *   [ThresholdConfig]. Note that the order of the states corresponds to the swipe direction.
+ * @param orientation The orientation in which the [swipeable] can be swiped.
+ * @param enabled Whether this [swipeable] is enabled and should react to the user's input.
+ * @param reverseDirection Whether to reverse the direction of the swipe, so a top to bottom swipe
+ *   will behave like bottom to top, and a left to right swipe will behave like right to left.
+ * @param interactionSource Optional [MutableInteractionSource] that will passed on to the internal
+ *   [Modifier.draggable].
+ * @param resistance Controls how much resistance will be applied when swiping past the bounds.
+ * @param velocityThreshold The threshold (in dp per second) that the end velocity has to exceed in
+ *   order to animate to the next state, even if the positional [thresholds] have not been reached.
+ * @sample androidx.compose.material.samples.SwipeableSample
+ */
+fun <T> Modifier.swipeable(
+    state: SwipeableState<T>,
+    anchors: Map<Float, T>,
+    orientation: Orientation,
+    enabled: Boolean = true,
+    reverseDirection: Boolean = false,
+    interactionSource: MutableInteractionSource? = null,
+    thresholds: (from: T, to: T) -> ThresholdConfig = { _, _ -> FixedThreshold(56.dp) },
+    resistance: ResistanceConfig? = resistanceConfig(anchors.keys),
+    velocityThreshold: Dp = VelocityThreshold
+) =
+    composed(
+        inspectorInfo =
+            debugInspectorInfo {
+                name = "swipeable"
+                properties["state"] = state
+                properties["anchors"] = anchors
+                properties["orientation"] = orientation
+                properties["enabled"] = enabled
+                properties["reverseDirection"] = reverseDirection
+                properties["interactionSource"] = interactionSource
+                properties["thresholds"] = thresholds
+                properties["resistance"] = resistance
+                properties["velocityThreshold"] = velocityThreshold
+            }
+    ) {
+        require(anchors.isNotEmpty()) { "You must have at least one anchor." }
+        require(anchors.values.distinct().count() == anchors.size) {
+            "You cannot have two anchors mapped to the same state."
+        }
+        val density = LocalDensity.current
+        state.ensureInit(anchors)
+        LaunchedEffect(anchors, state) {
+            val oldAnchors = state.anchors
+            state.anchors = anchors
+            state.resistance = resistance
+            state.thresholds = { a, b ->
+                val from = anchors.getValue(a)
+                val to = anchors.getValue(b)
+                with(thresholds(from, to)) { density.computeThreshold(a, b) }
+            }
+            with(density) { state.velocityThreshold = velocityThreshold.toPx() }
+            state.processNewAnchors(oldAnchors, anchors)
+        }
+
+        Modifier.draggable(
+            orientation = orientation,
+            enabled = enabled,
+            reverseDirection = reverseDirection,
+            interactionSource = interactionSource,
+            startDragImmediately = state.isAnimationRunning,
+            onDragStopped = { velocity -> launch { state.performFling(velocity) } },
+            state = state.draggableState
+        )
+    }
+
+/**
+ * Interface to compute a threshold between two anchors/states in a [swipeable].
+ *
+ * To define a [ThresholdConfig], consider using [FixedThreshold] and [FractionalThreshold].
+ */
+@Stable
+interface ThresholdConfig {
+    /** Compute the value of the threshold (in pixels), once the values of the anchors are known. */
+    fun Density.computeThreshold(fromValue: Float, toValue: Float): Float
+}
+
+/**
+ * A fixed threshold will be at an [offset] away from the first anchor.
+ *
+ * @param offset The offset (in dp) that the threshold will be at.
+ */
+@Immutable
+data class FixedThreshold(private val offset: Dp) : ThresholdConfig {
+    override fun Density.computeThreshold(fromValue: Float, toValue: Float): Float {
+        return fromValue + offset.toPx() * sign(toValue - fromValue)
+    }
+}
+
+/**
+ * A fractional threshold will be at a [fraction] of the way between the two anchors.
+ *
+ * @param fraction The fraction (between 0 and 1) that the threshold will be at.
+ */
+@Immutable
+data class FractionalThreshold(
+    /*@FloatRange(from = 0.0, to = 1.0)*/
+    private val fraction: Float
+) : ThresholdConfig {
+    override fun Density.computeThreshold(fromValue: Float, toValue: Float): Float {
+        return lerp(fromValue, toValue, fraction)
+    }
+}
+
+/**
+ * Specifies how resistance is calculated in [swipeable].
+ *
+ * There are two things needed to calculate resistance: the resistance basis determines how much
+ * overflow will be consumed to achieve maximum resistance, and the resistance factor determines the
+ * amount of resistance (the larger the resistance factor, the stronger the resistance).
+ *
+ * The resistance basis is usually either the size of the component which [swipeable] is applied to,
+ * or the distance between the minimum and maximum anchors. For a constructor in which the
+ * resistance basis defaults to the latter, consider using [resistanceConfig].
+ *
+ * You may specify different resistance factors for each bound. Consider using one of the default
+ * resistance factors in [SwipeableDefaults]: `StandardResistanceFactor` to convey that the user has
+ * run out of things to see, and `StiffResistanceFactor` to convey that the user cannot swipe this
+ * right now. Also, you can set either factor to 0 to disable resistance at that bound.
+ *
+ * @param basis Specifies the maximum amount of overflow that will be consumed. Must be positive.
+ * @param factorAtMin The factor by which to scale the resistance at the minimum bound. Must not be
+ *   negative.
+ * @param factorAtMax The factor by which to scale the resistance at the maximum bound. Must not be
+ *   negative.
+ */
+@Immutable
+class ResistanceConfig(
+    /*@FloatRange(from = 0.0, fromInclusive = false)*/
+    val basis: Float,
+    /*@FloatRange(from = 0.0)*/
+    val factorAtMin: Float = StandardResistanceFactor,
+    /*@FloatRange(from = 0.0)*/
+    val factorAtMax: Float = StandardResistanceFactor
+) {
+    fun computeResistance(overflow: Float): Float {
+        val factor = if (overflow < 0) factorAtMin else factorAtMax
+        if (factor == 0f) return 0f
+        val progress = (overflow / basis).coerceIn(-1f, 1f)
+        return basis / factor * sin(progress * PI.toFloat() / 2)
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other !is ResistanceConfig) return false
+
+        if (basis != other.basis) return false
+        if (factorAtMin != other.factorAtMin) return false
+        if (factorAtMax != other.factorAtMax) return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = basis.hashCode()
+        result = 31 * result + factorAtMin.hashCode()
+        result = 31 * result + factorAtMax.hashCode()
+        return result
+    }
+
+    override fun toString(): String {
+        return "ResistanceConfig(basis=$basis, factorAtMin=$factorAtMin, factorAtMax=$factorAtMax)"
+    }
+}
+
+/**
+ * Given an offset x and a set of anchors, return a list of anchors:
+ * 1. [ ] if the set of anchors is empty,
+ * 2. [ x' ] if x is equal to one of the anchors, accounting for a small rounding error, where x' is
+ *    x rounded to the exact value of the matching anchor,
+ * 3. [ min ] if min is the minimum anchor and x < min,
+ * 4. [ max ] if max is the maximum anchor and x > max, or
+ * 5. [ a , b ] if a and b are anchors such that a < x < b and b - a is minimal.
+ */
+private fun findBounds(offset: Float, anchors: Set<Float>): List<Float> {
+    // Find the anchors the target lies between with a little bit of rounding error.
+    val a = anchors.filter { it <= offset + 0.001 }.maxOrNull()
+    val b = anchors.filter { it >= offset - 0.001 }.minOrNull()
+
+    return when {
+        a == null ->
+            // case 1 or 3
+            listOfNotNull(b)
+        b == null ->
+            // case 4
+            listOf(a)
+        a == b ->
+            // case 2
+            // Can't return offset itself here since it might not be exactly equal
+            // to the anchor, despite being considered an exact match.
+            listOf(a)
+        else ->
+            // case 5
+            listOf(a, b)
+    }
+}
+
+private fun computeTarget(
+    offset: Float,
+    lastValue: Float,
+    anchors: Set<Float>,
+    thresholds: (Float, Float) -> Float,
+    velocity: Float,
+    velocityThreshold: Float
+): Float {
+    val bounds = findBounds(offset, anchors)
+    return when (bounds.size) {
+        0 -> lastValue
+        1 -> bounds[0]
+        else -> {
+            val lower = bounds[0]
+            val upper = bounds[1]
+            if (lastValue <= offset) {
+                // Swiping from lower to upper (positive).
+                if (velocity >= velocityThreshold) {
+                    return upper
+                } else {
+                    val threshold = thresholds(lower, upper)
+                    if (offset < threshold) lower else upper
+                }
+            } else {
+                // Swiping from upper to lower (negative).
+                if (velocity <= -velocityThreshold) {
+                    return lower
+                } else {
+                    val threshold = thresholds(upper, lower)
+                    if (offset > threshold) upper else lower
+                }
+            }
+        }
+    }
+}
+
+private fun <T> Map<Float, T>.getOffset(state: T): Float? {
+    return entries.firstOrNull { it.value == state }?.key
+}
+
+/** Contains useful defaults for [swipeable] and [SwipeableState]. */
+object SwipeableDefaults {
+    /** The default animation used by [SwipeableState]. */
+    val AnimationSpec = SpringSpec<Float>()
+
+    /** The default velocity threshold (1.8 dp per millisecond) used by [swipeable]. */
+    val VelocityThreshold = 125.dp
+
+    /** A stiff resistance factor which indicates that swiping isn't available right now. */
+    const val StiffResistanceFactor = 20f
+
+    /** A standard resistance factor which indicates that the user has run out of things to see. */
+    const val StandardResistanceFactor = 10f
+
+    /**
+     * The default resistance config used by [swipeable].
+     *
+     * This returns `null` if there is one anchor. If there are at least two anchors, it returns a
+     * [ResistanceConfig] with the resistance basis equal to the distance between the two bounds.
+     */
+    fun resistanceConfig(
+        anchors: Set<Float>,
+        factorAtMin: Float = StandardResistanceFactor,
+        factorAtMax: Float = StandardResistanceFactor
+    ): ResistanceConfig? {
+        return if (anchors.size <= 1) {
+            null
+        } else {
+            val basis = anchors.maxOrNull()!! - anchors.minOrNull()!!
+            ResistanceConfig(basis, factorAtMin, factorAtMax)
+        }
+    }
+}
+
+// temp default nested scroll connection for swipeables which desire as an opt in
+// revisit in b/174756744 as all types will have their own specific connection probably
+internal val <T> SwipeableState<T>.PreUpPostDownNestedScrollConnection: NestedScrollConnection
+    get() =
+        object : NestedScrollConnection {
+            override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
+                val delta = available.toFloat()
+                return if (delta < 0 && source == NestedScrollSource.Drag) {
+                    performDrag(delta).toOffset()
+                } else {
+                    Offset.Zero
+                }
+            }
+
+            override fun onPostScroll(
+                consumed: Offset,
+                available: Offset,
+                source: NestedScrollSource
+            ): Offset {
+                return if (source == NestedScrollSource.Drag) {
+                    performDrag(available.toFloat()).toOffset()
+                } else {
+                    Offset.Zero
+                }
+            }
+
+            override suspend fun onPreFling(available: Velocity): Velocity {
+                val toFling = Offset(available.x, available.y).toFloat()
+                return if (toFling < 0 && offset.value > minBound) {
+                    performFling(velocity = toFling)
+                    // since we go to the anchor with tween settling, consume all for the best UX
+                    available
+                } else {
+                    Velocity.Zero
+                }
+            }
+
+            override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
+                performFling(velocity = Offset(available.x, available.y).toFloat())
+                return available
+            }
+
+            private fun Float.toOffset(): Offset = Offset(0f, this)
+
+            private fun Offset.toFloat(): Float = this.y
+        }
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/ui/util/MathHelpers.kt b/packages/SystemUI/compose/core/src/com/android/compose/ui/util/MathHelpers.kt
new file mode 100644
index 0000000..c1defb7
--- /dev/null
+++ b/packages/SystemUI/compose/core/src/com/android/compose/ui/util/MathHelpers.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.compose.ui.util
+
+import kotlin.math.roundToInt
+import kotlin.math.roundToLong
+
+// TODO(b/272311106): this is a fork from material. Unfork it when MathHelpers.kt reaches material3.
+
+/** Linearly interpolate between [start] and [stop] with [fraction] fraction between them. */
+fun lerp(start: Float, stop: Float, fraction: Float): Float {
+    return (1 - fraction) * start + fraction * stop
+}
+
+/** Linearly interpolate between [start] and [stop] with [fraction] fraction between them. */
+fun lerp(start: Int, stop: Int, fraction: Float): Int {
+    return start + ((stop - start) * fraction.toDouble()).roundToInt()
+}
+
+/** Linearly interpolate between [start] and [stop] with [fraction] fraction between them. */
+fun lerp(start: Long, stop: Long, fraction: Float): Long {
+    return start + ((stop - start) * fraction.toDouble()).roundToLong()
+}
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 e253fb9..cc33745 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
@@ -21,8 +21,10 @@
 import android.view.View
 import androidx.activity.ComponentActivity
 import androidx.lifecycle.LifecycleOwner
+import com.android.systemui.multishade.ui.viewmodel.MultiShadeViewModel
 import com.android.systemui.people.ui.viewmodel.PeopleViewModel
 import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
+import com.android.systemui.util.time.SystemClock
 
 /** The Compose facade, when Compose is *not* available. */
 object ComposeFacade : BaseComposeFacade {
@@ -48,6 +50,14 @@
         throwComposeUnavailableError()
     }
 
+    override fun createMultiShadeView(
+        context: Context,
+        viewModel: MultiShadeViewModel,
+        clock: SystemClock,
+    ): View {
+        throwComposeUnavailableError()
+    }
+
     private fun throwComposeUnavailableError(): Nothing {
         error(
             "Compose is not available. Make sure to check isComposeAvailable() before calling any" +
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 1ea18fe..0e79b18 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
@@ -23,10 +23,13 @@
 import androidx.compose.ui.platform.ComposeView
 import androidx.lifecycle.LifecycleOwner
 import com.android.compose.theme.PlatformTheme
+import com.android.systemui.multishade.ui.composable.MultiShade
+import com.android.systemui.multishade.ui.viewmodel.MultiShadeViewModel
 import com.android.systemui.people.ui.compose.PeopleScreen
 import com.android.systemui.people.ui.viewmodel.PeopleViewModel
 import com.android.systemui.qs.footer.ui.compose.FooterActions
 import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
+import com.android.systemui.util.time.SystemClock
 
 /** The Compose facade, when Compose is available. */
 object ComposeFacade : BaseComposeFacade {
@@ -51,4 +54,21 @@
             setContent { PlatformTheme { FooterActions(viewModel, qsVisibilityLifecycleOwner) } }
         }
     }
+
+    override fun createMultiShadeView(
+        context: Context,
+        viewModel: MultiShadeViewModel,
+        clock: SystemClock,
+    ): View {
+        return ComposeView(context).apply {
+            setContent {
+                PlatformTheme {
+                    MultiShade(
+                        viewModel = viewModel,
+                        clock = clock,
+                    )
+                }
+            }
+        }
+    }
 }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/multishade/ui/composable/MultiShade.kt b/packages/SystemUI/compose/features/src/com/android/systemui/multishade/ui/composable/MultiShade.kt
new file mode 100644
index 0000000..b9e38cf
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/multishade/ui/composable/MultiShade.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.systemui.multishade.ui.composable
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.gestures.detectTapGestures
+import androidx.compose.foundation.gestures.detectVerticalDragGestures
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxWithConstraints
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+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.graphics.graphicsLayer
+import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.layout.onSizeChanged
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.res.colorResource
+import androidx.compose.ui.unit.IntSize
+import com.android.systemui.R
+import com.android.systemui.multishade.shared.model.ProxiedInputModel
+import com.android.systemui.multishade.ui.viewmodel.MultiShadeViewModel
+import com.android.systemui.notifications.ui.composable.Notifications
+import com.android.systemui.qs.footer.ui.compose.QuickSettings
+import com.android.systemui.statusbar.ui.composable.StatusBar
+import com.android.systemui.util.time.SystemClock
+
+@Composable
+fun MultiShade(
+    viewModel: MultiShadeViewModel,
+    clock: SystemClock,
+    modifier: Modifier = Modifier,
+) {
+    val isScrimEnabled: Boolean by viewModel.isScrimEnabled.collectAsState()
+
+    // TODO(b/273298030): find a different way to get the height constraint from its parent.
+    BoxWithConstraints(modifier = modifier) {
+        val maxHeightPx = with(LocalDensity.current) { maxHeight.toPx() }
+
+        Scrim(
+            modifier = Modifier.fillMaxSize(),
+            remoteTouch = viewModel::onScrimTouched,
+            alpha = { viewModel.scrimAlpha.value },
+            isScrimEnabled = isScrimEnabled,
+        )
+        Shade(
+            viewModel = viewModel.leftShade,
+            currentTimeMillis = clock::elapsedRealtime,
+            containerHeightPx = maxHeightPx,
+            modifier = Modifier.align(Alignment.TopStart),
+        ) {
+            Column {
+                StatusBar()
+                Notifications()
+            }
+        }
+        Shade(
+            viewModel = viewModel.rightShade,
+            currentTimeMillis = clock::elapsedRealtime,
+            containerHeightPx = maxHeightPx,
+            modifier = Modifier.align(Alignment.TopEnd),
+        ) {
+            Column {
+                StatusBar()
+                QuickSettings()
+            }
+        }
+        Shade(
+            viewModel = viewModel.singleShade,
+            currentTimeMillis = clock::elapsedRealtime,
+            containerHeightPx = maxHeightPx,
+            modifier = Modifier,
+        ) {
+            Column {
+                StatusBar()
+                Notifications()
+                QuickSettings()
+            }
+        }
+    }
+}
+
+@Composable
+private fun Scrim(
+    remoteTouch: (ProxiedInputModel) -> Unit,
+    alpha: () -> Float,
+    isScrimEnabled: Boolean,
+    modifier: Modifier = Modifier,
+) {
+    var size by remember { mutableStateOf(IntSize.Zero) }
+
+    Box(
+        modifier =
+            modifier
+                .graphicsLayer { this.alpha = alpha() }
+                .background(colorResource(R.color.opaque_scrim))
+                .fillMaxSize()
+                .onSizeChanged { size = it }
+                .then(
+                    if (isScrimEnabled) {
+                        Modifier.pointerInput(Unit) {
+                                detectTapGestures(onTap = { remoteTouch(ProxiedInputModel.OnTap) })
+                            }
+                            .pointerInput(Unit) {
+                                detectVerticalDragGestures(
+                                    onVerticalDrag = { change, dragAmount ->
+                                        remoteTouch(
+                                            ProxiedInputModel.OnDrag(
+                                                xFraction = change.position.x / size.width,
+                                                yDragAmountPx = dragAmount,
+                                            )
+                                        )
+                                    },
+                                    onDragEnd = { remoteTouch(ProxiedInputModel.OnDragEnd) },
+                                    onDragCancel = { remoteTouch(ProxiedInputModel.OnDragCancel) }
+                                )
+                            }
+                    } else {
+                        Modifier
+                    }
+                )
+    )
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/multishade/ui/composable/Shade.kt b/packages/SystemUI/compose/features/src/com/android/systemui/multishade/ui/composable/Shade.kt
new file mode 100644
index 0000000..98ef57f9
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/multishade/ui/composable/Shade.kt
@@ -0,0 +1,317 @@
+/*
+ * 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.multishade.ui.composable
+
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.interaction.DragInteraction
+import androidx.compose.foundation.interaction.InteractionSource
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Surface
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.snapshotFlow
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.graphics.graphicsLayer
+import androidx.compose.ui.input.pointer.util.VelocityTracker
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import com.android.compose.modifiers.height
+import com.android.compose.swipeable.FixedThreshold
+import com.android.compose.swipeable.SwipeableState
+import com.android.compose.swipeable.ThresholdConfig
+import com.android.compose.swipeable.rememberSwipeableState
+import com.android.compose.swipeable.swipeable
+import com.android.systemui.multishade.shared.model.ProxiedInputModel
+import com.android.systemui.multishade.ui.viewmodel.ShadeViewModel
+import kotlin.math.roundToInt
+import kotlinx.coroutines.launch
+
+/**
+ * Renders a shade (container and content).
+ *
+ * This should be allowed to grow to fill the width and height of its container.
+ *
+ * @param viewModel The view-model for this shade.
+ * @param currentTimeMillis A provider for the current time, in milliseconds.
+ * @param containerHeightPx The height of the container that this shade is being shown in, in
+ *   pixels.
+ * @param modifier The Modifier.
+ * @param content The content of the shade.
+ */
+@Composable
+fun Shade(
+    viewModel: ShadeViewModel,
+    currentTimeMillis: () -> Long,
+    containerHeightPx: Float,
+    modifier: Modifier = Modifier,
+    content: @Composable () -> Unit = {},
+) {
+    val isVisible: Boolean by viewModel.isVisible.collectAsState()
+    if (!isVisible) {
+        return
+    }
+
+    val interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
+    ReportNonProxiedInput(viewModel, interactionSource)
+
+    val swipeableState = rememberSwipeableState(initialValue = ShadeState.FullyCollapsed)
+    HandleForcedCollapse(viewModel, swipeableState)
+    HandleProxiedInput(viewModel, swipeableState, currentTimeMillis)
+    ReportShadeExpansion(viewModel, swipeableState, containerHeightPx)
+
+    val isSwipingEnabled: Boolean by viewModel.isSwipingEnabled.collectAsState()
+    val collapseThreshold: Float by viewModel.swipeCollapseThreshold.collectAsState()
+    val expandThreshold: Float by viewModel.swipeExpandThreshold.collectAsState()
+
+    val width: ShadeViewModel.Size by viewModel.width.collectAsState()
+    val density = LocalDensity.current
+
+    val anchors: Map<Float, ShadeState> =
+        remember(containerHeightPx) { swipeableAnchors(containerHeightPx) }
+
+    ShadeContent(
+        shadeHeightPx = { swipeableState.offset.value },
+        overstretch = { swipeableState.overflow.value / containerHeightPx },
+        isSwipingEnabled = isSwipingEnabled,
+        swipeableState = swipeableState,
+        interactionSource = interactionSource,
+        anchors = anchors,
+        thresholds = { _, to ->
+            swipeableThresholds(
+                to = to,
+                swipeCollapseThreshold = collapseThreshold.fractionToDp(density, containerHeightPx),
+                swipeExpandThreshold = expandThreshold.fractionToDp(density, containerHeightPx),
+            )
+        },
+        modifier = modifier.shadeWidth(width, density),
+        content = content,
+    )
+}
+
+/**
+ * Draws the content of the shade.
+ *
+ * @param shadeHeightPx Provider for the current expansion of the shade, in pixels, where `0` is
+ *   fully collapsed.
+ * @param overstretch Provider for the current amount of vertical "overstretch" that the shade
+ *   should be rendered with. This is `0` or a positive number that is a percentage of the total
+ *   height of the shade when fully expanded. A value of `0` means that the shade is not stretched
+ *   at all.
+ * @param isSwipingEnabled Whether swiping inside the shade is enabled or not.
+ * @param swipeableState The state to use for the [swipeable] modifier, allowing external control in
+ *   addition to direct control (proxied user input in addition to non-proxied/direct user input).
+ * @param anchors A map of [ShadeState] keyed by the vertical position, in pixels, where that state
+ *   occurs; this is used to configure the [swipeable] modifier.
+ * @param thresholds Function that returns the [ThresholdConfig] for going from one [ShadeState] to
+ *   another. This controls how the [swipeable] decides which [ShadeState] to animate to once the
+ *   user lets go of the shade; e.g. does it animate to fully collapsed or fully expanded.
+ * @param content The content to render inside the shade.
+ * @param modifier The [Modifier].
+ */
+@Composable
+private fun ShadeContent(
+    shadeHeightPx: () -> Float,
+    overstretch: () -> Float,
+    isSwipingEnabled: Boolean,
+    swipeableState: SwipeableState<ShadeState>,
+    interactionSource: MutableInteractionSource,
+    anchors: Map<Float, ShadeState>,
+    thresholds: (from: ShadeState, to: ShadeState) -> ThresholdConfig,
+    modifier: Modifier = Modifier,
+    content: @Composable () -> Unit = {},
+) {
+    Surface(
+        shape = RoundedCornerShape(32.dp),
+        modifier =
+            modifier
+                .padding(12.dp)
+                .fillMaxWidth()
+                .height { shadeHeightPx().roundToInt() }
+                .graphicsLayer {
+                    // Applies the vertical over-stretching of the shade content that may happen if
+                    // the user keep dragging down when the shade is already fully-expanded.
+                    transformOrigin = transformOrigin.copy(pivotFractionY = 0f)
+                    this.scaleY = 1 + overstretch().coerceAtLeast(0f)
+                }
+                .swipeable(
+                    enabled = isSwipingEnabled,
+                    state = swipeableState,
+                    interactionSource = interactionSource,
+                    anchors = anchors,
+                    thresholds = thresholds,
+                    orientation = Orientation.Vertical,
+                ),
+        content = content,
+    )
+}
+
+/** Funnels current shade expansion values into the view-model. */
+@Composable
+private fun ReportShadeExpansion(
+    viewModel: ShadeViewModel,
+    swipeableState: SwipeableState<ShadeState>,
+    containerHeightPx: Float,
+) {
+    LaunchedEffect(swipeableState.offset, containerHeightPx) {
+        snapshotFlow { swipeableState.offset.value / containerHeightPx }
+            .collect { expansion -> viewModel.onExpansionChanged(expansion) }
+    }
+}
+
+/** Funnels drag gesture start and end events into the view-model. */
+@Composable
+private fun ReportNonProxiedInput(
+    viewModel: ShadeViewModel,
+    interactionSource: InteractionSource,
+) {
+    LaunchedEffect(interactionSource) {
+        interactionSource.interactions.collect {
+            when (it) {
+                is DragInteraction.Start -> {
+                    viewModel.onDragStarted()
+                }
+                is DragInteraction.Stop -> {
+                    viewModel.onDragEnded()
+                }
+            }
+        }
+    }
+}
+
+/** When told to force collapse, collapses the shade. */
+@Composable
+private fun HandleForcedCollapse(
+    viewModel: ShadeViewModel,
+    swipeableState: SwipeableState<ShadeState>,
+) {
+    LaunchedEffect(viewModel) {
+        viewModel.isForceCollapsed.collect {
+            launch { swipeableState.animateTo(ShadeState.FullyCollapsed) }
+        }
+    }
+}
+
+/**
+ * Handles proxied input (input originating outside of the UI of the shade) by driving the
+ * [SwipeableState] accordingly.
+ */
+@Composable
+private fun HandleProxiedInput(
+    viewModel: ShadeViewModel,
+    swipeableState: SwipeableState<ShadeState>,
+    currentTimeMillis: () -> Long,
+) {
+    val velocityTracker: VelocityTracker = remember { VelocityTracker() }
+    LaunchedEffect(viewModel) {
+        viewModel.proxiedInput.collect {
+            when (it) {
+                is ProxiedInputModel.OnDrag -> {
+                    velocityTracker.addPosition(
+                        timeMillis = currentTimeMillis.invoke(),
+                        position = Offset(0f, it.yDragAmountPx),
+                    )
+                    swipeableState.performDrag(it.yDragAmountPx)
+                }
+                is ProxiedInputModel.OnDragEnd -> {
+                    launch {
+                        val velocity = velocityTracker.calculateVelocity().y
+                        velocityTracker.resetTracking()
+                        // We use a VelocityTracker to keep a record of how fast the pointer was
+                        // moving such that we know how far to fling the shade when the gesture
+                        // ends. Flinging the SwipeableState using performFling is required after
+                        // one or more calls to performDrag such that the swipeable settles into one
+                        // of the states. Without doing that, the shade would remain unmoving in an
+                        // in-between state on the screen.
+                        swipeableState.performFling(velocity)
+                    }
+                }
+                is ProxiedInputModel.OnDragCancel -> {
+                    launch {
+                        velocityTracker.resetTracking()
+                        swipeableState.animateTo(swipeableState.progress.from)
+                    }
+                }
+                else -> Unit
+            }
+        }
+    }
+}
+
+/**
+ * Converts the [Float] (which is assumed to be a fraction between `0` and `1`) to a value in dp.
+ *
+ * @param density The [Density] of the display.
+ * @param wholePx The whole amount that the given [Float] is a fraction of.
+ * @return The dp size that's a fraction of the whole amount.
+ */
+private fun Float.fractionToDp(density: Density, wholePx: Float): Dp {
+    return with(density) { (this@fractionToDp * wholePx).toDp() }
+}
+
+private fun Modifier.shadeWidth(
+    size: ShadeViewModel.Size,
+    density: Density,
+): Modifier {
+    return then(
+        when (size) {
+            is ShadeViewModel.Size.Fraction -> Modifier.fillMaxWidth(size.fraction)
+            is ShadeViewModel.Size.Pixels -> Modifier.width(with(density) { size.pixels.toDp() })
+        }
+    )
+}
+
+/** Returns the pixel positions for each of the supported shade states. */
+private fun swipeableAnchors(containerHeightPx: Float): Map<Float, ShadeState> {
+    return mapOf(
+        0f to ShadeState.FullyCollapsed,
+        containerHeightPx to ShadeState.FullyExpanded,
+    )
+}
+
+/**
+ * Returns the [ThresholdConfig] for how far the shade should be expanded or collapsed such that it
+ * actually completes the expansion or collapse after the user lifts their pointer.
+ */
+private fun swipeableThresholds(
+    to: ShadeState,
+    swipeExpandThreshold: Dp,
+    swipeCollapseThreshold: Dp,
+): ThresholdConfig {
+    return FixedThreshold(
+        when (to) {
+            ShadeState.FullyExpanded -> swipeExpandThreshold
+            ShadeState.FullyCollapsed -> swipeCollapseThreshold
+        }
+    )
+}
+
+/** Enumerates the shade UI states for [SwipeableState]. */
+private enum class ShadeState {
+    FullyCollapsed,
+    FullyExpanded,
+}
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
new file mode 100644
index 0000000..ca91b8a
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.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.notifications.ui.composable
+
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.defaultMinSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+
+@Composable
+fun Notifications(
+    modifier: Modifier = Modifier,
+) {
+    // TODO(b/272779828): implement.
+    Column(
+        modifier = modifier.fillMaxWidth().defaultMinSize(minHeight = 300.dp).padding(4.dp),
+    ) {
+        Text("Notifications", modifier = Modifier.align(Alignment.CenterHorizontally))
+        Spacer(modifier = Modifier.weight(1f))
+        Text("Shelf", modifier = Modifier.align(Alignment.CenterHorizontally))
+    }
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt
index 3eeadae..a74e56b 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt
@@ -60,7 +60,7 @@
  *
  * @param viewModel the [PeopleViewModel] that should be composed.
  * @param onResult the callback called with the result of this screen. Callers should usually finish
- * the Activity/Fragment/View hosting this Composable once a result is available.
+ *   the Activity/Fragment/View hosting this Composable once a result is available.
  */
 @Composable
 fun PeopleScreen(
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt
index 3f590df..0484ff4 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt
@@ -79,7 +79,9 @@
                     containerColor = androidColors.colorAccentPrimary,
                     contentColor = androidColors.textColorOnAccent,
                 )
-        ) { Text(stringResource(R.string.got_it)) }
+        ) {
+            Text(stringResource(R.string.got_it))
+        }
     }
 }
 
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/QuickSettings.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/QuickSettings.kt
new file mode 100644
index 0000000..665d6dd
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/QuickSettings.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.footer.ui.compose
+
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.defaultMinSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+
+@Composable
+fun QuickSettings(
+    modifier: Modifier = Modifier,
+) {
+    // TODO(b/272780058): implement.
+    Column(
+        modifier = modifier.fillMaxWidth().defaultMinSize(minHeight = 300.dp).padding(4.dp),
+    ) {
+        Text("Quick settings", modifier = Modifier.align(Alignment.CenterHorizontally))
+        Spacer(modifier = Modifier.weight(1f))
+        Text("QS footer actions", modifier = Modifier.align(Alignment.CenterHorizontally))
+    }
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/ui/composable/StatusBar.kt b/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/ui/composable/StatusBar.kt
new file mode 100644
index 0000000..f514ab4
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/ui/composable/StatusBar.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.statusbar.ui.composable
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.defaultMinSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+
+@Composable
+fun StatusBar(
+    modifier: Modifier = Modifier,
+) {
+    // TODO(b/272780101): implement.
+    Row(
+        modifier = modifier.fillMaxWidth().defaultMinSize(minHeight = 48.dp).padding(4.dp),
+        horizontalArrangement = Arrangement.Center,
+        verticalAlignment = Alignment.CenterVertically,
+    ) {
+        Text("Status bar")
+    }
+}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
index ab36d58..00c0a0b 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
@@ -38,6 +38,7 @@
 
 private val TAG = ClockRegistry::class.simpleName!!
 private const val DEBUG = true
+private val KEY_TIMESTAMP = "appliedTimestamp"
 
 /** ClockRegistry aggregates providers and plugins */
 open class ClockRegistry(
@@ -134,9 +135,9 @@
         assertNotMainThread()
 
         try {
-            value?._applied_timestamp = System.currentTimeMillis()
-            val json = ClockSettings.serialize(value)
+            value?.metadata?.put(KEY_TIMESTAMP, System.currentTimeMillis())
 
+            val json = ClockSettings.serialize(value)
             if (handleAllUsers) {
                 Settings.Secure.putStringForUser(
                     context.contentResolver,
@@ -172,7 +173,7 @@
         clockChangeListeners.forEach(func)
     }
 
-    private fun mutateSetting(mutator: (ClockSettings) -> ClockSettings) {
+    public fun mutateSetting(mutator: (ClockSettings) -> ClockSettings) {
         scope.launch(bgDispatcher) { applySettings(mutator(settings ?: ClockSettings())) }
     }
 
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
index 2a40f5c..4df7a44 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
@@ -95,7 +95,7 @@
 
     open inner class DefaultClockFaceController(
         override val view: AnimatableClockView,
-        val seedColor: Int?,
+        var seedColor: Int?,
     ) : ClockFaceController {
 
         // MAGENTA is a placeholder, and will be assigned correctly in initialize
@@ -111,9 +111,9 @@
 
         init {
             if (seedColor != null) {
-                currentColor = seedColor
+                currentColor = seedColor!!
             }
-            view.setColors(currentColor, currentColor)
+            view.setColors(DOZE_COLOR, currentColor)
         }
 
         override val events =
@@ -141,7 +141,7 @@
         fun updateColor() {
             val color =
                 if (seedColor != null) {
-                    seedColor
+                    seedColor!!
                 } else if (isRegionDark) {
                     resources.getColor(android.R.color.system_accent1_100)
                 } else {
@@ -194,6 +194,14 @@
             smallClock.updateColor()
         }
 
+        override fun onSeedColorChanged(seedColor: Int?) {
+            largeClock.seedColor = seedColor
+            smallClock.seedColor = seedColor
+
+            largeClock.updateColor()
+            smallClock.updateColor()
+        }
+
         override fun onLocaleChanged(locale: Locale) {
             val nf = NumberFormat.getInstance(locale)
             if (nf.format(FORMAT_NUMBER.toLong()) == burmeseNumerals) {
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt
index c120876..0d88075 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt
@@ -51,7 +51,7 @@
          *
          * Supported operations:
          * - Query - to know which slots are available, query the [SlotTable.URI] [Uri]. The result
-         * set will contain rows with the [SlotTable.Columns] columns.
+         *   set will contain rows with the [SlotTable.Columns] columns.
          */
         object SlotTable {
             const val TABLE_NAME = "slots"
@@ -74,8 +74,8 @@
          *
          * Supported operations:
          * - Query - to know about all the affordances that are available on the device, regardless
-         * of which ones are currently selected, query the [AffordanceTable.URI] [Uri]. The result
-         * set will contain rows, each with the columns specified in [AffordanceTable.Columns].
+         *   of which ones are currently selected, query the [AffordanceTable.URI] [Uri]. The result
+         *   set will contain rows, each with the columns specified in [AffordanceTable.Columns].
          */
         object AffordanceTable {
             const val TABLE_NAME = "affordances"
@@ -128,14 +128,14 @@
          *
          * Supported operations:
          * - Insert - to insert an affordance and place it in a slot, insert values for the columns
-         * into the [SelectionTable.URI] [Uri]. The maximum capacity rule is enforced by the system.
-         * Selecting a new affordance for a slot that is already full will automatically remove the
-         * oldest affordance from the slot.
+         *   into the [SelectionTable.URI] [Uri]. The maximum capacity rule is enforced by the
+         *   system. Selecting a new affordance for a slot that is already full will automatically
+         *   remove the oldest affordance from the slot.
          * - Query - to know which affordances are set on which slots, query the
-         * [SelectionTable.URI] [Uri]. The result set will contain rows, each of which with the
-         * columns from [SelectionTable.Columns].
+         *   [SelectionTable.URI] [Uri]. The result set will contain rows, each of which with the
+         *   columns from [SelectionTable.Columns].
          * - Delete - to unselect an affordance, removing it from a slot, delete from the
-         * [SelectionTable.URI] [Uri], passing in values for each column.
+         *   [SelectionTable.URI] [Uri], passing in values for each column.
          */
         object SelectionTable {
             const val TABLE_NAME = "selections"
@@ -160,7 +160,7 @@
      *
      * Supported operations:
      * - Query - to know the values of flags, query the [FlagsTable.URI] [Uri]. The result set will
-     * contain rows, each of which with the columns from [FlagsTable.Columns].
+     *   contain rows, each of which with the columns from [FlagsTable.Columns].
      */
     object FlagsTable {
         const val TABLE_NAME = "flags"
diff --git a/packages/SystemUI/docs/clock-plugins.md b/packages/SystemUI/docs/clock-plugins.md
index 5e4f6c7..2226d79 100644
--- a/packages/SystemUI/docs/clock-plugins.md
+++ b/packages/SystemUI/docs/clock-plugins.md
@@ -1,35 +1,92 @@
 # Clock Plugins
 
-## Introduction
-
 The clock appearing on the lock screen and always on display (AOD) can be
-customized via the ClockPlugin plugin interface.
+customized via the ClockProviderPlugin plugin interface.
+
+## Lock screen integration
+The lockscreen code has two main components, a [clock customization library](../customization), and
+the SystemUI [lockscreen host code](../src/com/android/keyguard). The customization library contains
+the default clock, and some support code for managing clocks and picking the correct one to render.
+It is used by both SystemUI for rendering and ThemePicker for selecting clocks. The SystemUI host is
+responsible for maintaining the view within the hierarchy and propagating events to the rendered
+clock controller.
+
+### Clock Library Code
+[ClockProvider and ClockController](../plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt)
+serve as the interface between the lockscreen (or other host application) and the clock that is
+being rendered. Implementing these interfaces is the primary integration point for rendering clocks
+in SystemUI. Many of the methods have an empty default implementation and are optional for
+implementations if the related event is not interesting to your use case.
+
+[DefaultClockProvider](../customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt) and
+[DefaultClockController](../customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt)
+implement these interfaces for the default lockscreen clock. They handle relevant events from the
+lockscreen to update and control the small and large clock view as appropriate.
+[AnimatableClockView](../customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt)
+is the view that DefaultClockController uses to render both the small and large clock.
+AnimatableClockView has moved location within the repo, but is largely unchanged from previous
+versions of android.
+
+The [ClockRegistry](../customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt)
+determines which clock should be shown, and handles creating them. It does this by maintaining a
+list of [ClockProviders](../plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt) and
+delegating work to them as appropriate. The DefaultClockProvider is compiled in so that it is
+guaranteed to be available, and additional ClockProviders are loaded at runtime via
+[PluginManager](../plugin_core/src/com/android/systemui/plugins/PluginManager.java).
+
+[ClockPlugin](../plugin/src/com/android/systemui/plugins/ClockPlugin.java) is deprecated and no
+longer used by keyguard to render clocks. The host code has been disabled but most of it is still
+present in the source tree, although it will likely be removed in a later patch.
+
+### Lockscreen Host
+[ClockEventController](../src/com/android/keyguard/ClockEventController.kt) propagates events from
+SystemUI event dispatchers to the clock controllers. It maintains a set of event listeners, but
+otherwise attempts to do as little work as possible. It does maintain some state where necessary.
+
+[KeyguardClockSwitchController](../src/com/android/keyguard/KeyguardClockSwitchController.java) is
+the primary controller for the [KeyguardClockSwitch](../src/com/android/keyguard/KeyguardClockSwitch.java),
+which serves as the view parent within SystemUI. Together they ensure the correct clock (either
+large or small) is shown, handle animation between clock sizes, and control some sizing/layout
+parameters for the clocks.
+
+### Creating a custom clock
+In order to create a custom clock, a partner must:
+ - Write an implementation of ClockProviderPlugin and the subinterfaces relevant to your use-case.
+ - Build this into a seperate plugin apk, and deploy that apk to the device.
+    - Alternatively, it could be compiled directly into the customization lib like DefaultClockProvider.
+ - PluginManager should automatically notify ClockRegistry of your plugin apk when it arrives on
+      device. ClockRegistry will print info logs when it successfully loads a plugin.
+ - Set the clock either in ThemePicker or through adb:
+      `adb shell settings put secure lock_screen_custom_clock_face '''{\"clockId\":\"ID\"}'''`
+ - SystemUI should immediately load and render the new clock if it is available.
+
+### Picker integration
+Picker logic for choosing between clocks is available to our partners as part of the ThemePicker.
+The clock picking UI will be enabled by default if there is more than 1 clock provided, otherwise
+it will be hidden from the UI.
 
 ## System Health
 
-Clocks are high risk for battery consumption and screen burn-in because they
-modify the UI of AOD.
+Clocks are high risk for battery consumption and screen burn-in because they modify the UI of AOD.
 
-To reduce battery consumption, it is recommended to
-target a maximum on-pixel-ratio (OPR) of 5%. Clocks that are composed of
-large blocks of color that cause the OPR to exceed 5% should be avoided.
+To reduce battery consumption, it is recommended to target a maximum on-pixel-ratio (OPR) of 10%.
+Clocks that are composed of large blocks of color that cause the OPR to exceed 10% should be
+avoided, but this target will differ depending on the device hardware.
 
-To prevent screen burn-in, clocks should not be composed of large solid
-blocks of color, and the clock should be moved around the screen to
-distribute the on pixels across a large number of pixels. Software
-burn-in testing is a good starting point to assess the pixel shifting
-(clock movement) scheme and shape of the clock.
+To prevent screen burn-in, clocks should not be composed of large solid blocks of color, and the
+clock should be moved around the screen to distribute the on pixels across a large number of pixels.
+Software burn-in testing is a good starting point to assess the pixel shifting (clock movement)
+scheme and shape of the clock. SystemUI currently treats all clocks the same in this regard using
+[KeyguardClockPositionAlgorithm](../src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java)
 
 ### Software Burn-In Test
 
-The goal is to look for bright spots in the luminosity average over a period of
-time. It is difficult to define a threshold where burn-in will occur. It is,
-therefore, recommended to compare against an element on AOD that is known not
-to cause problems.
+The goal is to look for bright spots in the luminosity average over a period of time. It is
+difficult to define a threshold where burn-in will occur. It is, therefore, recommended to compare
+against an element on AOD that is known not to cause problems.
 
-For clock face that contain color, it is recommended to use an all white
-version of the face. Since white has the highest luminosity, this version of
-the clock face represents the worst case scenario.
+For clock face that contain color, it is recommended to use an all white version of the face. Since
+white has the highest luminosity, this version of the clock face represents the worst case scenario.
 
 To start, generate a sequence of screenshots for each minute over a 12 hr interval.
 
@@ -87,6 +144,5 @@
   main(sys.argv[1])
 ```
 
-Look for bright spots in the luminosity average. If bright spots are found,
-action should be taken to change the shape of the clock face or increase the
-amount of pixel shifting.
+Look for bright spots in the luminosity average. If bright spots are found, action should be taken
+to change the shape of the clock face or increase the amount of pixel shifting.
diff --git a/packages/SystemUI/docs/plugin_hooks.md b/packages/SystemUI/docs/plugin_hooks.md
index cde5094..6ce7ee0 100644
--- a/packages/SystemUI/docs/plugin_hooks.md
+++ b/packages/SystemUI/docs/plugin_hooks.md
@@ -1,7 +1,6 @@
 # Plugin hooks
 ### Action: com.android.systemui.action.PLUGIN_OVERLAY
-Expected interface: [OverlayPlugin](/frameworks/base/packages/SystemUI/plugin/src/com/android
-/systemui/plugins/OverlayPlugin.java)
+Expected interface: [OverlayPlugin](/frameworks/base/packages/SystemUI/plugin/src/com/android/systemui/plugins/OverlayPlugin.java)
 
 Use: Allows plugin access to the status bar and nav bar window for whatever nefarious purposes you can imagine.
 
@@ -52,10 +51,10 @@
 
 Use: Control over swipes/input for notification views, can be used to control what happens when you swipe/long-press
 
-### Action: com.android.systemui.action.PLUGIN_CLOCK
-Expected interface: [ClockPlugin](/frameworks/base/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java)
+### Action: com.android.systemui.action.PLUGIN_CLOCK_PROVIDER
+Expected interface: [ClockProviderPlugin](/frameworks/base/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt)
 
-Use: Allows replacement of the keyguard main clock.
+Use: Allows replacement of the keyguard main clock. See [additional Documentation](./clock-plugins.md).
 
 ### Action: com.android.systemui.action.PLUGIN_TOAST
 Expected interface: [ToastPlugin](/frameworks/base/packages/SystemUI/plugin/src/com/android/systemui/plugins/ToastPlugin.java)
diff --git a/packages/SystemUI/ktfmt_includes.txt b/packages/SystemUI/ktfmt_includes.txt
index ec860b5..18753fd 100644
--- a/packages/SystemUI/ktfmt_includes.txt
+++ b/packages/SystemUI/ktfmt_includes.txt
@@ -1,28 +1,20 @@
 +packages/SystemUI
 -packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
 -packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
--packages/SystemUI/checks/src/com/android/internal/systemui/lint/BindServiceViaContextDetector.kt
 -packages/SystemUI/checks/src/com/android/internal/systemui/lint/BroadcastSentViaContextDetector.kt
--packages/SystemUI/checks/src/com/android/internal/systemui/lint/GetMainLooperViaContextDetector.kt
 -packages/SystemUI/checks/src/com/android/internal/systemui/lint/RegisterReceiverViaContextDetector.kt
 -packages/SystemUI/checks/src/com/android/internal/systemui/lint/SoftwareBitmapDetector.kt
--packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/BindServiceViaContextDetectorTest.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/BroadcastSentViaContextDetectorTest.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/GetMainLooperViaContextDetectorTest.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/RegisterReceiverViaContextDetectorTest.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/SoftwareBitmapDetectorTest.kt
+-packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
+-packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
 -packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
--packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSContainerController.kt
+-packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/View.kt
 -packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
 -packages/SystemUI/shared/src/com/android/systemui/flags/FlagListenable.kt
 -packages/SystemUI/shared/src/com/android/systemui/flags/FlagManager.kt
 -packages/SystemUI/shared/src/com/android/systemui/flags/FlagSerializer.kt
 -packages/SystemUI/shared/src/com/android/systemui/flags/FlagSettingsHelper.kt
 -packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt
--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionDarkness.kt
 -packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonPositionCalculator.kt
 -packages/SystemUI/shared/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerManager.kt
 -packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/SmartspaceState.kt
@@ -35,8 +27,6 @@
 -packages/SystemUI/src/com/android/keyguard/BouncerPanelExpansionCalculator.kt
 -packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
 -packages/SystemUI/src/com/android/keyguard/KeyguardBiometricLockoutLogger.kt
--packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
--packages/SystemUI/src/com/android/keyguard/KeyguardListenQueue.kt
 -packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt
 -packages/SystemUI/src/com/android/keyguard/KeyguardUserSwitcherAnchor.kt
 -packages/SystemUI/src/com/android/keyguard/clock/ClockPalette.kt
@@ -65,12 +55,10 @@
 -packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceView.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt
--packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricIconController.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/BiometricDisplayListener.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/DwellRippleShader.kt
--packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpView.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.kt
@@ -80,7 +68,6 @@
 -packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmEmptyView.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmEmptyViewController.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/UdfpsHapticsSimulator.kt
--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsOverlayParams.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/UdfpsShell.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt
@@ -93,8 +80,6 @@
 -packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
 -packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt
 -packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
--packages/SystemUI/src/com/android/systemui/camera/CameraIntents.kt
--packages/SystemUI/src/com/android/systemui/camera/CameraIntentsWrapper.kt
 -packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt
 -packages/SystemUI/src/com/android/systemui/controls/ControlStatus.kt
 -packages/SystemUI/src/com/android/systemui/controls/ControlsMetricsLogger.kt
@@ -102,7 +87,6 @@
 -packages/SystemUI/src/com/android/systemui/controls/ControlsServiceInfo.kt
 -packages/SystemUI/src/com/android/systemui/controls/CustomIconCache.kt
 -packages/SystemUI/src/com/android/systemui/controls/TooltipManager.kt
--packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
 -packages/SystemUI/src/com/android/systemui/controls/controller/ControlInfo.kt
 -packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt
 -packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
@@ -132,6 +116,7 @@
 -packages/SystemUI/src/com/android/systemui/controls/management/FavoritesModel.kt
 -packages/SystemUI/src/com/android/systemui/controls/management/ManagementPageIndicator.kt
 -packages/SystemUI/src/com/android/systemui/controls/management/StructureAdapter.kt
+-packages/SystemUI/src/com/android/systemui/controls/start/ControlsStartable.kt
 -packages/SystemUI/src/com/android/systemui/controls/ui/Behavior.kt
 -packages/SystemUI/src/com/android/systemui/controls/ui/ChallengeDialogs.kt
 -packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinator.kt
@@ -162,7 +147,6 @@
 -packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt
 -packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt
 -packages/SystemUI/src/com/android/systemui/demomode/DemoModeAvailabilityTracker.kt
--packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
 -packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
 -packages/SystemUI/src/com/android/systemui/doze/util/BurnInHelper.kt
 -packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamSmartspaceController.kt
@@ -172,20 +156,16 @@
 -packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt
 -packages/SystemUI/src/com/android/systemui/dump/LogBufferFreezer.kt
 -packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt
+-packages/SystemUI/src/com/android/systemui/flags/Flags.kt
 -packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt
 -packages/SystemUI/src/com/android/systemui/flags/SystemPropertiesHelper.kt
 -packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
--packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
+-packages/SystemUI/src/com/android/systemui/keyguard/LifecycleScreenStatusProvider.kt
+-packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfig.kt
+-packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartable.kt
+-packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
 -packages/SystemUI/src/com/android/systemui/log/LogBufferFactory.kt
--packages/SystemUI/src/com/android/systemui/log/LogLevel.kt
--packages/SystemUI/src/com/android/systemui/log/LogMessage.kt
--packages/SystemUI/src/com/android/systemui/log/LogMessageImpl.kt
--packages/SystemUI/src/com/android/systemui/log/LogcatEchoTracker.kt
--packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt
--packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerProd.kt
--packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
 -packages/SystemUI/src/com/android/systemui/media/MediaProjectionCaptureTarget.kt
--packages/SystemUI/src/com/android/systemui/media/dagger/MediaProjectionModule.kt
 -packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt
 -packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
 -packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt
@@ -202,9 +182,15 @@
 -packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt
 -packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
 -packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLogger.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorResultHandler.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewController.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionTaskView.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/RecentTasksAdapter.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDevicePolicyResolver.kt
 -packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt
 -packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
 -packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt
+-packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEventLogger.kt
 -packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt
 -packages/SystemUI/src/com/android/systemui/privacy/AppOpsPrivacyItemMonitor.kt
 -packages/SystemUI/src/com/android/systemui/privacy/MediaProjectionPrivacyItemMonitor.kt
@@ -220,8 +206,6 @@
 -packages/SystemUI/src/com/android/systemui/privacy/logging/PrivacyLogger.kt
 -packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt
 -packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
--packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
--packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt
 -packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt
 -packages/SystemUI/src/com/android/systemui/qs/QSEvents.kt
 -packages/SystemUI/src/com/android/systemui/qs/QSExpansionPathInterpolator.kt
@@ -237,7 +221,6 @@
 -packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialog.kt
 -packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialogEventLogger.kt
 -packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt
--packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
 -packages/SystemUI/src/com/android/systemui/qs/tileimpl/HeightOverrideable.kt
 -packages/SystemUI/src/com/android/systemui/qs/tileimpl/IgnorableChildLinearLayout.kt
 -packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -245,10 +228,6 @@
 -packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
 -packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
 -packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt
--packages/SystemUI/src/com/android/systemui/ripple/RippleShader.kt
--packages/SystemUI/src/com/android/systemui/ripple/RippleShaderUtilLibrary.kt
--packages/SystemUI/src/com/android/systemui/ripple/RippleView.kt
--packages/SystemUI/src/com/android/systemui/ripple/SdfShaderLibrary.kt
 -packages/SystemUI/src/com/android/systemui/screenshot/ImageCaptureImpl.kt
 -packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt
 -packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicy.kt
@@ -259,23 +238,21 @@
 -packages/SystemUI/src/com/android/systemui/settings/UserContentResolverProvider.kt
 -packages/SystemUI/src/com/android/systemui/settings/UserContextProvider.kt
 -packages/SystemUI/src/com/android/systemui/settings/UserFileManager.kt
--packages/SystemUI/src/com/android/systemui/settings/UserFileManagerImpl.kt
 -packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
 -packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
 -packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessMirrorHandler.kt
 -packages/SystemUI/src/com/android/systemui/settings/brightness/MirroredBrightnessController.kt
 -packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManager.kt
 -packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt
--packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt
 -packages/SystemUI/src/com/android/systemui/shade/NPVCDownEventState.kt
--packages/SystemUI/src/com/android/systemui/shade/NotifPanelEvents.kt
 -packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt
 -packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
 -packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt
+-packages/SystemUI/src/com/android/systemui/shade/ShadeHeightLogger.kt
 -packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
+-packages/SystemUI/src/com/android/systemui/shade/ShadeWindowLogger.kt
 -packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt
 -packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt
--packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeOverScroller.kt
 -packages/SystemUI/src/com/android/systemui/smartspace/SmartspacePrecondition.kt
 -packages/SystemUI/src/com/android/systemui/smartspace/SmartspaceTargetFilter.kt
 -packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt
@@ -284,9 +261,7 @@
 -packages/SystemUI/src/com/android/systemui/smartspace/preconditions/LockscreenPrecondition.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/AbstractLockscreenShadeTransitionController.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/ActionClickLogger.kt
--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBarWifiView.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
--packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/LockScreenShadeOverScroller.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeKeyguardTransitionController.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeScrimTransitionController.kt
@@ -311,10 +286,12 @@
 -packages/SystemUI/src/com/android/systemui/statusbar/dagger/StartCentralSurfacesModule.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/disableflags/DisableFlagsLogger.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/StatusBarEventsModule.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/gesture/GenericGestureDetector.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureHandler.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureLogger.kt
@@ -325,7 +302,6 @@
 -packages/SystemUI/src/com/android/systemui/statusbar/notification/LaunchAnimationParameters.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClickerLogger.kt
--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManagerLogger.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.kt
@@ -403,6 +379,7 @@
 -packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderLogger.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryViewWalker.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/notification/people/NotificationPersonExtractor.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/notification/people/ViewPipeline.kt
@@ -444,13 +421,10 @@
 -packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallFlags.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLogger.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/panelstate/PanelExpansionStateManager.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/panelstate/ShadeStateListener.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserInfoTracker.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherContainer.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherController.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherFeatureController.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/model/ConnectivitySlots.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsController.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt
@@ -470,19 +444,17 @@
 -packages/SystemUI/src/com/android/systemui/statusbar/tv/VpnStatusObserver.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowModule.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateController.kt
--packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt
 -packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt
+-packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt
 -packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarRootView.kt
 -packages/SystemUI/src/com/android/systemui/toast/ToastDefaultAnimation.kt
 -packages/SystemUI/src/com/android/systemui/toast/ToastLogger.kt
 -packages/SystemUI/src/com/android/systemui/tv/TVSystemUICoreStartableModule.kt
+-packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt
 -packages/SystemUI/src/com/android/systemui/unfold/FoldStateLogger.kt
 -packages/SystemUI/src/com/android/systemui/unfold/SysUIUnfoldModule.kt
--packages/SystemUI/src/com/android/systemui/unfold/UnfoldLatencyTracker.kt
 -packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt
 -packages/SystemUI/src/com/android/systemui/unfold/UnfoldProgressProvider.kt
--packages/SystemUI/src/com/android/systemui/user/UserCreator.kt
--packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt
 -packages/SystemUI/src/com/android/systemui/user/UserSwitcherPopupMenu.kt
 -packages/SystemUI/src/com/android/systemui/user/UserSwitcherRootView.kt
 -packages/SystemUI/src/com/android/systemui/util/AsyncActivityLauncher.kt
@@ -509,7 +481,6 @@
 -packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayout.kt
 -packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayoutController.kt
 -packages/SystemUI/src/com/android/systemui/util/animation/UniqueObjectHostView.kt
--packages/SystemUI/src/com/android/systemui/util/collection/RingBuffer.kt
 -packages/SystemUI/src/com/android/systemui/util/concurrency/Execution.kt
 -packages/SystemUI/src/com/android/systemui/util/concurrency/PendingTasksContainer.kt
 -packages/SystemUI/src/com/android/systemui/util/drawable/DrawableSize.kt
@@ -517,6 +488,7 @@
 -packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt
 -packages/SystemUI/src/com/android/systemui/util/kotlin/IpcSerializer.kt
 -packages/SystemUI/src/com/android/systemui/util/kotlin/nullability.kt
+-packages/SystemUI/src/com/android/systemui/util/recycler/HorizontalSpacerItemDecoration.kt
 -packages/SystemUI/src/com/android/systemui/util/view/ViewUtil.kt
 -packages/SystemUI/src/com/android/systemui/util/wrapper/RotationPolicyWrapper.kt
 -packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialogReceiver.kt
@@ -525,7 +497,6 @@
 -packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt
 -packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
 -packages/SystemUI/tests/src/com/android/keyguard/KeyguardBiometricLockoutLoggerTest.kt
--packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
 -packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
 -packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
 -packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.kt
@@ -549,8 +520,6 @@
 -packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt
--packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsViewTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/broadcast/ActionReceiverTest.kt
@@ -569,7 +538,6 @@
 -packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapperTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsTileResourceConfigurationImplTest.kt
--packages/SystemUI/tests/src/com/android/systemui/controls/controller/DeletionJobServiceTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/controls/controller/ServiceWrapperTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/controls/controller/StatefulControlSubscriberTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt
@@ -579,7 +547,6 @@
 -packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestDialogTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestReceiverTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/controls/management/FavoritesModelTest.kt
--packages/SystemUI/tests/src/com/android/systemui/controls/management/TestControlsRequestDialog.kt
 -packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlViewHolderTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt
@@ -596,13 +563,17 @@
 -packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartableTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/lifecycle/InstantTaskExecutorRule.kt
--packages/SystemUI/tests/src/com/android/systemui/log/LogBufferTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/media/nearby/NearbyMediaDevicesManagerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/FloatingRotationButtonPositionCalculatorTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/privacy/AppOpsPrivacyItemMonitorTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyChipBuilderTest.kt
@@ -610,7 +581,6 @@
 -packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/qs/HeaderPrivacyIconsControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/qs/QSContainerImplTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentDisableFlagsLoggerTest.kt
@@ -641,35 +611,28 @@
 -packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt
--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/ripple/RippleViewTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordDialogTest.kt
--packages/SystemUI/tests/src/com/android/systemui/screenshot/ImageCaptureImplTest.kt
--packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
--packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt
--packages/SystemUI/tests/src/com/android/systemui/settings/UserFileManagerImplTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
--packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt
--packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/shade/transition/SplitShadeOverScrollerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/navigationbar/RegionSamplingHelperTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/shared/rotation/RotationButtonControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenPreconditionTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/BlurUtilsTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/DragDownHelperTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/LightRevealScrimTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -683,6 +646,7 @@
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandRegistryTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableFlagsLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableStateTrackerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/gesture/GenericGestureDetectorTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt
@@ -719,7 +683,6 @@
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ConfigurationControllerImplTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/FoldStateListenerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxAppearanceCalculatorTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProviderTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconContainerTest.kt
@@ -733,8 +696,7 @@
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallChronometerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLoggerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/panelstate/ShadeExpansionStateManagerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherControllerOldImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ClockTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImplTest.kt
@@ -744,7 +706,6 @@
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SafetyControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerOldImplTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/VariableDateViewControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/WalletControllerImplTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt
@@ -753,40 +714,34 @@
 -packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfigTest.kt
--packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/unfold/util/FoldableTestUtils.kt
--packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
 -packages/SystemUI/tests/src/com/android/systemui/usb/UsbPermissionActivityTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/user/UserCreatorTest.kt
--packages/SystemUI/tests/src/com/android/systemui/user/UserSwitcherActivityTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/util/FakeSharedPreferencesTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/util/FloatingContentCoordinatorTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/util/ListenerSetTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/util/RingerModeLiveDataTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/util/WallpaperControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/util/animation/AnimationUtilTest.kt
--packages/SystemUI/tests/src/com/android/systemui/util/collection/RingBufferTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/util/drawable/DrawableSizeTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt
 -packages/SystemUI/tests/src/com/android/systemui/util/kotlin/IpcSerializerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/kotlin/SuspendUtilTests.kt
 -packages/SystemUI/tests/src/com/android/systemui/util/view/ViewUtilTest.kt
--packages/SystemUI/tests/utils/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt
 -packages/SystemUI/tests/utils/src/com/android/systemui/flags/FakeFeatureFlags.kt
 -packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSharedPreferences.kt
 -packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
 -packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt
 -packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionProgressProvider.kt
 -packages/SystemUI/unfold/src/com/android/systemui/unfold/compat/ScreenSizeFoldProvider.kt
 -packages/SystemUI/unfold/src/com/android/systemui/unfold/compat/SizeScreenStatusProvider.kt
 -packages/SystemUI/unfold/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt
--packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldBackground.kt
 -packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldMain.kt
 -packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
 -packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
 -packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
--packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/hinge/HingeSensorAngleProvider.kt
 -packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/screen/ScreenStatusProvider.kt
--packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt b/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
index 314c736..db88b59 100644
--- a/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
@@ -171,7 +171,7 @@
             a1 = TonalSpec(HueSource(), ChromaConstant(36.0)),
             a2 = TonalSpec(HueSource(), ChromaConstant(16.0)),
             a3 = TonalSpec(HueAdd(60.0), ChromaConstant(24.0)),
-            n1 = TonalSpec(HueSource(), ChromaConstant(4.0)),
+            n1 = TonalSpec(HueSource(), ChromaConstant(6.0)),
             n2 = TonalSpec(HueSource(), ChromaConstant(8.0))
     )),
     VIBRANT(CoreSpec(
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/DynamicColor.java b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/DynamicColor.java
index 3a6b362..e6b2c2f 100644
--- a/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/DynamicColor.java
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/DynamicColor.java
@@ -350,7 +350,7 @@
         if (bgDynamicColor != null) {
             final boolean bgHasBg =
                     bgDynamicColor.background != null && bgDynamicColor.background.apply(scheme)
-                            == null;
+                            != null;
             final double standardRatio =
                     Contrast.ratioOfTones(tone.apply(scheme), bgDynamicColor.tone.apply(scheme));
             if (decreasingContrast) {
@@ -358,15 +358,15 @@
                         Contrast.ratioOfTones(
                                 toneMinContrast.apply(scheme),
                                 bgDynamicColor.toneMinContrast.apply(scheme));
-                minRatio = bgHasBg ? 1.0 : minContrastRatio;
+                minRatio = bgHasBg ? minContrastRatio : 1.0;
                 maxRatio = standardRatio;
             } else {
                 final double maxContrastRatio =
                         Contrast.ratioOfTones(
                                 toneMaxContrast.apply(scheme),
                                 bgDynamicColor.toneMaxContrast.apply(scheme));
-                minRatio = !bgHasBg ? 1.0 : min(maxContrastRatio, standardRatio);
-                maxRatio = !bgHasBg ? 21.0 : max(maxContrastRatio, standardRatio);
+                minRatio = bgHasBg ? min(maxContrastRatio, standardRatio) : 1.0;
+                maxRatio = bgHasBg ? max(maxContrastRatio, standardRatio) : 21.0;
             }
         }
 
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
index ab4aca5..babe5700 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
@@ -112,6 +112,9 @@
     /** Call whenever the color palette should update */
     fun onColorPaletteChanged(resources: Resources) {}
 
+    /** Call if the seed color has changed and should be updated */
+    fun onSeedColorChanged(seedColor: Int?) {}
+
     /** Call whenever the weather data should update */
     fun onWeatherDataChanged(data: WeatherData) {}
 }
@@ -189,12 +192,13 @@
     val clockId: ClockId? = null,
     val seedColor: Int? = null,
 ) {
-    var _applied_timestamp: Long? = null
+    // Exclude metadata from equality checks
+    var metadata: JSONObject = JSONObject()
 
     companion object {
         private val KEY_CLOCK_ID = "clockId"
         private val KEY_SEED_COLOR = "seedColor"
-        private val KEY_TIMESTAMP = "_applied_timestamp"
+        private val KEY_METADATA = "metadata"
 
         fun serialize(setting: ClockSettings?): String {
             if (setting == null) {
@@ -204,7 +208,7 @@
             return JSONObject()
                 .put(KEY_CLOCK_ID, setting.clockId)
                 .put(KEY_SEED_COLOR, setting.seedColor)
-                .put(KEY_TIMESTAMP, setting._applied_timestamp)
+                .put(KEY_METADATA, setting.metadata)
                 .toString()
         }
 
@@ -216,11 +220,11 @@
             val json = JSONObject(jsonStr)
             val result =
                 ClockSettings(
-                    json.getString(KEY_CLOCK_ID),
+                    if (!json.isNull(KEY_CLOCK_ID)) json.getString(KEY_CLOCK_ID) else null,
                     if (!json.isNull(KEY_SEED_COLOR)) json.getInt(KEY_SEED_COLOR) else null
                 )
-            if (!json.isNull(KEY_TIMESTAMP)) {
-                result._applied_timestamp = json.getLong(KEY_TIMESTAMP)
+            if (!json.isNull(KEY_METADATA)) {
+                result.metadata = json.getJSONObject(KEY_METADATA)
             }
             return result
         }
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt
index e99b214..3e34885 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt
@@ -35,7 +35,6 @@
  * as the result of taking a bug report).
  *
  * You can dump the entire buffer at any time by running:
- *
  * ```
  * $ adb shell dumpsys activity service com.android.systemui/.SystemUIService <bufferName>
  * ```
@@ -46,13 +45,11 @@
  * locally (usually for debugging purposes).
  *
  * To enable logcat echoing for an entire buffer:
- *
  * ```
  * $ adb shell settings put global systemui/buffer/<bufferName> <level>
  * ```
  *
  * To enable logcat echoing for a specific tag:
- *
  * ```
  * $ adb shell settings put global systemui/tag/<tag> <level>
  * ```
@@ -64,10 +61,10 @@
  * LogBufferFactory.
  *
  * @param name The name of this buffer, printed when the buffer is dumped and in some other
- * situations.
+ *   situations.
  * @param maxSize The maximum number of messages to keep in memory at any one time. Buffers start
- * out empty and grow up to [maxSize] as new messages are logged. Once the buffer's size reaches the
- * maximum, it behaves like a ring buffer.
+ *   out empty and grow up to [maxSize] as new messages are logged. Once the buffer's size reaches
+ *   the maximum, it behaves like a ring buffer.
  */
 class LogBuffer
 @JvmOverloads
@@ -116,22 +113,22 @@
      * initializer stored and converts it to a human-readable log message.
      *
      * @param tag A string of at most 23 characters, used for grouping logs into categories or
-     * subjects. If this message is echoed to logcat, this will be the tag that is used.
+     *   subjects. If this message is echoed to logcat, this will be the tag that is used.
      * @param level Which level to log the message at, both to the buffer and to logcat if it's
-     * echoed. In general, a module should split most of its logs into either INFO or DEBUG level.
-     * INFO level should be reserved for information that other parts of the system might care
-     * about, leaving the specifics of code's day-to-day operations to DEBUG.
+     *   echoed. In general, a module should split most of its logs into either INFO or DEBUG level.
+     *   INFO level should be reserved for information that other parts of the system might care
+     *   about, leaving the specifics of code's day-to-day operations to DEBUG.
      * @param messageInitializer A function that will be called immediately to store relevant data
-     * on the log message. The value of `this` will be the LogMessage to be initialized.
+     *   on the log message. The value of `this` will be the LogMessage to be initialized.
      * @param messagePrinter A function that will be called if and when the message needs to be
-     * dumped to logcat or a bug report. It should read the data stored by the initializer and
-     * convert it to a human-readable string. The value of `this` will be the LogMessage to be
-     * printed. **IMPORTANT:** The printer should ONLY ever reference fields on the LogMessage and
-     * NEVER any variables in its enclosing scope. Otherwise, the runtime will need to allocate a
-     * new instance of the printer for each call, thwarting our attempts at avoiding any sort of
-     * allocation.
+     *   dumped to logcat or a bug report. It should read the data stored by the initializer and
+     *   convert it to a human-readable string. The value of `this` will be the LogMessage to be
+     *   printed. **IMPORTANT:** The printer should ONLY ever reference fields on the LogMessage and
+     *   NEVER any variables in its enclosing scope. Otherwise, the runtime will need to allocate a
+     *   new instance of the printer for each call, thwarting our attempts at avoiding any sort of
+     *   allocation.
      * @param exception Provide any exception that need to be logged. This is saved as
-     * [LogMessage.exception]
+     *   [LogMessage.exception]
      */
     @JvmOverloads
     inline fun log(
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt
index faf1b78..7a125ac 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt
@@ -28,7 +28,6 @@
  * Version of [LogcatEchoTracker] for debuggable builds
  *
  * The log level of individual buffers or tags can be controlled via global settings:
- *
  * ```
  * # Echo any message to <bufferName> of <level> or higher
  * $ adb shell settings put global systemui/buffer/<bufferName> <level>
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
index 1d28c63..c0b69c1 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
@@ -189,10 +189,12 @@
 
         /** Get the text for secondaryLabel. */
         public String getSecondaryLabel(String stateText) {
-            if (TextUtils.isEmpty(secondaryLabel)) {
+            // Use a local reference as the value might change from other threads
+            CharSequence localSecondaryLabel = secondaryLabel;
+            if (TextUtils.isEmpty(localSecondaryLabel)) {
                 return stateText;
             }
-            return secondaryLabel.toString();
+            return localSecondaryLabel.toString();
         }
 
         public boolean copyTo(State other) {
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt
index 68d7890..4773f54 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt
@@ -30,7 +30,7 @@
  *
  * @param maxSize The maximum size the buffer can grow to before it begins functioning as a ring.
  * @param factory A function that creates a fresh instance of T. Used by the buffer while it's
- * growing to [maxSize].
+ *   growing to [maxSize].
  */
 class RingBuffer<T>(private val maxSize: Int, private val factory: () -> T) : Iterable<T> {
 
diff --git a/packages/SystemUI/res-keyguard/drawable-mdpi/ic_lockscreen_sim.png b/packages/SystemUI/res-keyguard/drawable-mdpi/ic_lockscreen_sim.png
deleted file mode 100644
index 2e259c3..0000000
--- a/packages/SystemUI/res-keyguard/drawable-mdpi/ic_lockscreen_sim.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/drawable-xhdpi/ic_lockscreen_sim.png b/packages/SystemUI/res-keyguard/drawable-xhdpi/ic_lockscreen_sim.png
deleted file mode 100644
index f4de96a..0000000
--- a/packages/SystemUI/res-keyguard/drawable-xhdpi/ic_lockscreen_sim.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/drawable-hdpi/ic_lockscreen_sim.png b/packages/SystemUI/res-keyguard/drawable/ic_lockscreen_sim.png
similarity index 100%
rename from packages/SystemUI/res-keyguard/drawable-hdpi/ic_lockscreen_sim.png
rename to packages/SystemUI/res-keyguard/drawable/ic_lockscreen_sim.png
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/layout/fsi_chrome_view.xml b/packages/SystemUI/res-keyguard/layout/fsi_chrome_view.xml
deleted file mode 100644
index 4ff2967..0000000
--- a/packages/SystemUI/res-keyguard/layout/fsi_chrome_view.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<com.android.systemui.statusbar.notification.fsi.FsiChromeView android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_margin="50dp"
-    android:orientation="vertical"
-    xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:id="@+id/fsi_chrome"
-        android:layout_height="50dp"
-        android:orientation="horizontal">
-
-        <ImageView
-            android:id="@+id/fsi_app_icon"
-            android:layout_width="50dp"
-            android:layout_height="match_parent"
-            android:contentDescription="@null" />
-
-        <TextView
-            android:id="@+id/fsi_app_name"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:padding="10dp"
-            android:textSize="22dp"
-            android:gravity="center"
-            android:textColor="#FFFFFF"
-            android:text="AppName" />
-
-        <Space
-            android:layout_width="0dp"
-            android:layout_height="0dp"
-            android:layout_weight="1" />
-
-        <Button
-            android:id="@+id/fsi_fullscreen_button"
-            android:layout_width="100dp"
-            android:layout_height="match_parent"
-            android:text="fullscreen" />
-
-        <Button
-            android:id="@+id/fsi_dismiss_button"
-            android:layout_width="100dp"
-            android:layout_height="match_parent"
-            android:text="dismiss" />
-
-    </LinearLayout>
-
-</com.android.systemui.statusbar.notification.fsi.FsiChromeView>
\ No newline at end of file
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 411fea5..48769fd 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml
@@ -14,10 +14,12 @@
   ~ limitations under the License
   -->
 
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
+<merge xmlns:android="http://schemas.android.com/apk/res/android" >
     <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/layout/keyguard_sim_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
index 7db0fe9..728d861 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
 **
 ** Copyright 2012, The Android Open Source Project
 **
@@ -17,185 +16,185 @@
 */
 -->
 <!-- This is the SIM PIN view that allows the user to enter a SIM PIN to unlock the device. -->
-<com.android.keyguard.KeyguardSimPinView
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:androidprv="http://schemas.android.com/apk/res-auto"
-        android:id="@+id/keyguard_sim_pin_view"
-        android:orientation="vertical"
+<com.android.keyguard.KeyguardSimPinView xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/keyguard_sim_pin_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    androidprv:layout_maxWidth="@dimen/keyguard_security_width"
+    android:layout_gravity="center_horizontal|bottom">
+    <include layout="@layout/keyguard_bouncer_message_area"/>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        androidprv:layout_maxWidth="@dimen/keyguard_security_width"
-        android:layout_gravity="center_horizontal|bottom">
-    <include layout="@layout/keyguard_bouncer_message_area" />
-    <Space
-          android:layout_width="match_parent"
-          android:layout_height="0dp"
-          android:layout_weight="1" />
-    <ImageView
-            android:id="@+id/keyguard_sim"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:tint="@color/background_protected"
-            android:src="@drawable/ic_lockscreen_sim"/>
-    <LinearLayout
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:layoutDirection="ltr">
+        <LinearLayout
+            android:id="@+id/pin_area"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical"
-            android:gravity="center"
-            android:layoutDirection="ltr"
-            >
-        <include layout="@layout/keyguard_esim_area"
-             android:id="@+id/keyguard_esim_area"
-             android:layout_width="wrap_content"
-             android:layout_height="wrap_content" />
-        <RelativeLayout
-                android:id="@+id/row0"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:paddingBottom="4dp"
-                >
+            android:gravity="center_horizontal"
+            android:paddingTop="@dimen/num_pad_entry_row_margin_bottom"
+            android:paddingBottom="@dimen/num_pad_entry_row_margin_bottom"
+            androidprv:layout_constraintBottom_toTopOf="@+id/flow1"
+            androidprv:layout_constraintEnd_toEndOf="parent"
+            androidprv:layout_constraintStart_toStartOf="parent"
+            androidprv:layout_constraintTop_toTopOf="parent">
+
+            <ImageView
+                android:id="@+id/keyguard_sim"
+                android:layout_width="40dp"
+                android:layout_height="40dp"
+                android:layout_gravity="center_horizontal"
+                android:src="@drawable/ic_lockscreen_sim"
+                app:tint="@color/background_protected" />
+
+            <include
+                android:id="@+id/keyguard_esim_area"
+                layout="@layout/keyguard_esim_area"
+                android:layout_gravity="center_horizontal"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content" />
+
             <com.android.keyguard.PasswordTextView
                 android:id="@+id/simPinEntry"
                 style="@style/Widget.TextView.Password"
                 android:layout_width="@dimen/keyguard_security_width"
                 android:layout_height="@dimen/keyguard_password_height"
-                android:layout_centerHorizontal="true"
-                android:layout_marginRight="72dp"
                 android:contentDescription="@string/keyguard_accessibility_sim_pin_area"
-                android:gravity="center"
+                android:layout_gravity="center_horizontal"
                 androidprv:scaledTextSize="@integer/scaled_password_text_size" />
-        </RelativeLayout>
-        <LinearLayout
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:layout_gravity="center_horizontal"
-                android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
-                >
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key1"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/simPinEntry"
-                    androidprv:digit="1"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key2"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/simPinEntry"
-                    androidprv:digit="2"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key3"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    androidprv:textView="@+id/simPinEntry"
-                    androidprv:digit="3"
-                    />
         </LinearLayout>
-        <LinearLayout
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:layout_gravity="center_horizontal"
-                android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
-                >
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key4"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/simPinEntry"
-                    androidprv:digit="4"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key5"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/simPinEntry"
-                    androidprv:digit="5"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key6"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    androidprv:textView="@+id/simPinEntry"
-                    androidprv:digit="6"
-                    />
-        </LinearLayout>
-        <LinearLayout
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:layout_gravity="center_horizontal"
-                android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
-                >
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key7"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/simPinEntry"
-                    androidprv:digit="7"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key8"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/simPinEntry"
-                    androidprv:digit="8"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key9"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    androidprv:textView="@+id/simPinEntry"
-                    androidprv:digit="9"
-                    />
-        </LinearLayout>
-        <LinearLayout
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:layout_gravity="center_horizontal"
-                >
-            <com.android.keyguard.NumPadButton
-                    android:id="@+id/delete_button"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    android:contentDescription="@string/keyboardview_keycode_delete"
-                    style="@style/NumPadKey.Delete"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key0"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/simPinEntry"
-                    androidprv:digit="0"
-                    />
-            <com.android.keyguard.NumPadButton
-                    android:id="@+id/key_enter"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    style="@style/NumPadKey.Enter"
-                    android:contentDescription="@string/keyboardview_keycode_enter"
-                    />
-        </LinearLayout>
-    </LinearLayout>
-    <include layout="@layout/keyguard_eca"
-             android:id="@+id/keyguard_selector_fade_container"
-             android:layout_width="match_parent"
-             android:layout_height="wrap_content"
-             android:orientation="vertical"
-             android:layout_gravity="bottom|center_horizontal"
-             android:layout_marginTop="@dimen/keyguard_eca_top_margin"
-             android:layout_marginBottom="2dp"
-             android:gravity="center_horizontal"/>
+
+        <androidx.constraintlayout.helper.widget.Flow
+            android:id="@+id/flow1"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:clipChildren="false"
+            android:clipToPadding="false"
+            android:orientation="horizontal"
+            androidprv:constraint_referenced_ids="key1,key2,key3,key4,key5,key6,key7,key8,key9,delete_button,key0,key_enter"
+            androidprv:flow_horizontalGap="@dimen/num_pad_key_margin_end"
+            androidprv:flow_horizontalStyle="packed"
+            androidprv:flow_maxElementsWrap="3"
+            androidprv:flow_verticalBias="1.0"
+            androidprv:flow_verticalGap="@dimen/num_pad_entry_row_margin_bottom"
+            androidprv:flow_verticalStyle="packed"
+            androidprv:flow_wrapMode="aligned"
+            androidprv:layout_constraintBottom_toBottomOf="parent"
+            androidprv:layout_constraintEnd_toEndOf="parent"
+            androidprv:layout_constraintStart_toStartOf="parent"
+            androidprv:layout_constraintTop_toBottomOf="@id/pin_area" />
+
+        <com.android.keyguard.NumPadButton
+            android:id="@+id/delete_button"
+            style="@style/NumPadKey.Delete"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key0"
+            android:contentDescription="@string/keyboardview_keycode_delete" />
+
+        <com.android.keyguard.NumPadButton
+            android:id="@+id/key_enter"
+            style="@style/NumPadKey.Enter"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:contentDescription="@string/keyboardview_keycode_enter" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key1"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key2"
+            androidprv:digit="1"
+            androidprv:textView="@+id/simPinEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key2"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key3"
+            androidprv:digit="2"
+            androidprv:textView="@+id/simPinEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key3"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key4"
+            androidprv:digit="3"
+            androidprv:textView="@+id/simPinEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key4"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key5"
+            androidprv:digit="4"
+            androidprv:textView="@+id/simPinEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key5"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key6"
+            androidprv:digit="5"
+            androidprv:textView="@+id/simPinEntry" />
+
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key6"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key7"
+            androidprv:digit="6"
+            androidprv:textView="@+id/simPinEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key7"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key8"
+            androidprv:digit="7"
+            androidprv:textView="@+id/simPinEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key8"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key9"
+            androidprv:digit="8"
+            androidprv:textView="@+id/simPinEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key9"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/delete_button"
+            androidprv:digit="9"
+            androidprv:textView="@+id/simPinEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key0"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key_enter"
+            androidprv:digit="0"
+            androidprv:textView="@+id/simPinEntry" />
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+    <include
+        android:id="@+id/keyguard_selector_fade_container"
+        layout="@layout/keyguard_eca"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="bottom|center_horizontal"
+        android:layout_marginBottom="2dp"
+        android:layout_marginTop="@dimen/keyguard_eca_top_margin"
+        android:gravity="center_horizontal"
+        android:orientation="vertical" />
 </com.android.keyguard.KeyguardSimPinView>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
index 422bd4c..7e24d12 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
@@ -21,6 +21,7 @@
 <com.android.keyguard.KeyguardSimPukView
         xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:androidprv="http://schemas.android.com/apk/res-auto"
+        xmlns:app="http://schemas.android.com/apk/res-auto"
         android:id="@+id/keyguard_sim_puk_view"
         android:orientation="vertical"
         android:layout_width="match_parent"
@@ -29,173 +30,165 @@
         android:layout_gravity="center_horizontal|bottom">
     <include layout="@layout/keyguard_bouncer_message_area"/>
 
-    <Space
+    <androidx.constraintlayout.widget.ConstraintLayout
         android:layout_width="match_parent"
         android:layout_height="0dp"
-        android:layout_weight="1" />
-
-    <ImageView
-            android:id="@+id/keyguard_sim"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:tint="@color/background_protected"
-            android:src="@drawable/ic_lockscreen_sim"/>
-
-    <LinearLayout
+        android:layout_weight="1"
+        android:layoutDirection="ltr">
+        <LinearLayout
+            android:id="@+id/pin_area"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical"
-            android:gravity="center"
-            android:layoutDirection="ltr"
-            >
-        <include layout="@layout/keyguard_esim_area"
-            android:id="@+id/keyguard_esim_area"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content" />
+            android:gravity="center_horizontal"
+            android:paddingTop="@dimen/num_pad_entry_row_margin_bottom"
+            android:paddingBottom="@dimen/num_pad_entry_row_margin_bottom"
+            androidprv:layout_constraintBottom_toTopOf="@+id/flow1"
+            androidprv:layout_constraintEnd_toEndOf="parent"
+            androidprv:layout_constraintStart_toStartOf="parent"
+            androidprv:layout_constraintTop_toTopOf="parent">
 
-        <RelativeLayout
-                android:id="@+id/row0"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:paddingBottom="4dp"
-                >
+            <ImageView
+                android:id="@+id/keyguard_sim"
+                android:layout_width="40dp"
+                android:layout_height="40dp"
+                android:layout_gravity="center_horizontal"
+                android:src="@drawable/ic_lockscreen_sim"
+                app:tint="@color/background_protected" />
+
+            <include
+                android:id="@+id/keyguard_esim_area"
+                layout="@layout/keyguard_esim_area"
+                android:layout_gravity="center_horizontal"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content" />
 
             <com.android.keyguard.PasswordTextView
                 android:id="@+id/pukEntry"
                 style="@style/Widget.TextView.Password"
                 android:layout_width="@dimen/keyguard_security_width"
                 android:layout_height="@dimen/keyguard_password_height"
-                android:layout_centerHorizontal="true"
-                android:layout_marginRight="72dp"
-                android:contentDescription="@string/keyguard_accessibility_sim_puk_area"
-                android:gravity="center"
+                android:contentDescription="@string/keyguard_accessibility_sim_pin_area"
+                android:layout_gravity="center_horizontal"
                 androidprv:scaledTextSize="@integer/scaled_password_text_size" />
-        </RelativeLayout>
-        <LinearLayout
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:layout_gravity="center_horizontal"
-                android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
-                >
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key1"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/pukEntry"
-                    androidprv:digit="1"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key2"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/pukEntry"
-                    androidprv:digit="2"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key3"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    androidprv:textView="@+id/pukEntry"
-                    androidprv:digit="3"
-                    />
         </LinearLayout>
-        <LinearLayout
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:layout_gravity="center_horizontal"
-                android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
 
-                >
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key4"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/pukEntry"
-                    androidprv:digit="4"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key5"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/pukEntry"
-                    androidprv:digit="5"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key6"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    androidprv:textView="@+id/pukEntry"
-                    androidprv:digit="6"
-                    />
-        </LinearLayout>
-        <LinearLayout
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:layout_gravity="center_horizontal"
-                android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
-                >
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key7"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/pukEntry"
-                    androidprv:digit="7"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key8"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/pukEntry"
-                    androidprv:digit="8"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key9"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    androidprv:textView="@+id/pukEntry"
-                    androidprv:digit="9"
-                    />
-        </LinearLayout>
-        <LinearLayout
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:layout_gravity="center_horizontal"
-                >
-            <com.android.keyguard.NumPadButton
-                    android:id="@+id/delete_button"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    android:contentDescription="@string/keyboardview_keycode_delete"
-                    style="@style/NumPadKey.Delete"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key0"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/pukEntry"
-                    androidprv:digit="0"
-                    />
-            <com.android.keyguard.NumPadButton
-                    android:id="@+id/key_enter"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    style="@style/NumPadKey.Enter"
-                    android:contentDescription="@string/keyboardview_keycode_enter"
-                    />
-        </LinearLayout>
-    </LinearLayout>
+        <androidx.constraintlayout.helper.widget.Flow
+            android:id="@+id/flow1"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:clipChildren="false"
+            android:clipToPadding="false"
+            android:orientation="horizontal"
+            androidprv:constraint_referenced_ids="key1,key2,key3,key4,key5,key6,key7,key8,key9,delete_button,key0,key_enter"
+            androidprv:flow_horizontalGap="@dimen/num_pad_key_margin_end"
+            androidprv:flow_horizontalStyle="packed"
+            androidprv:flow_maxElementsWrap="3"
+            androidprv:flow_verticalBias="1.0"
+            androidprv:flow_verticalGap="@dimen/num_pad_entry_row_margin_bottom"
+            androidprv:flow_verticalStyle="packed"
+            androidprv:flow_wrapMode="aligned"
+            androidprv:layout_constraintBottom_toBottomOf="parent"
+            androidprv:layout_constraintEnd_toEndOf="parent"
+            androidprv:layout_constraintStart_toStartOf="parent"
+            androidprv:layout_constraintTop_toBottomOf="@id/pin_area" />
+
+        <com.android.keyguard.NumPadButton
+            android:id="@+id/delete_button"
+            style="@style/NumPadKey.Delete"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key0"
+            android:contentDescription="@string/keyboardview_keycode_delete" />
+
+        <com.android.keyguard.NumPadButton
+            android:id="@+id/key_enter"
+            style="@style/NumPadKey.Enter"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:contentDescription="@string/keyboardview_keycode_enter" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key1"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key2"
+            androidprv:digit="1"
+            androidprv:textView="@+id/pukEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key2"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key3"
+            androidprv:digit="2"
+            androidprv:textView="@+id/pukEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key3"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key4"
+            androidprv:digit="3"
+            androidprv:textView="@+id/pukEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key4"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key5"
+            androidprv:digit="4"
+            androidprv:textView="@+id/pukEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key5"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key6"
+            androidprv:digit="5"
+            androidprv:textView="@+id/pukEntry" />
+
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key6"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key7"
+            androidprv:digit="6"
+            androidprv:textView="@+id/pukEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key7"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key8"
+            androidprv:digit="7"
+            androidprv:textView="@+id/pukEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key8"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key9"
+            androidprv:digit="8"
+            androidprv:textView="@+id/pukEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key9"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/delete_button"
+            androidprv:digit="9"
+            androidprv:textView="@+id/pukEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key0"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key_enter"
+            androidprv:digit="0"
+            androidprv:textView="@+id/pukEntry" />
+    </androidx.constraintlayout.widget.ConstraintLayout>
 
     <include layout="@layout/keyguard_eca"
              android:id="@+id/keyguard_selector_fade_container"
diff --git a/packages/SystemUI/res-keyguard/values-af/strings.xml b/packages/SystemUI/res-keyguard/values-af/strings.xml
index 205b9e0..9c8907f 100644
--- a/packages/SystemUI/res-keyguard/values-af/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-af/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans vinnig"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans stadig"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laaiproses word geoptimeer om battery te beskerm"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Onversoenbare laaiproses"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kwessie met laaibykomstigheid"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Druk Kieslys om te ontsluit."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Netwerk is gesluit"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Geen SIM nie"</string>
diff --git a/packages/SystemUI/res-keyguard/values-am/strings.xml b/packages/SystemUI/res-keyguard/values-am/strings.xml
index 47b7bbe..9cbb627 100644
--- a/packages/SystemUI/res-keyguard/values-am/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-am/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • በፍጥነት ኃይልን በመሙላት ላይ"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • በዝግታ ኃይልን በመሙላት ላይ"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ባትሪን ለመጠበቅ ኃይል መሙላት ተብቷል"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ተኳሃኝ ባልሆነ ኃይል በመሙላት ላይ"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ለመክፈት ምናሌ ተጫን።"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"አውታረ መረብ ተቆልፏል"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"ምንም SIM የለም"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ar/strings.xml b/packages/SystemUI/res-keyguard/values-ar/strings.xml
index 76b8d46..ad931fe 100644
--- a/packages/SystemUI/res-keyguard/values-ar/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ar/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن سريعًا"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن ببطء"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • تم تحسين الشحن لحماية البطارية"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • شاحن غير متوافق"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"اضغط على \"القائمة\" لإلغاء التأمين."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"الشبكة مؤمّنة"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"‏لا تتوفر شريحة SIM."</string>
diff --git a/packages/SystemUI/res-keyguard/values-as/strings.xml b/packages/SystemUI/res-keyguard/values-as/strings.xml
index 716699b..cdc260e 100644
--- a/packages/SystemUI/res-keyguard/values-as/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-as/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • দ্ৰুত গতিৰে চ্চাৰ্জ কৰি থকা হৈছে"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • লাহে লাহে চ্চাৰ্জ কৰি থকা হৈছে"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • বেটাৰী সুৰক্ষিত কৰিবলৈ চাৰ্জিং অপ্টিমাইজ কৰা হৈছে"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • অমিল চাৰ্জিং"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"আনলক কৰিবলৈ মেনু টিপক।"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"নেটৱর্ক লক কৰা অৱস্থাত আছে"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"কোনো ছিম নাই"</string>
diff --git a/packages/SystemUI/res-keyguard/values-az/strings.xml b/packages/SystemUI/res-keyguard/values-az/strings.xml
index 1626fd8..4339169 100644
--- a/packages/SystemUI/res-keyguard/values-az/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-az/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sürətlə enerji yığır"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Yavaş enerji yığır"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Batareyanı qorumaq üçün şarj optimallaşdırılıb"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Uyğunsuz şarj"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Şarj aksesuarı ilə bağlı problem"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Kilidi açmaq üçün Menyu düyməsinə basın."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Şəbəkə kilidlidir"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM yoxdur"</string>
diff --git a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
index 9be3eaa..30a55d1 100644
--- a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Brzo se puni"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sporo se puni"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje je optimizovano da bi se zaštitila baterija"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nekompatibilno punjenje"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pritisnite Meni da biste otključali."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Nema SIM-a"</string>
diff --git a/packages/SystemUI/res-keyguard/values-be/strings.xml b/packages/SystemUI/res-keyguard/values-be/strings.xml
index 0c6826c..844ed93 100644
--- a/packages/SystemUI/res-keyguard/values-be/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-be/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе хуткая зарадка"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе павольная зарадка"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • У мэтах зберажэння акумулятара зарадка аптымізавана"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Несумяшчальная зарадная прылада"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Націсніце кнопку \"Меню\", каб разблакіраваць."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Сетка заблакіравана"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Няма SIM-карты"</string>
diff --git a/packages/SystemUI/res-keyguard/values-bg/strings.xml b/packages/SystemUI/res-keyguard/values-bg/strings.xml
index 683c87b..3302189 100644
--- a/packages/SystemUI/res-keyguard/values-bg/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bg/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се бързо"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се бавно"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зареждането е оптимизирано с цел запазване на батерията"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • несъвместим начин на зареждане"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Проблем със зарядното устройство"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Натиснете „Меню“, за да отключите."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежата е заключена"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Няма SIM карта"</string>
diff --git a/packages/SystemUI/res-keyguard/values-bn/strings.xml b/packages/SystemUI/res-keyguard/values-bn/strings.xml
index ebcf9fb..cb25c99 100644
--- a/packages/SystemUI/res-keyguard/values-bn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bn/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • দ্রুত চার্জ হচ্ছে"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ধীরে চার্জ হচ্ছে"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ব্যাটারি ভাল রাখতে চার্জিং অপ্টিমাইজ করা হয়েছে"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • মানানসই নয় এমন চার্জিং"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"আনলক করতে মেনুতে টিপুন।"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"নেটওয়ার্ক লক করা আছে"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"কোনও সিম নেই"</string>
diff --git a/packages/SystemUI/res-keyguard/values-bs/strings.xml b/packages/SystemUI/res-keyguard/values-bs/strings.xml
index a3280c3..8b9eda2 100644
--- a/packages/SystemUI/res-keyguard/values-bs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bs/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Brzo punjenje"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sporo punjenje"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje je optimizirano radi zaštite baterije"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nekompatibilno punjenje"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problem s opremom za punjenje"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pritisnite meni da otključate."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Nema SIM-a"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ca/strings.xml b/packages/SystemUI/res-keyguard/values-ca/strings.xml
index 0cb55af..185461f 100644
--- a/packages/SystemUI/res-keyguard/values-ca/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ca/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant ràpidament"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant lentament"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Càrrega optimitzada per protegir la bateria"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Càrrega incompatible"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Prem Menú per desbloquejar."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"La xarxa està bloquejada"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"No hi ha cap SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-cs/strings.xml b/packages/SystemUI/res-keyguard/values-cs/strings.xml
index 75ddff8..f2ebe80 100644
--- a/packages/SystemUI/res-keyguard/values-cs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-cs/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Rychlé nabíjení"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pomalé nabíjení"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimalizované nabíjení za účelem ochrany baterie"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nekompatibilní nabíjení"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Klávesy odemknete stisknutím tlačítka nabídky."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Síť je blokována"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Žádná SIM karta"</string>
diff --git a/packages/SystemUI/res-keyguard/values-da/strings.xml b/packages/SystemUI/res-keyguard/values-da/strings.xml
index 47d9416..aedfa58 100644
--- a/packages/SystemUI/res-keyguard/values-da/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-da/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader hurtigt"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader langsomt"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Opladning er optimeret for at beskytte batteriet"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ikke-kompatibel opladning"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tryk på menuen for at låse op."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Netværket er låst"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Intet SIM-kort"</string>
diff --git a/packages/SystemUI/res-keyguard/values-de/strings.xml b/packages/SystemUI/res-keyguard/values-de/strings.xml
index 4eae7d9..294bb68 100644
--- a/packages/SystemUI/res-keyguard/values-de/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-de/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird schnell geladen"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird langsam geladen"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimiertes Laden zur Akkuschonung"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inkompatibles Ladegerät"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Zum Entsperren die Menütaste drücken."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Netzwerk gesperrt"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Keine SIM-Karte"</string>
diff --git a/packages/SystemUI/res-keyguard/values-el/strings.xml b/packages/SystemUI/res-keyguard/values-el/strings.xml
index 81ac3dc..0518885 100644
--- a/packages/SystemUI/res-keyguard/values-el/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-el/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Γρήγορη φόρτιση"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Αργή φόρτιση"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Η φόρτιση βελτιστοποιήθηκε για την προστασία της μπαταρίας"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Μη συμβατή φόρτιση"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Πρόβλημα αξεσουάρ φόρτισης"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Πατήστε \"Μενού\" για ξεκλείδωμα."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Κλειδωμένο δίκτυο"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Δεν υπάρχει SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
index 0f84823..9df8586 100644
--- a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging optimised to protect battery"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Incompatible charging"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Issue with charging accessory"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"No SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
index a28506b..d6d4b48 100644
--- a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging optimized to protect battery"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Incompatible charging"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Issue with charging accessory"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"No SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
index 0f84823..9df8586 100644
--- a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging optimised to protect battery"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Incompatible charging"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Issue with charging accessory"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"No SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
index 0f84823..9df8586 100644
--- a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging optimised to protect battery"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Incompatible charging"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Issue with charging accessory"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"No SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
index 3f1b30a..566c8b0 100644
--- a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‎‎‎‎‎‎‏‎‏‎‎‎‎‎‎‎‏‎‏‎‏‏‎‏‎‏‏‏‎‎‏‎‎‎‏‏‏‏‏‎‏‎‎‎‎‏‎‎‎‏‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Charging rapidly‎‏‎‎‏‎"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‏‎‏‏‎‎‎‏‎‎‏‎‎‏‎‏‏‏‏‎‏‏‏‎‏‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Charging slowly‎‏‎‎‏‎"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‏‏‎‏‎‏‏‏‏‎‎‎‏‎‏‎‎‎‎‎‏‎‏‏‎‎‏‎‎‏‎‏‎‎‎‏‎‎‎‏‏‏‎‎‎‎‎‏‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Charging optimized to protect battery‎‏‎‎‏‎"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‎‎‏‎‎‎‎‏‏‎‏‏‏‎‏‏‎‏‏‏‎‎‏‏‏‏‎‎‏‎‏‏‏‏‎‎‏‏‏‎‏‎‎‎‏‏‏‏‎‎‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Incompatible charging‎‏‎‎‏‎"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‎‏‏‏‎‎‏‎‎‎‏‎‏‏‎‏‏‏‎‎‎‎‎‎‏‏‏‏‎‎‏‎‎‏‏‏‏‎‎‏‎‏‏‎‎‎‏‎‎‎‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Issue with charging accessory‎‏‎‎‏‎"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‎‎‎‎‎‏‎‏‏‏‎‏‎‏‎‎‎‏‏‎‏‎‏‏‎‏‏‎‎‎‏‏‎‎‎‏‎‎‏‏‏‎‎‎‎‏‏‏‎‏‎‎Press Menu to unlock.‎‏‎‎‏‎"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‎‏‎‎‏‏‎‎‏‎‎‏‎‏‏‏‏‏‎‏‎‏‏‏‏‏‎‎‏‎‎‎‏‏‎‎‏‎‏‏‎‎‏‎‏‎‎‎‎‎‎‎‎‎‎‎Network locked‎‏‎‎‏‎"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‏‎‎‎‎‎‎‏‏‎‏‏‎‏‏‎‏‏‎‎‎‏‏‏‎‏‏‏‏‎‎‎‏‎‎‎‎‎‎‎‎‏‏‏‏‎‎‏‎‎‏‎‏‎‎‎‎No SIM‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
index 4b735e9..fec15b4 100644
--- a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rápidamente"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carga optimizada para proteger la batería"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carga no compatible"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Presiona Menú para desbloquear."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada para la red"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"No hay ninguna tarjeta SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-es/strings.xml b/packages/SystemUI/res-keyguard/values-es/strings.xml
index 986192f..04e02d8 100644
--- a/packages/SystemUI/res-keyguard/values-es/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-es/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rápidamente"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carga optimizada para proteger la batería"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carga no compatible"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pulsa el menú para desbloquear la pantalla."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada para la red"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"No hay ninguna SIM."</string>
diff --git a/packages/SystemUI/res-keyguard/values-et/strings.xml b/packages/SystemUI/res-keyguard/values-et/strings.xml
index f551ab2..2b387a4 100644
--- a/packages/SystemUI/res-keyguard/values-et/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-et/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kiirlaadimine"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Aeglane laadimine"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laadimine on aku kaitsmiseks optimeeritud"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ühildumatu laadimine"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • probleem laadimistarvikuga"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Vajutage avamiseks menüüklahvi."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Võrk on lukus"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM-i pole"</string>
diff --git a/packages/SystemUI/res-keyguard/values-eu/strings.xml b/packages/SystemUI/res-keyguard/values-eu/strings.xml
index ce88d5b..bfe9778 100644
--- a/packages/SystemUI/res-keyguard/values-eu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-eu/strings.xml
@@ -30,9 +30,8 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kargatzen"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bizkor kargatzen"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mantso kargatzen"</string>
-    <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kargatzea optimizatu da bateria ez kaltetzeko"</string>
-    <!-- no translation found for keyguard_plugged_in_incompatible_charger (5712938022567388098) -->
-    <skip />
+    <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bateria ez kaltetzeko, kargatzeko modua optimizatu da"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Arazo bat dago kargatzeko osagarriarekin"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Desblokeatzeko, sakatu Menua."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Sarea blokeatuta dago"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Ez dago SIMik"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fa/strings.xml b/packages/SystemUI/res-keyguard/values-fa/strings.xml
index ea591b8..edb4761 100644
--- a/packages/SystemUI/res-keyguard/values-fa/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fa/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ سریع"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • آهسته‌آهسته شارژ می‌شود"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • برای محافظت از باتری، شارژ بهینه می‌شود"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • شارژ ناسازگار است"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"برای باز کردن قفل روی «منو» فشار دهید."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"شبکه قفل شد"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"سیم‌کارتی وجود ندارد"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fi/strings.xml b/packages/SystemUI/res-keyguard/values-fi/strings.xml
index 9e26025f..e6b1400 100644
--- a/packages/SystemUI/res-keyguard/values-fi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fi/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan nopeasti"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan hitaasti"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lataus optimoitu akun suojaamiseksi"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laturi ei ole yhteensopiva"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Poista lukitus painamalla Valikkoa."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Verkko lukittu"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Ei SIM-korttia"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
index 80bd0bf..57e4664 100644
--- a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"En recharge rapide : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"En recharge lente : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge optimisée pour protéger la pile"</string>
-    <!-- no translation found for keyguard_plugged_in_incompatible_charger (5712938022567388098) -->
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
     <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Appuyez sur la touche Menu pour déverrouiller l\'appareil."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Réseau verrouillé"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fr/strings.xml b/packages/SystemUI/res-keyguard/values-fr/strings.xml
index 77d3987..81f0034 100644
--- a/packages/SystemUI/res-keyguard/values-fr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge rapide…"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge lente"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge optimisée pour protéger la batterie"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge incompatible"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Appuyez sur \"Menu\" pour déverrouiller le clavier."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Réseau verrouillé"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Aucune SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-gl/strings.xml b/packages/SystemUI/res-keyguard/values-gl/strings.xml
index 9feb174..43d41e1 100644
--- a/packages/SystemUI/res-keyguard/values-gl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gl/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rapidamente"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carga optimizada para protexer a batería"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carga incompatible"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Preme Menú para desbloquear."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada pola rede"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Non hai ningunha SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-gu/strings.xml b/packages/SystemUI/res-keyguard/values-gu/strings.xml
index 6d68426..2524397 100644
--- a/packages/SystemUI/res-keyguard/values-gu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gu/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ઝડપથી ચાર્જિંગ"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ધીમેથી ચાર્જિંગ"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • બૅટરીની સુરક્ષા કરવા માટે, ચાર્જિંગ ઑપ્ટિમાઇઝ કરવામાં આવ્યું છે"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • અસંગત ચાર્જિંગ"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"અનલૉક કરવા માટે મેનૂ દબાવો."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"નેટવર્ક લૉક થયું"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"કોઈ સિમ કાર્ડ નથી"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml
index 335931b..8ae56cb 100644
--- a/packages/SystemUI/res-keyguard/values-hi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml
@@ -30,8 +30,8 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज हो रहा है"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • तेज़ चार्ज हो रहा है"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • धीरे चार्ज हो रहा है"</string>
-    <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • बैटरी को नुकसान से बचाने के लिए, उसकी चार्जिंग को ऑप्टिमाइज़ किया गया"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • फ़ोन के साथ काम न करने वाला चार्जर"</string>
+    <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • बैटरी को नुकसान से बचाने के लिए, चार्जिंग को ऑप्टिमाइज़ किया गया"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्जर ऐक्सेसरी से जुड़ी समस्या"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"लॉक खोलने के लिए मेन्यू दबाएं."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लॉक किया हुआ है"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"कोई सिम नहीं है"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hr/strings.xml b/packages/SystemUI/res-keyguard/values-hr/strings.xml
index a865b37..5b121dd 100644
--- a/packages/SystemUI/res-keyguard/values-hr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hr/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • brzo punjenje"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • sporo punjenje"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje se optimizira radi zaštite baterije"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nekompatibilno punjenje"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problem s priborom za punjenje"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pritisnite Izbornik da biste otključali."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Nema SIM-a"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hu/strings.xml b/packages/SystemUI/res-keyguard/values-hu/strings.xml
index 06dd876..649952a 100644
--- a/packages/SystemUI/res-keyguard/values-hu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hu/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Gyors töltés"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lassú töltés"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimalizált töltés az akkumulátor védelme érdekében"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nem kompatibilis töltés"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Probléma van a töltőtartozékkal"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"A feloldáshoz nyomja meg a Menü gombot."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Hálózat zárolva"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Nincs SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hy/strings.xml b/packages/SystemUI/res-keyguard/values-hy/strings.xml
index d131046..0ecc55c 100644
--- a/packages/SystemUI/res-keyguard/values-hy/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hy/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Արագ լիցքավորում"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Դանդաղ լիցքավորում"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Մարտկոցը պաշտպանելու համար լիցքավորումն օպտիմալացվել է"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Անհամատեղելի ադապտերով լիցքավորում"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ապակողպելու համար սեղմեք Ընտրացանկը:"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Ցանցը կողպված է"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM քարտ չկա"</string>
diff --git a/packages/SystemUI/res-keyguard/values-in/strings.xml b/packages/SystemUI/res-keyguard/values-in/strings.xml
index b6a4185..39f6553 100644
--- a/packages/SystemUI/res-keyguard/values-in/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-in/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya dengan cepat"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya dengan lambat"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pengisian daya dioptimalkan untuk melindungi baterai"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pengisi daya tidak kompatibel"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tekan Menu untuk membuka kunci."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Jaringan terkunci"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Tidak ada SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-is/strings.xml b/packages/SystemUI/res-keyguard/values-is/strings.xml
index de0dc64..c06109d 100644
--- a/packages/SystemUI/res-keyguard/values-is/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-is/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hröð hleðsla"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hæg hleðsla"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hleðsla fínstillt til að vernda rafhlöðuna"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ósamhæf hleðsla"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ýttu á valmyndarhnappinn til að taka úr lás."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Net læst"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Ekkert SIM-kort"</string>
diff --git a/packages/SystemUI/res-keyguard/values-it/strings.xml b/packages/SystemUI/res-keyguard/values-it/strings.xml
index c0bccec..cc05bee 100644
--- a/packages/SystemUI/res-keyguard/values-it/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-it/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica veloce"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica lenta"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica ottimizzata per proteggere la batteria"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica con un alimentatore non compatibile"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Premi Menu per sbloccare."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rete bloccata"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Nessuna SIM presente"</string>
diff --git a/packages/SystemUI/res-keyguard/values-iw/strings.xml b/packages/SystemUI/res-keyguard/values-iw/strings.xml
index 3d2bd46..d1f8760 100644
--- a/packages/SystemUI/res-keyguard/values-iw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-iw/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה מהירה"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה איטית"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • הטעינה עברה אופטימיזציה כדי להגן על הסוללה"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • טעינה לא תואמת"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • יש בעיה עם אביזר הטעינה"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"יש ללחוץ על \'תפריט\' כדי לבטל את הנעילה."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"הרשת נעולה"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"‏אין כרטיס SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ja/strings.xml b/packages/SystemUI/res-keyguard/values-ja/strings.xml
index a990b8d..8057dfd 100644
--- a/packages/SystemUI/res-keyguard/values-ja/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ja/strings.xml
@@ -30,8 +30,8 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電中"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 急速充電中"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 低速充電中"</string>
-    <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電最適化済み(バッテリーを保護)"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電器が対応していません"</string>
+    <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • バッテリーを保護するために、充電が最適化されています"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電用アクセサリに関する問題"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"メニューからロックを解除できます。"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"ネットワークがロックされました"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM がありません"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ka/strings.xml b/packages/SystemUI/res-keyguard/values-ka/strings.xml
index 8121538..eb96a9e 100644
--- a/packages/SystemUI/res-keyguard/values-ka/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ka/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • სწრაფად იტენება"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ნელა იტენება"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • დატენვა ოპტიმიზირებულია ბატარეის დასაცავად"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • არათავსებადი დატენვა"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"განსაბლოკად დააჭირეთ მენიუს."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"ქსელი ჩაკეტილია"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM არ არის"</string>
diff --git a/packages/SystemUI/res-keyguard/values-kk/strings.xml b/packages/SystemUI/res-keyguard/values-kk/strings.xml
index bfd65c4..90519df 100644
--- a/packages/SystemUI/res-keyguard/values-kk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kk/strings.xml
@@ -30,8 +30,9 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарядталуда"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Жылдам зарядталуда"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Баяу зарядталуда"</string>
-    <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батареяны қорғау үшін, зарядтау оңтайландырылды"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Үйлесімді емес зарядтағыш"</string>
+    <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батареяны қорғау үшін зарядтау оңтайландырылды"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ашу үшін \"Мәзір\" пернесін басыңыз."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Желі құлыптаулы"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM картасы жоқ."</string>
diff --git a/packages/SystemUI/res-keyguard/values-km/strings.xml b/packages/SystemUI/res-keyguard/values-km/strings.xml
index cdc1ddf..5a3b30b 100644
--- a/packages/SystemUI/res-keyguard/values-km/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-km/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុង​សាកថ្មយ៉ាង​ឆាប់រហ័ស"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុង​សាកថ្មយឺត"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • បានបង្កើនប្រសិទ្ធភាពនៃការសាក ដើម្បីការពារថ្ម"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ការសាកថ្មដែលមិនត្រូវគ្នា"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • បញ្ហាពាក់ព័ន្ធនឹងគ្រឿងសាកថ្ម"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ចុចម៉ឺនុយ ​ដើម្បី​ដោះ​សោ។"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"បណ្ដាញ​ជាប់​សោ"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"គ្មានស៊ីមទេ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-kn/strings.xml b/packages/SystemUI/res-keyguard/values-kn/strings.xml
index 66adecb..e74dd1a 100644
--- a/packages/SystemUI/res-keyguard/values-kn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kn/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ವೇಗವಾಗಿ ಚಾರ್ಜ್‌ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ನಿಧಾನವಾಗಿ ಚಾರ್ಜ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಬ್ಯಾಟರಿಯನ್ನು ರಕ್ಷಿಸಲು ಚಾರ್ಜಿಂಗ್ ಅನ್ನು ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗಿದೆ"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಹೊಂದಾಣಿಕೆಯಾಗದ ಚಾರ್ಜಿಂಗ್"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಚಾರ್ಜಿಂಗ್ ಪರಿಕರ ಕುರಿತು ಸಮಸ್ಯೆ ಇದೆ"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ಅನ್‌ಲಾಕ್ ಮಾಡಲು ಮೆನು ಒತ್ತಿರಿ."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"ನೆಟ್‌ವರ್ಕ್ ಲಾಕ್ ಆಗಿದೆ"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM ಇಲ್ಲ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ko/strings.xml b/packages/SystemUI/res-keyguard/values-ko/strings.xml
index b2058a1..8d54aef 100644
--- a/packages/SystemUI/res-keyguard/values-ko/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ko/strings.xml
@@ -31,8 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 고속 충전 중"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 저속 충전 중"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 배터리 보호를 위해 충전 최적화됨"</string>
-    <!-- no translation found for keyguard_plugged_in_incompatible_charger (5712938022567388098) -->
-    <skip />
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 충전 액세서리 문제"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"잠금 해제하려면 메뉴를 누르세요."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"네트워크 잠김"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM 없음"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ky/strings.xml b/packages/SystemUI/res-keyguard/values-ky/strings.xml
index afae9bc..5cf8ad3 100644
--- a/packages/SystemUI/res-keyguard/values-ky/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ky/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Тез кубатталууда"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Жай кубатталууда"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батареяны коргоо үчүн кубаттоо процесси оптималдаштырылды"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Кубаттагыч туура келбейт"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Кулпуну ачуу үчүн Менюну басыңыз."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Тармак кулпуланган"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM карта жок"</string>
diff --git a/packages/SystemUI/res-keyguard/values-land/dimens.xml b/packages/SystemUI/res-keyguard/values-land/dimens.xml
index f1aa544..a4e7a5f 100644
--- a/packages/SystemUI/res-keyguard/values-land/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values-land/dimens.xml
@@ -27,6 +27,4 @@
     <integer name="scaled_password_text_size">26</integer>
 
     <dimen name="bouncer_user_switcher_y_trans">@dimen/status_bar_height</dimen>
-    <dimen name="bouncer_user_switcher_view_mode_user_switcher_bottom_margin">0dp</dimen>
-    <dimen name="bouncer_user_switcher_view_mode_view_flipper_bottom_margin">0dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values-lo/strings.xml b/packages/SystemUI/res-keyguard/values-lo/strings.xml
index 70cc481..7e3cd89 100644
--- a/packages/SystemUI/res-keyguard/values-lo/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lo/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກແບບດ່ວນ"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກແບບຊ້າ"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ການສາກຖືກປັບໃຫ້ເໝາະສົມເພື່ອປົກປ້ອງແບັດເຕີຣີ"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ການສາກທີ່ເຂົ້າກັນບໍ່ໄດ້"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ກົດ \"ເມນູ\" ເພື່ອປົດລັອກ."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"ເຄືອຂ່າຍຖືກລັອກ"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"ບໍ່ມີຊິມ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-lt/strings.xml b/packages/SystemUI/res-keyguard/values-lt/strings.xml
index 6703894..23601d3 100644
--- a/packages/SystemUI/res-keyguard/values-lt/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lt/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Greitai įkraunama"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lėtai įkraunama"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Įkrovimas optimizuotas siekiant apsaugoti akumuliatorių"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nesuderinamas įkrovimas"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Paspauskite meniu, jei norite atrakinti."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Tinklas užrakintas"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Nėra SIM kortelės"</string>
diff --git a/packages/SystemUI/res-keyguard/values-lv/strings.xml b/packages/SystemUI/res-keyguard/values-lv/strings.xml
index c40245e..e66a018 100644
--- a/packages/SystemUI/res-keyguard/values-lv/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lv/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek ātrā uzlāde"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek lēnā uzlāde"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Uzlāde optimizēta, lai saudzētu akumulatoru"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nesaderīgs lādētājs"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Lai atbloķētu, nospiediet izvēlnes ikonu."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Tīkls ir bloķēts."</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Nav SIM kartes"</string>
diff --git a/packages/SystemUI/res-keyguard/values-mk/strings.xml b/packages/SystemUI/res-keyguard/values-mk/strings.xml
index ff4d368..28d6988 100644
--- a/packages/SystemUI/res-keyguard/values-mk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mk/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Брзо полнење"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Бавно полнење"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Полнењето е оптимизирано за да се заштити батеријата"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Некомпатибилно полнење"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Притиснете „Мени“ за отклучување."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежата е заклучена"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Нема SIM-картичка"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ml/strings.xml b/packages/SystemUI/res-keyguard/values-ml/strings.xml
index c841033..385aadf 100644
--- a/packages/SystemUI/res-keyguard/values-ml/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ml/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • വേഗത്തിൽ ചാർജ് ചെയ്യുന്നു"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • പതുക്കെ ചാർജ് ചെയ്യുന്നു"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ബാറ്ററി പരിരക്ഷിക്കാൻ ചാർജിംഗ് ഒപ്റ്റിമൈസ് ചെയ്തു"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • അനുയോജ്യമല്ലാത്ത ചാർജിംഗ്"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ചാർജിംഗ് ആക്സസറിയുമായി ബന്ധപ്പെട്ട പ്രശ്നം"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"അൺലോക്കുചെയ്യാൻ മെനു അമർത്തുക."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"നെറ്റ്‌വർക്ക് ലോക്കുചെയ്‌തു"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"സിം ഇല്ല"</string>
diff --git a/packages/SystemUI/res-keyguard/values-mn/strings.xml b/packages/SystemUI/res-keyguard/values-mn/strings.xml
index 6ad6d8d..1b36541 100644
--- a/packages/SystemUI/res-keyguard/values-mn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mn/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Хурдан цэнэглэж байна"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Удаан цэнэглэж байна"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батарейг хамгаалахын тулд цэнэглэх явцыг оновчилсон"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Тохиромжгүй адаптераар цэнэглэх"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Түгжээг тайлах бол цэсийг дарна уу."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Сүлжээ түгжигдсэн"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM байхгүй"</string>
diff --git a/packages/SystemUI/res-keyguard/values-mr/strings.xml b/packages/SystemUI/res-keyguard/values-mr/strings.xml
index 951cf8d..400d884 100644
--- a/packages/SystemUI/res-keyguard/values-mr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mr/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • वेगाने चार्ज होत आहे"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • सावकाश चार्ज होत आहे"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • बॅटरीचे संरक्षण करण्यासाठी चार्जिंग ऑप्टिमाइझ केले आहे"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • कंपॅटिबल नसलेले चार्जिंग"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"अनलॉक करण्यासाठी मेनू दाबा."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लॉक केले"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"सिम नाही"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ms/strings.xml b/packages/SystemUI/res-keyguard/values-ms/strings.xml
index 7096565..de9cb80 100644
--- a/packages/SystemUI/res-keyguard/values-ms/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ms/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas dengan cepat"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas dengan perlahan"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pengecasan dioptimumkan untuk melindungi bateri"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pengecasan tidak serasi"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Isu berkaitan aksesori pengecasan"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tekan Menu untuk membuka kunci."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rangkaian dikunci"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Tiada SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-my/strings.xml b/packages/SystemUI/res-keyguard/values-my/strings.xml
index d4251cd..3be9890 100644
--- a/packages/SystemUI/res-keyguard/values-my/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-my/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အမြန်အားသွင်းနေသည်"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • နှေးကွေးစွာ အားသွင်းနေသည်"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ဘက်ထရီကာကွယ်ရန် အားသွင်းခြင်းကို အကောင်းဆုံးပြင်ဆင်ထားသည်"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အားသွင်းမှု မကိုက်ညီပါ"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အားသွင်းပစ္စည်းတွင် ပြဿနာရှိသည်"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"မီနူးကို နှိပ်၍ လော့ခ်ဖွင့်ပါ။"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"ကွန်ရက်ကို လော့ခ်ချထားသည်"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"ဆင်းမ်မရှိပါ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-nb/strings.xml b/packages/SystemUI/res-keyguard/values-nb/strings.xml
index 9a5e6e5..a9a051e 100644
--- a/packages/SystemUI/res-keyguard/values-nb/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nb/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader raskt"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader sakte"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladingen er optimalisert for å beskytte batteriet"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ukompatibel lading"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Trykk på menyknappen for å låse opp."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Nettverket er låst"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Ingen SIM-kort"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ne/strings.xml b/packages/SystemUI/res-keyguard/values-ne/strings.xml
index e35e394..f533610 100644
--- a/packages/SystemUI/res-keyguard/values-ne/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ne/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • द्रुत गतिमा चार्ज गरिँदै छ"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • मन्द गतिमा चार्ज गरिँदै"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ब्याट्री जोगाउन चार्ज गर्ने प्रक्रिया अप्टिमाइज गरिएको छ"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • नमिल्दो चार्जिङ"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"अनलक गर्न मेनु थिच्नुहोस्।"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लक भएको छ"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM कार्ड हालिएको छैन"</string>
diff --git a/packages/SystemUI/res-keyguard/values-nl/strings.xml b/packages/SystemUI/res-keyguard/values-nl/strings.xml
index ca5bf2a..8278d11 100644
--- a/packages/SystemUI/res-keyguard/values-nl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nl/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Snel opladen"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Langzaam opladen"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Opladen geoptimaliseerd om de batterij te beschermen"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Incompatibele oplader"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Probleem met oplaadaccessoire"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Druk op Menu om te ontgrendelen."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Netwerk vergrendeld"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Geen simkaart"</string>
diff --git a/packages/SystemUI/res-keyguard/values-or/strings.xml b/packages/SystemUI/res-keyguard/values-or/strings.xml
index aea95e4..c698727 100644
--- a/packages/SystemUI/res-keyguard/values-or/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-or/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଦ୍ରୁତ ଭାବେ ଚାର୍ଜ ହେଉଛି"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଧୀରେ ଚାର୍ଜ ହେଉଛି"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ବେଟେରୀକୁ ସୁରକ୍ଷିତ ରଖିବା ପାଇଁ ଚାର୍ଜିଂକୁ ଅପ୍ଟିମାଇଜ କରାଯାଇଛି"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଇନକମ୍ପାଟିବଲ ଚାର୍ଜିଂ"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଚାର୍ଜିଂ ଆକସେସୋରୀ ସହ ସମସ୍ୟା"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ଅନଲକ୍‌ କରିବା ପାଇଁ ମେନୁକୁ ଦବାନ୍ତୁ।"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"ନେଟୱର୍କକୁ ଲକ୍‌ କରାଯାଇଛି"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"କୌଣସି SIM ନାହିଁ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pa/strings.xml b/packages/SystemUI/res-keyguard/values-pa/strings.xml
index ac6209e..bf435ee 100644
--- a/packages/SystemUI/res-keyguard/values-pa/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pa/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਤੇਜ਼ੀ ਨਾਲ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਹੌਲੀ-ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਬੈਟਰੀ ਦੀ ਸੁਰੱਖਿਆ ਲਈ ਚਾਰਜਿੰਗ ਨੂੰ ਸੁਯੋਗ ਬਣਾਇਆ ਗਿਆ"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਗੈਰ-ਅਨੁਰੂਪ ਚਾਰਜਿੰਗ"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ਅਣਲਾਕ ਕਰਨ ਲਈ \"ਮੀਨੂ\" ਦਬਾਓ।"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"ਨੈੱਟਵਰਕ  ਲਾਕ  ਕੀਤਾ ਗਿਆ"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"ਕੋਈ ਸਿਮ ਨਹੀਂ ਹੈ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pl/strings.xml b/packages/SystemUI/res-keyguard/values-pl/strings.xml
index ebfe22f3..9d45b5a 100644
--- a/packages/SystemUI/res-keyguard/values-pl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pl/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Szybkie ładowanie"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wolne ładowanie"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ładowanie zoptymalizowane w celu ochrony baterii"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Niezgodne ładowanie"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problem z akcesoriami do ładowania"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Naciśnij Menu, aby odblokować."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Sieć zablokowana"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Brak karty SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
index 282c403..8534575 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando rapidamente"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando lentamente"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregamento otimizado para proteger a bateria"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregamento incompatível"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problema com o acessório de carregamento"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pressione Menu para desbloquear."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Sem chip"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
index 16326dd..5a5212e 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar rapidamente…"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar lentamente…"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregamento otimizado para proteger a bateria"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregamento incompatível"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Prima Menu para desbloquear."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Sem SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt/strings.xml b/packages/SystemUI/res-keyguard/values-pt/strings.xml
index 282c403..8534575 100644
--- a/packages/SystemUI/res-keyguard/values-pt/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando rapidamente"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando lentamente"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregamento otimizado para proteger a bateria"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregamento incompatível"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problema com o acessório de carregamento"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pressione Menu para desbloquear."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Sem chip"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ro/strings.xml b/packages/SystemUI/res-keyguard/values-ro/strings.xml
index a9596fe..4730293 100644
--- a/packages/SystemUI/res-keyguard/values-ro/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ro/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă rapid"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă lent"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Încărcarea este optimizată pentru a proteja bateria"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Încărcare incompatibilă"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Apasă pe Meniu pentru a debloca."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rețea blocată"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Niciun card SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ru/strings.xml b/packages/SystemUI/res-keyguard/values-ru/strings.xml
index 6190ae4..792af9d 100644
--- a/packages/SystemUI/res-keyguard/values-ru/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ru/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"Идет быстрая зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"Идет медленная зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарядка оптимизирована для защиты батареи"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Несовместимое зарядное устройство"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Для разблокировки нажмите \"Меню\"."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Сеть заблокирована"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM-карта отсутствует"</string>
diff --git a/packages/SystemUI/res-keyguard/values-si/strings.xml b/packages/SystemUI/res-keyguard/values-si/strings.xml
index 2cac6fe..1bb6f04 100644
--- a/packages/SystemUI/res-keyguard/values-si/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-si/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • වේගයෙන් ආරෝපණය වෙමින්"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • සෙමින් ආරෝපණය වෙමින්"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • බැටරිය ආරක්ෂා කිරීම සඳහා ආරෝපණය ප්‍රශස්ත කර ඇත"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • නොගැළපෙන ආරෝපණය"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ආරෝපණ උපාංගයේ ගැටලුව"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"අගුලු හැරීමට මෙනුව ඔබන්න."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"ජාලය අගුළු දමා ඇත"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM නැත"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sk/strings.xml b/packages/SystemUI/res-keyguard/values-sk/strings.xml
index a893949d1..12028a6 100644
--- a/packages/SystemUI/res-keyguard/values-sk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sk/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa rýchlo"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa pomaly"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíjanie je optimalizované, aby sa chránila batéria"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nekompatibilná nabíjačka"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problém s nabíjacím príslušenstvom"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Odomknete stlačením tlačidla ponuky."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Sieť je zablokovaná"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Žiadna SIM karta"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sl/strings.xml b/packages/SystemUI/res-keyguard/values-sl/strings.xml
index cd4d944..114fc52 100644
--- a/packages/SystemUI/res-keyguard/values-sl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sl/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • hitro polnjenje"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • počasno polnjenje"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Polnjenje je optimizirano zaradi zaščite baterije"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Polnjenje z nezdružljivim polnilnikom"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • težava s pripomočkom za polnjenje"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Če želite odkleniti, pritisnite meni."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Omrežje je zaklenjeno"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Ni kartice SIM."</string>
diff --git a/packages/SystemUI/res-keyguard/values-sq/strings.xml b/packages/SystemUI/res-keyguard/values-sq/strings.xml
index b941fd0..5d8173b 100644
--- a/packages/SystemUI/res-keyguard/values-sq/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sq/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet me shpejtësi"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet ngadalë"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Karikimi u optimizua për të mbrojtur baterinë"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Karikim i papërputhshëm"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problem me aksesorin e karikimit"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Shtyp \"Meny\" për të shkyçur."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rrjeti është i kyçur"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Nuk ka kartë SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sr/strings.xml b/packages/SystemUI/res-keyguard/values-sr/strings.xml
index e4632f3..98d9029 100644
--- a/packages/SystemUI/res-keyguard/values-sr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sr/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Брзо се пуни"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Споро се пуни"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Пуњење је оптимизовано да би се заштитила батерија"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Некомпатибилно пуњење"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Притисните Мени да бисте откључали."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежа је закључана"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Нема SIM-а"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sv/strings.xml b/packages/SystemUI/res-keyguard/values-sv/strings.xml
index 8e46838..22e7fdb 100644
--- a/packages/SystemUI/res-keyguard/values-sv/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sv/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas snabbt"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas långsamt"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddningen har optimerats för att skydda batteriet"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inkompatibel laddare"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Lås upp genom att trycka på Meny."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Nätverk låst"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Inget SIM-kort"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sw/strings.xml b/packages/SystemUI/res-keyguard/values-sw/strings.xml
index 9a64f57..bdf5b00 100644
--- a/packages/SystemUI/res-keyguard/values-sw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sw/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji kwa kasi"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji pole pole"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hali ya kuchaji imeboreshwa ili kulinda betri"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Chaja isiyooana"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Bonyeza Menyu ili kufungua."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mtandao umefungwa"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Hakuna SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ta/strings.xml b/packages/SystemUI/res-keyguard/values-ta/strings.xml
index 6b9f826..f23c839 100644
--- a/packages/SystemUI/res-keyguard/values-ta/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ta/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • வேகமாகச் சார்ஜாகிறது"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • மெதுவாகச் சார்ஜாகிறது"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • பேட்டரியைப் பாதுகாக்க சார்ஜிங் மேம்படுத்தப்பட்டுள்ளது"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • இணக்கமற்ற சார்ஜிங்"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"அன்லாக் செய்ய மெனுவை அழுத்தவும்."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"நெட்வொர்க் பூட்டப்பட்டது"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"சிம் இல்லை"</string>
diff --git a/packages/SystemUI/res-keyguard/values-te/strings.xml b/packages/SystemUI/res-keyguard/values-te/strings.xml
index 2922bc6..1684eb87b 100644
--- a/packages/SystemUI/res-keyguard/values-te/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-te/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • వేగంగా ఛార్జ్ అవుతోంది"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • నెమ్మదిగా ఛార్జ్ అవుతోంది"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • బ్యాటరీని రక్షించడానికి ఛార్జింగ్ ఆప్టిమైజ్ చేయబడింది"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ఛార్జింగ్ అనుకూలంగా లేదు"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ఛార్జింగ్ యాక్సెసరీతో సమస్య ఉంది"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"అన్‌లాక్ చేయడానికి మెనూను నొక్కండి."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"నెట్‌వర్క్ లాక్ చేయబడింది"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM లేదు"</string>
diff --git a/packages/SystemUI/res-keyguard/values-th/strings.xml b/packages/SystemUI/res-keyguard/values-th/strings.xml
index 830e14a..f268e60 100644
--- a/packages/SystemUI/res-keyguard/values-th/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-th/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จอย่างเร็ว"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จอย่างช้าๆ"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ปรับการชาร์จให้เหมาะสมเพื่อถนอมแบตเตอรี่"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ที่ชาร์จใช้ร่วมกันไม่ได้"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ปัญหาเกี่ยวกับอุปกรณ์เสริมสำหรับการชาร์จ"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"กด \"เมนู\" เพื่อปลดล็อก"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"เครือข่ายถูกล็อก"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"ไม่มี SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-tl/strings.xml b/packages/SystemUI/res-keyguard/values-tl/strings.xml
index e4b6361..b96f0ae 100644
--- a/packages/SystemUI/res-keyguard/values-tl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-tl/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mabilis na nagcha-charge"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mabagal na nagcha-charge"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Naka-optimize ang pag-charge para protektahan ang baterya"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hindi compatible na pag-charge"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Isyu sa pag-charge ng accessory"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pindutin ang Menu upang i-unlock."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Naka-lock ang network"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Walang SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-tr/strings.xml b/packages/SystemUI/res-keyguard/values-tr/strings.xml
index 028cd37..2ee4e67 100644
--- a/packages/SystemUI/res-keyguard/values-tr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-tr/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hızlı şarj oluyor"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Yavaş şarj oluyor"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Şarj işlemi pili korumak üzere optimize edildi"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Uyumsuz şarj"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Kilidi açmak için Menü\'ye basın."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Ağ kilitli"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM yok"</string>
diff --git a/packages/SystemUI/res-keyguard/values-uk/strings.xml b/packages/SystemUI/res-keyguard/values-uk/strings.xml
index 78187b7..52daa8e 100644
--- a/packages/SystemUI/res-keyguard/values-uk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-uk/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Швидке заряджання"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Повільне заряджання"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Заряджання оптимізовано, щоб захистити акумулятор"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Несумісний зарядний пристрій"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Натисніть меню, щоб розблокувати."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Мережу заблоковано"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Немає SIM-карти"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ur/strings.xml b/packages/SystemUI/res-keyguard/values-ur/strings.xml
index 34a3eaa..dac46fd 100644
--- a/packages/SystemUI/res-keyguard/values-ur/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ur/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • تیزی سے چارج ہو رہا ہے"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • آہستہ چارج ہو رہا ہے"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • بیٹری کی حفاظت کے لیے چارجنگ کو بہتر بنایا گیا"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • غیر مطابقت پذیر چارجنگ"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • چارجنگ ایکسیسری کے ساتھ مسئلہ"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"غیر مقفل کرنے کیلئے مینو دبائیں۔"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"نیٹ ورک مقفل ہو گیا"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"‏کوئی SIM نہیں ہے"</string>
diff --git a/packages/SystemUI/res-keyguard/values-uz/strings.xml b/packages/SystemUI/res-keyguard/values-uz/strings.xml
index d448467..7091405 100644
--- a/packages/SystemUI/res-keyguard/values-uz/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-uz/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Tezkor quvvat olmoqda"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sekin quvvat olmoqda"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Batareyani himoyalash uchun quvvatlash optimallashtirildi"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Moslanmagan quvvatlash"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Quvvatlash aksessuari bilan muammo"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Qulfdan chiqarish uchun Menyu tugmasini bosing."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Tarmoq qulflangan"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM kartasiz"</string>
diff --git a/packages/SystemUI/res-keyguard/values-vi/strings.xml b/packages/SystemUI/res-keyguard/values-vi/strings.xml
index dcca1ca..287363d 100644
--- a/packages/SystemUI/res-keyguard/values-vi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-vi/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc nhanh"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc chậm"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Quá trình sạc được tối ưu hoá để bảo vệ pin"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bộ sạc không tương thích"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Nhấn vào Menu để mở khóa."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mạng đã bị khóa"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Không có SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
index 3c41e8c..a2387b0 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
@@ -30,8 +30,8 @@
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在充电"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在快速充电"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在慢速充电"</string>
-    <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 为保护电池,充电过程已优化"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充电器不兼容"</string>
+    <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 为保护电池,充电方式已优化"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充电配件有问题"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按“菜单”即可解锁。"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"网络已锁定"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"没有 SIM 卡"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
index a07082e..d69bbc0 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 快速充電中"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 慢速充電中"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 為保護電池,系統已優化充電"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在使用不兼容的充電器充電"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按下 [選單] 即可解鎖。"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"網絡已鎖定"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"沒有 SIM 卡"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
index 01bd491..c11959c 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
@@ -31,7 +31,8 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 快速充電中"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 慢速充電中"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 為保護電池,充電效能已最佳化"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在使用不相容的充電器充電"</string>
+    <!-- no translation found for keyguard_plugged_in_incompatible_charger (3687961801947819076) -->
+    <skip />
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按選單鍵解鎖。"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"網路已鎖定"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"沒有 SIM 卡"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zu/strings.xml b/packages/SystemUI/res-keyguard/values-zu/strings.xml
index c6cabf7..94bd6a1 100644
--- a/packages/SystemUI/res-keyguard/values-zu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zu/strings.xml
@@ -31,7 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ishaja kaningi"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ishaja kancane"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ukushaja kuthuthukisiwe ukuze kuvikelwe ibhethri"</string>
-    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ukushaja okungahambisani"</string>
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • • Inkinga ngesisekeli sokushaja"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Chofoza Menyu ukuvula."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Inethiwekhi ivaliwe"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Ayikho i-SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index b6a78f5..1f44f05 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -82,7 +82,7 @@
     <!-- The vertical margin between the date and the owner info. -->
 
     <!-- The translation for disappearing security views after having solved them. -->
-    <dimen name="disappear_y_translation">-32dp</dimen>
+    <dimen name="disappear_y_translation">-50dp</dimen>
 
     <!-- Dimens for animation for the Bouncer PIN view -->
     <dimen name="pin_view_trans_y_entry">120dp</dimen>
@@ -127,9 +127,7 @@
     <dimen name="bouncer_user_switcher_item_padding_vertical">10dp</dimen>
     <dimen name="bouncer_user_switcher_item_padding_horizontal">12dp</dimen>
     <dimen name="bouncer_user_switcher_header_padding_end">44dp</dimen>
-    <dimen name="bouncer_user_switcher_y_trans">0dp</dimen>
-    <dimen name="bouncer_user_switcher_view_mode_user_switcher_bottom_margin">0dp</dimen>
-    <dimen name="bouncer_user_switcher_view_mode_view_flipper_bottom_margin">0dp</dimen>
+    <dimen name="bouncer_user_switcher_y_trans">80dp</dimen>
 
     <!-- 2 * the margin + size should equal the plus_margin -->
     <dimen name="user_switcher_icon_large_margin">16dp</dimen>
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 51f507c..11b4d79 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -56,7 +56,7 @@
     <string name="keyguard_plugged_in_charging_limited"><xliff:g id="percentage">%s</xliff:g> • Charging optimized to protect battery</string>
 
     <!-- When the lock screen is showing and the phone plugged in with incompatible charger. -->
-    <string name="keyguard_plugged_in_incompatible_charger"><xliff:g id="percentage">%s</xliff:g> • Incompatible charging</string>
+    <string name="keyguard_plugged_in_incompatible_charger"><xliff:g id="percentage">%s</xliff:g> • Issue with charging accessory</string>
 
     <!-- On the keyguard screen, when pattern lock is disabled, only tell them to press menu to unlock.  This is shown in small font at the bottom. -->
     <string name="keyguard_instructions_when_pattern_disabled">Press Menu to unlock.</string>
diff --git a/packages/SystemUI/res-product/values-af/strings.xml b/packages/SystemUI/res-product/values-af/strings.xml
index 18f6d44..8d416b3 100644
--- a/packages/SystemUI/res-product/values-af/strings.xml
+++ b/packages/SystemUI/res-product/values-af/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Jy het die foon <xliff:g id="NUMBER">%d</xliff:g> keer verkeerd probeer ontsluit. Die werkprofiel sal verwyder word, wat alle profieldata sal uitvee."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerd geteken. Na nóg <xliff:g id="NUMBER_1">%2$d</xliff:g> onsuksesvolle pogings sal jy gevra word om jou e-posrekening te gebruik om jou tablet te ontsluit.\n\n Probeer weer oor <xliff:g id="NUMBER_2">%3$d</xliff:g> sekondes."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerd geteken. Na nóg <xliff:g id="NUMBER_1">%2$d</xliff:g> onsuksesvolle pogings sal jy gevra word om jou e-posrekening te gebruik om jou foon te ontsluit.\n\n Probeer weer oor <xliff:g id="NUMBER_2">%3$d</xliff:g> sekondes."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Die vingerafdruksensor is op die aan/af-skakelaar. Dit is die plat knoppie langs die verhewe volumeknoppie aan die kant van die tablet.\n\nDie skerm skakel af wanneer iemand die aan/af-skakelaar druk."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Die vingerafdruksensor is op die aan/af-skakelaar. Dit is die plat knoppie langs die verhewe volumeknoppie aan die kant van die toestel.\n\nDie skerm skakel af wanneer iemand die aan/af-skakelaar druk."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Die vingerafdruksensor is op die aan/af-skakelaar. Dit is die plat knoppie langs die verhewe volumeknoppie aan die kant van die foon.\n\nDie skerm skakel af wanneer iemand die aan/af-skakelaar druk."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Ontsluit jou foon vir meer opsies"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Ontsluit jou tablet vir meer opsies"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Ontsluit jou toestel vir meer opsies"</string>
diff --git a/packages/SystemUI/res-product/values-am/strings.xml b/packages/SystemUI/res-product/values-am/strings.xml
index ad2d80d..ca062e1 100644
--- a/packages/SystemUI/res-product/values-am/strings.xml
+++ b/packages/SystemUI/res-product/values-am/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ስልኩን <xliff:g id="NUMBER">%d</xliff:g> ጊዜ ትክክል ባልሆነ መልኩ ለመክፈት ሞክረዋል። የስራ መገለጫው ይወገዳል፣ ይህም ሁሉንም የመገለጫ ውሂብ ይሰርዛል።"</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"የመክፈቻ ስርዓተ ጥለቱን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ በትክክል አልሳሉትም። ከ<xliff:g id="NUMBER_1">%2$d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ የኢሜይል መለያ ተጠቅመው ጡባዊዎን እንዲከፍቱ ይጠየቃሉ።\n\n ከ<xliff:g id="NUMBER_2">%3$d</xliff:g> ከሰከንዶች በኋላ እንደገና ይሞክሩ።"</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"የመክፈቻ ስርዓተ ጥለቱን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ በትክክል አልሳሉትም። ከ<xliff:g id="NUMBER_1">%2$d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ የኢሜይል መለያ ተጠቅመው ስልክዎን እንዲከፍቱ ይጠየቃሉ።\n\nእባክዎ ከ<xliff:g id="NUMBER_2">%3$d</xliff:g> ሰከንዶች በኋላ እንደገና ይሞክሩ።"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"የጣት አሻራ ዳሳሹ የማብሪያ/ማጥፊያ ቁልፉ ላይ ነው። በጡባዊው ጫፍ ላይ ከፍ ካለው የድምፅ አዝራር ቀጥሎ ያለው ጠፍጣፋ አዝራር ነው።\n\nየማብሪያ/ማጥፊያ ቁልፉን መጫን ማያ ገጹን ያጠፋዋል።"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"የጣት አሻራ ዳሳሹ የማብሪያ/ማጥፊያ ቁልፉ ላይ ነው። በመሣሪያው ጫፍ ላይ ከፍ ካለው የድምፅ አዝራር ቀጥሎ ያለው ጠፍጣፋ አዝራር ነው።\n\nየማብሪያ/ማጥፊያ ቁልፉን መጫን ማያ ገጹን ያጠፋዋል።"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"የጣት አሻራ ዳሳሹ የማብሪያ/ማጥፊያ ቁልፉ ላይ ነው። በስልኩ ጫፍ ላይ ከፍ ካለው የድምፅ አዝራር ቀጥሎ ያለው ጠፍጣፋ አዝራር ነው።\n\nየማብሪያ/ማጥፊያ ቁልፉን መጫን ማያ ገጹን ያጠፋዋል።"</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"ለተጨማሪ አማራጮች የእርስዎን ስልክ ይክፈቱ"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"ለተጨማሪ አማራጮች የእርስዎን ጡባዊ ይክፈቱ"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"ለተጨማሪ አማራጮች የእርስዎን መሣሪያ ይክፈቱ"</string>
diff --git a/packages/SystemUI/res-product/values-ar/strings.xml b/packages/SystemUI/res-product/values-ar/strings.xml
index 7e28dfe..6955f20 100644
--- a/packages/SystemUI/res-product/values-ar/strings.xml
+++ b/packages/SystemUI/res-product/values-ar/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"أخطأت في محاولة فتح قفل الهاتف <xliff:g id="NUMBER">%d</xliff:g> مرة. ستتم إزالة الملف الشخصي للعمل، ومن ثم يتم حذف جميع بياناته."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"رسمت نقش فتح القفل بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة غير ناجحة أخرى، ستُطالَب بفتح قفل الجهاز اللوحي باستخدام معلومات حساب بريد إلكتروني.\n\n يُرجى إعادة المحاولة خلال <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانية."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"رسمت نقش فتح القفل بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%2$d</xliff:g> محاولة غير ناجحة أخرى، ستُطالَب بفتح قفل الهاتف باستخدام حساب بريد إلكتروني.\n\n يُرجى إعادة المحاولة خلال <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانية."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"توجد أداة استشعار بصمة الإصبع على زر التشغيل. زر التشغيل هو الزر المسطّح بجانب زرّي التحكم بمستوى الصوت البارزين في الجزء الجانبي من الجهاز اللوحي.\n\nيؤدي الضغط على زر التشغيل إلى إطفاء الشاشة."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"توجد أداة استشعار بصمة الإصبع على زر التشغيل. زر التشغيل هو الزر المسطّح بجانب زرّي التحكم بمستوى الصوت البارزين في الجزء الجانبي من الجهاز.\n\nيؤدي الضغط على زر التشغيل إلى إطفاء الشاشة."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"توجد أداة استشعار بصمة الإصبع على زر التشغيل. زر التشغيل هو الزر المسطّح بجانب زرّي التحكم بمستوى الصوت البارزين في الجزء الجانبي من الهاتف.\n\nيؤدي الضغط على زر التشغيل إلى إطفاء الشاشة."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"يمكنك فتح قفل هاتفك للوصول إلى مزيد من الخيارات."</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"يمكنك فتح قفل جهازك اللوحي للوصول إلى مزيد من الخيارات."</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"يمكنك فتح قفل جهازك للوصول إلى مزيد من الخيارات."</string>
diff --git a/packages/SystemUI/res-product/values-as/strings.xml b/packages/SystemUI/res-product/values-as/strings.xml
index 4a9a0d4..687feae 100644
--- a/packages/SystemUI/res-product/values-as/strings.xml
+++ b/packages/SystemUI/res-product/values-as/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"আপুনি ফ’নটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। কৰ্মস্থানৰ প্ৰ’ফাইলটো আঁতৰোৱা হ’ব, যিয়ে প্ৰ’ফাইলটোৰ আটাইবোৰ ডেটা মচি পেলাব।"</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"আপুনি নিজৰ আনলক কৰা আৰ্হিটো <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ আঁকিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত আপোনাক নিজৰ টেবলেটটো এটা ইমেইল একাউণ্টৰ জৰিয়তে আনলক কৰিবলৈ কোৱা হ’ব।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ছেকেণ্ডৰ পাছত পুনৰ চেষ্টা কৰক।"</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"আপুনি নিজৰ আনলক কৰা আৰ্হিটো <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ আঁকিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত আপোনাক নিজৰ ফ’নটো এটা ইমেইল একাউণ্টৰ জৰিয়তে আনলক কৰিবলৈ কোৱা হ’ব।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ছেকেণ্ডৰ পাছত পুনৰ চেষ্টা কৰক।"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"ফিংগাৰপ্ৰিণ্ট ছেন্সৰটো পাৱাৰ বুটামটোত আছে। এইটো হৈছে টেবলেটটোৰ প্ৰান্তত থকা ভলিউম বঢ়োৱা বুটামটোৰ কাষত থকা সমতল বুটামটো।\n\nপাৱাৰ বুটাম টিপিলে স্ক্ৰীনখন অফ হৈ যায়।"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"ফিংগাৰপ্ৰিণ্ট ছেন্সৰটো পাৱাৰ বুটামটোত আছে। এইটো হৈছে ডিভাইচটোৰ প্ৰান্তত থকা ভলিউম বঢ়োৱা বুটামটোৰ কাষত থকা সমতল বুটামটো।\n\nপাৱাৰ বুটাম টিপিলে স্ক্ৰীনখন অফ হৈ যায়।"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"ফিংগাৰপ্ৰিণ্ট ছেন্সৰটো পাৱাৰ বুটামটোত আছে। এইটো হৈছে ফ’নটোৰ প্ৰান্তত থকা ভলিউম বঢ়োৱা বুটামটোৰ কাষত থকা সমতল বুটামটো।\n\nপাৱাৰ বুটাম টিপিলে স্ক্ৰীনখন অফ হৈ যায়।"</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"অধিক বিকল্পৰ বাবে আপোনাৰ ফ’নটো আনলক কৰক"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"অধিক বিকল্পৰ বাবে আপোনাৰ টেবলেটটো আনলক কৰক"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"অধিক বিকল্পৰ বাবে আপোনাৰ ডিভাইচটো আনলক কৰক"</string>
diff --git a/packages/SystemUI/res-product/values-az/strings.xml b/packages/SystemUI/res-product/values-az/strings.xml
index c15bfec..848b88d 100644
--- a/packages/SystemUI/res-product/values-az/strings.xml
+++ b/packages/SystemUI/res-product/values-az/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Telefonun kilidini açmaq üçün <xliff:g id="NUMBER">%d</xliff:g> dəfə yanlış cəhd etmisiniz. İş profili silinəcək və bütün data ləğv ediləcək."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Kilid açma modelini <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış çəkmisiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> uğursuz cəhddən sonra planşet kilidini e-poçt hesabınızla açmaq tələb olunacaq.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniyə sonra cəhd edin."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Kilid açma modelini artıq <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış çəkmisiniz. Daha <xliff:g id="NUMBER_1">%2$d</xliff:g> uğursuz cəhddən sonra telefon kilidini e-poçt hesabınızla açmaq tələb olunacaq.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniyə sonra cəhd edin."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Barmaq izi sensoru enerji düyməsinin üzərindədir. Bu, planşetin kənarındakı qabarıq səs düyməsinin yanındakı yastı düymədir.\n\nEnerji düyməsini basdıqda ekran sönür."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Barmaq izi sensoru enerji düyməsinin üzərindədir. Bu, cihazın kənarındakı qabarıq səs düyməsinin yanındakı yastı düymədir.\n\nEnerji düyməsini basdıqda ekran sönür."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Barmaq izi sensoru enerji düyməsinin üzərindədir. Bu, telefonun kənarındakı qabarıq səs düyməsinin yanındakı yastı düymədir.\n\nEnerji düyməsini basdıqda ekran sönür."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Daha çox seçim üçün telefonu kiliddən çıxarın"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Daha çox seçim üçün planşeti kiliddən çıxarın"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Daha çox seçim üçün cihazı kiliddən çıxarın"</string>
diff --git a/packages/SystemUI/res-product/values-b+sr+Latn/strings.xml b/packages/SystemUI/res-product/values-b+sr+Latn/strings.xml
index c0e32c2..6d480bf 100644
--- a/packages/SystemUI/res-product/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res-product/values-b+sr+Latn/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Pogrešno ste pokušali da otključate telefon <xliff:g id="NUMBER">%d</xliff:g> puta. Uklonićemo poslovni profil, čime se brišu svi podaci sa profila."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Netačno ste nacrtali šablon za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Ako pogrešno pokušate još <xliff:g id="NUMBER_1">%2$d</xliff:g> puta, zatražićemo da otključate tablet pomoću imejl naloga.\n\n Probajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Netačno ste nacrtali šablon za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Ako pogrešno pokušate još <xliff:g id="NUMBER_1">%2$d</xliff:g> puta, zatražićemo da otključate telefon pomoću imejl naloga.\n\n Probajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Senzor za otisak prsta se nalazi na dugmetu za uključivanje. To je ravno dugme pored izdignutog dugmeta za jačinu zvuka na ivici tableta.\n\nPritiskom na dugme za uključivanje isključuje se ekran."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Senzor za otisak prsta se nalazi na dugmetu za uključivanje. To je ravno dugme pored izdignutog dugmeta za jačinu zvuka na ivici uređaja.\n\nPritiskom na dugme za uključivanje isključuje se ekran."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Senzor za otisak prsta se nalazi na dugmetu za uključivanje. To je ravno dugme pored izdignutog dugmeta za jačinu zvuka na ivici telefona.\n\nPritiskom na dugme za uključivanje isključuje se ekran."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Otključajte telefon za još opcija"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Otključajte tablet za još opcija"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Otključajte uređaj za još opcija"</string>
diff --git a/packages/SystemUI/res-product/values-be/strings.xml b/packages/SystemUI/res-product/values-be/strings.xml
index e5d5aae..132a605 100644
--- a/packages/SystemUI/res-product/values-be/strings.xml
+++ b/packages/SystemUI/res-product/values-be/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Вы не змаглі разблакіраваць тэлефон столькі разоў: <xliff:g id="NUMBER">%d</xliff:g>. Працоўны профіль будзе выдалены, і гэта прывядзе да выдалення ўсіх даных у профілі."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Вы няправільна ўвялі ўзор разблакіроўкі столькі разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Пасля яшчэ некалькіх няўдалых спроб (<xliff:g id="NUMBER_1">%2$d</xliff:g>) вам будзе прапанавана разблакіраваць планшэт, увайшоўшы ва ўліковы запіс электроннай пошты.\n\n Паўтарыце спробу праз <xliff:g id="NUMBER_2">%3$d</xliff:g> с."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Вы няправільна ўвялі ўзор разблакіроўкі столькі разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Пасля яшчэ некалькіх няўдалых спроб (<xliff:g id="NUMBER_1">%2$d</xliff:g>) вам будзе прапанавана разблакіраваць тэлефон, увайшоўшы ва ўліковы запіс электроннай пошты.\n\n Паўтарыце спробу праз <xliff:g id="NUMBER_2">%3$d</xliff:g> с."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Сканер адбіткаў пальцаў знаходзіцца на кнопцы сілкавання. Гэта плоская кнопка побач з выпуклай кнопкай гучнасці на бакавой грані планшэта.\n\nНацісканне кнопкі сілкавання выключае экран."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Сканер адбіткаў пальцаў знаходзіцца на кнопцы сілкавання. Гэта плоская кнопка побач з выпуклай кнопкай гучнасці на бакавой грані прылады.\n\nНацісканне кнопкі сілкавання выключае экран."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Сканер адбіткаў пальцаў знаходзіцца на кнопцы сілкавання. Гэта плоская кнопка побач з выпуклай кнопкай гучнасці на бакавой грані тэлефона.\n\nНацісканне кнопкі сілкавання выключае экран."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Каб адкрыць іншыя параметры, разблакіруйце тэлефон"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Каб адкрыць іншыя параметры, разблакіруйце планшэт"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Каб адкрыць іншыя параметры, разблакіруйце прыладу"</string>
diff --git a/packages/SystemUI/res-product/values-bg/strings.xml b/packages/SystemUI/res-product/values-bg/strings.xml
index f8ca530..586f156 100644
--- a/packages/SystemUI/res-product/values-bg/strings.xml
+++ b/packages/SystemUI/res-product/values-bg/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Опитахте да отключите телефона и сбъркахте <xliff:g id="NUMBER">%d</xliff:g> пъти. Служебният потребителски профил ще бъде премахнат, при което ще се изтрият всички данни за него."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Начертахте неправилно фигурата си за отключване <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни опита ще бъдете помолени да отключите таблета си посредством имейл адрес.\n\n Опитайте отново след <xliff:g id="NUMBER_2">%3$d</xliff:g> секунди."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Начертахте неправилно фигурата си за отключване <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни опита ще бъдете помолени да отключите телефона посредством имейл адрес.\n\n Опитайте отново след <xliff:g id="NUMBER_2">%3$d</xliff:g> секунди."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Сензорът за отпечатъци се намира върху бутона за захранване. Този бутон е плосък и е разположен на ръба на таблета до повдигнатия бутон за силата на звука.\n\nС натискането на бутона за захранване се изключва екранът."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Сензорът за отпечатъци се намира върху бутона за захранване. Този бутон е плосък и е разположен на ръба на устройството до повдигнатия бутон за силата на звука.\n\nС натискането на бутона за захранване се изключва екранът."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Сензорът за отпечатъци се намира върху бутона за захранване. Този бутон е плосък и е разположен на ръба на телефона до повдигнатия бутон за силата на звука.\n\nС натискането на бутона за захранване се изключва екранът."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Отключете телефона си за още опции"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Отключете таблета си за още опции"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Отключете устройството си за още опции"</string>
diff --git a/packages/SystemUI/res-product/values-bn/strings.xml b/packages/SystemUI/res-product/values-bn/strings.xml
index ca3f903..322fb63 100644
--- a/packages/SystemUI/res-product/values-bn/strings.xml
+++ b/packages/SystemUI/res-product/values-bn/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"আপনি <xliff:g id="NUMBER">%d</xliff:g> বার ভুল পদ্ধতিতে ফোন আনলক করার চেষ্টা করেছেন। অফিস প্রোফাইলটি সরিয়ে দেওয়া হবে, যার ফলে প্রোফাইলের সমস্ত ডেটা মুছে যাবে।"</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল পদ্ধতিতে প্যাটার্ন আনলক করার চেষ্টা করেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার এটি করলে আপনাকে প্যাটার্ন আনলক করতে একটি ইমেল অ্যাকাউন্ট ব্যবহার করতে বলা হবে।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> সেকেন্ড পরে আবার চেষ্টা করুন।"</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল পদ্ধতিতে প্যাটার্ন আনলক করার চেষ্টা করেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার এটি করলে আপনাকে প্যাটার্ন আনলক করতে একটি ইমেল অ্যাকাউন্ট ব্যবহারের করতে বলা হবে।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> সেকেন্ড পরে আবার চেষ্টা করুন।"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"\'পাওয়ার\' বোতামের উপরে ফিঙ্গারপ্রিন্ট সেন্সর আছে। এটি ট্যাবলেটের প্রান্তে উঁচু \'ভলিউম\' বোতামের পাশে থাকা চ্যাপ্টা বোতাম।\n\n\'পাওয়ার\' বোতাম প্রেস করলে স্ক্রিন বন্ধ হয়ে যায়।"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"\'পাওয়ার\' বোতামের উপরে ফিঙ্গারপ্রিন্ট সেন্সর আছে। এটি ডিভাইসের প্রান্তে উঁচু \'ভলিউম\' বোতামের পাশে থাকা চ্যাপ্টা বোতাম।\n\n\'পাওয়ার\' বোতাম প্রেস করলে স্ক্রিন বন্ধ হয়ে যায়।"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"\'পাওয়ার\' বোতামের উপরে ফিঙ্গারপ্রিন্ট সেন্সর আছে। এটি ফোনের প্রান্তে উঁচু \'ভলিউম\' বোতামের পাশে থাকা চ্যাপ্টা বোতাম।\n\n\'পাওয়ার\' বোতাম প্রেস করলে স্ক্রিন বন্ধ হয়ে যায়।"</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"আরও বিকল্প দেখতে আপনার ফোন আনলক করুন"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"আরও বিকল্প দেখতে আপনার ট্যাবলেট আনলক করুন"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"আরও বিকল্প দেখতে আপনার ডিভাইস আনলক করুন"</string>
diff --git a/packages/SystemUI/res-product/values-bs/strings.xml b/packages/SystemUI/res-product/values-bs/strings.xml
index 50c216e..ac1771f 100644
--- a/packages/SystemUI/res-product/values-bs/strings.xml
+++ b/packages/SystemUI/res-product/values-bs/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Pokušali ste neispravno otključati telefon <xliff:g id="NUMBER">%d</xliff:g> puta. Radni profil će se ukloniti i svi podaci s profila će se izbrisati."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Pogrešno ste nacrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, od vas će se tražiti da otključate tablet pomoću računa e-pošte. \n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Pogrešno ste nacrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, od vas će se tražiti da otključate telefon pomoću računa e-pošte. \n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Senzor za otisak prsta je na dugmetu za uključivanje. To je ravno dugme pored izdignutog dugmeta za jačinu zvuka na rubu tableta.\n\nPritiskanjem dugmeta za uključivanje isključuje se ekran."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Senzor za otisak prsta je na dugmetu za uključivanje. To je ravno dugme pored izdignutog dugmeta za jačinu zvuka na rubu uređaja.\n\nPritiskanjem dugmeta za uključivanje isključuje se ekran."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Senzor za otisak prsta je na dugmetu za uključivanje. To je ravno dugme pored izdignutog dugmeta za jačinu zvuka na rubu telefona.\n\nPritiskanjem dugmeta za uključivanje isključuje se ekran."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Otključajte telefon za više opcija"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Otključajte tablet za više opcija"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Otključajte uređaj za više opcija"</string>
diff --git a/packages/SystemUI/res-product/values-ca/strings.xml b/packages/SystemUI/res-product/values-ca/strings.xml
index c2e09cb..9b5469a 100644
--- a/packages/SystemUI/res-product/values-ca/strings.xml
+++ b/packages/SystemUI/res-product/values-ca/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Has provat de desbloquejar el telèfon <xliff:g id="NUMBER">%d</xliff:g> vegades de manera incorrecta. El perfil de treball se suprimirà, juntament amb totes les dades que contingui."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Has dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, se\'t demanarà que desbloquegis la tauleta amb un compte de correu electrònic.\n\n Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_2">%3$d</xliff:g> segons."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Has dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, se\'t demanarà que desbloquegis el telèfon amb un compte de correu electrònic.\n\n Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_2">%3$d</xliff:g> segons."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"El sensor d\'empremtes digitals es troba al botó d\'engegada. És el botó pla situat al costat del botó de volum amb relleu al lateral de la tauleta.\n\nEn prémer el botó d\'engegada, la pantalla es desactiva."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"El sensor d\'empremtes digitals es troba al botó d\'engegada. És el botó pla situat al costat del botó de volum amb relleu al lateral del dispositiu.\n\nEn prémer el botó d\'engegada, la pantalla es desactiva."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"El sensor d\'empremtes digitals es troba al botó d\'engegada. És el botó pla situat al costat del botó de volum amb relleu al lateral del telèfon.\n\nEn prémer el botó d\'engegada, la pantalla es desactiva."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Desbloqueja el teu telèfon per veure més opcions"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Desbloqueja la teva tauleta per veure més opcions"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desbloqueja el teu dispositiu per veure més opcions"</string>
diff --git a/packages/SystemUI/res-product/values-cs/strings.xml b/packages/SystemUI/res-product/values-cs/strings.xml
index 81d49b0..a1c1691 100644
--- a/packages/SystemUI/res-product/values-cs/strings.xml
+++ b/packages/SystemUI/res-product/values-cs/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Již <xliff:g id="NUMBER">%d</xliff:g>krát jste se pokusili odemknout telefon nesprávným způsobem. Pracovní profil bude odstraněn, čímž budou smazána všechna jeho data."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Již <xliff:g id="NUMBER_0">%1$d</xliff:g>krát jste nesprávně zadali své bezpečnostní gesto. Po <xliff:g id="NUMBER_1">%2$d</xliff:g>dalších neúspěšných pokusech budete požádáni o odemčení tabletu pomocí e-mailového účtu.\n\n Zkuste to znovu za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Již <xliff:g id="NUMBER_0">%1$d</xliff:g>krát jste nesprávně zadali své bezpečnostní gesto. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> dalších neúspěšných pokusech budete požádáni o odemčení telefonu pomocí e-mailového účtu.\n\n Zkuste to znovu za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Snímač otisků prstů je na vypínači. Je to ploché tlačítko vedle vystouplého tlačítka hlasitosti na hraně tabletu.\n\nStisknutím vypínače vypnete obrazovku."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Snímač otisků prstů je na vypínači. Je to ploché tlačítko vedle vystouplého tlačítka hlasitosti na hraně zařízení.\n\nStisknutím vypínače vypnete obrazovku."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Snímač otisků prstů je na vypínači. Je to ploché tlačítko vedle vystouplého tlačítka hlasitosti na hraně telefonu.\n\nStisknutím vypínače vypnete obrazovku."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Chcete-li zobrazit další možnosti, odemkněte telefon"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Chcete-li zobrazit další možnosti, odemkněte tablet"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Chcete-li zobrazit další možnosti, odemkněte zařízení"</string>
diff --git a/packages/SystemUI/res-product/values-da/strings.xml b/packages/SystemUI/res-product/values-da/strings.xml
index e029e2c..87e1c5e 100644
--- a/packages/SystemUI/res-product/values-da/strings.xml
+++ b/packages/SystemUI/res-product/values-da/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Du har forsøgt at låse telefonen op med den forkerte adgangskode <xliff:g id="NUMBER">%d</xliff:g> gange. Arbejdsprofilen fjernes, hvilket sletter alle profildata."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykkede forsøg bliver du bedt om at låse din tablet op ved hjælp af en mailkonto.\n\n Prøv igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter endnu <xliff:g id="NUMBER_1">%2$d</xliff:g> mislykkede forsøg bliver du bedt om at låse din telefon op ved hjælp af en mailkonto.\n\n Prøv igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Fingeraftrykssensoren sidder på afbryderknappen. Det er den flade knap ud for den hævede lydstyrkeknap på din tablets kant.\n\nNår du trykker på afbryderknappen, slukkes skærmen."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Fingeraftrykssensoren sidder på afbryderknappen. Det er den flade knap ud for den hævede lydstyrkeknap på enhedens kant.\n\nNår du trykker på afbryderknappen, slukkes skærmen."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Fingeraftrykssensoren sidder på afbryderknappen. Det er den flade knap ud for den hævede lydstyrkeknap på telefonens kant.\n\nNår du trykker på afbryderknappen, slukkes skærmen."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Lås din telefon op for at se flere valgmuligheder"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Lås din tablet op for at se flere valgmuligheder"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Lås din enhed op for at se flere valgmuligheder"</string>
diff --git a/packages/SystemUI/res-product/values-de/strings.xml b/packages/SystemUI/res-product/values-de/strings.xml
index 787f885..e0683eb 100644
--- a/packages/SystemUI/res-product/values-de/strings.xml
+++ b/packages/SystemUI/res-product/values-de/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Du hast <xliff:g id="NUMBER">%d</xliff:g>-mal erfolglos versucht, das Smartphone zu entsperren. Das Arbeitsprofil wird nun entfernt und alle Profildaten werden gelöscht."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Du hast dein Entsperrungsmuster <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch gezeichnet. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wirst du aufgefordert, dein Tablet mithilfe eines E-Mail-Kontos zu entsperren.\n\n Versuche es in <xliff:g id="NUMBER_2">%3$d</xliff:g> Sekunden noch einmal."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Du hast dein Entsperrungsmuster <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch gezeichnet. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wirst du aufgefordert, dein Smartphone mithilfe eines E-Mail-Kontos zu entsperren.\n\n Versuche es in <xliff:g id="NUMBER_2">%3$d</xliff:g> Sekunden noch einmal."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Der Fingerabdrucksensor befindet sich auf der Ein-/Aus-Taste. Das ist die flache Taste neben der erhöhten Lautstärketaste an der Seite des Tablets.\n\nWenn du die Ein-/Aus-Taste drückst, schaltet sich das Display aus."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Der Fingerabdrucksensor befindet sich auf der Ein-/Aus-Taste. Das ist die flache Taste neben der erhöhten Lautstärketaste an der Seite des Geräts.\n\nWenn du die Ein-/Aus-Taste drückst, schaltet sich das Display aus."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Der Fingerabdrucksensor befindet sich auf der Ein-/Aus-Taste. Das ist die flache Taste neben der erhöhten Lautstärketaste an der Seite des Smartphones.\n\nWenn du die Ein-/Aus-Taste drückst, schaltet sich das Display aus."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Entsperre dein Smartphone für weitere Optionen"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Entsperre dein Tablet für weitere Optionen"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Entsperre dein Gerät für weitere Optionen"</string>
diff --git a/packages/SystemUI/res-product/values-el/strings.xml b/packages/SystemUI/res-product/values-el/strings.xml
index eb4836f..5b571d8 100644
--- a/packages/SystemUI/res-product/values-el/strings.xml
+++ b/packages/SystemUI/res-product/values-el/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Δοκιμάσατε να ξεκλειδώσετε το τηλέφωνο <xliff:g id="NUMBER">%d</xliff:g> φορές χωρίς επιτυχία. Το προφίλ εργασίας θα καταργηθεί και θα διαγραφούν όλα τα δεδομένα προφίλ."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Σχεδιάσατε το μοτίβο ξεκλειδώματος εσφαλμένα <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές. Μετά από <xliff:g id="NUMBER_1">%2$d</xliff:g> ακόμα ανεπιτυχείς προσπάθειες, θα σας ζητηθεί να ξεκλειδώσετε το tablet με τη χρήση ενός λογαριασμού ηλεκτρονικού ταχυδρομείου.\n\n Δοκιμάστε να συνδεθείτε ξανά σε <xliff:g id="NUMBER_2">%3$d</xliff:g> δευτερόλεπτα."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Σχεδιάσατε το μοτίβο ξεκλειδώματος εσφαλμένα <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές. Μετά από <xliff:g id="NUMBER_1">%2$d</xliff:g> ακόμα ανεπιτυχείς προσπάθειες, θα σας ζητηθεί να ξεκλειδώσετε το τηλέφωνό σας με τη χρήση ενός λογαριασμού ηλεκτρονικού ταχυδρομείου.\n\n Δοκιμάστε ξανά σε <xliff:g id="NUMBER_2">%3$d</xliff:g> δευτερόλεπτα."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Ο αισθητήρας δακτυλικών αποτυπωμάτων βρίσκεται στο κουμπί λειτουργίας. Είναι το επίπεδο κουμπί δίπλα στο ανυψωμένο κουμπί έντασης ήχου στο άκρο του tablet.\n\nΜε πάτημα του κουμπιού λειτουργίας απενεργοποιείται η οθόνη."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Ο αισθητήρας δακτυλικών αποτυπωμάτων βρίσκεται στο κουμπί λειτουργίας. Είναι το επίπεδο κουμπί δίπλα στο ανυψωμένο κουμπί έντασης ήχου στο άκρο της συσκευής.\n\nΜε πάτημα του κουμπιού λειτουργίας απενεργοποιείται η οθόνη."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Ο αισθητήρας δακτυλικών αποτυπωμάτων βρίσκεται στο κουμπί λειτουργίας. Είναι το επίπεδο κουμπί δίπλα στο ανυψωμένο κουμπί έντασης ήχου στο άκρο του τηλεφώνου.\n\nΜε πάτημα του κουμπιού λειτουργίας απενεργοποιείται η οθόνη."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Ξεκλειδώστε το τηλέφωνό σας για περισσότερες επιλογές"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Ξεκλειδώστε το tablet για περισσότερες επιλογές"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Ξεκλειδώστε τη συσκευή σας για περισσότερες επιλογές"</string>
diff --git a/packages/SystemUI/res-product/values-en-rAU/strings.xml b/packages/SystemUI/res-product/values-en-rAU/strings.xml
index dcc38ab..46c1dc5 100644
--- a/packages/SystemUI/res-product/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res-product/values-en-rAU/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. The work profile will be removed, which will delete all profile data."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your tablet using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the tablet.\n\nPressing the power button turns off the screen."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the device.\n\nPressing the power button turns off the screen."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the phone.\n\nPressing the power button turns off the screen."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Unlock your phone for more options"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Unlock your tablet for more options"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Unlock your device for more options"</string>
diff --git a/packages/SystemUI/res-product/values-en-rCA/strings.xml b/packages/SystemUI/res-product/values-en-rCA/strings.xml
index 422a2e8..37d1000 100644
--- a/packages/SystemUI/res-product/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res-product/values-en-rCA/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. The work profile will be removed, which will delete all profile data."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your tablet using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the tablet.\n\nPressing the power button turns off the screen."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the device.\n\nPressing the power button turns off the screen."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the phone.\n\nPressing the power button turns off the screen."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Unlock your phone for more options"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Unlock your tablet for more options"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Unlock your device for more options"</string>
diff --git a/packages/SystemUI/res-product/values-en-rGB/strings.xml b/packages/SystemUI/res-product/values-en-rGB/strings.xml
index dcc38ab..46c1dc5 100644
--- a/packages/SystemUI/res-product/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res-product/values-en-rGB/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. The work profile will be removed, which will delete all profile data."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your tablet using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the tablet.\n\nPressing the power button turns off the screen."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the device.\n\nPressing the power button turns off the screen."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the phone.\n\nPressing the power button turns off the screen."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Unlock your phone for more options"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Unlock your tablet for more options"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Unlock your device for more options"</string>
diff --git a/packages/SystemUI/res-product/values-en-rIN/strings.xml b/packages/SystemUI/res-product/values-en-rIN/strings.xml
index dcc38ab..46c1dc5 100644
--- a/packages/SystemUI/res-product/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res-product/values-en-rIN/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"You have incorrectly attempted to unlock the phone <xliff:g id="NUMBER">%d</xliff:g> times. The work profile will be removed, which will delete all profile data."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your tablet using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the tablet.\n\nPressing the power button turns off the screen."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the device.\n\nPressing the power button turns off the screen."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the phone.\n\nPressing the power button turns off the screen."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Unlock your phone for more options"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Unlock your tablet for more options"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Unlock your device for more options"</string>
diff --git a/packages/SystemUI/res-product/values-en-rXC/strings.xml b/packages/SystemUI/res-product/values-en-rXC/strings.xml
index 98396f4..141ec04 100644
--- a/packages/SystemUI/res-product/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res-product/values-en-rXC/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‎‎‎‎‎‎‏‏‏‏‎‎‎‏‏‎‏‎‏‏‎‎‏‏‎‎‎‎‎‏‎‎‏‏‎‏‏‎‎You have incorrectly attempted to unlock the phone ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎ times. The work profile will be removed, which will delete all profile data.‎‏‎‎‏‎"</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‏‎‎‎‎‎‎‏‏‏‎‎‏‏‎‎‏‏‎‎‎‏‎‎‎‏‏‎‏‎‏‏‏‎‎‎‏‏‎‎‎‏‎‏‎‏‏‏‏‏‎‎‎‎You have incorrectly drawn your unlock pattern ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. After ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ more unsuccessful attempts, you will be asked to unlock your tablet using an email account.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎ Try again in ‎‏‎‎‏‏‎<xliff:g id="NUMBER_2">%3$d</xliff:g>‎‏‎‎‏‏‏‎ seconds.‎‏‎‎‏‎"</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‎‏‎‎‏‏‏‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‏‎‎‎‏‏‎‎‎‏‏‏‎‏‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎You have incorrectly drawn your unlock pattern ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. After ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ more unsuccessful attempts, you will be asked to unlock your phone using an email account.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎ Try again in ‎‏‎‎‏‏‎<xliff:g id="NUMBER_2">%3$d</xliff:g>‎‏‎‎‏‏‏‎ seconds.‎‏‎‎‏‎"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‎‎‎‎‎‎‏‎‎‎‏‏‏‎‏‎‏‏‏‏‏‏‎‎‏‎‎‏‎‎‎‏‎‎‎‎‏‏‎The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the tablet.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Pressing the power button turns off the screen.‎‏‎‎‏‎"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‎‎‏‏‎‎‏‎‎‎‎‏‎‏‎‎‎‏‎‏‏‎‎‏‎‎‏‏‎The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the device.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Pressing the power button turns off the screen.‎‏‎‎‏‎"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‏‏‎‎‎‏‏‎‎‎‎‏‎‎‎‎‎‎‎‏‏‏‎‏‎‏‎‏‏‎‏‏‏‏‏‎‏‎‏‎‎‏‏‎‏‏‎‎‏‎‏‎‎‏‎The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the phone.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Pressing the power button turns off the screen.‎‏‎‎‏‎"</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‎‏‏‎‏‎‏‏‏‏‎‏‏‎‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‏‎‏‏‏‏‏‎‏‏‎‏‏‎‎‏‏‏‎‎‎‎‏‏‎Unlock your phone for more options‎‏‎‎‏‎"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‎‏‏‎‏‏‎‎‏‎‏‏‏‏‎‎‏‏‏‏‎‎‏‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‎‏‎‎‎‎‏‏‏‎‎‏‎‏‎Unlock your tablet for more options‎‏‎‎‏‎"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‏‎‏‏‎‏‎‎‏‎‎‎‏‏‎‏‎‎‎‏‏‎‎‎‎‏‏‎‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎Unlock your device for more options‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res-product/values-es-rUS/strings.xml b/packages/SystemUI/res-product/values-es-rUS/strings.xml
index b3551d2..4364a6f 100644
--- a/packages/SystemUI/res-product/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res-product/values-es-rUS/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Intentaste desbloquear el teléfono <xliff:g id="NUMBER">%d</xliff:g> veces de manera incorrecta. Se quitará el perfil de trabajo, lo que borrará todos los datos asociados."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Dibujaste el patrón de desbloqueo <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de manera incorrecta. Después de <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se te solicitará que desbloquees la tablet mediante una cuenta de correo electrónico.\n\n Vuelve a intentarlo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Dibujaste el patrón de desbloqueo <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de manera incorrecta. Después de <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se te solicitará que desbloquees el dispositivo mediante una cuenta de correo electrónico.\n\n Vuelve a intentarlo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"El sensor de huellas dactilares está en el botón de encendido. Es el botón plano que está junto al botón de volumen en relieve, en el borde de la tablet.\n\nSi presionas el botón de encendido, se apaga la pantalla."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"El sensor de huellas dactilares está en el botón de encendido. Es el botón plano que está junto al botón de volumen en relieve, en el borde del dispositivo.\n\nSi presionas el botón de encendido, se apaga la pantalla."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"El sensor de huellas dactilares está en el botón de encendido. Es el botón plano que está junto al botón de volumen en relieve, en el borde del teléfono.\n\nSi presionas el botón de encendido, se apaga la pantalla."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Desbloquea el teléfono para ver más opciones"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Desbloquea la tablet para ver más opciones"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desbloquea el dispositivo para ver más opciones"</string>
diff --git a/packages/SystemUI/res-product/values-es/strings.xml b/packages/SystemUI/res-product/values-es/strings.xml
index b973813..2e6a2ae 100644
--- a/packages/SystemUI/res-product/values-es/strings.xml
+++ b/packages/SystemUI/res-product/values-es/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Has intentado desbloquear el teléfono de forma incorrecta <xliff:g id="NUMBER">%d</xliff:g> veces. Se quitará este perfil de trabajo y se eliminarán todos sus datos."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Has dibujado un patrón de desbloqueo incorrecto <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. Si se producen <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se te pedirá que desbloquees el tablet con una cuenta de correo electrónico.\n\n Vuelve a intentarlo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Has dibujado un patrón de desbloqueo incorrecto <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. Si se producen <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se te pedirá que desbloquees el teléfono con una cuenta de correo electrónico.\n\n Vuelve a intentarlo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"El sensor de huellas digitales está en el botón de encendido. Es el botón plano situado junto al botón de volumen con relieve en el lateral del tablet.\n\nAl pulsar el botón de encendido, se apagará la pantalla."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"El sensor de huellas digitales está en el botón de encendido. Es el botón plano situado junto al botón de volumen con relieve en el lateral del dispositivo.\n\nAl pulsar el botón de encendido, se apagará la pantalla."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"El sensor de huellas digitales está en el botón de encendido. Es el botón plano situado junto al botón de volumen con relieve en el lateral del teléfono.\n\nAl pulsar el botón de encendido, se apagará la pantalla."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Desbloquea el teléfono para ver más opciones"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Desbloquea el tablet para ver más opciones"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desbloquea el dispositivo para ver más opciones"</string>
diff --git a/packages/SystemUI/res-product/values-et/strings.xml b/packages/SystemUI/res-product/values-et/strings.xml
index 6f84f0e..5abd1ca 100644
--- a/packages/SystemUI/res-product/values-et/strings.xml
+++ b/packages/SystemUI/res-product/values-et/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Olete püüdnud <xliff:g id="NUMBER">%d</xliff:g> korda telefoni valesti avada. Tööprofiil eemaldatakse ja kõik profiiliandmed kustutatakse."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Joonistasite oma avamismustri <xliff:g id="NUMBER_0">%1$d</xliff:g> korda valesti. Pärast veel <xliff:g id="NUMBER_1">%2$d</xliff:g> ebaõnnestunud katset palutakse teil tahvelarvuti avada meilikontoga.\n\n Proovige uuesti <xliff:g id="NUMBER_2">%3$d</xliff:g> sekundi pärast."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Joonistasite oma avamismustri <xliff:g id="NUMBER_0">%1$d</xliff:g> korda valesti. Pärast veel <xliff:g id="NUMBER_1">%2$d</xliff:g> ebaõnnestunud katset palutakse teil telefon avada meilikontoga.\n\n Proovige uuesti <xliff:g id="NUMBER_2">%3$d</xliff:g> sekundi pärast."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Sõrmejäljeandur asub toitenupul. See on tahvelarvuti küljel helitugevuse kõrgendatud nupu kõrval olev lame nupp.\n\nToitenupu vajutamisel lülitatakse ekraan välja."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Sõrmejäljeandur asub toitenupul. See on seadme küljel helitugevuse kõrgendatud nupu kõrval olev lame nupp.\n\nToitenupu vajutamisel lülitatakse ekraan välja."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Sõrmejäljeandur asub toitenupul. See on telefoni küljel helitugevuse kõrgendatud nupu kõrval olev lame nupp.\n\nToitenupu vajutamisel lülitatakse ekraan välja."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Lisavalikute nägemiseks avage oma telefon"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Lisavalikute nägemiseks avage oma tahvelarvuti"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Lisavalikute nägemiseks avage oma seade"</string>
diff --git a/packages/SystemUI/res-product/values-eu/strings.xml b/packages/SystemUI/res-product/values-eu/strings.xml
index 5c1646c..6d67390 100644
--- a/packages/SystemUI/res-product/values-eu/strings.xml
+++ b/packages/SystemUI/res-product/values-eu/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"<xliff:g id="NUMBER">%d</xliff:g> aldiz saiatu zara telefonoa desblokeatzen, baina huts egin duzu denetan. Laneko profila kendu egingo da eta, ondorioz, profileko datu guztiak ezabatuko dira."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Desblokeatzeko eredua oker marraztu duzu <xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz oker marrazten baduzu, tableta posta-kontu baten bidez desblokeatzeko eskatuko dizugu.\n\n Saiatu berriro <xliff:g id="NUMBER_2">%3$d</xliff:g> segundo barru."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Desblokeatzeko eredua oker marraztu duzu <xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz oker marrazten baduzu, telefonoa posta-kontu baten bidez desblokeatzeko eskatuko dizugu.\n\n Saiatu berriro <xliff:g id="NUMBER_2">%3$d</xliff:g> segundo barru."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Hatz-marken sentsorea etengailuan dago. Tabletaren ertzeko bolumen-botoi goratuaren ondoan dagoen botoi laua da.\n\nEtengailua sakatuz gero, pantaila itzaliko da."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Hatz-marken sentsorea etengailuan dago. Gailuaren ertzeko bolumen-botoi goratuaren ondoan dagoen botoi laua da.\n\nEtengailua sakatuz gero, pantaila itzaliko da."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Hatz-marken sentsorea etengailuan dago. Telefonoaren ertzeko bolumen-botoi goratuaren ondoan dagoen botoi laua da.\n\nEtengailua sakatuz gero, pantaila itzaliko da."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Desblokeatu telefonoa aukera gehiago ikusteko"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Desblokeatu tableta aukera gehiago ikusteko"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desblokeatu gailua aukera gehiago ikusteko"</string>
diff --git a/packages/SystemUI/res-product/values-fa/strings.xml b/packages/SystemUI/res-product/values-fa/strings.xml
index 606227a..62efff0 100644
--- a/packages/SystemUI/res-product/values-fa/strings.xml
+++ b/packages/SystemUI/res-product/values-fa/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"<xliff:g id="NUMBER">%d</xliff:g> تلاش ناموفق برای باز کردن قفل تلفن داشته‌اید. نمایه کاری پاک می‌شود که با آن همه داده‌های نمایه حذف می‌شود."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"‏الگوی بازگشایی قفل را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه کشیده‌اید. بعداز <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق، از شما خواسته می‌‎شود که بااستفاده از یک حساب ایمیل قفل رایانه لوحی‌تان را باز کنید.\n\n لطفاً پس‌از <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"الگوی بازگشایی قفل را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه کشیده‌اید. پس‌از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق، از شما خواسته می‌شود که بااستفاده از یک حساب ایمیل قفل تلفن را باز کنید.\n\n لطفاً پس‌از <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"حسگر اثر انگشت روی دکمه روشن/خاموش قرار دارد. این همان دکمه مسطحی است که کنار دکمه برآمده صدا در لبه رایانه لوحی قرار دارد.\n\nفشار دادن دکمه روشن/خاموش، صفحه‌نمایش را خاموش می‌کند."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"حسگر اثر انگشت روی دکمه روشن/خاموش قرار دارد. این همان دکمه مسطحی است که کنار دکمه برآمده صدا در لبه دستگاه قرار دارد.\n\nفشار دادن دکمه روشن/خاموش، صفحه‌نمایش را خاموش می‌کند."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"حسگر اثر انگشت روی دکمه روشن/خاموش قرار دارد. این همان دکمه مسطحی است که کنار دکمه برآمده صدا در لبه تلفن قرار دارد.\n\nفشار دادن دکمه روشن/خاموش، صفحه‌نمایش را خاموش می‌کند."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"برای گزینه‌های بیشتر، قفل تلفن را باز کنید"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"برای گزینه‌های بیشتر، قفل رایانه لوحی را باز کنید"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"برای گزینه‌های بیشتر، قفل دستگاه را باز کنید"</string>
diff --git a/packages/SystemUI/res-product/values-fi/strings.xml b/packages/SystemUI/res-product/values-fi/strings.xml
index 0df7104..da3592dd 100644
--- a/packages/SystemUI/res-product/values-fi/strings.xml
+++ b/packages/SystemUI/res-product/values-fi/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Yritit avata puhelimen lukituksen virheellisillä tiedoilla <xliff:g id="NUMBER">%d</xliff:g> kertaa. Työprofiili ja kaikki sen data poistetaan."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Piirsit lukituksenpoistokuvion väärin <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. Jos piirrät kuvion väärin vielä <xliff:g id="NUMBER_1">%2$d</xliff:g> kertaa, sinua pyydetään avaamaan tabletin lukitus sähköpostitilin avulla.\n\n Yritä uudelleen <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunnin kuluttua."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Piirsit lukituksenpoistokuvion väärin <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. Jos piirrät kuvion väärin vielä <xliff:g id="NUMBER_1">%2$d</xliff:g> kertaa, sinua pyydetään avaamaan puhelimesi lukitus sähköpostitilin avulla.\n\n Yritä uudelleen <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunnin kuluttua."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Sormenjälkitunnistin on virtapainikkeessa. Se on litteä painike koholla olevan äänenvoimakkuuspainikkeen vieressä tabletin sivussa.\n\nJos painat virtapainiketta, näyttö sammuu."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Sormenjälkitunnistin on virtapainikkeessa. Se on litteä painike koholla olevan äänenvoimakkuuspainikkeen vieressä laitteen sivussa.\n\nJos painat virtapainiketta, näyttö sammuu."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Sormenjälkitunnistin on virtapainikkeessa. Se on litteä painike koholla olevan äänenvoimakkuuspainikkeen vieressä puhelimen sivussa.\n\nJos painat virtapainiketta, näyttö sammuu."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Avaa puhelimen lukitus, niin näet enemmän vaihtoehtoja"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Avaa tabletin lukitus, niin näet enemmän vaihtoehtoja"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Avaa laitteen lukitus, niin näet enemmän vaihtoehtoja"</string>
diff --git a/packages/SystemUI/res-product/values-fr-rCA/strings.xml b/packages/SystemUI/res-product/values-fr-rCA/strings.xml
index efbdca2..bc01dde 100644
--- a/packages/SystemUI/res-product/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res-product/values-fr-rCA/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Vous avez tenté de déverrouiller ce téléphone à <xliff:g id="NUMBER">%d</xliff:g> reprises. Le profil professionnel sera supprimé, ce qui entraîne la suppression de toutes ses données."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, vous devrez déverrouiller votre tablette à l\'aide d\'un compte de courriel.\n\nVeuillez réessayer dans <xliff:g id="NUMBER_2">%3$d</xliff:g> secondes."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, vous devrez déverrouiller votre téléphone à l\'aide d\'un compte de courriel.\n\nVeuillez réessayer dans <xliff:g id="NUMBER_2">%3$d</xliff:g> secondes."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Le capteur d\'empreintes digitales est situé sur l\'interrupteur. Il s\'agit du bouton plat situé à côté du bouton de volume surélevé, sur le bord de la tablette.\n\nEn appuyant sur l\'interrupteur, vous éteignez l\'écran."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Le capteur d\'empreintes digitales est situé sur l\'interrupteur. Il s\'agit du bouton plat situé à côté du bouton de volume surélevé, sur le bord de l\'appareil.\n\nEn appuyant sur l\'interrupteur, vous éteignez l\'écran."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Le capteur d\'empreintes digitales est situé sur l\'interrupteur. Il s\'agit du bouton plat situé à côté du bouton de volume surélevé, sur le bord du téléphone.\n\nEn appuyant sur l\'interrupteur, vous éteignez l\'écran."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Déverrouillez votre téléphone pour afficher davantage d\'options"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Déverrouillez votre tablette pour afficher davantage d\'options"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Déverrouillez votre appareil pour afficher davantage d\'options"</string>
diff --git a/packages/SystemUI/res-product/values-fr/strings.xml b/packages/SystemUI/res-product/values-fr/strings.xml
index 817f4a3..0fc6fda 100644
--- a/packages/SystemUI/res-product/values-fr/strings.xml
+++ b/packages/SystemUI/res-product/values-fr/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Vous avez tenté de déverrouiller le téléphone à <xliff:g id="NUMBER">%d</xliff:g> reprises. Le profil professionnel et toutes les données associées vont être supprimés."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, vous devrez déverrouiller votre tablette à l\'aide d\'un compte de messagerie électronique.\n\nRéessayez dans <xliff:g id="NUMBER_2">%3$d</xliff:g> secondes."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, vous devrez déverrouiller votre téléphone à l\'aide d\'un compte de messagerie électronique.\n\nRéessayez dans <xliff:g id="NUMBER_2">%3$d</xliff:g> secondes."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Le lecteur d\'empreinte digitale se trouve sur le bouton Marche/Arrêt. C\'est le bouton plat à côté du bouton de volume en relief sur un bord de la tablette.\n\nAppuyer sur le bouton Marche/Arrêt éteint l\'écran."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Le lecteur d\'empreinte digitale se trouve sur le bouton Marche/Arrêt. C\'est le bouton plat à côté du bouton de volume en relief sur un bord de l\'appareil.\n\nAppuyer sur le bouton Marche/Arrêt éteint l\'écran."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Le lecteur d\'empreinte digitale se trouve sur le bouton Marche/Arrêt. C\'est le bouton plat à côté du bouton de volume en relief sur un bord du téléphone.\n\nAppuyer sur le bouton Marche/Arrêt éteint l\'écran."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Déverrouillez votre téléphone pour obtenir plus d\'options"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Déverrouillez votre tablette pour obtenir plus d\'options"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Déverrouillez votre appareil pour obtenir plus d\'options"</string>
diff --git a/packages/SystemUI/res-product/values-gl/strings.xml b/packages/SystemUI/res-product/values-gl/strings.xml
index 18d5be9..c27408e 100644
--- a/packages/SystemUI/res-product/values-gl/strings.xml
+++ b/packages/SystemUI/res-product/values-gl/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Tentaches desbloquear o teléfono <xliff:g id="NUMBER">%d</xliff:g> veces de forma incorrecta. Quitarase o perfil de traballo e, por conseguinte, todos os seus datos."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Debuxaches o padrón de desbloqueo <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de forma incorrecta. Se realizas <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos máis, terás que desbloquear a tableta a través dunha conta de correo electrónico.\n\n Téntao de novo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Debuxaches o padrón de desbloqueo <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de forma incorrecta. Se realizas <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos máis, terás que desbloquear o teléfono a través dunha conta de correo electrónico.\n\n Téntao de novo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"O sensor de impresión dixital está no botón de acendido. É o botón plano que está ao lado do botón de volume con relevo, no lateral da tableta.\n\nAo premer o botón de acendido, apágase a pantalla."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"O sensor de impresión dixital está no botón de acendido. É o botón plano que está ao lado do botón de volume con relevo, no lateral do dispositivo.\n\nAo premer o botón de acendido, apágase a pantalla."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"O sensor de impresión dixital está no botón de acendido. É o botón plano que está ao lado do botón de volume con relevo, no lateral do teléfono.\n\nAo premer o botón de acendido, apágase a pantalla."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Desbloquea o teléfono para ver máis opcións"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Desbloquea a tableta para ver máis opcións"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desbloquea o dispositivo para ver máis opcións"</string>
diff --git a/packages/SystemUI/res-product/values-gu/strings.xml b/packages/SystemUI/res-product/values-gu/strings.xml
index 4e6f78e..f7a2256 100644
--- a/packages/SystemUI/res-product/values-gu/strings.xml
+++ b/packages/SystemUI/res-product/values-gu/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"તમે ફોનને <xliff:g id="NUMBER">%d</xliff:g> વખત ખોટી રીતે અનલૉક કરવાનો પ્રયાસ કર્યો છે. આ કાર્યાલયની પ્રોફાઇલ કાઢી નાખવામાં આવશે, જે તમામ પ્રોફાઇલ ડેટાને ડિલીટ કરી દેશે."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"તમે તમારી અનલૉક પૅટર્ન <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે દોરી છે. વધુ <xliff:g id="NUMBER_1">%2$d</xliff:g> અસફળ પ્રયાસો પછી, તમને એક ઇમેઇલ એકાઉન્ટનો ઉપયોગ કરીને તમારા ટૅબ્લેટને અનલૉક કરવાનું કહેવામાં આવશે.\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> સેકન્ડમાં ફરી પ્રયાસ કરો."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"તમે તમારી અનલૉક પૅટર્ન <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે દોરી છે. વધુ <xliff:g id="NUMBER_1">%2$d</xliff:g> અસફળ પ્રયાસો પછી, તમને ઇમેઇલ એકાઉન્ટનો ઉપયોગ કરીને તમારા ફોનને અનલૉક કરવાનું કહેવામાં આવશે.\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> સેકન્ડમાં ફરીથી પ્રયાસ કરો."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"ફિંગરપ્રિન્ટ સેન્સર પાવર બટન પર છે. તે ટૅબ્લેટની કિનારીએ આવેલા ઉપસેલા વૉલ્યૂમ બટનની બાજુમાં આવેલું સપાટ બટન છે.\n\nપાવર બટન દબાવવાથી સ્ક્રીન બંધ થાય છે."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"ફિંગરપ્રિન્ટ સેન્સર પાવર બટન પર છે. તે ડિવાઇસની કિનારીએ આવેલા ઉપસેલા વૉલ્યૂમ બટનની બાજુમાં આવેલું સપાટ બટન છે.\n\nપાવર બટન દબાવવાથી સ્ક્રીન બંધ થાય છે."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"ફિંગરપ્રિન્ટ સેન્સર પાવર બટન પર છે. તે ફોનની કિનારીએ આવેલા ઉપસેલા વૉલ્યૂમ બટનની બાજુમાં આવેલું સપાટ બટન છે.\n\nપાવર બટન દબાવવાથી સ્ક્રીન બંધ થાય છે."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"વધુ વિકલ્પો માટે તમારા ફોનને અનલૉક કરો"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"વધુ વિકલ્પો માટે તમારા ટૅબ્લેટને અનલૉક કરો"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"વધુ વિકલ્પો માટે તમારા ડિવાઇસને અનલૉક કરો"</string>
diff --git a/packages/SystemUI/res-product/values-hi/strings.xml b/packages/SystemUI/res-product/values-hi/strings.xml
index faa9459..0fa377d 100644
--- a/packages/SystemUI/res-product/values-hi/strings.xml
+++ b/packages/SystemUI/res-product/values-hi/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"आप फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत पासवर्ड डाल चुके हैं. इसकी वजह से वर्क प्रोफ़ाइल को हटा दिया जाएगा जिससे उपयोगकर्ता की प्रोफ़ाइल का सारा डेटा मिट जाएगा."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"आपने लॉक खोलने के पैटर्न को <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से बनाया है. इसलिए, <xliff:g id="NUMBER_1">%2$d</xliff:g> और गलत पैटर्न बनाने के बाद, टैबलेट को अनलॉक करने के लिए आपसे ईमेल खाते का इस्तेमाल करने को कहा जाएगा.\n\n अनलॉक करने के लिए <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंड में फिर से कोशिश करें."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"आपने लॉक खोलने के पैटर्न को <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से बनाया है. इसलिए, <xliff:g id="NUMBER_1">%2$d</xliff:g> और गलत पैटर्न बनाने के बाद, आपसे फ़ोन को अनलॉक करने के लिए ईमेल खाते का इस्तेमाल करने को कहा जाएगा.\n\n अनलॉक करने के लिए <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंड में फिर से कोशिश करें."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"फ़िंगरप्रिंट सेंसर, पावर बटन पर होता है. यह टैबलेट के किनारे पर मौजूद एक फ़्लैट बटन होता है, जो कि आपको आवाज़ कम या ज़्यादा करने वाले उभरे हुए बटन के नीचे मिलेगा.\n\nपावर बटन दबाने से स्क्रीन बंद हो जाती है."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"फ़िंगरप्रिंट सेंसर, पावर बटन पर होता है. यह डिवाइस के किनारे पर मौजूद एक फ़्लैट बटन होता है, जो कि आपको आवाज़ कम या ज़्यादा करने वाले उभरे हुए बटन के नीचे मिलेगा.\n\nपावर बटन दबाने से स्क्रीन बंद हो जाती है."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"फ़िंगरप्रिंट सेंसर, पावर बटन पर होता है. यह फ़ोन के किनारे पर मौजूद एक फ़्लैट बटन होता है, जो कि आपको आवाज़ कम या ज़्यादा करने वाले उभरे हुए बटन के नीचे मिलेगा.\n\nपावर बटन दबाने से स्क्रीन बंद हो जाती है."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"ज़्यादा विकल्प देखने के लिए, अपना फ़ोन अनलॉक करें"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"ज़्यादा विकल्प देखने के लिए, अपना टैबलेट अनलॉक करें"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"ज़्यादा विकल्प देखने के लिए, अपना डिवाइस अनलॉक करें"</string>
diff --git a/packages/SystemUI/res-product/values-hr/strings.xml b/packages/SystemUI/res-product/values-hr/strings.xml
index 8ebd987..f467291 100644
--- a/packages/SystemUI/res-product/values-hr/strings.xml
+++ b/packages/SystemUI/res-product/values-hr/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Neuspješno ste pokušali otključati telefon <xliff:g id="NUMBER">%d</xliff:g> put/a. Radni će se profil ukloniti, a time će se izbrisati i svi njegovi podaci."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Netočno ste iscrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja morat ćete otključati tablet pomoću računa e-pošte.\n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Netočno ste iscrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja morat ćete otključati telefon pomoću računa e-pošte.\n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Senzor otiska prsta nalazi se na tipki za uključivanje/isključivanje. To je ravni gumb pored izdignutog gumba za glasnoću na rubu tableta.\n\nPritiskom na tipku za uključivanje/isključivanje isključuje se zaslon."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Senzor otiska prsta nalazi se na tipki za uključivanje/isključivanje. To je ravni gumb pored izdignutog gumba za glasnoću na rubu uređaja.\n\nPritiskom na tipku za uključivanje/isključivanje isključuje se zaslon."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Senzor otiska prsta nalazi se na tipki za uključivanje/isključivanje. To je ravni gumb pored izdignutog gumba za glasnoću na rubu telefona.\n\nPritiskom na tipku za uključivanje/isključivanje isključuje se zaslon."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Za više opcija otključajte telefon"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Za više opcija otključajte tablet"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Za više opcija otključajte uređaj"</string>
diff --git a/packages/SystemUI/res-product/values-hu/strings.xml b/packages/SystemUI/res-product/values-hu/strings.xml
index 821b572..d5f44e9 100644
--- a/packages/SystemUI/res-product/values-hu/strings.xml
+++ b/packages/SystemUI/res-product/values-hu/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"<xliff:g id="NUMBER">%d</xliff:g> alkalommal próbálkozott sikertelenül a telefon zárolásának feloldásával. A rendszer eltávolítja a munkaprofilt, és ezzel a profil összes adata törlődik."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal helytelenül rajzolta le a feloldási mintát. További <xliff:g id="NUMBER_1">%2$d</xliff:g> sikertelen kísérlet után e-mail-fiók használatával kell feloldania táblagépét.\n\nPróbálja újra <xliff:g id="NUMBER_2">%3$d</xliff:g> másodperc múlva."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal helytelenül rajzolta le a feloldási mintát. További <xliff:g id="NUMBER_1">%2$d</xliff:g> sikertelen kísérlet után e-mail-fiók használatával kell feloldania telefonját.\n\nPróbálja újra <xliff:g id="NUMBER_2">%3$d</xliff:g> másodperc múlva."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Az ujjlenyomat-érzékelő a bekapcsológombon található. A kiemelkedő hangerőgomb melletti lapos gomb a táblagép szélén.\n\nA bekapcsológomb lenyomásával kikapcsol a képernyő."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Az ujjlenyomat-érzékelő a bekapcsológombon található. A kiemelkedő hangerőgomb melletti lapos gomb az eszköz szélén.\n\nA bekapcsológomb lenyomásával kikapcsol a képernyő."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Az ujjlenyomat-érzékelő a bekapcsológombon található. A kiemelkedő hangerőgomb melletti lapos gomb a telefon szélén.\n\nA bekapcsológomb lenyomásával kikapcsol a képernyő."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"További lehetőségekért oldja fel a telefont"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"További lehetőségekért oldja fel a táblagépet"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"További lehetőségekért oldja fel az eszközt"</string>
diff --git a/packages/SystemUI/res-product/values-hy/strings.xml b/packages/SystemUI/res-product/values-hy/strings.xml
index 3aae6ac..74d115b 100644
--- a/packages/SystemUI/res-product/values-hy/strings.xml
+++ b/packages/SystemUI/res-product/values-hy/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Դուք կատարել եք հեռախոսն ապակողպելու <xliff:g id="NUMBER">%d</xliff:g> անհաջող փորձ: Աշխատանքային պրոֆիլը կհեռացվի, և պրոֆիլի բոլոր տվյալները կջնջվեն:"</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Դուք կատարել եք ապակողպման նախշը մուտքագրելու <xliff:g id="NUMBER_0">%1$d</xliff:g> անհաջող փորձ: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո ձեզանից կպահանջվի ապակողպել պլանշետը էլփոստի հաշվի միջոցով։\n\n Խնդրում ենք կրկին փորձել <xliff:g id="NUMBER_2">%3$d</xliff:g> վայրկյանից:"</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Դուք <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ սխալ եք հավաքել ձեր ապակողպման նմուշը: Եվս <xliff:g id="NUMBER_1">%2$d</xliff:g> անհաջող փորձից հետո ձեզ կառաջարկվի ապակողպել հեռախոսը` օգտագործելով էլփոստի հաշիվ:\n\n Կրկին փորձեք <xliff:g id="NUMBER_2">%3$d</xliff:g> վայրկյանից:"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Մատնահետքերի սկաները սնուցման կոճակի վրա է։ Այն հարթ կոճակն է՝ ձայնի ուժգնության ուռուցիկ կոճակի կողքին, պլանշետի եզրային մասում։\n\nՍնուցման կոճակի սեղմումով էկրանն անջատվում է։"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Մատնահետքերի սկաները սնուցման կոճակի վրա է։ Այն հարթ կոճակն է՝ ձայնի ուժգնության ուռուցիկ կոճակի կողքին, սարքի եզրային մասում։\n\nՍնուցման կոճակի սեղմումով էկրանն անջատվում է։"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Մատնահետքերի սկաները սնուցման կոճակի վրա է։ Այն հարթ կոճակ է՝ ձայնի ուժգնության ուռուցիկ կոճակի կողքին, հեռախոսի եզրային մասում։\n\nՍնուցման կոճակի սեղմումով էկրանն անջատվում է։"</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Ապակողպեք ձեր հեռախոսը՝ լրացուցիչ կարգավորումները տեսնելու համար"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Ապակողպեք ձեր պլանշետը՝ լրացուցիչ կարգավորումները տեսնելու համար"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Ապակողպեք ձեր սարքը՝ լրացուցիչ կարգավորումները տեսնելու համար"</string>
diff --git a/packages/SystemUI/res-product/values-in/strings.xml b/packages/SystemUI/res-product/values-in/strings.xml
index 3710317..d4363b8 100644
--- a/packages/SystemUI/res-product/values-in/strings.xml
+++ b/packages/SystemUI/res-product/values-in/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Anda telah <xliff:g id="NUMBER">%d</xliff:g> kali berupaya membuka kunci ponsel dengan tidak benar. Profil kerja akan dihapus, sehingga semua data profil akan dihapus."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali salah menggambar pola pembuka kunci. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya yang tidak berhasil, Anda akan diminta membuka kunci tablet menggunakan akun email.\n\n Coba lagi dalam <xliff:g id="NUMBER_2">%3$d</xliff:g> detik."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali salah menggambar pola pembuka kunci. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya yang tidak berhasil, Anda akan diminta membuka kunci ponsel menggunakan akun email.\n\n Coba lagi dalam <xliff:g id="NUMBER_2">%3$d</xliff:g> detik."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Sensor sidik jari ada di tombol daya. Tombol ini berupa tombol datar di samping tombol volume timbul di tepi tablet.\n\nMenekan tombol daya akan menonaktifkan layar."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Sensor sidik jari ada di tombol daya. Tombol ini berupa tombol datar di samping tombol volume timbul di tepi perangkat.\n\nMenekan tombol daya akan menonaktifkan layar."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Sensor sidik jari ada di tombol daya. Tombol ini berupa tombol datar di samping tombol volume timbul di tepi ponsel.\n\nMenekan tombol daya akan menonaktifkan layar."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Buka kunci ponsel untuk melihat opsi lainnya"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Buka kunci tablet untuk melihat opsi lainnya"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Buka kunci perangkat untuk melihat opsi lainnya"</string>
diff --git a/packages/SystemUI/res-product/values-is/strings.xml b/packages/SystemUI/res-product/values-is/strings.xml
index b7f1c1b..4923f1b 100644
--- a/packages/SystemUI/res-product/values-is/strings.xml
+++ b/packages/SystemUI/res-product/values-is/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Þú hefur gert <xliff:g id="NUMBER">%d</xliff:g> árangurslausar tilraunir til að opna símann. Vinnusniðið verður fjarlægt, með þeim afleiðingum að öllum gögnum þess verður eytt."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Þú hefur teiknað rangt opnunarmynstur <xliff:g id="NUMBER_0">%1$d</xliff:g> sinnum. Eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> árangurslausar tilraunir í viðbót verðurðu beðin(n) um að opna spjaldtölvuna með tölvupóstreikningi.\n\n Reyndu aftur eftir <xliff:g id="NUMBER_2">%3$d</xliff:g> sekúndur."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Þú hefur teiknað rangt opnunarmynstur <xliff:g id="NUMBER_0">%1$d</xliff:g> sinnum. Eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> árangurslausar tilraunir í viðbót verðurðu beðin(n) um að opna símann með tölvupóstreikningi.\n\n Reyndu aftur eftir <xliff:g id="NUMBER_2">%3$d</xliff:g> sekúndur."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Fingrafaralesarinn er á aflrofanum. Það er flati hnappurinn við hliðina á upphleypta hljóðstyrkshnappnum á hlið spjaldtölvunnar.\n\nÞegar ýtt er á aflrofann slokknar á skjánum."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Fingrafaralesarinn er á aflrofanum. Það er flati hnappurinn við hliðina á upphleypta hljóðstyrkshnappnum á hlið tækisins.\n\nÞegar ýtt er á aflrofann slokknar á skjánum."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Fingrafaralesarinn er á aflrofanum. Það er flati hnappurinn við hliðina á upphleypta hljóðstyrkshnappnum á hlið símans.\n\nÞegar ýtt er á aflrofann slokknar á skjánum."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Taktu símann úr lás til að fá fleiri valkosti"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Taktu spjaldtölvuna úr lás til að fá fleiri valkosti"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Taktu tækið úr lás til að fá fleiri valkosti"</string>
diff --git a/packages/SystemUI/res-product/values-it/strings.xml b/packages/SystemUI/res-product/values-it/strings.xml
index 14f3747..7718e28 100644
--- a/packages/SystemUI/res-product/values-it/strings.xml
+++ b/packages/SystemUI/res-product/values-it/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Hai tentato di sbloccare il telefono senza riuscirci per <xliff:g id="NUMBER">%d</xliff:g> volte. Il profilo di lavoro verrà rimosso e verranno quindi eliminati tutti i dati associati."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"<xliff:g id="NUMBER_0">%1$d</xliff:g> tentativi errati di inserimento della sequenza di sblocco. Dopo altri <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativi falliti, ti verrà chiesto di sbloccare il tablet con un account email.\n\n Riprova tra <xliff:g id="NUMBER_2">%3$d</xliff:g> secondi."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"<xliff:g id="NUMBER_0">%1$d</xliff:g> tentativi errati di inserimento della sequenza di sblocco. Dopo altri <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativi falliti, ti verrà chiesto di sbloccare il telefono con un account email.\n\n Riprova tra <xliff:g id="NUMBER_2">%3$d</xliff:g> secondi."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Il sensore di impronte digitali si trova sul tasto di accensione. Si tratta del tasto piatto accanto al tasto del volume in rilievo sulla parte laterale del tablet.\n\nSe premi il tasto di accensione viene disattivato lo schermo."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Il sensore di impronte digitali si trova sul tasto di accensione. Si tratta del tasto piatto accanto al tasto del volume in rilievo sulla parte laterale del dispositivo.\n\nSe premi il tasto di accensione viene disattivato lo schermo."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Il sensore di impronte digitali si trova sul tasto di accensione. Si tratta del tasto piatto accanto al tasto del volume in rilievo sulla parte laterale del telefono.\n\nSe premi il tasto di accensione viene disattivato lo schermo."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Sblocca il telefono per visualizzare altre opzioni"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Sblocca il tablet per visualizzare altre opzioni"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Sblocca il dispositivo per visualizzare altre opzioni"</string>
diff --git a/packages/SystemUI/res-product/values-iw/strings.xml b/packages/SystemUI/res-product/values-iw/strings.xml
index d51f71c..b32f21b 100644
--- a/packages/SystemUI/res-product/values-iw/strings.xml
+++ b/packages/SystemUI/res-product/values-iw/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ניסית לבטל את נעילת הטלפון <xliff:g id="NUMBER">%d</xliff:g> פעמים. פרופיל העבודה יוסר וכל נתוני הפרופיל יימחקו."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"שרטטת קו ביטול נעילה שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, ,תישלח אליך בקשה לבטל את נעילת הטאבלט באמצעות חשבון אימייל‏.\n\n יש לנסות שוב בעוד <xliff:g id="NUMBER_2">%3$d</xliff:g> שניות."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"שרטטת קו ביטול נעילה שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, תישלח אליך בקשה לבטל את נעילת הטלפון באמצעות חשבון אימייל‏.\n\n יש לנסות שוב בעוד <xliff:g id="NUMBER_2">%3$d</xliff:g> שניות."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"חיישן טביעת האצבע נמצא על לחצן ההפעלה. זה הלחצן השטוח ליד הלחצן הבולט של עוצמת הקול בפינת הטאבלט.\n\nלחיצה על לחצן ההפעלה מכבה את המסך."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"חיישן טביעת האצבע נמצא על לחצן ההפעלה. זה הלחצן השטוח ליד הלחצן הבולט של עוצמת הקול בפינת המכשיר.\n\nלחיצה על לחצן ההפעלה מכבה את המסך."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"חיישן טביעת האצבע נמצא על לחצן ההפעלה. זה הלחצן השטוח ליד הלחצן הבולט של עוצמת הקול בפינת הטלפון.\n\nלחיצה על לחצן ההפעלה מכבה את המסך."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"לאפשרויות נוספות, יש לבטל את נעילת הטלפון"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"לאפשרויות נוספות, יש לבטל את נעילת הטאבלט"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"לאפשרויות נוספות, יש לבטל את נעילת המכשיר"</string>
diff --git a/packages/SystemUI/res-product/values-ja/strings.xml b/packages/SystemUI/res-product/values-ja/strings.xml
index 44ddf4f..19e00d1 100644
--- a/packages/SystemUI/res-product/values-ja/strings.xml
+++ b/packages/SystemUI/res-product/values-ja/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"スマートフォンのロック解除に <xliff:g id="NUMBER">%d</xliff:g> 回失敗しました。仕事用プロファイルは削除され、プロファイルのデータはすべて消去されます。"</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"ロック解除パターンの入力を <xliff:g id="NUMBER_0">%1$d</xliff:g> 回間違えました。あと <xliff:g id="NUMBER_1">%2$d</xliff:g> 回間違えると、タブレットのロック解除にメール アカウントが必要になります。\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後にもう一度お試しください。"</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"ロック解除パターンの入力を <xliff:g id="NUMBER_0">%1$d</xliff:g> 回間違えました。あと <xliff:g id="NUMBER_1">%2$d</xliff:g> 回間違えると、スマートフォンのロック解除にメール アカウントが必要になります。\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後にもう一度お試しください。"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"指紋認証センサーは電源ボタンに内蔵されています。タブレットの端にある盛り上がった音量ボタンの横のフラットなボタンです。\n\n電源ボタンを押すと画面が OFF になります。"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"指紋認証センサーは電源ボタンに内蔵されています。デバイスの端にある盛り上がった音量ボタンの横のフラットなボタンです。\n\n電源ボタンを押すと画面が OFF になります。"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"指紋認証センサーは電源ボタンに内蔵されています。スマートフォンの端にある盛り上がった音量ボタンの横のフラットなボタンです。\n\n電源ボタンを押すと画面が OFF になります。"</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"スマートフォンのロックを解除してその他のオプションを表示する"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"タブレットのロックを解除してその他のオプションを表示する"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"デバイスのロックを解除してその他のオプションを表示する"</string>
diff --git a/packages/SystemUI/res-product/values-ka/strings.xml b/packages/SystemUI/res-product/values-ka/strings.xml
index 8d423a2..fe6fcbd 100644
--- a/packages/SystemUI/res-product/values-ka/strings.xml
+++ b/packages/SystemUI/res-product/values-ka/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"თქვენ არასწორად ცადეთ ტელეფონის განბლოკვა <xliff:g id="NUMBER">%d</xliff:g>-ჯერ. ამის გამო, სამსახურის პროფილი ამოიშლება, რაც პროფილის ყველა მონაცემის წაშლას გამოიწვევს."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"თქვენ არასწორად დახატეთ თქვენი განბლოკვის ნიმუში <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. კიდევ <xliff:g id="NUMBER_1">%2$d</xliff:g> წარუმატებელი მცდელობის შემდეგ მოგთხოვთ, ტაბლეტი თქვენი ელფოსტის ანგარიშის მეშვეობით განბლოკოთ.\n\n ცადეთ ხელახლა <xliff:g id="NUMBER_2">%3$d</xliff:g> წამში."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"თქვენ არასწორად დახატეთ თქვენი განბლოკვის ნიმუში <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. კიდევ <xliff:g id="NUMBER_1">%2$d</xliff:g> წარუმატებელი მცდელობის შემდეგ მოგთხოვთ, ტელეფონი თქვენი ელფოსტის ანგარიშის მეშვეობით განბლოკოთ.\n\n ცადეთ ხელახლა <xliff:g id="NUMBER_2">%3$d</xliff:g> წამში."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"თითის ანაბეჭდის სენსორი ჩართვის ღილაკზეა. ეს არის ბრტყელი ღილაკი ხმის აწევის ღილაკის გვერდით ტაბლეტის კიდეზე.\n\nჩართვის ღილაკზე დაწკაპუნება გამორთავს ეკრანს."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"თითის ანაბეჭდის სენსორი ჩართვის ღილაკზეა. ეს არის ბრტყელი ღილაკი ხმის აწევის ღილაკის გვერდით მოწყობილობის კიდეზე.\n\nჩართვის ღილაკზე დაწკაპუნება გამორთავს ეკრანს."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"თითის ანაბეჭდის სენსორი ჩართვის ღილაკზეა. ეს არის ბრტყელი ღილაკი ხმის აწევის ღილაკის გვერდით ტელეფონის კიდეზე.\n\nჩართვის ღილაკზე დაწკაპუნება გამორთავს ეკრანს."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"მეტი ვარიანტის სანახავად განბლოკეთ თქვენი ტელეფონი"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"მეტი ვარიანტის სანახავად განბლოკეთ თქვენი ტაბლეტი"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"მეტი ვარიანტის სანახავად განბლოკეთ თქვენი მოწყობილობა"</string>
diff --git a/packages/SystemUI/res-product/values-kk/strings.xml b/packages/SystemUI/res-product/values-kk/strings.xml
index 428cfa3..3f94907 100644
--- a/packages/SystemUI/res-product/values-kk/strings.xml
+++ b/packages/SystemUI/res-product/values-kk/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Телефон құлпын ашуға <xliff:g id="NUMBER">%d</xliff:g> рет сәтсіз әрекет жасалды. Жұмыс профилі өшіріліп, оның бүкіл деректері жойылады."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Құлыпты ашу өрнегі <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате енгізілді. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін планшетті аккаунт арқылы ашу сұралады. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін әрекетті қайталаңыз."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Құлыпты ашу өрнегі <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате енгізілді. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін телефонды аккаунт арқылы ашу сұралады. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін әрекетті қайталаңыз."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Саусақ ізін оқу сканері қуат түймесінде орналасқан. Ол – планшеттің шетіндегі шығыңқы дыбыс деңгейі түймесінің жанында орналасқан жалпақ түйме.\n\nҚуат түймесі басылса, экран өшеді."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Саусақ ізін оқу сканері қуат түймесінде орналасқан. Ол – құрылғының шетіндегі шығыңқы дыбыс деңгейі түймесінің жанында орналасқан жалпақ түйме.\n\nҚуат түймесі басылса, экран өшеді."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Саусақ ізін оқу сканері қуат түймесінде орналасқан. Ол – телефонның шетіндегі шығыңқы дыбыс деңгейі түймесінің жанында орналасқан жалпақ түйме.\n\nҚуат түймесі басылса, экран өшеді."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Басқа опцияларды көру үшін телефон құлпын ашыңыз."</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Басқа опцияларды көру үшін планшет құлпын ашыңыз."</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Басқа опцияларды көру үшін құрылғы құлпын ашыңыз."</string>
diff --git a/packages/SystemUI/res-product/values-km/strings.xml b/packages/SystemUI/res-product/values-km/strings.xml
index 9dd1b1a..46bf9af 100644
--- a/packages/SystemUI/res-product/values-km/strings.xml
+++ b/packages/SystemUI/res-product/values-km/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"អ្នក​បាន​ព្យាយាម​ដោះសោ​ទូរសព្ទ​នេះ​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER">%d</xliff:g> ដង​ហើយ។ កម្រង​ព័ត៌មាន​ការងារ​នេះ​នឹង​ត្រូវ​បាន​លុប ហើយ​វា​នឹង​លុប​ទិន្នន័យ​កម្រង​ព័ត៌មាន​ទាំងអស់។"</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"អ្នក​បាន​គូរ​លំនាំ​ដោះ​សោ​របស់​អ្នក​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដង​ហើយ។ បន្ទាប់ពីមានការ​ព្យាយាម​ដោះ​សោ​ចំនួន <xliff:g id="NUMBER_1">%2$d</xliff:g> ដងទៀត​មិន​ទទួល​បាន​ជោគជ័យ អ្នក​នឹង​ត្រូវ​បាន​ស្នើ​ឱ្យ​ដោះ​សោ​ថេប្លេត​របស់​អ្នក​ ដោយ​ប្រើ​គណនី​អ៊ីមែល។\n\n សូមព្យាយាម​ម្ដង​ទៀត​ក្នុង​រយៈ​ពេល <xliff:g id="NUMBER_2">%3$d</xliff:g> វិនាទី​ទៀត។"</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"អ្នកបានគូរលំនាំ​ដោះសោ​របស់អ្នក​មិន​ត្រឹមត្រូវចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដងហើយ។ បន្ទាប់ពីមាន​ការព្យាយាម​ដោះសោចំនួន <xliff:g id="NUMBER_1">%2$d</xliff:g> ដងទៀតមិនទទួលបាន​ជោគជ័យ អ្នកនឹង​ត្រូវបាន​ស្នើឱ្យ​ដោះសោ​ទូរសព្ទ​របស់​អ្នកដោយ​ប្រើគណនី​អ៊ីមែល។\n\n សូមព្យាយាម​ម្ដងទៀតក្នុង​រយៈពេល <xliff:g id="NUMBER_2">%3$d</xliff:g> វិនាទីទៀត។"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"សេនស័រចាប់ស្នាមម្រាមដៃ​ស្ថិតនៅលើប៊ូតុង​ថាមពល។ វាជាប៊ូតុងរាបស្មើ​នៅ​ជាប់​នឹង​ប៊ូតុង​កម្រិត​សំឡេង​ដែល​លៀន​ចេញ​មក​នៅ​លើ​គែម​ថេប្លេត។\n\nការចុច​ប៊ូតុង​ថាមពល​នឹង​បិទ​អេក្រង់។"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"សេនស័រចាប់ស្នាមម្រាមដៃ​ស្ថិតនៅលើប៊ូតុង​ថាមពល។ វាជាប៊ូតុងរាបស្មើ​នៅ​ជាប់​នឹង​ប៊ូតុង​កម្រិត​សំឡេង​ដែល​លៀន​ចេញ​មក​នៅ​លើ​គែម​ឧបករណ៍។\n\nការចុច​ប៊ូតុង​ថាមពល​នឹង​បិទ​អេក្រង់។"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"សេនស័រចាប់ស្នាមម្រាមដៃ​ស្ថិតនៅលើប៊ូតុង​ថាមពល។ វាជាប៊ូតុងរាបស្មើ​នៅ​ជាប់​នឹង​ប៊ូតុង​កម្រិត​សំឡេង​ដែល​លៀន​ចេញ​មក​នៅ​លើ​គែម​ទូរសព្ទ។\n\nការចុច​ប៊ូតុង​ថាមពល​នឹង​បិទ​អេក្រង់។"</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"ដោះសោ​ទូរសព្ទរបស់អ្នក​សម្រាប់​ជម្រើសច្រើនទៀត"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"ដោះសោ​ថេប្លេតរបស់អ្នក​សម្រាប់​ជម្រើសច្រើនទៀត"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"ដោះសោ​ឧបករណ៍របស់អ្នក​សម្រាប់​ជម្រើសច្រើនទៀត"</string>
diff --git a/packages/SystemUI/res-product/values-kn/strings.xml b/packages/SystemUI/res-product/values-kn/strings.xml
index b6551ba..44bcf55 100644
--- a/packages/SystemUI/res-product/values-kn/strings.xml
+++ b/packages/SystemUI/res-product/values-kn/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ಫೋನ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನೀವು <xliff:g id="NUMBER">%d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್ ಅನ್ನು ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ, ಇದು ಪ್ರೊಫೈಲ್‌ನ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"ನಿಮ್ಮ ಅನ್‍‍ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಅನ್ನು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಡ್ರಾ ಮಾಡಿರುವಿರಿ. <xliff:g id="NUMBER_1">%2$d</xliff:g> ಕ್ಕೂ ಹೆಚ್ಚಿನ ವಿಫಲ ಪ್ರಯತ್ನಗಳ ಬಳಿಕ, ನಿಮ್ಮ ಇಮೇಲ್ ಖಾತೆಯನ್ನು ಬಳಸಿ ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನಿಮ್ಮನ್ನು ಕೇಳಲಾಗುತ್ತದೆ.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ಸೆಕೆಂಡ್‌ಗಳಲ್ಲಿ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"ನಿಮ್ಮ ಅನ್‍‍ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಅನ್ನು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಡ್ರಾ ಮಾಡಿರುವಿರಿ. <xliff:g id="NUMBER_1">%2$d</xliff:g> ಕ್ಕೂ ಹೆಚ್ಚಿನ ವಿಫಲ ಪ್ರಯತ್ನಗಳ ಬಳಿಕ, ಇಮೇಲ್ ಖಾತೆಯನ್ನು ಬಳಸಿ ನಿಮ್ಮ ಫೋನ್ ಅನ್‌ಲಾಕ್ ಮಾಡಲು ನಿಮ್ಮನ್ನು ಕೇಳಲಾಗುತ್ತದೆ.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ಸೆಕೆಂಡ್‌ಗಳಲ್ಲಿ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ಪವರ್ ಬಟನ್‌ನಲ್ಲಿದೆ. ಇದು ಟ್ಯಾಬ್ಲೆಟ್‌ನ ಅಂಚಿನಲ್ಲಿರುವ ಎತ್ತರಿಸಿದ ವಾಲ್ಯೂಮ್ ಬಟನ್‌ನ ಪಕ್ಕದಲ್ಲಿರುವ ಚಪ್ಪಟೆ ಬಟನ್ ಆಗಿದೆ.\n\nಪವರ್ ಬಟನ್ ಅನ್ನು ಒತ್ತುವುದರಿಂದ ಸ್ಕ್ರೀನ್ ಆಫ್ ಆಗುತ್ತದೆ."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ಪವರ್ ಬಟನ್‌ನಲ್ಲಿದೆ. ಇದು ಸಾಧನದ ಅಂಚಿನಲ್ಲಿರುವ ಎತ್ತರಿಸಿದ ವಾಲ್ಯೂಮ್ ಬಟನ್‌ನ ಪಕ್ಕದಲ್ಲಿರುವ ಚಪ್ಪಟೆ ಬಟನ್ ಆಗಿದೆ.\n\nಪವರ್ ಬಟನ್ ಅನ್ನು ಒತ್ತುವುದರಿಂದ ಸ್ಕ್ರೀನ್ ಆಫ್ ಆಗುತ್ತದೆ."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ಪವರ್ ಬಟನ್‌ನಲ್ಲಿದೆ. ಇದು ಫೋನ್ ಅಂಚಿನಲ್ಲಿರುವ ಎತ್ತರಿಸಿದ ವಾಲ್ಯೂಮ್ ಬಟನ್‌ನ ಪಕ್ಕದಲ್ಲಿರುವ ಚಪ್ಪಟೆ ಬಟನ್ ಆಗಿದೆ.\n\nಪವರ್ ಬಟನ್ ಅನ್ನು ಒತ್ತುವುದರಿಂದ ಸ್ಕ್ರೀನ್ ಆಫ್ ಆಗುತ್ತದೆ."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"ಹೆಚ್ಚಿನ ಆಯ್ಕೆಗಳಿಗಾಗಿ ನಿಮ್ಮ ಫೋನ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಿ"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"ಹೆಚ್ಚಿನ ಆಯ್ಕೆಗಳಿಗಾಗಿ ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಿ"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"ಹೆಚ್ಚಿನ ಆಯ್ಕೆಗಳಿಗಾಗಿ ನಿಮ್ಮ ಸಾಧನವನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಿ"</string>
diff --git a/packages/SystemUI/res-product/values-ko/strings.xml b/packages/SystemUI/res-product/values-ko/strings.xml
index cca0ace..d9ca699 100644
--- a/packages/SystemUI/res-product/values-ko/strings.xml
+++ b/packages/SystemUI/res-product/values-ko/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"휴대전화 잠금 해제에 <xliff:g id="NUMBER">%d</xliff:g>번 실패했습니다. 직장 프로필과 모든 프로필 데이터가 삭제됩니다."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"잠금 해제 패턴을 <xliff:g id="NUMBER_0">%1$d</xliff:g>회 잘못 그렸습니다. <xliff:g id="NUMBER_1">%2$d</xliff:g>회 더 실패하면 이메일 계정을 사용하여 태블릿을 잠금 해제해야 합니다.\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g>초 후에 다시 시도해 주세요."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"잠금 해제 패턴을 <xliff:g id="NUMBER_0">%1$d</xliff:g>회 잘못 그렸습니다. <xliff:g id="NUMBER_1">%2$d</xliff:g>회 더 실패하면 이메일 계정을 사용하여 휴대전화를 잠금 해제해야 합니다.\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g>초 후에 다시 시도해 주세요."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"지문 센서는 전원 버튼에 있습니다. 태블릿 옆면의 튀어나온 볼륨 버튼 옆에 있는 평평한 버튼입니다.\n\n전원 버튼을 누르면 화면이 꺼집니다."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"지문 센서는 전원 버튼에 있습니다. 기기 옆면의 튀어나온 볼륨 버튼 옆에 있는 평평한 버튼입니다.\n\n전원 버튼을 누르면 화면이 꺼집니다."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"지문 센서는 전원 버튼에 있습니다. 휴대전화 옆면의 튀어나온 볼륨 버튼 옆에 있는 평평한 버튼입니다.\n\n전원 버튼을 누르면 화면이 꺼집니다."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"더 많은 옵션을 확인하려면 휴대전화를 잠금 해제하세요."</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"더 많은 옵션을 확인하려면 태블릿을 잠금 해제하세요."</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"더 많은 옵션을 확인하려면 기기를 잠금 해제하세요."</string>
diff --git a/packages/SystemUI/res-product/values-ky/strings.xml b/packages/SystemUI/res-product/values-ky/strings.xml
index a0d77f9..9e22bfe 100644
--- a/packages/SystemUI/res-product/values-ky/strings.xml
+++ b/packages/SystemUI/res-product/values-ky/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Телефондун кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Жумуш профили өчүрүлүп, андагы бардык нерселер өчүрүлөт."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тарттыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> ийгиликсиз аракеттен кийин планшетиңизди бөгөттөн электрондук почтаңыз аркылуу чыгаруу талап кылынат.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секунддан кийин кайра аракеттениңиз."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тарттыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> ийгиликсиз аракеттен кийин телефонуңузду бөгөттөн электрондук почтаңыз аркылуу чыгаруу талап кылынат.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секунддан кийин кайра аракеттениңиз."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Манжа изинин сенсору кубат баскычында жайгашкан. Бул планшеттин четиндеги үндү катуулатуу/акырындатуу баскычынын жанындагы жалпак баскыч.\n\nКубат баскычы басылса, экран өчөт."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Манжа изинин сенсору кубат баскычында жайгашкан. Ал түзмөктүн четиндеги үндү катуулатуу/акырындатуу баскычынын жанындагы жалпак баскыч.\n\nКубат баскычы басылса, экран өчөт."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Манжа изинин сенсору кубат баскычында жайгашкан. Ал телефондун четиндеги үндү катуулатуу/акырындатуу баскычынын жанындагы жалпак баскыч.\n\nКубат баскычы басылса, экран өчөт."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Дагы башка параметрлерди көрүү үчүн телефонуңуздун кулпусун ачыңыз"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Дагы башка параметрлерди көрүү үчүн планшетиңиздин кулпусун ачыңыз"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Дагы башка параметрлерди көрүү үчүн түзмөгүңүздүн кулпусун ачыңыз"</string>
diff --git a/packages/SystemUI/res-product/values-lo/strings.xml b/packages/SystemUI/res-product/values-lo/strings.xml
index dee445b..b022567 100644
--- a/packages/SystemUI/res-product/values-lo/strings.xml
+++ b/packages/SystemUI/res-product/values-lo/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ທ່ານພະຍາຍາມປົດລັອກໂທລະສັບຜິດ <xliff:g id="NUMBER">%d</xliff:g> ເທື່ອແລ້ວ. ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກຈະຖືກລຶບອອກ, ເຊິ່ງຈະລຶບຂໍ້ມູນໂປຣໄຟລ໌ທັງໝົດອອກນຳ."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"ທ່ານແຕ້ມຮູບແບບປົດລັອກຜິດ <xliff:g id="NUMBER_0">%1$d</xliff:g> ເທື່ອແລ້ວ. ຫຼັງຈາກແຕ້ມຜິດອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ເທື່ອ, ທ່ານຈະຖືກຖາມໃຫ້ປົດລັອກແທັບເລັດຂອງທ່ານດ້ວຍການເຂົ້າສູ່ລະບົບໂດຍໃຊ້ອີເມວຂອງທ່ານ.\n\n ກະລຸນາລອງໃໝ່ໃນອີກ <xliff:g id="NUMBER_2">%3$d</xliff:g> ວິນາທີ."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"ທ່ານແຕ້ມຮູບແບບປົດລັອກຜິດ <xliff:g id="NUMBER_0">%1$d</xliff:g> ເທື່ອແລ້ວ. ຫຼັງຈາກແຕ້ມຜິດອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ເທື່ອ, ທ່ານຈະຖືກຖາມໃຫ້ປົດໂທລະສັບຂອງທ່ານດ້ວຍການເຂົ້າສູ່ລະບົບໂດຍໃຊ້ບັນຊີອີເມວ.\n\n ກະລຸນາລອງໃໝ່ໃນອີກ <xliff:g id="NUMBER_2">%3$d</xliff:g> ວິນາທີ."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"ເຊັນເຊີລາຍນິ້ວມືແມ່ນຢູ່ປຸ່ມເປີດປິດ. ມັນເປັນປຸ່ມຮາບພຽງທີ່ຢູ່ຖັດຈາກປຸ່ມລະດັບສຽງທີ່ຍົກຂຶ້ນມາຢູ່ຂອບຂອງແທັບເລັດ.\n\nການກົດປຸ່ມເປີດປິດຈະປິດໜ້າຈໍ."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"ເຊັນເຊີລາຍນິ້ວມືແມ່ນຢູ່ປຸ່ມເປີດປິດ. ມັນເປັນປຸ່ມຮາບພຽງທີ່ຢູ່ຖັດຈາກປຸ່ມລະດັບສຽງທີ່ຍົກຂຶ້ນມາຢູ່ຂອບຂອງອຸປະກອນ.\n\nການກົດປຸ່ມເປີດປິດຈະປິດໜ້າຈໍ."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"ເຊັນເຊີລາຍນິ້ວມືແມ່ນຢູ່ປຸ່ມເປີດປິດ. ມັນເປັນປຸ່ມຮາບພຽງທີ່ຢູ່ຖັດຈາກປຸ່ມລະດັບສຽງທີ່ຍົກຂຶ້ນມາຢູ່ຂອບຂອງໂທລະສັບ.\n\nການກົດປຸ່ມເປີດປິດຈະປິດໜ້າຈໍ."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"ປົດລັອກໂທລະສັບຂອງທ່ານເພື່ອໃຊ້ຕົວເລືອກເພີ່ມເຕີມ"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"ປົດລັອກແທັບເລັດຂອງທ່ານເພື່ອໃຊ້ຕົວເລືອກເພີ່ມເຕີມ"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"ປົດລັອກອຸປະກອນຂອງທ່ານເພື່ອໃຊ້ຕົວເລືອກເພີ່ມເຕີມ"</string>
diff --git a/packages/SystemUI/res-product/values-lt/strings.xml b/packages/SystemUI/res-product/values-lt/strings.xml
index 3f36427..945a45e 100644
--- a/packages/SystemUI/res-product/values-lt/strings.xml
+++ b/packages/SystemUI/res-product/values-lt/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"<xliff:g id="NUMBER">%d</xliff:g> kart. nesėkmingai bandėte atrakinti telefoną. Darbo profilis bus pašalintas ir visi profilio duomenys bus ištrinti."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"<xliff:g id="NUMBER_0">%1$d</xliff:g> kart. netinkamai nupiešėte atrakinimo piešinį. Po dar <xliff:g id="NUMBER_1">%2$d</xliff:g> nesėkm. band. būsite paprašyti atrakinti planšetinį kompiuterį naudodami el. pašto paskyrą.\n\n Bandykite dar kartą po <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"<xliff:g id="NUMBER_0">%1$d</xliff:g> kart. netinkamai nupiešėte atrakinimo piešinį. Po dar <xliff:g id="NUMBER_1">%2$d</xliff:g> nesėkm. band. būsite paprašyti atrakinti telefoną naudodami el. pašto paskyrą.\n\n Bandykite dar kartą po <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Piršto atspaudo jutiklis yra ant maitinimo mygtuko. Tai yra plokščias mygtukas šalia iškilusio garsumo mygtuko ant planšetinio kompiuterio krašto.\n\nPaspaudus maitinimo mygtuką išjungiamas ekranas."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Piršto atspaudo jutiklis yra ant maitinimo mygtuko. Tai yra plokščias mygtukas šalia iškilusio garsumo mygtuko ant įrenginio krašto.\n\nPaspaudus maitinimo mygtuką išjungiamas ekranas."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Piršto atspaudo jutiklis yra ant maitinimo mygtuko. Tai yra plokščias mygtukas šalia iškilusio garsumo mygtuko ant telefono krašto.\n\nPaspaudus maitinimo mygtuką išjungiamas ekranas."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Atrakinkite telefoną, kad galėtumėte naudoti daugiau parinkčių"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Atrakinkite planšetinį kompiuterį, kad galėtumėte naudoti daugiau parinkčių"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Atrakinkite įrenginį, kad galėtumėte naudoti daugiau parinkčių"</string>
diff --git a/packages/SystemUI/res-product/values-lv/strings.xml b/packages/SystemUI/res-product/values-lv/strings.xml
index e079324..a7842bd 100644
--- a/packages/SystemUI/res-product/values-lv/strings.xml
+++ b/packages/SystemUI/res-product/values-lv/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Jūs <xliff:g id="NUMBER">%d</xliff:g> reizi(-es) nesekmīgi mēģinājāt atbloķēt tālruni. Darba profils tiks noņemts, kā arī visi profila dati tiks dzēsti."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Jūs <xliff:g id="NUMBER_0">%1$d</xliff:g> reizi(-es) nepareizi norādījāt atbloķēšanas kombināciju. Pēc vēl <xliff:g id="NUMBER_1">%2$d</xliff:g> neveiksmīga(-iem) mēģinājuma(-iem) planšetdators būs jāatbloķē, izmantojot e-pasta kontu.\n\nMēģiniet vēlreiz pēc <xliff:g id="NUMBER_2">%3$d</xliff:g> sekundes(-ēm)."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Jūs <xliff:g id="NUMBER_0">%1$d</xliff:g> reizi(-es) nepareizi norādījāt atbloķēšanas kombināciju. Pēc vēl <xliff:g id="NUMBER_1">%2$d</xliff:g> nesekmīga(-iem) mēģinājuma(-iem) tālrunis būs jāatbloķē, izmantojot e-pasta kontu.\n\nMēģiniet vēlreiz pēc <xliff:g id="NUMBER_2">%3$d</xliff:g> sekundes(-ēm)."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Pirksta nospieduma sensors atrodas uz barošanas pogas. Barošanas poga ir plakanā poga, kas atrodas blakus augstākai skaļuma pogai planšetdatora sānos.\n\nNospiežot barošanas pogu, tiek izslēgts ekrāns."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Pirksta nospieduma sensors atrodas uz barošanas pogas. Barošanas poga ir plakanā poga, kas atrodas blakus augstākai skaļuma pogai ierīces sānos.\n\nNospiežot barošanas pogu, tiek izslēgts ekrāns."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Pirksta nospieduma sensors atrodas uz barošanas pogas. Barošanas poga ir plakanā poga, kas atrodas blakus augstākai skaļuma pogai tālruņa sānos.\n\nNospiežot barošanas pogu, tiek izslēgts ekrāns."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Atbloķējiet tālruni, lai skatītu citas opcijas."</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Atbloķējiet planšetdatoru, lai skatītu citas opcijas."</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Atbloķējiet ierīci, lai skatītu citas opcijas."</string>
diff --git a/packages/SystemUI/res-product/values-mk/strings.xml b/packages/SystemUI/res-product/values-mk/strings.xml
index c8be656..23649d3 100644
--- a/packages/SystemUI/res-product/values-mk/strings.xml
+++ b/packages/SystemUI/res-product/values-mk/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Погрешно се обидовте да го отклучите телефонот <xliff:g id="NUMBER">%d</xliff:g> пати. Работниот профил ќе се отстрани, со што ќе се избришат сите податоци на профилот."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Погрешно ја употребивте вашата шема на отклучување <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. По уште <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни обиди, ќе побараме да го отклучите таблетот со сметка на е-пошта.\n\n Обидете се повторно за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунди."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Погрешно ја употребивте вашата шема на отклучување <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. По уште <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни обиди, ќе побараме да го отклучите телефонот со сметка на е-пошта.\n\n Обидете се повторно за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунди."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Сензорот за отпечатоци се наоѓа на копчето за вклучување. Тоа е рамното копче веднаш до подигнатото копче за јачина на звук на работ на таблетот.\n\nАко го притиснете копчето за вклучување, ќе се исклучи екранот."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Сензорот за отпечатоци се наоѓа на копчето за вклучување. Тоа е рамното копче веднаш до подигнатото копче за јачина на звук на работ на уредот.\n\nАко го притиснете копчето за вклучување, ќе се исклучи екранот."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Сензорот за отпечатоци се наоѓа на копчето за вклучување. Тоа е рамното копче веднаш до подигнатото копче за јачина на звук на работ на телефонот.\n\nАко го притиснете копчето за вклучување, ќе се исклучи екранот."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Отклучето го вашиот телефон за повеќе опции"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Отклучето го вашиот таблет за повеќе опции"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Отклучето го вашиот уред за повеќе опции"</string>
diff --git a/packages/SystemUI/res-product/values-ml/strings.xml b/packages/SystemUI/res-product/values-ml/strings.xml
index 756e165..23a8a50 100644
--- a/packages/SystemUI/res-product/values-ml/strings.xml
+++ b/packages/SystemUI/res-product/values-ml/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"നിങ്ങൾ <xliff:g id="NUMBER">%d</xliff:g> തവണ തെറ്റായ രീതിയിൽ ഫോൺ അൺലോക്ക് ചെയ്യാൻ ശ്രമിച്ചു. ഔദ്യോഗിക പ്രൊഫൈൽ നീക്കം ചെയ്യപ്പെടുകയും, അതുവഴി എല്ലാ പ്രൊഫൈൽ ഡാറ്റയും ഇല്ലാതാകുകയും ചെയ്യും."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായ രീതിയിൽ അൺലോക്ക് പാറ്റേൺ വരച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെട്ടാൽ, ഒരു ഇമെയിൽ അക്കൗണ്ടുപയോഗിച്ച് ടാബ്‌ലെറ്റ് അൺലോക്ക് ചെയ്യാൻ നിങ്ങളോട് ആവശ്യപ്പെടും.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> സെക്കന്റ് കഴിഞ്ഞ് വീണ്ടും ശ്രമിക്കുക."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായ രീതിയിൽ അൺലോക്ക് പാറ്റേൺ വരച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി പരാജയപ്പെട്ടാൽ, ഒരു ഇമെയിൽ അക്കൗണ്ടുപയോഗിച്ച് ഫോൺ അൺലോക്ക് ചെയ്യാൻ നിങ്ങളോട് ആവശ്യപ്പെടും.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> സെക്കന്റ് കഴിഞ്ഞ് വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"പവർ ബട്ടണിലാണ് ഫിംഗർപ്രിന്റ് സെൻസർ ഉള്ളത്. ടാബ്‌ലെറ്റിന്റെ അരികിൽ ഉയർന്ന് നിൽക്കുന്ന ശബ്ദ ബട്ടണിന്റെ അടുത്തുള്ള പരന്ന ബട്ടൺ ആണ് ഇത്.\n\nപവർ ബട്ടൺ അമർത്തുമ്പോൾ സ്ക്രീൻ ഓഫാകും."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"പവർ ബട്ടണിലാണ് ഫിംഗർപ്രിന്റ് സെൻസർ ഉള്ളത്. ഉപകരണത്തിന്റെ അരികിൽ ഉയർന്ന് നിൽക്കുന്ന ശബ്ദ ബട്ടണിന്റെ അടുത്തുള്ള പരന്ന ബട്ടൺ ആണ് ഇത്.\n\nപവർ ബട്ടൺ അമർത്തുമ്പോൾ സ്ക്രീൻ ഓഫാകും."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"പവർ ബട്ടണിലാണ് ഫിംഗർപ്രിന്റ് സെൻസർ ഉള്ളത്. ഫോണിന്റെ അരികിൽ ഉയർന്ന് നിൽക്കുന്ന ശബ്ദ ബട്ടണിന്റെ അടുത്തുള്ള പരന്ന ബട്ടൺ ആണ് ഇത്.\n\nപവർ ബട്ടൺ അമർത്തുമ്പോൾ സ്ക്രീൻ ഓഫാകും."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"കൂടുതൽ ഓപ്ഷനുകൾക്ക് നിങ്ങളുടെ ഫോൺ അൺലോക്ക് ചെയ്യുക"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"കൂടുതൽ ഓപ്ഷനുകൾക്ക് നിങ്ങളുടെ ടാബ്‌ലെറ്റ് അൺലോക്ക് ചെയ്യുക"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"കൂടുതൽ ഓപ്ഷനുകൾക്ക് നിങ്ങളുടെ ഉപകരണം അൺലോക്ക് ചെയ്യുക"</string>
diff --git a/packages/SystemUI/res-product/values-mn/strings.xml b/packages/SystemUI/res-product/values-mn/strings.xml
index 984337b..f0fce01 100644
--- a/packages/SystemUI/res-product/values-mn/strings.xml
+++ b/packages/SystemUI/res-product/values-mn/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Та утасны түгжээг тайлах оролдлогыг <xliff:g id="NUMBER">%d</xliff:g> удаа буруу хийсэн байна. Ажлын профайлыг устгах бөгөөд ингэснээр профайлын бүх өгөгдлийг устгах болно."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Та тайлах хээгээ <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу зурсан байна. Дахин <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа буруу зурсны дараа та имэйл бүртгэл ашиглан таблетынхаа түгжээг тайлах шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундийн дараа дахин оролдоно уу."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Та тайлах хээгээ <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу зурсан байна. Дахин <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа буруу зурсны дараа та имэйл бүртгэл ашиглан утасныхаа түгжээг тайлах шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундийн дараа дахин оролдоно уу."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Хурууны хээ мэдрэгч асаах/унтраах товчин дээр байдаг. Энэ нь таблетын ирмэг дээрх дууны түвшний товгор товчлуурын хажууд байх хавтгай товчлуур юм.\n\nАсаах/унтраах товчийг дарснаар дэлгэц унтарна."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Хурууны хээ мэдрэгч асаах/унтраах товчин дээр байдаг. Энэ нь төхөөрөмжийн ирмэг дээрх дууны түвшний товгор товчлуурын хажууд байх хавтгай товчлуур юм.\n\nАсаах/унтраах товчийг дарснаар дэлгэц унтарна."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Хурууны хээ мэдрэгч асаах/унтраах товчин дээр байдаг. Энэ нь утасны ирмэг дээрх дууны түвшний товгор товчлуурын хажууд байх хавтгай товчлуур юм.\n\nАсаах/унтраах товчийг дарснаар дэлгэц унтарна."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Бусад сонголтыг харахын тулд утасныхаа түгжээг тайлна уу"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Бусад сонголтыг харахын тулд таблетынхаа түгжээг тайлна уу"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Бусад сонголтыг харахын тулд төхөөрөмжийнхөө түгжээг тайлна уу"</string>
diff --git a/packages/SystemUI/res-product/values-mr/strings.xml b/packages/SystemUI/res-product/values-mr/strings.xml
index d8191a8..e76b185 100644
--- a/packages/SystemUI/res-product/values-mr/strings.xml
+++ b/packages/SystemUI/res-product/values-mr/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"तुम्ही फोन अनलॉक करण्याचा <xliff:g id="NUMBER">%d</xliff:g> वेळा चुकीच्या पद्धतीने प्रयत्न केला आहे. कार्य प्रोफाइल काढली जाईल, त्यामुळे सर्व प्रोफाइल डेटा हटवला जाईल."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"तुम्ही तुमचा अनलॉक पॅटर्न <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा चुकीच्या पद्धतीने काढला आहे. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, तुम्हाला ईमेल खाते वापरून तुमचा टॅबलेट अनलॉक करण्यास सांगितले जाईल.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"तुम्ही तुमचा अनलॉक पॅटर्न <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा चुकीच्या पद्धतीने काढला आहे. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, तुम्हाला ईमेल खाते वापरून तुमचा फोन अनलॉक करण्यास सांगितले जाईल.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"फिंगरप्रिंट सेन्सर हे पॉवर बटणावर आहे. हे टॅबलेटच्या कडेला वरती आलेल्या व्हॉल्यूम बटणाच्या बाजूला असलेले सपाट बटण आहे.\n\nपॉवर बटण प्रेस केल्याने स्क्रीन बंद होते."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"फिंगरप्रिंट सेन्सर हे पॉवर बटणावर आहे. हे डिव्हाइसच्या कडेला वरती आलेल्या व्हॉल्यूम बटणाच्या बाजूला असलेले सपाट बटण आहे.\n\nपॉवर बटण प्रेस केल्याने स्क्रीन बंद होते."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"फिंगरप्रिंट सेन्सर हे पॉवर बटणावर आहे. हे फोनच्या कडेला वरती आलेल्या व्हॉल्यूम बटणाच्या बाजूला असलेले सपाट बटण आहे.\n\nपॉवर बटण प्रेस केल्याने स्क्रीन बंद होते."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"आणखी पर्यायांसाठी तुमचा फोन अनलॉक करा"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"आणखी पर्यायांसाठी तुमचा टॅबलेट अनलॉक करा"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"आणखी पर्यायांसाठी तुमचे डिव्हाइस अनलॉक करा"</string>
diff --git a/packages/SystemUI/res-product/values-ms/strings.xml b/packages/SystemUI/res-product/values-ms/strings.xml
index 08aa4a8..1db5ded 100644
--- a/packages/SystemUI/res-product/values-ms/strings.xml
+++ b/packages/SystemUI/res-product/values-ms/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Anda telah salah membuka kunci telefon sebanyak <xliff:g id="NUMBER">%d</xliff:g> kali. Profil kerja ini akan dialih keluar sekali gus memadamkan semua data profil."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Anda telah tersilap lukis corak buka kunci sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi percubaan yang gagal, anda akan diminta membuka kunci tablet anda menggunakan akaun e-mel.\n\n Cuba lagi dalam <xliff:g id="NUMBER_2">%3$d</xliff:g> saat."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Anda telah tersilap lukis corak buka kunci sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi percubaan yang gagal, anda akan diminta membuka kunci telefon anda menggunakan akaun e-mel.\n\n Cuba lagi dalam <xliff:g id="NUMBER_2">%3$d</xliff:g> saat."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Penderia cap jari berada pada butang kuasa. Penderia cap jari ialah butang rata yang terletak bersebelahan butang kelantangan yang timbul pada bahagian tepi tablet.\n\nPenekanan butang kuasa akan mematikan skrin."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Penderia cap jari berada pada butang kuasa. Penderia cap jari ialah butang rata yang terletak bersebelahan butang kelantangan yang timbul pada bahagian tepi peranti.\n\nPenekanan butang kuasa akan mematikan skrin."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Penderia cap jari berada pada butang kuasa. Penderia cap jari ialah butang rata yang terletak bersebelahan butang kelantangan yang timbul pada bahagian tepi telefon.\n\nPenekanan butang kuasa akan mematikan skrin."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Buka kunci telefon anda untuk mendapatkan lagi pilihan"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Buka kunci tablet anda untuk mendapatkan lagi pilihan"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Buka kunci peranti anda untuk mendapatkan lagi pilihan"</string>
diff --git a/packages/SystemUI/res-product/values-my/strings.xml b/packages/SystemUI/res-product/values-my/strings.xml
index 6ca5e7f..7b56302 100644
--- a/packages/SystemUI/res-product/values-my/strings.xml
+++ b/packages/SystemUI/res-product/values-my/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ဖုန်းကို <xliff:g id="NUMBER">%d</xliff:g> ကြိမ် မှားယွင်းစွာ လော့ခ်ဖွင့်ရန် ကြိုးစားခဲ့ပါသည်။ အလုပ်ပရိုဖိုင်ကို ဖယ်ရှားလိုက်မည်ဖြစ်ပြီး ပရိုဖိုင်ဒေတာ အားလုံးကိုလည်း ဖျက်လိုက်ပါမည်။"</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"သင်သည် သင်၏ လော့ခ်ဖွင့်ခြင်းပုံစံကို <xliff:g id="NUMBER_0">%1$d</xliff:g> ကြိမ် မှားယွင်းစွာ ဆွဲခဲ့ပါသည်။ <xliff:g id="NUMBER_1">%2$d</xliff:g> ကြိမ် ထပ်မံမှားယွင်းပြီးသည့်နောက်တွင် သင့်အီးမေးလ်အကောင့်အား အသုံးပြု၍ တက်ဘလက်ကို လော့ခ်ဖွင့်ရန် တောင်းဆိုသွားပါမည်။\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> စက္ကန့်အကြာတွင် ထပ်စမ်းကြည့်ပါ။"</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"သင်သည် သင်၏ လော့ခ်ဖွင့်ခြင်းပုံစံကို <xliff:g id="NUMBER_0">%1$d</xliff:g> ကြိမ် မှားယွင်းစွာ ဆွဲခဲ့ပါသည်။ <xliff:g id="NUMBER_1">%2$d</xliff:g> ကြိမ် ထပ်မံမှားယွင်းပြီးသည့်နောက်တွင် သင့်အီးမေးလ်အကောင့်အား အသုံးပြု၍ ဖုန်းကို လော့ခ်ဖွင့်ရန် တောင်းဆိုသွားပါမည်။\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> စက္ကန့်အကြာတွင် ထပ်စမ်းကြည့်ပါ။"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"လက်ဗွေ အာရုံခံကိရိယာသည် ဖွင့်ပိတ်ခလုတ်ပေါ်တွင် ရှိသည်။ တက်ဘလက်ဘေးဘက်ရှိ မြင့်တက်နေသည့်အသံထိန်း ခလုတ်၏ ကပ်လျက်ရှိ ခလုတ်ပြားဖြစ်သည်။\n\nဖွင့်ပိတ်ခလုတ်ကိုနှိပ်ပါက ဖန်သားပြင်ပိတ်သွားမည်။"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"လက်ဗွေ အာရုံခံကိရိယာသည် ဖွင့်ပိတ်ခလုတ်ပေါ်တွင် ရှိသည်။ စက်ဘေးဘက်ရှိ မြင့်တက်နေသည့်အသံထိန်း ခလုတ်၏ ကပ်လျက်ရှိ ခလုတ်ပြားဖြစ်သည်။\n\nဖွင့်ပိတ်ခလုတ်ကိုနှိပ်ပါက ဖန်သားပြင်ပိတ်သွားမည်။"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"လက်ဗွေ အာရုံခံကိရိယာသည် ဖွင့်ပိတ်ခလုတ်ပေါ်တွင် ရှိသည်။ ဖုန်းဘေးဘက်ရှိ မြင့်တက်နေသည့်အသံထိန်း ခလုတ်၏ ကပ်လျက်ရှိ ခလုတ်ပြားဖြစ်သည်။\n\nဖွင့်ပိတ်ခလုတ်ကိုနှိပ်ပါက ဖန်သားပြင်ပိတ်သွားမည်။"</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"နောက်ထပ် ထိန်းချုပ်မှုများအတွက် သင့်ဖုန်းကို လော့ခ်ဖွင့်ပါ"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"နောက်ထပ် ထိန်းချုပ်မှုများအတွက် သင့်တက်ဘလက်ကို လော့ခ်ဖွင့်ပါ"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"နောက်ထပ် ထိန်းချုပ်မှုများအတွက် သင့်စက်ကို လော့ခ်ဖွင့်ပါ"</string>
diff --git a/packages/SystemUI/res-product/values-nb/strings.xml b/packages/SystemUI/res-product/values-nb/strings.xml
index 93f528e..621b393 100644
--- a/packages/SystemUI/res-product/values-nb/strings.xml
+++ b/packages/SystemUI/res-product/values-nb/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Du har gjort feil i forsøket på å låse opp telefonen <xliff:g id="NUMBER">%d</xliff:g> ganger. Jobbprofilen blir fjernet, og alle profildataene blir slettet."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Du har tegnet opplåsingsmønsteret feil <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. Etter ytterligere <xliff:g id="NUMBER_1">%2$d</xliff:g> nye mislykkede forsøk blir du bedt om å låse opp nettbrettet via en e-postkonto.\n\n Prøv på nytt om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Du har tegnet opplåsingsmønsteret feil <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. Etter ytterligere <xliff:g id="NUMBER_1">%2$d</xliff:g> nye mislykkede forsøk blir du bedt om å låse opp telefonen via en e-postkonto.\n\n Prøv på nytt om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Fingeravtrykkssensoren er på av/på-knappen. Det er den flate knappen ved siden av den opphøyde volumknappen på kanten av nettbrettet.\n\nHvis du trykker på av/på-knappen, slås skjermen av."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Fingeravtrykkssensoren er på av/på-knappen. Det er den flate knappen ved siden av den opphøyde volumknappen på kanten av enheten.\n\nHvis du trykker på av/på-knappen, slås skjermen av."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Fingeravtrykkssensoren er på av/på-knappen. Det er den flate knappen ved siden av den opphøyde volumknappen på kanten av telefonen.\n\nHvis du trykker på av/på-knappen, slås skjermen av."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Lås opp telefonen din for å få flere alternativer"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Lås opp nettbrettet ditt for å få flere alternativer"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Lås opp enheten din for å få flere alternativer"</string>
diff --git a/packages/SystemUI/res-product/values-ne/strings.xml b/packages/SystemUI/res-product/values-ne/strings.xml
index ffcbbf9..5a56c54 100644
--- a/packages/SystemUI/res-product/values-ne/strings.xml
+++ b/packages/SystemUI/res-product/values-ne/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"तपाईंले <xliff:g id="NUMBER">%d</xliff:g> पटक गलत तरिकाले फोन अनलक गर्ने प्रयास गर्नुभएको छ। कार्य प्रोफाइललाई यसका सबै डेटा मेटिने गरी हटाइने छ।"</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक आफ्नो अनलक गर्ने ढाँचा गलत रूपमा कोर्नुभयो। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> पटक असफल प्रयास गरेपछि, तपाईंलाई एउटा इमेल खाता प्रयोग गरेर आफ्नो ट्याब्लेट अनलक गर्न आग्रह गरिने छ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक आफ्नो अनलक गर्ने ढाँचा गलत रूपमा कोर्नुभयो। थप <xliff:g id="NUMBER_1">%2$d</xliff:g> पटक असफल प्रयास गरेपछि, तपाईंलाई एउटा इमेल खाता प्रयोग गरेर आफ्नो फोन अनलक गर्न आग्रह गरिने छ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"फिंगरप्रिन्ट सेन्सर पावर बटनमा छ। यो बटन ट्याब्लेटको किनारामा रहेको थोरै उचालिएको भोल्युम बटनको छेउमा रहेको समतल बटन हो।\n\nतपाईंले पावर बटन थिच्नुभयो भने स्क्रिन अफ हुन्छ।"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"फिंगरप्रिन्ट सेन्सर पावर बटनमा छ। यो बटन डिभाइसको किनारामा रहेको थोरै उचालिएको भोल्युम बटनको छेउमा रहेको समतल बटन हो।\n\nतपाईंले पावर बटन थिच्नुभयो भने स्क्रिन अफ हुन्छ।"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"फिंगरप्रिन्ट सेन्सर पावर बटनमा छ। यो बटन फोनको किनारामा रहेको थोरै उचालिएको भोल्युम बटनको छेउमा रहेको समतल बटन हो।\n\nतपाईंले पावर बटन थिच्नुभयो भने स्क्रिन अफ हुन्छ।"</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"थप विकल्पहरू हेर्न आफ्नो फोन अनलक गर्नुहोस्"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"थप विकल्पहरू हेर्न आफ्नो ट्याब्लेट अनलक गर्नुहोस्"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"थप विकल्पहरू हेर्न आफ्नो डिभाइस अनलक गर्नुहोस्"</string>
diff --git a/packages/SystemUI/res-product/values-nl/strings.xml b/packages/SystemUI/res-product/values-nl/strings.xml
index c7a46b0..b2343c3 100644
--- a/packages/SystemUI/res-product/values-nl/strings.xml
+++ b/packages/SystemUI/res-product/values-nl/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Je hebt <xliff:g id="NUMBER">%d</xliff:g> mislukte pogingen ondernomen om de telefoon te ontgrendelen. Het werkprofiel wordt verwijderd, waardoor alle profielgegevens worden verwijderd."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Je hebt je ontgrendelingspatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer onjuist getekend. Na nog eens <xliff:g id="NUMBER_1">%2$d</xliff:g> mislukte pogingen wordt je gevraagd je tablet te ontgrendelen via een e-mailaccount.\n\n Probeer het over <xliff:g id="NUMBER_2">%3$d</xliff:g> seconden opnieuw."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Je hebt je ontgrendelingspatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer onjuist getekend. Na nog eens <xliff:g id="NUMBER_1">%2$d</xliff:g> mislukte pogingen wordt je gevraagd je telefoon te ontgrendelen via een e-mailaccount.\n\n Probeer het over <xliff:g id="NUMBER_2">%3$d</xliff:g> seconden opnieuw."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Je vindt de vingerafdruksensor onder de aan/uit-knop. Het is de platte knop naast de verhoogde volumeknop aan de zijkant van de tablet.\n\nAls je op de aan/uit-knop drukt, gaat het scherm uit."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Je vindt de vingerafdruksensor onder de aan/uit-knop. Het is de platte knop naast de verhoogde volumeknop aan de zijkant van het apparaat.\n\nAls je op de aan/uit-knop drukt, gaat het scherm uit."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Je vindt de vingerafdruksensor onder de aan/uit-knop. Het is de platte knop naast de verhoogde volumeknop aan de zijkant van de telefoon.\n\nAls je op de aan/uit-knop drukt, gaat het scherm uit."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Ontgrendel je telefoon voor meer opties"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Ontgrendel je tablet voor meer opties"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Ontgrendel je apparaat voor meer opties"</string>
diff --git a/packages/SystemUI/res-product/values-or/strings.xml b/packages/SystemUI/res-product/values-or/strings.xml
index 8e3f2ed..85efb09 100644
--- a/packages/SystemUI/res-product/values-or/strings.xml
+++ b/packages/SystemUI/res-product/values-or/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ଆପଣ ଫୋନ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବାକୁ<xliff:g id="NUMBER">%d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। କାର୍ଯ୍ୟ ପ୍ରୋଫାଇଲ୍ ବାହାର କରିଦିଆଯିବ, ଯାହା ଫଳରେ ସମସ୍ତ ପ୍ରୋଫାଇଲ୍ ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"ଆପଣ ଆପଣଙ୍କ ଅନ୍‌ଲକ୍ ପାଟର୍ନକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ଭାବେ ଡ୍ର କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ ପ୍ରୟାସ ପରେ ଆପଣଙ୍କୁ ଏକ ଇମେଲ୍ ଆକାଉଣ୍ଟ ବ୍ୟବହାର କରି ଆପଣଙ୍କ ଟାବ୍‌ଲୋଟ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବା ପାଇଁ କୁହାଯିବ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"ଆପଣ ଆପଣଙ୍କ ଅନ୍‌ଲକ୍ ପାଟର୍ନକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ଭାବେ ଡ୍ର କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ ପ୍ରୟାସ ପରେ ଆପଣଙ୍କୁ ଏକ ଇମେଲ୍ ଆକାଉଣ୍ଟ ବ୍ୟବହାର କରି ଆପଣଙ୍କ ଫୋନ୍‌କୁ ଅନ୍‌ଲକ୍‌ କରିବା ପାଇଁ କୁହାଯିବ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"ଟିପଚିହ୍ନ ସେନ୍ସର ପାୱାର ବଟନରେ ଅଛି। ଟାବଲେଟର ଧାରରେ ଥିବା ବଢ଼ାଯାଇଥିବା ଭଲ୍ୟୁମ ବଟନ ପାଖରେ ଏହା ଫ୍ଲାଟ ବଟନ ଅଟେ।\n\nପାୱାର ବଟନକୁ ଦବାଇବା ଦ୍ୱାରା ସ୍କ୍ରିନ ବନ୍ଦ ହୋଇଥାଏ।"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"ଟିପଚିହ୍ନ ସେନ୍ସର ପାୱାର ବଟନରେ ଅଛି। ଡିଭାଇସର ଧାରରେ ଥିବା ବଢ଼ାଯାଇଥିବା ଭଲ୍ୟୁମ ବଟନ ପାଖରେ ଏହା ଫ୍ଲାଟ ବଟନ ଅଟେ।\n\nପାୱାର ବଟନକୁ ଦବାଇବା ଦ୍ୱାରା ସ୍କ୍ରିନ ବନ୍ଦ ହୋଇଥାଏ।"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"ଟିପଚିହ୍ନ ସେନ୍ସର ପାୱାର ବଟନରେ ଅଛି। ଫୋନର ଧାରରେ ଥିବା ବଢ଼ାଯାଇଥିବା ଭଲ୍ୟୁମ ବଟନ ପାଖରେ ଏହା ଫ୍ଲାଟ ବଟନ ଅଟେ।\n\nପାୱାର ବଟନକୁ ଦବାଇବା ଦ୍ୱାରା ସ୍କ୍ରିନ ବନ୍ଦ ହୋଇଥାଏ।"</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"ଅଧିକ ବିକଳ୍ପ ପାଇଁ ଆପଣଙ୍କ ଫୋନ୍ ଅନଲକ୍ କରନ୍ତୁ"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"ଅଧିକ ବିକଳ୍ପ ପାଇଁ ଆପଣଙ୍କ ଟାବଲେଟ୍ ଅନଲକ୍ କରନ୍ତୁ"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"ଅଧିକ ବିକଳ୍ପ ପାଇଁ ଆପଣଙ୍କ ଡିଭାଇସ୍ ଅନଲକ୍ କରନ୍ତୁ"</string>
diff --git a/packages/SystemUI/res-product/values-pa/strings.xml b/packages/SystemUI/res-product/values-pa/strings.xml
index bc1c60f..149e58f 100644
--- a/packages/SystemUI/res-product/values-pa/strings.xml
+++ b/packages/SystemUI/res-product/values-pa/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਪ੍ਰੋਫਾਈਲ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਉਲੀਕਿਆ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਇੱਕ ਈਮੇਲ ਖਾਤਾ ਵਰਤਦੇ ਹੋਏ ਆਪਣੇ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਵੇਗਾ।\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਡ੍ਰਾ ਕੀਤਾ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਇੱਕ ਈਮੇਲ ਖਾਤਾ ਵਰਤਦੇ ਹੋਏ ਆਪਣਾ ਫ਼ੋਨ ਅਣਲਾਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਏਗਾ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਪਾਵਰ ਬਟਨ \'ਤੇ ਹੈ। ਇਹ ਟੈਬਲੈੱਟ ਦੇ ਕਿਨਾਰੇ \'ਤੇ ਅਜਿਹਾ ਸਮਤਲ ਬਟਨ ਹੁੰਦਾ ਹੈ ਜੋ ਉੱਭਰੇ ਹੋਏ ਅਵਾਜ਼ ਬਟਨ ਦੇ ਅੱਗੇ ਹੁੰਦਾ ਹੈ।\n\nਪਾਵਰ ਬਟਨ ਦਬਾਉਣ ਨਾਲ ਸਕ੍ਰੀਨ ਬੰਦ ਹੋ ਜਾਂਦੀ ਹੈ।"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਪਾਵਰ ਬਟਨ \'ਤੇ ਹੈ। ਇਹ ਡੀਵਾਈਸ ਦੇ ਕਿਨਾਰੇ \'ਤੇ ਅਜਿਹਾ ਸਮਤਲ ਬਟਨ ਹੁੰਦਾ ਹੈ ਜੋ ਉੱਭਰੇ ਹੋਏ ਅਵਾਜ਼ ਬਟਨ ਦੇ ਅੱਗੇ ਹੁੰਦਾ ਹੈ।\n\nਪਾਵਰ ਬਟਨ ਦਬਾਉਣ ਨਾਲ ਸਕ੍ਰੀਨ ਬੰਦ ਹੋ ਜਾਂਦੀ ਹੈ।"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਪਾਵਰ ਬਟਨ \'ਤੇ ਹੈ। ਇਹ ਫ਼ੋਨ ਦੇ ਕਿਨਾਰੇ \'ਤੇ ਅਜਿਹਾ ਸਮਤਲ ਬਟਨ ਹੁੰਦਾ ਹੈ ਜੋ ਉੱਭਰੇ ਹੋਏ ਅਵਾਜ਼ ਬਟਨ ਦੇ ਅੱਗੇ ਹੁੰਦਾ ਹੈ।\n\nਪਾਵਰ ਬਟਨ ਦਬਾਉਣ ਨਾਲ ਸਕ੍ਰੀਨ ਬੰਦ ਹੋ ਜਾਂਦੀ ਹੈ।"</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"ਹੋਰ ਵਿਕਲਪਾਂ ਲਈ ਆਪਣਾ ਫ਼ੋਨ ਅਣਲਾਕ ਕਰੋ"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"ਹੋਰ ਵਿਕਲਪਾਂ ਲਈ ਆਪਣਾ ਟੈਬਲੈੱਟ ਅਣਲਾਕ ਕਰੋ"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"ਹੋਰ ਵਿਕਲਪਾਂ ਲਈ ਆਪਣਾ ਡੀਵਾਈਸ ਅਣਲਾਕ ਕਰੋ"</string>
diff --git a/packages/SystemUI/res-product/values-pl/strings.xml b/packages/SystemUI/res-product/values-pl/strings.xml
index a8596a6..dcd2736 100644
--- a/packages/SystemUI/res-product/values-pl/strings.xml
+++ b/packages/SystemUI/res-product/values-pl/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Po raz <xliff:g id="NUMBER">%d</xliff:g> próbowano nieprawidłowo odblokować telefon. Profil służbowy zostanie usunięty, co spowoduje skasowanie wszystkich jego danych."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> nieprawidłowo narysowano wzór odblokowania. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach konieczne będzie odblokowanie tabletu przy użyciu konta e-mail.\n\n Spróbuj ponownie za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> nieprawidłowo narysowano wzór odblokowania. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach konieczne będzie odblokowanie telefonu przy użyciu konta e-mail.\n\n Spróbuj ponownie za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Czytnik linii papilarnych znajduje się na przycisku zasilania. To płaski przycisk przy uniesionym przycisku głośności na krawędzi tabletu.\n\nNaciśnięcie przycisku zasilania wyłącza ekran."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Czytnik linii papilarnych znajduje się na przycisku zasilania. To płaski przycisk przy uniesionym przycisku głośności na krawędzi urządzenia.\n\nNaciśnięcie przycisku zasilania wyłącza ekran."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Czytnik linii papilarnych znajduje się na przycisku zasilania. To płaski przycisk przy uniesionym przycisku głośności na krawędzi telefonu.\n\nNaciśnięcie przycisku zasilania wyłącza ekran."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Odblokuj telefon, by wyświetlić więcej opcji"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Odblokuj tablet, by wyświetlić więcej opcji"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Odblokuj urządzenie, by wyświetlić więcej opcji"</string>
diff --git a/packages/SystemUI/res-product/values-pt-rBR/strings.xml b/packages/SystemUI/res-product/values-pt-rBR/strings.xml
index bccf53d..3190721 100644
--- a/packages/SystemUI/res-product/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res-product/values-pt-rBR/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. O perfil de trabalho será removido, o que excluirá todos os dados do perfil."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Você desenhou seu padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use uma conta de e-mail para desbloquear o tablet.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Você desenhou seu padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use uma conta de e-mail para desbloquear o smartphone.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"O sensor de impressão digital fica no botão liga/desliga. Ele é plano e está ao lado do botão de volume na borda do tablet.\n\nAo pressionar o botão liga/desliga, a tela é desativada."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"O sensor de impressão digital fica no botão liga/desliga. Ele é plano e está ao lado do botão de volume na borda do dispositivo.\n\nAo pressionar o botão liga/desliga, a tela é desativada."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"O sensor de impressão digital fica no botão liga/desliga. Ele é plano e está ao lado do botão de volume na borda do smartphone.\n\nAo pressionar o botão liga/desliga, a tela é desativada."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Desbloqueie seu smartphone para ver mais opções"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Desbloqueie seu tablet para ver mais opções"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desbloqueie seu dispositivo para ver mais opções"</string>
diff --git a/packages/SystemUI/res-product/values-pt-rPT/strings.xml b/packages/SystemUI/res-product/values-pt-rPT/strings.xml
index d941c80..a801da1 100644
--- a/packages/SystemUI/res-product/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res-product/values-pt-rPT/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Tentou desbloquear incorretamente o telemóvel <xliff:g id="NUMBER">%d</xliff:g> vezes. O perfil de trabalho será removido, o que eliminará todos os dados do mesmo."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Desenhou o padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Após mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas sem êxito, ser-lhe-á pedido para desbloquear o tablet através de uma conta de email.\n\n Tente novamente dentro de <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Desenhou o padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Após mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas sem êxito, ser-lhe-á pedido para desbloquear o telemóvel através de uma conta de email.\n\n Tente novamente dentro de <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"O sensor de impressões digitais encontra-se no botão ligar/desligar. É o botão plano junto ao botão de volume com relevo na extremidade do tablet.\n\nPremir o botão ligar/desligar desativa o ecrã."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"O sensor de impressões digitais encontra-se no botão ligar/desligar. É o botão plano junto ao botão de volume com relevo na extremidade do dispositivo.\n\nPremir o botão ligar/desligar desativa o ecrã."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"O sensor de impressões digitais encontra-se no botão ligar/desligar. É o botão plano junto ao botão de volume com relevo na extremidade do telemóvel.\n\nPremir o botão ligar/desligar desativa o ecrã."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Desbloqueie o telemóvel para obter mais opções."</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Desbloqueie o tablet para obter mais opções."</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desbloqueie o dispositivo para obter mais opções."</string>
diff --git a/packages/SystemUI/res-product/values-pt/strings.xml b/packages/SystemUI/res-product/values-pt/strings.xml
index bccf53d..3190721 100644
--- a/packages/SystemUI/res-product/values-pt/strings.xml
+++ b/packages/SystemUI/res-product/values-pt/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Você tentou desbloquear o smartphone incorretamente <xliff:g id="NUMBER">%d</xliff:g> vezes. O perfil de trabalho será removido, o que excluirá todos os dados do perfil."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Você desenhou seu padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use uma conta de e-mail para desbloquear o tablet.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Você desenhou seu padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use uma conta de e-mail para desbloquear o smartphone.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"O sensor de impressão digital fica no botão liga/desliga. Ele é plano e está ao lado do botão de volume na borda do tablet.\n\nAo pressionar o botão liga/desliga, a tela é desativada."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"O sensor de impressão digital fica no botão liga/desliga. Ele é plano e está ao lado do botão de volume na borda do dispositivo.\n\nAo pressionar o botão liga/desliga, a tela é desativada."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"O sensor de impressão digital fica no botão liga/desliga. Ele é plano e está ao lado do botão de volume na borda do smartphone.\n\nAo pressionar o botão liga/desliga, a tela é desativada."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Desbloqueie seu smartphone para ver mais opções"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Desbloqueie seu tablet para ver mais opções"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desbloqueie seu dispositivo para ver mais opções"</string>
diff --git a/packages/SystemUI/res-product/values-ro/strings.xml b/packages/SystemUI/res-product/values-ro/strings.xml
index 722ef90..101ebe7f 100644
--- a/packages/SystemUI/res-product/values-ro/strings.xml
+++ b/packages/SystemUI/res-product/values-ro/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Ai făcut <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a telefonului. Profilul de serviciu va fi eliminat, iar toate datele profilului vor fi șterse."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Ai desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, ți se va solicita să deblochezi tableta cu ajutorul unui cont de e-mail.\n\n Încearcă din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> secunde."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Ai desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, ți se va solicita să deblochezi telefonul cu ajutorul unui cont de e-mail.\n\n Încearcă din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> secunde."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Senzorul de amprentă se află pe butonul de pornire. Este butonul plat de lângă butonul de volum în relief de pe marginea tabletei.\n\nDacă apeși butonul de pornire, ecranul se va dezactiva."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Senzorul de amprentă se află pe butonul de pornire. Este butonul plat de lângă butonul de volum în relief de pe marginea dispozitivului.\n\nDacă apeși butonul de pornire, ecranul se va dezactiva."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Senzorul de amprentă se află pe butonul de pornire. Este butonul plat de lângă butonul de volum în relief de pe marginea telefonului.\n\nDacă apeși butonul de pornire, ecranul se va dezactiva."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Deblochează telefonul pentru mai multe opțiuni"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Deblochează tableta pentru mai multe opțiuni"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Deblochează dispozitivul pentru mai multe opțiuni"</string>
diff --git a/packages/SystemUI/res-product/values-ru/strings.xml b/packages/SystemUI/res-product/values-ru/strings.xml
index 6266caa..32e18c4 100644
--- a/packages/SystemUI/res-product/values-ru/strings.xml
+++ b/packages/SystemUI/res-product/values-ru/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Вы несколько раз (<xliff:g id="NUMBER">%d</xliff:g>) не смогли разблокировать телефон. Рабочий профиль и все его данные будут удалены."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Вы несколько раз (<xliff:g id="NUMBER_0">%1$d</xliff:g>) ввели неверный графический ключ. Осталось попыток: <xliff:g id="NUMBER_1">%2$d</xliff:g>. В случае неудачи вам будет предложено разблокировать планшет с помощью аккаунта электронной почты.\n\nПовторите попытку через <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Вы несколько раз (<xliff:g id="NUMBER_0">%1$d</xliff:g>) ввели неверный графический ключ. Осталось попыток: <xliff:g id="NUMBER_1">%2$d</xliff:g>. В случае неудачи вам будет предложено разблокировать телефон с помощью аккаунта электронной почты.\n\nПовторите попытку через <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Сканер отпечатков пальцев находится на кнопке питания. Это плоская кнопка рядом с приподнятой кнопкой регулировки громкости на боковой стороне устройства.\n\nНажав кнопку питания, вы выключите экран."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Сканер отпечатков пальцев находится на кнопке питания. Это плоская кнопка рядом с приподнятой кнопкой регулировки громкости на боковой стороне устройства.\n\nНажав кнопку питания, вы выключите экран."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Сканер отпечатков пальцев находится на кнопке питания. Это плоская кнопка рядом с приподнятой кнопкой регулировки громкости на боковой стороне устройства.\n\nНажав кнопку питания, вы выключите экран."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Чтобы посмотреть дополнительные параметры, разблокируйте телефон."</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Чтобы посмотреть дополнительные параметры, разблокируйте планшет."</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Чтобы посмотреть дополнительные параметры, разблокируйте устройство."</string>
diff --git a/packages/SystemUI/res-product/values-si/strings.xml b/packages/SystemUI/res-product/values-si/strings.xml
index 36cae4f..bbd7aa5 100644
--- a/packages/SystemUI/res-product/values-si/strings.xml
+++ b/packages/SystemUI/res-product/values-si/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"ඔබ දුරකථනය අගුළු හැරීමට <xliff:g id="NUMBER">%d</xliff:g> වරක් වැරදියට උත්සාහ කර ඇත. කාර්යාල පැතිකඩ ඉවත් කරනු ඇති අතර, එය සියලු පැතිකඩ දත්ත මකනු ඇත."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"ඔබ අගුළු ඇරිමේ රටාව <xliff:g id="NUMBER_0">%1$d</xliff:g> වතාවක් වැරදියට ඇඳ ඇත. තවත් අසාර්ථක උත්සාහ <xliff:g id="NUMBER_1">%2$d</xliff:g> කින් පසුව, ඊ-තැපැල් ගිණුම භාවිතා කරමින් ඔබගේ ටැබ්ලටයේ අගුළු ඇරීමට ඔබට පවසනු ඇත.\n\n නැවත තත්පර <xliff:g id="NUMBER_2">%3$d</xliff:g> කින් උත්සාහ කරන්න."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"ඔබ වැරදියට <xliff:g id="NUMBER_0">%1$d</xliff:g> වතාවක් ඔබගේ අගුළු හැරීමේ රටාව ඇඳ ඇත. අසාර්ථක උත්සහ කිරීම් <xliff:g id="NUMBER_1">%2$d</xliff:g> න් පසුව, ඔබගේ ඊ-තැපැල් ලිපිනය භාවිතයෙන් ඔබගේ දුරකථනය අගුළු හැරීමට ඔබගෙන් අසයි.\n\n තත්පර <xliff:g id="NUMBER_2">%3$d</xliff:g> න් පසුව නැවත උත්සහ කරන්න."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"ඇඟිලි සලකුණු සංවේදකය බල බොත්තම මත ඇත. එය ටැබ්ලටයෙහි කෙළවරේ ඇති ඉහළ හඬ පරිමා බොත්තම අසල ඇති පැතලි බොත්තමයි.\n\nබල බොත්තම එබීම තිරය ක්‍රියා විරහිත කරයි."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"ඇඟිලි සලකුණු සංවේදකය බල බොත්තම මත ඇත. එය උපාංගයෙහි කෙළවරේ ඇති ඉහළ හඬ පරිමා බොත්තම අසල ඇති පැතලි බොත්තමයි.\n\nබල බොත්තම එබීම තිරය ක්‍රියා විරහිත කරයි."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"ඇඟිලි සලකුණු සංවේදකය බල බොත්තම මත ඇත. එය දුරකථනයෙහි කෙළවරේ ඇති ඉහළ හඬ පරිමා බොත්තම අසල ඇති පැතලි බොත්තමයි.\n\nබල බොත්තම එබීම තිරය ක්‍රියා විරහිත කරයි."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"තව විකල්ප සඳහා ඔබේ දුරකථනය අගුලු හරින්න"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"තව විකල්ප සඳහා ඔබේ ටැබ්ලට් පරිගණකය අගුලු හරින්න"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"තව විකල්ප සඳහා ඔබේ උපාංගය අගුලු හරින්න"</string>
diff --git a/packages/SystemUI/res-product/values-sk/strings.xml b/packages/SystemUI/res-product/values-sk/strings.xml
index d07afbd..4a142081 100644
--- a/packages/SystemUI/res-product/values-sk/strings.xml
+++ b/packages/SystemUI/res-product/values-sk/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Telefón ste sa pokúsili <xliff:g id="NUMBER">%d</xliff:g>‑krát nesprávne odomknúť. Pracovný profil bude odstránený spolu so všetkými údajmi."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"<xliff:g id="NUMBER_0">%1$d</xliff:g>‑krát ste nesprávne nakreslili svoj bezpečnostný vzor. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> ďalších neúspešných pokusoch sa zobrazí výzva na odomknutie tabletu pomocou e‑mailového účtu.\n\n Skúste to znova o <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Už ste <xliff:g id="NUMBER_0">%1$d</xliff:g>‑krát nesprávne nakreslili svoj bezpečnostný vzor. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> ďalších neúspešných pokusoch sa zobrazí výzva na odomknutie telefónu pomocou e‑mailového účtu.\n\n Skúste to znova o <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Senzor odtlačkov prstov je na vypínači. Ide o ploché tlačidlo vedľa vypuklého tlačidla hlasitosti na okraji tabletu.\n\nStlačením vypínača vypnete obrazovku."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Senzor odtlačkov prstov je na vypínači. Ide o ploché tlačidlo vedľa vypuklého tlačidla hlasitosti na okraji zariadenia.\n\nStlačením vypínača vypnete obrazovku."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Senzor odtlačkov prstov je na vypínači. Ide o ploché tlačidlo vedľa vypuklého tlačidla hlasitosti na okraji telefónu.\n\nStlačením vypínača vypnete obrazovku."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Ak chcete zobraziť ďalšie možnosti, odomknite telefón"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Ak chcete zobraziť ďalšie možnosti, odomknite tablet"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Ak chcete zobraziť ďalšie možnosti, odomknite zariadenie"</string>
diff --git a/packages/SystemUI/res-product/values-sl/strings.xml b/packages/SystemUI/res-product/values-sl/strings.xml
index fc9886c..8119335 100644
--- a/packages/SystemUI/res-product/values-sl/strings.xml
+++ b/packages/SystemUI/res-product/values-sl/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Telefon ste neuspešno poskusili odkleniti <xliff:g id="NUMBER">%d</xliff:g>-krat. Delovni profil bo odstranjen in vsi podatki profila bodo izbrisani."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Vzorec za odklepanje ste <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat napačno vnesli. Če ga neuspešno poskusite vnesti še <xliff:g id="NUMBER_1">%2$d</xliff:g>-krat, boste pozvani, da tablični računalnik odklenete z e-poštnim računom.\n\nPoskusite znova čez <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Vzorec za odklepanje ste <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat napačno vnesli. Če ga neuspešno poskusite vnesti še <xliff:g id="NUMBER_1">%2$d</xliff:g>-krat, boste pozvani, da telefon odklenete z e-poštnim računom.\n\nPoskusite znova čez <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Tipalo prstnih odtisov je na gumbu za vklop. To je ploski gumb ob izbočenem gumbu za glasnost na robu tabličnega računalnika.\n\nČe pritisnete gumb za vklop, se zaslon izklopi."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Tipalo prstnih odtisov je na gumbu za vklop. To je ploski gumb ob izbočenem gumbu za glasnost na robu naprave.\n\nČe pritisnete gumb za vklop, se zaslon izklopi."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Tipalo prstnih odtisov je na gumbu za vklop. To je ploski gumb ob izbočenem gumbu za glasnost na robu telefona.\n\nČe pritisnete gumb za vklop, se zaslon izklopi."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Za več možnosti odklenite telefon"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Za več možnosti odklenite tablični računalnik"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Za več možnosti odklenite napravo"</string>
diff --git a/packages/SystemUI/res-product/values-sq/strings.xml b/packages/SystemUI/res-product/values-sq/strings.xml
index 774099b..0b7b77d 100644
--- a/packages/SystemUI/res-product/values-sq/strings.xml
+++ b/packages/SystemUI/res-product/values-sq/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Ke tentuar <xliff:g id="NUMBER">%d</xliff:g> herë pa sukses për ta shkyçur telefonin. Profili i punës do të hiqet, gjë që do të fshijë të gjitha të dhënat e profilit."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Ke vizatuar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë pa sukses motivin tënd të shkyçjes. Pas <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativave të tjera të pasuksesshme, do të të duhet ta shkyçësh tabletin duke përdorur një llogari email-i.\n\n Provo sërish për <xliff:g id="NUMBER_2">%3$d</xliff:g> sekonda."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Ke vizatuar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë pa sukses motivin tënd. Pas <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativave të tjera të pasuksesshme, do të të duhet ta shkyçësh telefonin duke përdorur një llogari email-i.\n\n Provo sërish për <xliff:g id="NUMBER_2">%3$d</xliff:g> sekonda."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Sensori i gjurmës së gishtit është në butonin e energjisë. Ai është butoni i rrafshët pranë butonit të ngritur të volumit në anë të tabletit.\n\nShtypja e butonit të energjisë e fik ekranin."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Sensori i gjurmës së gishtit është në butonin e energjisë. Ai është butoni i rrafshët pranë butonit të ngritur të volumit në anë të pajisjes.\n\nShtypja e butonit të energjisë e fik ekranin."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Sensori i gjurmës së gishtit është në butonin e energjisë. Ai është butoni i rrafshët pranë butonit të ngritur të volumit në anë të telefonit.\n\nShtypja e butonit të energjisë e fik ekranin."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Shkyçe telefonin për më shumë opsione"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Shkyçe tabletin për më shumë opsione"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Shkyçe pajisjen për më shumë opsione"</string>
diff --git a/packages/SystemUI/res-product/values-sr/strings.xml b/packages/SystemUI/res-product/values-sr/strings.xml
index 0c9bb75..00269da 100644
--- a/packages/SystemUI/res-product/values-sr/strings.xml
+++ b/packages/SystemUI/res-product/values-sr/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Погрешно сте покушали да откључате телефон <xliff:g id="NUMBER">%d</xliff:g> пута. Уклонићемо пословни профил, чиме се бришу сви подаци са профила."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Нетачно сте нацртали шаблон за откључавање <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. Ако погрешно покушате још <xliff:g id="NUMBER_1">%2$d</xliff:g> пута, затражићемо да откључате таблет помоћу имејл налога.\n\n Пробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Нетачно сте нацртали шаблон за откључавање <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. Ако погрешно покушате још <xliff:g id="NUMBER_1">%2$d</xliff:g> пута, затражићемо да откључате телефон помоћу имејл налога.\n\n Пробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Сензор за отисак прста се налази на дугмету за укључивање. То је равно дугме поред издигнутог дугмета за јачину звука на ивици таблета.\n\nПритиском на дугме за укључивање искључује се екран."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Сензор за отисак прста се налази на дугмету за укључивање. То је равно дугме поред издигнутог дугмета за јачину звука на ивици уређаја.\n\nПритиском на дугме за укључивање искључује се екран."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Сензор за отисак прста се налази на дугмету за укључивање. То је равно дугме поред издигнутог дугмета за јачину звука на ивици телефона.\n\nПритиском на дугме за укључивање искључује се екран."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Откључајте телефон за још опција"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Откључајте таблет за још опција"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Откључајте уређај за још опција"</string>
diff --git a/packages/SystemUI/res-product/values-sv/strings.xml b/packages/SystemUI/res-product/values-sv/strings.xml
index 7d83808..c0c1a10 100644
--- a/packages/SystemUI/res-product/values-sv/strings.xml
+++ b/packages/SystemUI/res-product/values-sv/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Du har försökt låsa upp telefonen på ett felaktigt sätt <xliff:g id="NUMBER">%d</xliff:g> gånger. Jobbprofilen tas bort och all profildata raderas."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Du har ritat ditt grafiska lösenord fel <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%2$d</xliff:g> försök måste du låsa upp surfplattan med hjälp av ett e-postkonto.\n\n Försök igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Du har ritat ditt grafiska lösenord fel <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%2$d</xliff:g> försök måste du låsa upp telefonen med hjälp av ett e-postkonto.\n\n Försök igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Fingeravtryckssensorn sitter på av/på-knappen. Det är den platta knappen bredvid den upphöjda volymknappen på kanten av surfplattan.\n\nOm du trycker på av/på-knappen stängs skärmen av."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Fingeravtryckssensorn sitter på av/på-knappen. Det är den platta knappen bredvid den upphöjda volymknappen på kanten av enheten.\n\nOm du trycker på av/på-knappen stängs skärmen av."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Fingeravtryckssensorn sitter på av/på-knappen. Det är den platta knappen bredvid den upphöjda volymknappen på kanten av telefonen.\n\nOm du trycker på av/på-knappen stängs skärmen av."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Lås upp telefonen för fler alternativ"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Lås upp surfplattan för fler alternativ"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Lås upp enheten för fler alternativ"</string>
diff --git a/packages/SystemUI/res-product/values-sw/strings.xml b/packages/SystemUI/res-product/values-sw/strings.xml
index 2def779..8edbede 100644
--- a/packages/SystemUI/res-product/values-sw/strings.xml
+++ b/packages/SystemUI/res-product/values-sw/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Umejaribu kufungua simu mara <xliff:g id="NUMBER">%d</xliff:g> bila mafanikio. Wasifu wa kazini utaondolewa, hatua itakayofuta data yote ya wasifu."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Umeweka mchoro usio sahihi wa kufungua skrini mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Baada ya majaribio <xliff:g id="NUMBER_1">%2$d</xliff:g> zaidi bila mafanikio, utaombwa ufungue kompyuta yako kibao kwa kutumia akaunti ya barua pepe.\n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_2">%3$d</xliff:g>."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Umeweka mchoro usio sahihi wa kufungua skrini mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Ukikosea mara nyingine <xliff:g id="NUMBER_1">%2$d</xliff:g>, utaombwa ufungue simu yako kwa kutumia akaunti ya barua pepe.\n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_2">%3$d</xliff:g>."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Kitambuzi cha alama ya kidole kinapatikana kwenye kitufe cha kuwasha/kuzima. Ni kitufe bapa pembeni pa kitufe cha sauti kilichoinuka kwenye ukingo wa kompyuta kibao.\n\nUkibonyeza kitufe cha kuwasha/kuzima skrini itazima."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Kitambuzi cha alama ya kidole kinapatikana kwenye kitufe cha kuwasha/kuzima. Ni kitufe bapa pembeni pa kitufe cha sauti kilichoinuka kwenye ukingo wa kifaa.\n\nUkibonyeza kitufe cha kuwasha/kuzima skrini itazima."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Kitambuzi cha alama ya kidole kinapatikana kwenye kitufe cha kuwasha/kuzima. Ni kitufe bapa pembeni pa kitufe cha sauti kilichoinuka kwenye ukingo wa simu.\n\nUkibonyeza kitufe cha kuwasha/kuzima skrini itazima."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Fungua simu yako ili upate chaguo zaidi"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Fungua kompyuta yako kibao ili upate chaguo zaidi"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Fungua kifaa chako ili upate chaguo zaidi"</string>
diff --git a/packages/SystemUI/res-product/values-ta/strings.xml b/packages/SystemUI/res-product/values-ta/strings.xml
index 3e31913..84c9f4d 100644
--- a/packages/SystemUI/res-product/values-ta/strings.xml
+++ b/packages/SystemUI/res-product/values-ta/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"மொபைலை அன்லாக் செய்ய, <xliff:g id="NUMBER">%d</xliff:g> முறை தவறாக முயன்றுவிட்டதனால் பணிக் கணக்கு அகற்றப்படும். இதனால் அதிலுள்ள அனைத்துச் சுயவிவரத் தரவும் நீக்கப்படும்."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"அன்லாக் பேட்டர்னை, <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக வரைந்துவிட்டீர்கள். இன்னும் <xliff:g id="NUMBER_1">%2$d</xliff:g> முறை தவறாக வரைந்தால், மின்னஞ்சல் கணக்கைப் பயன்படுத்தி டேப்லெட்டை அன்லாக் செய்யும்படி கேட்கப்படுவீர்கள்.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> வினாடிகளில் மீண்டும் முயலவும்."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"அன்லாக் பேட்டர்னை, <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக வரைந்துவிட்டீர்கள். இன்னும் <xliff:g id="NUMBER_1">%2$d</xliff:g> முறை தவறாக வரைந்தால், மின்னஞ்சல் கணக்கைப் பயன்படுத்தி மொபைலை அன்லாக் செய்யும்படி கேட்கப்படுவீர்கள்.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> வினாடிகளில் மீண்டும் முயலவும்."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"\'கைரேகை சென்சார்\' பவர் பட்டனில் உள்ளது. இது டேப்லெட்டின் விளிம்பில் சற்று மேலெழும்பிய ஒலியளவு பட்டனுக்கு அருகில் இருக்கும் தட்டையான பட்டனாகும்.\n\nபவர் பட்டனை அழுத்தினால் திரை ஆஃப் ஆகும்."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"\'கைரேகை சென்சார்\' பவர் பட்டனில் உள்ளது. இது சாதனத்தின் விளிம்பில் சற்று மேலெழும்பிய ஒலியளவு பட்டனுக்கு அருகில் இருக்கும் தட்டையான பட்டனாகும்.\n\nபவர் பட்டனை அழுத்தினால் திரை ஆஃப் ஆகும்."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"\'கைரேகை சென்சார்\' பவர் பட்டனில் உள்ளது. இது மொபைலின் விளிம்பில் சற்று மேலெழும்பிய ஒலியளவு பட்டனுக்கு அருகில் இருக்கும் தட்டையான பட்டனாகும்.\n\nபவர் பட்டனை அழுத்தினால் திரை ஆஃப் ஆகும்."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"மேலும் விருப்பங்களுக்கு மொபைலை அன்லாக் செய்யவும்"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"மேலும் விருப்பங்களுக்கு டேப்லெட்டை அன்லாக் செய்யவும்"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"மேலும் விருப்பங்களுக்குச் சாதனத்தை அன்லாக் செய்யவும்"</string>
diff --git a/packages/SystemUI/res-product/values-te/strings.xml b/packages/SystemUI/res-product/values-te/strings.xml
index 0e1ccdd..1f66c50 100644
--- a/packages/SystemUI/res-product/values-te/strings.xml
+++ b/packages/SystemUI/res-product/values-te/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"మీరు ఫోన్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> సార్లు తప్పు ప్రయత్నాలు చేశారు. కార్యాలయ ప్రొఫైల్ తీసివేయబడుతుంది, దీని వలన ప్రొఫైల్ డేటా మొత్తం తొలగించబడుతుంది."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"మీరు మీ అన్‌లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> ప్రయత్నాలలో విఫలమైతే, మీరు ఈమెయిల్‌ ఖాతాను ఉపయోగించి మీ టాబ్లెట్‌ను అన్‌లాక్ చేయాల్సి వస్తుంది.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"మీరు మీ అన్‌లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> ప్రయత్నాలలో విఫలమైతే, మీరు ఈమెయిల్‌ ఖాతాను ఉపయోగించి మీ ఫోన్‌ను అన్‌లాక్ చేయాల్సి వస్తుంది.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"వేలిముద్ర సెన్సార్ పవర్ బటన్‌పై ఉంది. ఇది టాబ్లెట్ అంచున వాల్యూమ్ పెంచడానికి ఉపయోగించే వాల్యూమ్ బటన్ పక్కన ఉన్న ఫ్లాట్ బటన్.\n\nపవర్ బటన్‌ను నొక్కితే స్క్రీన్ ఆఫ్ అవుతుంది."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"వేలిముద్ర సెన్సార్ పవర్ బటన్‌పై ఉంది. ఇది పరికరం అంచున వాల్యూమ్ పెంచడానికి ఉపయోగించే వాల్యూమ్ బటన్ పక్కన ఉన్న ఫ్లాట్ బటన్.\n\nపవర్ బటన్‌ను నొక్కితే స్క్రీన్ ఆఫ్ అవుతుంది."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"వేలిముద్ర సెన్సార్ పవర్ బటన్‌పై ఉంది. ఇది ఫోన్ అంచున వాల్యూమ్ పెంచడానికి ఉపయోగించే వాల్యూమ్ బటన్ పక్కన ఉన్న ఫ్లాట్ బటన్.\n\nపవర్ బటన్‌ను నొక్కితే స్క్రీన్ ఆఫ్ అవుతుంది."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"మరిన్ని ఆప్షన్‌ల కోసం మీ ఫోన్‌ను అన్‌లాక్ చేయండి"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"మరిన్ని ఆప్షన్‌ల కోసం మీ టాబ్లెట్‌ను అన్‌లాక్ చేయండి"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"మరిన్ని ఆప్షన్‌ల కోసం మీ పరికరాన్ని అన్‌లాక్ చేయండి"</string>
diff --git a/packages/SystemUI/res-product/values-th/strings.xml b/packages/SystemUI/res-product/values-th/strings.xml
index 765ef7d..e78cbc4 100644
--- a/packages/SystemUI/res-product/values-th/strings.xml
+++ b/packages/SystemUI/res-product/values-th/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"คุณปลดล็อกโทรศัพท์ไม่ถูกต้อง <xliff:g id="NUMBER">%d</xliff:g> ครั้งแล้ว ระบบจะนำโปรไฟล์งานออก ซึ่งจะเป็นการลบข้อมูลทั้งหมดในโปรไฟล์"</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกแท็บเล็ตโดยใช้บัญชีอีเมล\n\n โปรดลองอีกครั้งใน <xliff:g id="NUMBER_2">%3$d</xliff:g> วินาที"</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกโทรศัพท์โดยใช้บัญชีอีเมล\n\n โปรดลองอีกครั้งในอีก <xliff:g id="NUMBER_2">%3$d</xliff:g> วินาที"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"เซ็นเซอร์ลายนิ้วมืออยู่ที่ปุ่มเปิด/ปิด ซึ่งเป็นปุ่มแบนข้างปุ่มนูนที่ใช้ปรับระดับเสียงตรงบริเวณขอบของแท็บเล็ต\n\nการกดปุ่มเปิด/ปิดจะเป็นการปิดหน้าจอ"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"เซ็นเซอร์ลายนิ้วมืออยู่ที่ปุ่มเปิด/ปิด ซึ่งเป็นปุ่มแบนข้างปุ่มนูนที่ใช้ปรับระดับเสียงตรงบริเวณขอบของอุปกรณ์\n\nการกดปุ่มเปิด/ปิดจะเป็นการปิดหน้าจอ"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"เซ็นเซอร์ลายนิ้วมืออยู่ที่ปุ่มเปิด/ปิด ซึ่งเป็นปุ่มแบนข้างปุ่มนูนที่ใช้ปรับระดับเสียงตรงบริเวณขอบของโทรศัพท์\n\nการกดปุ่มเปิด/ปิดจะเป็นการปิดหน้าจอ"</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"ปลดล็อกโทรศัพท์เพื่อดูตัวเลือกเพิ่มเติม"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"ปลดล็อกแท็บเล็ตเพื่อดูตัวเลือกเพิ่มเติม"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"ปลดล็อกอุปกรณ์เพื่อดูตัวเลือกเพิ่มเติม"</string>
diff --git a/packages/SystemUI/res-product/values-tl/strings.xml b/packages/SystemUI/res-product/values-tl/strings.xml
index df87136..4adad1f 100644
--- a/packages/SystemUI/res-product/values-tl/strings.xml
+++ b/packages/SystemUI/res-product/values-tl/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"<xliff:g id="NUMBER">%d</xliff:g> (na) beses mo nang sinubukang i-unlock ang telepono gamit ang maling password. Aalisin ang profile sa trabaho, na magiging dahilan para ma-delete ang lahat ng data sa profile."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"<xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses kang nagkamali sa pagguhit ng iyong pattern sa pag-unlock. Pagkatapos ng <xliff:g id="NUMBER_1">%2$d</xliff:g> pang hindi matagumpay na pagsubok, hihilingin sa iyong i-unlock ang tablet mo gamit ang isang email account.\n\n Subukan ulit sa loob ng <xliff:g id="NUMBER_2">%3$d</xliff:g> (na) segundo."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"<xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses kang nagkamali sa pagguhit ng iyong pattern sa pag-unlock. Pagkatapos ng <xliff:g id="NUMBER_1">%2$d</xliff:g> pang hindi matagumpay na pagsubok, hihilingin sa iyong i-unlock ang telepono mo gamit ang isang email account.\n\n Subukan ulit sa loob ng <xliff:g id="NUMBER_2">%3$d</xliff:g> (na) segundo."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Nasa power button ang sensor para sa fingerprint. Ito ang flat na button sa tabi ng nakaangat na button ng volume sa gilid ng tablet.\n\nMamamatay ang screen kapag pinindot ang power button."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Nasa power button ang sensor para sa fingerprint. Ito ang flat na button sa tabi ng nakaangat na button ng volume sa gilid ng device.\n\nMamamatay ang screen kapag pinindot ang power button."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Nasa power button ang sensor para sa fingerprint. Ito ang flat na button sa tabi ng nakaangat na button ng volume sa gilid ng telepono.\n\nMamamatay ang screen kapag pinindot ang power button."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"I-unlock ang iyong telepono para sa higit pang opsyon"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"I-unlock ang iyong tablet para sa higit pang opsyon"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"I-unlock ang iyong device para sa higit pang opsyon"</string>
diff --git a/packages/SystemUI/res-product/values-tr/strings.xml b/packages/SystemUI/res-product/values-tr/strings.xml
index 0512acb..53c6054 100644
--- a/packages/SystemUI/res-product/values-tr/strings.xml
+++ b/packages/SystemUI/res-product/values-tr/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Telefonun kilidini <xliff:g id="NUMBER">%d</xliff:g> kez hatalı bir şekilde açmayı denediniz. İş profili kaldırılacak ve tüm profil verileri silinecektir."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Kilit açma deseninizi <xliff:g id="NUMBER_0">%1$d</xliff:g> kez hatalı çizdiniz. <xliff:g id="NUMBER_1">%2$d</xliff:g> başarısız deneme daha yaparsanız tabletinizin kilidini bir e-posta hesabı kullanarak açmanız istenir.\n<xliff:g id="NUMBER_2">%3$d</xliff:g>\n saniye içinde tekrar deneyin."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Kilit açma deseninizi <xliff:g id="NUMBER_0">%1$d</xliff:g> kez yanlış çizdiniz. <xliff:g id="NUMBER_1">%2$d</xliff:g> başarısız deneme daha yaparsanız telefonunuzu bir e-posta hesabı kullanarak açmanız istenir.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniye içinde tekrar deneyin."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Parmak izi sensörü güç düğmesinin üzerindedir. Bu sensör, tabletin kenarındaki ses yükseltme düğmesinin yanında bulunan düz düğmedir.\n\nGüç düğmesine bastığınızda ekran kapanır."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Parmak izi sensörü güç düğmesinin üzerindedir. Bu sensör, cihazın kenarındaki ses yükseltme düğmesinin yanında bulunan düz düğmedir.\n\nGüç düğmesine bastığınızda ekran kapanır."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Parmak izi sensörü güç düğmesinin üzerindedir. Bu sensör, telefonun kenarındaki ses yükseltme düğmesinin yanında bulunan düz düğmedir.\n\nGüç düğmesine bastığınızda ekran kapanır."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Diğer seçenekler için telefonunuzun kilidini açın"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Diğer seçenekler için tabletinizin kilidini açın"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Diğer seçenekler için cihazınızın kilidini açın"</string>
diff --git a/packages/SystemUI/res-product/values-uk/strings.xml b/packages/SystemUI/res-product/values-uk/strings.xml
index d5399ad..ef62fff 100644
--- a/packages/SystemUI/res-product/values-uk/strings.xml
+++ b/packages/SystemUI/res-product/values-uk/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Кількість невдалих спроб розблокувати телефон: <xliff:g id="NUMBER">%d</xliff:g>. Буде видалено робочий профіль і всі його дані."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Ключ розблокування неправильно намальовано стільки разів: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Залишилося спроб: <xliff:g id="NUMBER_1">%2$d</xliff:g>. У разі невдачі з\'явиться запит розблокувати планшет за допомогою облікового запису електронної пошти.\n\n Повторіть спробу за <xliff:g id="NUMBER_2">%3$d</xliff:g> с."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Ключ розблокування неправильно намальовано стільки разів: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Залишилося спроб: <xliff:g id="NUMBER_1">%2$d</xliff:g>. У разі невдачі з\'явиться запит розблокувати телефон за допомогою облікового запису електронної пошти.\n\n Повторіть спробу за <xliff:g id="NUMBER_2">%3$d</xliff:g> с."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Сканер відбитків пальців розташовано на кнопці живлення. Це плоска кнопка, розташована поруч із кнопкою збільшення гучності на бічній крайці планшета.\n\nЯкщо натиснути кнопку живлення, екран вимкнеться."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Сканер відбитків пальців розташовано на кнопці живлення. Це плоска кнопка, розташована поруч із кнопкою збільшення гучності на бічній крайці пристрою.\n\nЯкщо натиснути кнопку живлення, екран вимкнеться."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Сканер відбитків пальців розташовано на кнопці живлення. Це плоска кнопка, розташована поруч із кнопкою збільшення гучності на бічній крайці телефона.\n\nЯкщо натиснути кнопку живлення, екран вимкнеться."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Розблокуйте телефон, щоб переглянути інші параметри"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Розблокуйте планшет, щоб переглянути інші параметри"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Розблокуйте пристрій, щоб переглянути інші параметри"</string>
diff --git a/packages/SystemUI/res-product/values-ur/strings.xml b/packages/SystemUI/res-product/values-ur/strings.xml
index ac243de..e272a33 100644
--- a/packages/SystemUI/res-product/values-ur/strings.xml
+++ b/packages/SystemUI/res-product/values-ur/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"آپ نے فون کو غیر مقفل کرنے کیلئے <xliff:g id="NUMBER">%d</xliff:g> بار غلط طریقے سے کوشش کی ہے۔ دفتری پروفائل ہٹا دی جائے گی، جس سے پروفائل کا سبھی ڈیٹا حذف ہو جائے گا۔"</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"آپ نے اپنا غیر مقفل کرنے کا پیٹرن <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے ڈرا کیا ہے۔ <xliff:g id="NUMBER_1">%2$d</xliff:g> مزید ناکام کوششوں کے بعد، آپ سے ایک ای میل اکاؤنٹ استعمال کر کے اپنا ٹیبلیٹ غیر مقفل کرنے کو کہا جائے گا۔\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں۔"</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"آپ نے اپنا غیر مقفل کرنے کا پیٹرن <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے ڈرا کیا ہے۔ <xliff:g id="NUMBER_1">%2$d</xliff:g> مزید ناکام کوششوں کے بعد، آپ سے ایک ای میل اکاؤنٹ استعمال کر کے اپنا فون غیر مقفل کرنے کو کہا جائے گا۔\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں۔"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"فنگر پرنٹ سینسر پاور بٹن پر موجود ہے۔ یہ ٹیبلیٹ کے کنارے پر ابھرے ہوئے والیوم بٹن کے آگے والا ہموار بٹن ہے۔\n\nپاور بٹن دبانے سے اسکرین آف ہو جاتی ہے۔"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"فنگر پرنٹ سینسر پاور بٹن پر موجود ہے۔ یہ آلے کے کنارے پر ابھرے ہوئے والیوم بٹن کے آگے والا ہموار بٹن ہے۔\n\nپاور بٹن دبانے سے اسکرین آف ہو جاتی ہے۔"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"فنگر پرنٹ سینسر پاور بٹن پر موجود ہے۔ یہ فون کے کنارے پر ابھرے ہوئے والیوم بٹن کے آگے والا ہموار بٹن ہے۔\n\nپاور بٹن دبانے سے اسکرین آف ہو جاتی ہے۔"</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"مزید اختیارات کے لیے اپنا فون غیر مقفل کریں"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"مزید اختیارات کے لیے اپنا ٹیبلیٹ غیر مقفل کریں"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"مزید اختیارات کے لیے اپنا آلہ غیر مقفل کریں"</string>
diff --git a/packages/SystemUI/res-product/values-uz/strings.xml b/packages/SystemUI/res-product/values-uz/strings.xml
index c10d54f..d23f541 100644
--- a/packages/SystemUI/res-product/values-uz/strings.xml
+++ b/packages/SystemUI/res-product/values-uz/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Siz telefonni qulfdan chiqarish uchun <xliff:g id="NUMBER">%d</xliff:g> marta xato urinish qildingiz. Endi ish profili oʻchirib tashlanadi va undagi barcha maʼlumotlar ham oʻchib ketadi."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Grafik kalit <xliff:g id="NUMBER_0">%1$d</xliff:g> marta xato chizildi. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishdan keyin sizdan emailingizdan foydalanib, planshet qulfini ochishingiz soʻraladi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan keyin yana urinib koʻring."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Grafik kalit <xliff:g id="NUMBER_0">%1$d</xliff:g> marta xato chizildi. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishdan keyin sizdan emailngizdan foydalanib, telefon qulfini ochishingiz soʻraladi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan keyin qayta urinib koʻring."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Barmoq izi sensori quvvat tugmasida joylashgan. U tekis tugma planshetning yon chekkasida tovush balandligi tugmasining yonida joylashgan\n\nQuvvat tugmasi bosilganda ekran oʻchadi."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Barmoq izi sensori quvvat tugmasida joylashgan. U tekis tugma qurilmaning yon chekkasida tovush balandligi tugmasining yonida joylashgan.\n\nQuvvat tugmasi bosilganda ekran oʻchadi."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Barmoq izi sensori quvvat tugmasida joylashgan. U tekis tugma telefonning yon chekkasida tovush balandligi tugmasining yonida joylashgan\n\nQuvvat tugmasi bosilganda ekran oʻchadi."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Boshqa parametrlar uchun telefoningiz qulfini oching"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Boshqa parametrlar uchun planshetingiz qulfini oching"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Boshqa parametrlar uchun qurilmangiz qulfini oching"</string>
diff --git a/packages/SystemUI/res-product/values-vi/strings.xml b/packages/SystemUI/res-product/values-vi/strings.xml
index 1a8fabd..ff87ea8 100644
--- a/packages/SystemUI/res-product/values-vi/strings.xml
+++ b/packages/SystemUI/res-product/values-vi/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Bạn đã mở khóa điện thoại sai <xliff:g id="NUMBER">%d</xliff:g> lần. Hồ sơ công việc sẽ bị xóa, tức là tất cả dữ liệu hồ sơ sẽ bị xóa."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Bạn đã vẽ không chính xác hình mở khóa <xliff:g id="NUMBER_0">%1$d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%2$d</xliff:g> lần thử không thành công nữa, bạn sẽ được yêu cầu mở khóa máy tính bảng bằng tài khoản email.\n\n Hãy thử lại sau <xliff:g id="NUMBER_2">%3$d</xliff:g> giây."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Bạn đã vẽ không chính xác hình mở khóa <xliff:g id="NUMBER_0">%1$d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%2$d</xliff:g> lần thử không thành công nữa, bạn sẽ được yêu cầu mở khóa điện thoại bằng tài khoản email.\n\n Hãy thử lại sau <xliff:g id="NUMBER_2">%3$d</xliff:g> giây."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Cảm biến vân tay nằm trên nút nguồn. Đó là nút phẳng bên cạnh nút tăng âm lượng trên cạnh của máy tính bảng.\n\nKhi bạn nhấn nút nguồn, màn hình sẽ tắt."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Cảm biến vân tay nằm trên nút nguồn. Đó là nút phẳng bên cạnh nút tăng âm lượng trên cạnh của thiết bị.\n\nKhi bạn nhấn nút nguồn, màn hình sẽ tắt."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Cảm biến vân tay nằm trên nút nguồn. Đó là nút phẳng bên cạnh nút tăng âm lượng trên cạnh của điện thoại.\n\nKhi bạn nhấn nút nguồn, màn hình sẽ tắt."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Mở khóa điện thoại của bạn để xem thêm tùy chọn"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Mở khóa máy tính bảng của bạn để xem thêm tùy chọn"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Mở khóa thiết bị của bạn để xem thêm tùy chọn"</string>
diff --git a/packages/SystemUI/res-product/values-zh-rCN/strings.xml b/packages/SystemUI/res-product/values-zh-rCN/strings.xml
index 1f88251..f51437e 100644
--- a/packages/SystemUI/res-product/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res-product/values-zh-rCN/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"您尝试解锁手机后失败的次数已达 <xliff:g id="NUMBER">%d</xliff:g> 次。系统将移除此工作资料,而这将删除所有的工作资料数据。"</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"您已 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次画错解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐号解锁平板电脑。\n\n请在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒后重试。"</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"您已 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次画错解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐号解锁手机。\n\n请在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒后重试。"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"指纹传感器在电源按钮上。电源按钮是一个扁平按钮,位于平板电脑边缘凸起的音量按钮旁边。\n\n按下电源按钮会关闭屏幕。"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"指纹传感器在电源按钮上。电源按钮是一个扁平按钮,位于设备边缘凸起的音量按钮旁边。\n\n按下电源按钮会关闭屏幕。"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"指纹传感器在电源按钮上。电源按钮是一个扁平按钮,位于手机边缘凸起的音量按钮旁边。\n\n按下电源按钮会关闭屏幕。"</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"解锁手机即可查看更多选项"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"解锁平板电脑即可查看更多选项"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"解锁设备即可查看更多选项"</string>
diff --git a/packages/SystemUI/res-product/values-zh-rHK/strings.xml b/packages/SystemUI/res-product/values-zh-rHK/strings.xml
index 00f3f35..0d529f9 100644
--- a/packages/SystemUI/res-product/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res-product/values-zh-rHK/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"您嘗試解鎖手機已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。系統將移除此工作設定檔,而所有設定檔資料亦會一併刪除。"</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"您已畫錯解鎖圖案 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果之後再嘗試 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次仍未成功,系統會要求您透過電郵帳戶解鎖平板電腦。\n\n請在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後再試一次。"</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"您已畫錯解鎖圖案 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。如果之後再嘗試 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次仍未成功,系統會要求您透過電郵帳戶解鎖手機。\n\n請在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後再試一次。"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"指紋感應器位於開關按鈕上,開關按鈕形狀扁平,位於平板電腦邊緣凸起的音量按鈕旁。\n\n按下開關按鈕即可關閉螢幕。"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"指紋感應器位於開關按鈕上,開關按鈕形狀扁平,位於裝置邊緣凸起的音量按鈕旁。\n\n按下開關按鈕即可關閉螢幕。"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"指紋感應器位於開關按鈕上,開關按鈕形狀扁平,位於手機邊緣凸起的音量按鈕旁。\n\n按下開關按鈕即可關閉螢幕。"</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"解鎖手機以存取更多選項"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"解鎖平板電腦以存取更多選項"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"解鎖裝置以存取更多選項"</string>
diff --git a/packages/SystemUI/res-product/values-zh-rTW/strings.xml b/packages/SystemUI/res-product/values-zh-rTW/strings.xml
index a91e744..4715cdbe 100644
--- a/packages/SystemUI/res-product/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res-product/values-zh-rTW/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"你嘗試解鎖手機已失敗 <xliff:g id="NUMBER">%d</xliff:g> 次。你的工作資料夾將遭到移除,所有設定檔資料也會一併遭到刪除。"</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"你的解鎖圖案已畫錯 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,目前還剩 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次機會。如果失敗次數超過限制,系統會要求你透過電子郵件帳戶將平板電腦解鎖。\n\n請在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後再試一次。"</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"你的解鎖圖案已畫錯 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,目前還剩 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次機會。如果失敗次數超過限制,系統會要求你透過電子郵件帳戶將手機解鎖。\n\n請在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後再試一次。"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"指紋感應器在電源鍵上。電源鍵形狀扁平,位於平板電腦側邊的調高音量按鈕旁。\n\n按下電源鍵可關閉螢幕。"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"指紋感應器在電源鍵上。電源鍵形狀扁平,位於裝置側邊的調高音量按鈕旁。\n\n按下電源鍵可關閉螢幕。"</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"指紋感應器在電源鍵上。電源鍵形狀扁平,位於手機側邊的調高音量按鈕旁。\n\n按下電源鍵可關閉螢幕。"</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"解鎖手機可查看更多選項"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"解鎖平板電腦可查看更多選項"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"解鎖裝置可查看更多選項"</string>
diff --git a/packages/SystemUI/res-product/values-zu/strings.xml b/packages/SystemUI/res-product/values-zu/strings.xml
index 8a00490b3..26a6f4e 100644
--- a/packages/SystemUI/res-product/values-zu/strings.xml
+++ b/packages/SystemUI/res-product/values-zu/strings.xml
@@ -40,6 +40,9 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Uzame ngokungalungile ukuvula ifoni izikhathi ezingu-<xliff:g id="NUMBER">%d</xliff:g>. Iphrofayela yomsebenzi izosuswa, okuzosusa yonke idatha yephrofayela."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Udwebe ngokungalungile iphethini yakho yokuvula ngezikhathi ezingu-<xliff:g id="NUMBER_0">%1$d</xliff:g>. Ngemuva kwemizamo engaphumelelanga kaningi engu-<xliff:g id="NUMBER_1">%2$d</xliff:g>, uzocelwa ukuthi uvule ithebulethi yakho usebenzisa i-akhawunti ye-imeyili.\n\nZama futhi kumasekhondi angu-<xliff:g id="NUMBER_2">%3$d</xliff:g>."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Ukulayisha ungenisa iphathini yakho yokuvula ngendlela engalungile izikhathi ezi-<xliff:g id="NUMBER_0">%1$d</xliff:g> Emva kweminye imizamo engu-<xliff:g id="NUMBER_1">%2$d</xliff:g>, uzocelwa ukuvula ifoni yakho usebenzisa ukungena ngemvume ku-Google\n\n Zame futhi emumva kwengu- <xliff:g id="NUMBER_2">%3$d</xliff:g> imizuzwana."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet" msgid="1242939073723573315">"Inzwa yesigxivizo somunwe esenkinobhweni yamandla. Yinkinobho eyisicaba eduze kwenkinobho yevolumu ephakanyisiwe emaphethelweni ethebulethi.\n\nUkucindezela inkinobho yamandla kuvala isikrini."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device" msgid="7305137594359170451">"Inzwa yesigxivizo somunwe esenkinobhweni yamandla. Yinkinobho eyisicaba eduze kwenkinobho yevolumu ephakanyisiwe emaphethelweni edivayisi.\n\nUkucindezela inkinobho yamandla kuvala isikrini."</string>
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default" msgid="3238514774114999081">"Inzwa yesigxivizo somunwe esenkinobhweni yamandla. Yinkinobho eyisicaba eduze kwenkinobho yevolumu ephakanyisiwe emaphethelweni efoni.\n\nUkucindezela inkinobho yamandla kuvala isikrini."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Vula ifoni yakho ukuthola okunye okungakhethwa"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Vula ithebulethi yakho ukuthola okunye okungakhethwa"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Vula idivayisi yakho ukuthola okunye okungakhethwa"</string>
diff --git a/packages/SystemUI/res-product/values/strings.xml b/packages/SystemUI/res-product/values/strings.xml
index 75c8286..13f72af0 100644
--- a/packages/SystemUI/res-product/values/strings.xml
+++ b/packages/SystemUI/res-product/values/strings.xml
@@ -122,6 +122,12 @@
        Try again in <xliff:g id="number">%3$d</xliff:g> seconds.
     </string>
 
+    <!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, to locate the sensor (tablet) for accessibility (not shown on the screen). [CHAR LIMIT=NONE]-->
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet">The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the tablet.</string>
+    <!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, to locate the sensor (device) for accessibility (not shown on the screen). [CHAR LIMIT=NONE]-->
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device">The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the device.</string>
+    <!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, to locate the sensor (default) for accessibility (not shown on the screen). [CHAR LIMIT=NONE]-->
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default">The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the phone.</string>
 
     <!-- Text shown when viewing global actions while phone is locked and additional controls are hidden [CHAR LIMIT=NONE] -->
     <string name="global_action_lock_message" product="default">Unlock your phone for more options</string>
@@ -134,4 +140,7 @@
     <string name="media_transfer_playing_this_device" product="default">Playing on this phone</string>
     <!-- Text informing the user that their media is now playing on this tablet device. [CHAR LIMIT=50] -->
     <string name="media_transfer_playing_this_device" product="tablet">Playing on this tablet</string>
+
+
+
 </resources>
diff --git a/packages/SystemUI/res/drawable/accessibility_window_magnification_background.xml b/packages/SystemUI/res/drawable/accessibility_window_magnification_background.xml
index 58fe368..97bd18e 100644
--- a/packages/SystemUI/res/drawable/accessibility_window_magnification_background.xml
+++ b/packages/SystemUI/res/drawable/accessibility_window_magnification_background.xml
@@ -27,7 +27,7 @@
         <shape android:shape="rectangle">
             <corners android:radius="@dimen/magnifier_outer_corner_radius" />
             <stroke
-                android:color="@android:color/black"
+                android:color="@color/magnification_drag_handle_stroke"
                 android:width="@dimen/magnifier_stroke_width"/>
         </shape>
     </item>
diff --git a/packages/SystemUI/res/drawable/accessibility_window_magnification_drag_handle_background.xml b/packages/SystemUI/res/drawable/accessibility_window_magnification_drag_handle_background.xml
index a52e805..66617e1 100644
--- a/packages/SystemUI/res/drawable/accessibility_window_magnification_drag_handle_background.xml
+++ b/packages/SystemUI/res/drawable/accessibility_window_magnification_drag_handle_background.xml
@@ -16,7 +16,7 @@
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
     <stroke
-        android:color="@android:color/black"
+        android:color="@color/magnification_drag_handle_stroke"
         android:width="@dimen/magnifier_stroke_width"/>
     <corners android:radius="@dimen/magnifier_corner_radius" />
     <solid android:color="@color/magnification_border_color" />
diff --git a/packages/SystemUI/res/drawable/accessibility_window_magnification_drag_handle_background_change.xml b/packages/SystemUI/res/drawable/accessibility_window_magnification_drag_handle_background_change.xml
new file mode 100644
index 0000000..e367f50
--- /dev/null
+++ b/packages/SystemUI/res/drawable/accessibility_window_magnification_drag_handle_background_change.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.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+    <stroke
+        android:color="@color/magnification_border_color"
+        android:width="@dimen/magnifier_stroke_width"/>
+    <corners android:radius="@dimen/magnifier_corner_radius" />
+    <solid android:color="@color/magnification_drag_handle_background_change" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/media_ttt_chip_background.xml b/packages/SystemUI/res/drawable/chipbar_background.xml
similarity index 92%
rename from packages/SystemUI/res/drawable/media_ttt_chip_background.xml
rename to packages/SystemUI/res/drawable/chipbar_background.xml
index 3abf4d7..5722177 100644
--- a/packages/SystemUI/res/drawable/media_ttt_chip_background.xml
+++ b/packages/SystemUI/res/drawable/chipbar_background.xml
@@ -17,6 +17,6 @@
 <shape
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
-    <solid android:color="?androidprv:attr/colorSurface" />
+    <solid android:color="?androidprv:attr/colorAccentSecondary" />
     <corners android:radius="32dp" />
 </shape>
diff --git a/packages/SystemUI/res/drawable/media_ttt_undo_background.xml b/packages/SystemUI/res/drawable/chipbar_end_button_background.xml
similarity index 93%
rename from packages/SystemUI/res/drawable/media_ttt_undo_background.xml
rename to packages/SystemUI/res/drawable/chipbar_end_button_background.xml
index 3e2e4f0..80c7207 100644
--- a/packages/SystemUI/res/drawable/media_ttt_undo_background.xml
+++ b/packages/SystemUI/res/drawable/chipbar_end_button_background.xml
@@ -20,7 +20,7 @@
     android:color="?android:textColorPrimary">
     <item android:id="@android:id/background">
         <shape>
-            <solid android:color="?androidprv:attr/colorAccentPrimary"/>
+            <solid android:color="@android:color/system_accent1_200"/>
             <corners android:radius="24dp" />
         </shape>
     </item>
diff --git a/packages/SystemUI/res/drawable/controls_panel_background.xml b/packages/SystemUI/res/drawable/controls_panel_background.xml
index 9092877..fc108a5 100644
--- a/packages/SystemUI/res/drawable/controls_panel_background.xml
+++ b/packages/SystemUI/res/drawable/controls_panel_background.xml
@@ -18,5 +18,5 @@
 
 <shape xmlns:android="http://schemas.android.com/apk/res/android">
     <solid android:color="#1F1F1F" />
-    <corners android:radius="@dimen/notification_corner_radius" />
+    <corners android:radius="@dimen/controls_panel_corner_radius" />
 </shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/dream_overlay_bottom_affordance_bg.xml b/packages/SystemUI/res/drawable/dream_overlay_bottom_affordance_bg.xml
new file mode 100644
index 0000000..3b67ddd
--- /dev/null
+++ b/packages/SystemUI/res/drawable/dream_overlay_bottom_affordance_bg.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright 2023, The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    android:shape="rectangle">
+  <solid android:color="?androidprv:attr/colorSurface"/>
+  <size
+      android:width="@dimen/dream_overlay_bottom_affordance_height"
+      android:height="@dimen/dream_overlay_bottom_affordance_width"/>
+  <corners android:radius="@dimen/dream_overlay_bottom_affordance_radius" />
+</shape>
diff --git a/packages/SystemUI/res/drawable/ic_keyboard_backlight.xml b/packages/SystemUI/res/drawable/ic_keyboard_backlight.xml
new file mode 100644
index 0000000..d123caf
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_keyboard_backlight.xml
@@ -0,0 +1,12 @@
+<vector android:height="11dp" android:viewportHeight="12"
+    android:viewportWidth="22" android:width="20.166666dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <group>
+        <clip-path android:pathData="M0,0.5h22v11h-22z"/>
+        <path android:fillColor="#231F20" android:pathData="M6.397,9.908H0V11.5H6.397V9.908Z"/>
+        <path android:fillColor="#231F20" android:pathData="M14.199,9.908H7.801V11.5H14.199V9.908Z"/>
+        <path android:fillColor="#231F20" android:pathData="M11.858,0.5H10.142V6.434H11.858V0.5Z"/>
+        <path android:fillColor="#231F20" android:pathData="M8.348,7.129L3.885,2.975L3.823,2.932L2.668,4.003L2.621,4.046L7.084,8.2L7.146,8.243L8.301,7.172L8.348,7.129Z"/>
+        <path android:fillColor="#231F20" android:pathData="M18.224,2.975L18.177,2.932L13.653,7.129L14.807,8.2L14.854,8.243L19.379,4.046L18.224,2.975Z"/>
+        <path android:fillColor="#231F20" android:pathData="M22,9.908H15.603V11.5H22V9.908Z"/>
+    </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_magnification_menu_large.xml b/packages/SystemUI/res/drawable/ic_magnification_menu_large.xml
index 92c9527..401ac73 100644
--- a/packages/SystemUI/res/drawable/ic_magnification_menu_large.xml
+++ b/packages/SystemUI/res/drawable/ic_magnification_menu_large.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="48dp"
-    android:height="48dp"
+    android:width="32dp"
+    android:height="32dp"
     android:viewportWidth="48"
     android:viewportHeight="48"
     android:tint="?attr/colorControlNormal">
diff --git a/packages/SystemUI/res/drawable/ic_magnification_menu_medium.xml b/packages/SystemUI/res/drawable/ic_magnification_menu_medium.xml
index 209681f..9a850e8 100644
--- a/packages/SystemUI/res/drawable/ic_magnification_menu_medium.xml
+++ b/packages/SystemUI/res/drawable/ic_magnification_menu_medium.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="48dp"
-    android:height="48dp"
+    android:width="32dp"
+    android:height="32dp"
     android:viewportWidth="48"
     android:viewportHeight="48"
     android:tint="?attr/colorControlNormal">
diff --git a/packages/SystemUI/res/drawable/ic_magnification_menu_small.xml b/packages/SystemUI/res/drawable/ic_magnification_menu_small.xml
index a3dc816..54322c5 100644
--- a/packages/SystemUI/res/drawable/ic_magnification_menu_small.xml
+++ b/packages/SystemUI/res/drawable/ic_magnification_menu_small.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="48dp"
-    android:height="48dp"
+    android:width="32dp"
+    android:height="32dp"
     android:viewportWidth="48"
     android:viewportHeight="48"
     android:tint="?attr/colorControlNormal">
diff --git a/packages/SystemUI/res/drawable/ic_move_magnification.xml b/packages/SystemUI/res/drawable/ic_move_magnification.xml
index 641bb43..0796007 100644
--- a/packages/SystemUI/res/drawable/ic_move_magnification.xml
+++ b/packages/SystemUI/res/drawable/ic_move_magnification.xml
@@ -20,6 +20,6 @@
     android:viewportHeight="24"
     android:tint="?attr/colorControlNormal">
   <path
-      android:fillColor="@color/magnification_drag_handle_tint"
+      android:fillColor="@color/magnification_drag_handle_stroke"
       android:pathData="M12,15Q10.75,15 9.875,14.125Q9,13.25 9,12Q9,10.75 9.875,9.875Q10.75,9 12,9Q13.25,9 14.125,9.875Q15,10.75 15,12Q15,13.25 14.125,14.125Q13.25,15 12,15ZM12,22 L7.75,17.75 9.15,16.35 12,19.15 14.85,16.35 16.25,17.75ZM6.25,16.25 L2,12 6.25,7.75 7.65,9.15 4.85,12 7.65,14.85ZM9.15,7.65 L7.75,6.25 12,2 16.25,6.25 14.85,7.65 12,4.85ZM17.75,16.25 L16.35,14.85 19.15,12 16.35,9.15 17.75,7.75 22,12Z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_open_in_full.xml b/packages/SystemUI/res/drawable/ic_open_in_full.xml
index c7f3236..7081c4b 100644
--- a/packages/SystemUI/res/drawable/ic_open_in_full.xml
+++ b/packages/SystemUI/res/drawable/ic_open_in_full.xml
@@ -14,8 +14,8 @@
   ~ limitations under the License.
   -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="48dp"
-    android:height="48dp"
+    android:width="24dp"
+    android:height="24dp"
     android:viewportWidth="48"
     android:viewportHeight="48"
     android:tint="?attr/colorControlNormal">
diff --git a/packages/SystemUI/res/drawable/qs_footer_edit_circle.xml b/packages/SystemUI/res/drawable/qs_footer_edit_circle.xml
new file mode 100644
index 0000000..2e29cae
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_footer_edit_circle.xml
@@ -0,0 +1,36 @@
+<?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.
+  -->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+       android:inset="@dimen/qs_footer_action_inset">
+    <ripple
+        android:color="?android:attr/colorControlHighlight">
+        <item android:id="@android:id/mask">
+            <!-- We make this shape a rounded rectangle instead of a oval so that it can animate -->
+            <!-- properly into an app/dialog. -->
+            <shape android:shape="rectangle">
+                <solid android:color="@android:color/white"/>
+                <corners android:radius="@dimen/qs_footer_action_corner_radius"/>
+            </shape>
+        </item>
+        <item>
+            <shape android:shape="rectangle">
+                <corners android:radius="@dimen/qs_footer_action_corner_radius"/>
+            </shape>
+        </item>
+
+    </ripple>
+</inset>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/qs_media_rec_scrim.xml b/packages/SystemUI/res/drawable/qs_media_rec_scrim.xml
new file mode 100644
index 0000000..de0a620
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_media_rec_scrim.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
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <!-- gradient from 25% in the center to 100% at edges -->
+    <gradient
+        android:type="radial"
+        android:gradientRadius="40%p"
+        android:startColor="#AE000000"
+        android:endColor="#00000000" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/chipbar.xml b/packages/SystemUI/res/layout/chipbar.xml
index 0ff944c..a317178 100644
--- a/packages/SystemUI/res/layout/chipbar.xml
+++ b/packages/SystemUI/res/layout/chipbar.xml
@@ -29,8 +29,8 @@
         android:orientation="horizontal"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:padding="@dimen/media_ttt_chip_outer_padding"
-        android:background="@drawable/media_ttt_chip_background"
+        android:padding="@dimen/chipbar_outer_padding"
+        android:background="@drawable/chipbar_background"
         android:layout_marginTop="20dp"
         android:layout_marginStart="@dimen/notification_side_paddings"
         android:layout_marginEnd="@dimen/notification_side_paddings"
@@ -43,8 +43,8 @@
 
         <com.android.internal.widget.CachingIconView
             android:id="@+id/start_icon"
-            android:layout_width="@dimen/media_ttt_app_icon_size"
-            android:layout_height="@dimen/media_ttt_app_icon_size"
+            android:layout_width="@dimen/chipbar_start_icon_size"
+            android:layout_height="@dimen/chipbar_start_icon_size"
             android:layout_marginEnd="12dp"
             android:alpha="0.0"
             />
@@ -54,47 +54,46 @@
             android:layout_width="0dp"
             android:layout_height="wrap_content"
             android:layout_weight="1"
-            android:textSize="@dimen/media_ttt_text_size"
-            android:textColor="?android:attr/textColorPrimary"
+            android:textSize="@dimen/chipbar_text_size"
+            android:textColor="@android:color/system_accent2_900"
             android:alpha="0.0"
             />
 
         <!-- At most one of [loading, failure_icon, undo] will be visible at a time. -->
         <ImageView
             android:id="@+id/loading"
-            android:layout_width="@dimen/media_ttt_status_icon_size"
-            android:layout_height="@dimen/media_ttt_status_icon_size"
-            android:layout_marginStart="@dimen/media_ttt_last_item_start_margin"
+            android:layout_width="@dimen/chipbar_end_icon_size"
+            android:layout_height="@dimen/chipbar_end_icon_size"
+            android:layout_marginStart="@dimen/chipbar_end_item_start_margin"
             android:src="@drawable/ic_progress_activity"
-            android:tint="?androidprv:attr/colorAccentPrimaryVariant"
+            android:tint="@android:color/system_accent2_700"
             android:alpha="0.0"
             />
 
         <ImageView
             android:id="@+id/error"
-            android:layout_width="@dimen/media_ttt_status_icon_size"
-            android:layout_height="@dimen/media_ttt_status_icon_size"
-            android:layout_marginStart="@dimen/media_ttt_last_item_start_margin"
+            android:layout_width="@dimen/chipbar_end_icon_size"
+            android:layout_height="@dimen/chipbar_end_icon_size"
+            android:layout_marginStart="@dimen/chipbar_end_item_start_margin"
             android:src="@drawable/ic_warning"
-            android:tint="@color/GM2_red_500"
+            android:tint="@color/GM2_red_600"
             android:alpha="0.0"
             />
 
-        <!-- TODO(b/245610654): Re-name all the media-specific dimens to chipbar dimens instead. -->
         <TextView
             android:id="@+id/end_button"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:textColor="?androidprv:attr/textColorOnAccent"
-            android:layout_marginStart="@dimen/media_ttt_last_item_start_margin"
-            android:textSize="@dimen/media_ttt_text_size"
-            android:paddingStart="@dimen/media_ttt_chip_outer_padding"
-            android:paddingEnd="@dimen/media_ttt_chip_outer_padding"
-            android:paddingTop="@dimen/media_ttt_undo_button_vertical_padding"
-            android:paddingBottom="@dimen/media_ttt_undo_button_vertical_padding"
-            android:layout_marginTop="@dimen/media_ttt_undo_button_vertical_negative_margin"
-            android:layout_marginBottom="@dimen/media_ttt_undo_button_vertical_negative_margin"
-            android:background="@drawable/media_ttt_undo_background"
+            android:layout_marginStart="@dimen/chipbar_end_item_start_margin"
+            android:textSize="@dimen/chipbar_text_size"
+            android:paddingStart="@dimen/chipbar_outer_padding"
+            android:paddingEnd="@dimen/chipbar_outer_padding"
+            android:paddingTop="@dimen/chipbar_end_button_vertical_padding"
+            android:paddingBottom="@dimen/chipbar_end_button_vertical_padding"
+            android:layout_marginTop="@dimen/chipbar_end_button_vertical_negative_margin"
+            android:layout_marginBottom="@dimen/chipbar_end_button_vertical_negative_margin"
+            android:background="@drawable/chipbar_end_button_background"
             android:alpha="0.0"
             />
 
diff --git a/packages/SystemUI/res/layout/controls_fullscreen.xml b/packages/SystemUI/res/layout/controls_fullscreen.xml
index e08e63b..fa70303 100644
--- a/packages/SystemUI/res/layout/controls_fullscreen.xml
+++ b/packages/SystemUI/res/layout/controls_fullscreen.xml
@@ -15,19 +15,11 @@
      limitations under the License.
 -->
 
-<FrameLayout
+<LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/control_detail_root"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical">
 
-
-    <LinearLayout
-        android:id="@+id/global_actions_controls"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:orientation="vertical"
-        android:paddingHorizontal="@dimen/controls_padding_horizontal" />
-
-</FrameLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/controls_with_favorites.xml b/packages/SystemUI/res/layout/controls_with_favorites.xml
index aa211bf..71561c0 100644
--- a/packages/SystemUI/res/layout/controls_with_favorites.xml
+++ b/packages/SystemUI/res/layout/controls_with_favorites.xml
@@ -13,82 +13,94 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<merge
-    xmlns:android="http://schemas.android.com/apk/res/android">
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:orientation="vertical"
+    tools:parentTag="android.widget.LinearLayout">
 
-  <LinearLayout
-      android:layout_width="match_parent"
-      android:layout_height="wrap_content"
-      android:orientation="horizontal"
-      android:layout_marginBottom="@dimen/controls_header_bottom_margin">
-
-    <!-- make sure the header stays centered in the layout by adding a spacer -->
-    <Space
-        android:id="@+id/controls_spacer"
-        android:layout_width="@dimen/controls_header_menu_size"
-        android:layout_height="1dp"
-        android:visibility="gone" />
-
-    <ImageView
-        android:id="@+id/controls_close"
-        android:contentDescription="@string/accessibility_desc_close"
-        android:src="@drawable/ic_close"
-        android:background="?android:attr/selectableItemBackgroundBorderless"
-        android:tint="@color/control_primary_text"
-        android:layout_width="@dimen/controls_header_menu_size"
-        android:layout_height="@dimen/controls_header_menu_size"
-        android:padding="12dp"
-        android:visibility="gone" />
-    <!-- need to keep this outer view in order to have a correctly sized anchor
-         for the dropdown menu, as well as dropdown background in the right place -->
     <LinearLayout
-        android:id="@+id/controls_header"
-        android:orientation="horizontal"
-        android:layout_width="0dp"
-        android:layout_weight="1"
-        android:minHeight="48dp"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_gravity="center"
-        android:gravity="center">
-      <TextView
-          style="@style/Control.Spinner.Header"
-          android:clickable="false"
-          android:id="@+id/app_or_structure_spinner"
-          android:layout_width="wrap_content"
-          android:layout_height="wrap_content"
-          android:layout_gravity="center" />
-    </LinearLayout>
-    <ImageView
-        android:id="@+id/controls_more"
-        android:src="@drawable/ic_more_vert"
-        android:layout_width="@dimen/controls_header_menu_size"
-        android:layout_height="@dimen/controls_header_menu_size"
-        android:padding="12dp"
-        android:tint="@color/control_more_vert"
-        android:layout_gravity="center"
-        android:contentDescription="@string/accessibility_menu"
-        android:background="?android:attr/selectableItemBackgroundBorderless" />
-  </LinearLayout>
+        android:paddingHorizontal="@dimen/controls_header_horizontal_padding"
+        android:layout_marginBottom="@dimen/controls_header_bottom_margin"
+        android:orientation="horizontal">
 
-  <ScrollView
+        <!-- make sure the header stays centered in the layout by adding a spacer -->
+        <Space
+            android:id="@+id/controls_spacer"
+            android:layout_width="@dimen/controls_header_menu_button_size"
+            android:layout_height="1dp"
+            android:visibility="gone" />
+
+        <ImageView
+            android:id="@+id/controls_close"
+            android:layout_width="@dimen/controls_header_menu_button_size"
+            android:layout_height="@dimen/controls_header_menu_button_size"
+            android:layout_gravity="center_vertical"
+            android:background="?android:attr/selectableItemBackgroundBorderless"
+            android:contentDescription="@string/accessibility_desc_close"
+            android:padding="12dp"
+            android:src="@drawable/ic_close"
+            android:tint="@color/control_primary_text"
+            android:visibility="gone"
+            tools:visibility="visible" />
+
+        <!-- need to keep this outer view in order to have a correctly sized anchor
+             for the dropdown menu, as well as dropdown background in the right place -->
+        <LinearLayout
+            android:id="@+id/controls_header"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:layout_weight="1"
+            android:gravity="center"
+            android:minHeight="48dp"
+            android:orientation="horizontal">
+
+            <TextView
+                android:id="@+id/app_or_structure_spinner"
+                style="@style/Control.Spinner.Header"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:clickable="false"
+                tools:text="Test app" />
+        </LinearLayout>
+
+        <ImageView
+            android:id="@+id/controls_more"
+            android:layout_width="@dimen/controls_header_menu_button_size"
+            android:layout_height="@dimen/controls_header_menu_button_size"
+            android:layout_gravity="center_vertical"
+            android:background="?android:attr/selectableItemBackgroundBorderless"
+            android:contentDescription="@string/accessibility_menu"
+            android:padding="12dp"
+            android:src="@drawable/ic_more_vert"
+            android:tint="@color/control_more_vert" />
+    </LinearLayout>
+
+    <ScrollView
         android:id="@+id/controls_scroll_view"
         android:layout_width="match_parent"
         android:layout_height="0dp"
+        android:layout_marginHorizontal="@dimen/controls_content_margin_horizontal"
         android:layout_weight="1"
-        android:orientation="vertical"
         android:clipChildren="true"
+        android:orientation="vertical"
         android:paddingHorizontal="16dp"
         android:scrollbars="none">
-    <include layout="@layout/global_actions_controls_list_view" />
 
-  </ScrollView>
+        <include layout="@layout/global_actions_controls_list_view" />
 
-  <FrameLayout
-      android:id="@+id/controls_panel"
-      android:layout_width="match_parent"
-      android:layout_height="0dp"
-      android:layout_weight="1"
-      android:background="@drawable/controls_panel_background"
-      android:visibility="gone"
-      />
+    </ScrollView>
+
+    <FrameLayout
+        android:id="@+id/controls_panel"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_marginHorizontal="@dimen/controls_content_margin_horizontal"
+        android:layout_weight="1"
+        android:background="@drawable/controls_panel_background"
+        android:visibility="gone"
+        tools:visibility="visible" />
 </merge>
diff --git a/packages/SystemUI/res/layout/dream_overlay_home_controls_chip.xml b/packages/SystemUI/res/layout/dream_overlay_home_controls_chip.xml
index fb78b49..5b2ec48 100644
--- a/packages/SystemUI/res/layout/dream_overlay_home_controls_chip.xml
+++ b/packages/SystemUI/res/layout/dream_overlay_home_controls_chip.xml
@@ -22,13 +22,14 @@
 
     <com.android.systemui.animation.view.LaunchableImageView
         android:id="@+id/home_controls_chip"
-        android:layout_height="@dimen/keyguard_affordance_fixed_height"
-        android:layout_width="@dimen/keyguard_affordance_fixed_width"
+        android:layout_height="@dimen/dream_overlay_bottom_affordance_height"
+        android:layout_width="@dimen/dream_overlay_bottom_affordance_width"
         android:layout_gravity="bottom|start"
-        android:scaleType="center"
+        android:padding="@dimen/dream_overlay_bottom_affordance_padding"
+        android:background="@drawable/dream_overlay_bottom_affordance_bg"
+        android:scaleType="fitCenter"
         android:tint="?android:attr/textColorPrimary"
         android:src="@drawable/controls_icon"
-        android:background="@drawable/keyguard_bottom_affordance_bg"
         android:contentDescription="@string/quick_controls_title" />
 
 </FrameLayout>
diff --git a/packages/SystemUI/res/layout/media_recommendation_view.xml b/packages/SystemUI/res/layout/media_recommendation_view.xml
index c54c4e4..a4aeba1 100644
--- a/packages/SystemUI/res/layout/media_recommendation_view.xml
+++ b/packages/SystemUI/res/layout/media_recommendation_view.xml
@@ -22,9 +22,10 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:translationZ="0dp"
-        android:scaleType="centerCrop"
+        android:scaleType="matrix"
         android:adjustViewBounds="true"
         android:clipToOutline="true"
+        android:layerType="hardware"
         android:background="@drawable/bg_smartspace_media_item"/>
 
     <!-- App icon -->
diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml
index b1d3ed05..745cfc6 100644
--- a/packages/SystemUI/res/layout/qs_footer_impl.xml
+++ b/packages/SystemUI/res/layout/qs_footer_impl.xml
@@ -64,7 +64,7 @@
                     android:layout_width="@dimen/qs_footer_action_button_size"
                     android:layout_height="@dimen/qs_footer_action_button_size"
                     android:layout_gravity="center_vertical|end"
-                    android:background="?android:attr/selectableItemBackground"
+                    android:background="@drawable/qs_footer_edit_circle"
                     android:clickable="true"
                     android:contentDescription="@string/accessibility_quick_settings_edit"
                     android:focusable="true"
diff --git a/packages/SystemUI/res/layout/window_magnification_settings_view.xml b/packages/SystemUI/res/layout/window_magnification_settings_view.xml
index 7dfe7c4..3d0741c 100644
--- a/packages/SystemUI/res/layout/window_magnification_settings_view.xml
+++ b/packages/SystemUI/res/layout/window_magnification_settings_view.xml
@@ -21,7 +21,9 @@
     android:layout_height="wrap_content"
     android:background="@drawable/accessibility_magnification_setting_view_bg"
     android:orientation="vertical"
-    android:padding="@dimen/magnification_setting_background_padding">
+    android:padding="@dimen/magnification_setting_background_padding"
+    android:focusable="true"
+    android:contentDescription="@string/accessibility_magnification_settings_panel_description">
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
@@ -33,7 +35,7 @@
             android:text="@string/accessibility_magnifier_size"
             android:textAppearance="@style/TextAppearance.MagnificationSetting.Title"
             android:focusable="true"
-            android:layout_gravity="center_vertical|left" />
+            android:layout_gravity="center_vertical" />
 
         <Button
             android:id="@+id/magnifier_edit_button"
@@ -43,25 +45,22 @@
             android:text="@string/accessibility_magnifier_edit"
             android:textAppearance="@style/TextAppearance.MagnificationSetting.EditButton"
             android:focusable="true"
-            android:layout_gravity="right" />
+            android:layout_gravity="center_vertical" />
     </LinearLayout>
 
     <LinearLayout
         android:background="@drawable/accessibility_magnification_setting_view_image_btn_layout_bg"
-        android:layout_width="@dimen/magnification_setting_image_button_background_width"
+        android:layout_width="match_parent"
         android:layout_height="@dimen/magnification_setting_image_button_height"
+        android:minWidth="@dimen/magnification_setting_image_button_background_width"
         android:orientation="horizontal">
         <ImageButton
             android:id="@+id/magnifier_small_button"
             android:layout_width="0dp"
             android:layout_height="@dimen/magnification_setting_image_button_height"
             android:layout_weight="1"
-            android:scaleType="fitCenter"
+            android:scaleType="center"
             android:background="@drawable/accessibility_magnification_setting_view_image_btn_bg"
-            android:paddingLeft="@dimen/magnification_setting_image_button_padding_horizontal"
-            android:paddingRight="@dimen/magnification_setting_image_button_padding_horizontal"
-            android:paddingTop="@dimen/magnification_setting_image_button_padding_vertical"
-            android:paddingBottom="@dimen/magnification_setting_image_button_padding_vertical"
             android:src="@drawable/ic_magnification_menu_small"
             android:tint="@color/accessibility_magnification_image_button_tint"
             android:tintMode="src_atop" />
@@ -71,12 +70,8 @@
             android:layout_width="0dp"
             android:layout_height="@dimen/magnification_setting_image_button_height"
             android:layout_weight="1"
-            android:scaleType="fitCenter"
+            android:scaleType="center"
             android:background="@drawable/accessibility_magnification_setting_view_image_btn_bg"
-            android:paddingLeft="@dimen/magnification_setting_image_button_padding_horizontal"
-            android:paddingRight="@dimen/magnification_setting_image_button_padding_horizontal"
-            android:paddingTop="@dimen/magnification_setting_image_button_padding_vertical"
-            android:paddingBottom="@dimen/magnification_setting_image_button_padding_vertical"
             android:src="@drawable/ic_magnification_menu_medium"
             android:tint="@color/accessibility_magnification_image_button_tint"
             android:tintMode="src_atop" />
@@ -86,12 +81,8 @@
             android:layout_width="0dp"
             android:layout_height="@dimen/magnification_setting_image_button_height"
             android:layout_weight="1"
-            android:scaleType="fitCenter"
+            android:scaleType="center"
             android:background="@drawable/accessibility_magnification_setting_view_image_btn_bg"
-            android:paddingLeft="@dimen/magnification_setting_image_button_padding_horizontal"
-            android:paddingRight="@dimen/magnification_setting_image_button_padding_horizontal"
-            android:paddingTop="@dimen/magnification_setting_image_button_padding_vertical"
-            android:paddingBottom="@dimen/magnification_setting_image_button_padding_vertical"
             android:src="@drawable/ic_magnification_menu_large"
             android:tint="@color/accessibility_magnification_image_button_tint"
             android:tintMode="src_atop" />
@@ -101,16 +92,8 @@
             android:layout_width="0dp"
             android:layout_height="@dimen/magnification_setting_image_button_height"
             android:layout_weight="1"
-            android:scaleType="fitCenter"
+            android:scaleType="center"
             android:background="@drawable/accessibility_magnification_setting_view_image_btn_bg"
-            android:paddingLeft
-                ="@dimen/magnification_setting_image_button_open_in_full_padding_horizontal"
-            android:paddingRight
-                ="@dimen/magnification_setting_image_button_open_in_full_padding_horizontal"
-            android:paddingTop
-                ="@dimen/magnification_setting_image_button_open_in_full_padding_vertical"
-            android:paddingBottom
-                ="@dimen/magnification_setting_image_button_open_in_full_padding_vertical"
             android:src="@drawable/ic_open_in_full"
             android:tint="@color/accessibility_magnification_image_button_tint"
             android:tintMode="src_atop" />
@@ -128,7 +111,6 @@
             android:layout_width="0dp"
             android:layout_height="wrap_content"
             android:layout_weight="1"
-            android:singleLine="true"
             android:text="@string/accessibility_allow_diagonal_scrolling"
             android:textAppearance="@style/TextAppearance.MagnificationSetting.Title"
             android:layout_gravity="center_vertical" />
@@ -164,16 +146,11 @@
     <Button
         android:id="@+id/magnifier_done_button"
         android:background="@drawable/accessibility_window_magnification_button_done_bg"
-        android:minHeight="@dimen/magnification_setting_button_done_height"
-        android:layout_width="@dimen/magnification_setting_button_done_width"
+        android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="@string/accessibility_magnification_done"
         android:textAppearance="@style/TextAppearance.MagnificationSetting.DoneButton"
         android:focusable="true"
         android:layout_gravity="center_horizontal"
-        android:layout_marginTop="@dimen/magnification_setting_view_margin"
-        android:paddingLeft="@dimen/magnification_setting_button_done_padding_horizontal"
-        android:paddingRight="@dimen/magnification_setting_button_done_padding_horizontal"
-        android:paddingTop="@dimen/magnification_setting_button_done_padding_vertical"
-        android:paddingBottom="@dimen/magnification_setting_button_done_padding_vertical" />
+        android:layout_marginTop="@dimen/magnification_setting_view_margin"/>
 </LinearLayout>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index be9ef9d..6657544 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Aktiveer USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Kom meer te wete"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Skermkiekie"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock is gedeaktiveer"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"het \'n prent gestuur"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Stoor tans skermkiekie..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Stoor tans skermskoot in werkprofiel …"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"As jy met jou volgende poging \'n verkeerde PIN invoer, sal jou werkprofiel en die data daarvan uitgevee word."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"As jy met jou volgende poging \'n verkeerde wagwoord invoer, sal jou werkprofiel en die data daarvan uitgevee word."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Raak die vingerafdruksensor"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Vingerafdrukikoon"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Kan nie gesig herken nie. Gebruik eerder vingerafdruk."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Kennisgewingskerm."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Vinnige instellings."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Kitsinstellings en kennisgewingskerm."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Sluitskerm."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Werksluitskerm"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Maak toe"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Vergroot die hele skerm"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Vergroot \'n deel van die skerm"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Wissel"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Sleep hoek om grootte te verander"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Laat diagonale rollees toe"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Verander grootte"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Linkerhandvatsel"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Regterhandvatsel"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Onderste handvatsel"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Vergrootglasgrootte"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoem"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Medium"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kontrole bygevoeg.}other{# kontroles bygevoeg.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Verwyder"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Voeg <xliff:g id="APPNAME">%s</xliff:g> by?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Wanneer jy <xliff:g id="APPNAME">%s</xliff:g> byvoeg, kan dit kontroles en inhoud by hierdie paneel voeg. Jy kan in sommige apps kies watter kontroles hier verskyn."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Verwyder kontroles vir <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"As gunsteling gemerk"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"As gunsteling gemerk; posisie <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"As gunsteling ontmerk"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Ander"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Voeg by toestelkontroles"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Voeg by"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Verwyder"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Voorgestel deur <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Toestel is gesluit"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Wys en beheer toestelle van sluitskerm af?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Jy kan vir jou eksterne toestelle kontroles op die sluitskerm byvoeg.\n\nJou toestelprogram kan jou dalk toelaat om sommige toestelle te beheer sonder om jou foon of tablet te ontsluit.\n\nJy kan enige tyd in Instellings veranderings maak."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Beheer toestelle van sluitskerm af?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Jy kan sommige toestelle beheer sonder om jou foon of tablet te ontsluit.\n\nJou toestelprogram bepaal watter toestelle op dié manier beheer kan word."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Nee, dankie"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ja"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN bevat letters of simbole"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Voeg kontroles by"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Wysig kontroles"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Voeg app by"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Verwyder app"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Voeg uitvoere by"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Groep"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 toestel gekies"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 949f19a..1d414aa4 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"ዩኤስቢ አንቃ"</string>
     <string name="learn_more" msgid="4690632085667273811">"የበለጠ ለመረዳት"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ቅጽበታዊ ገጽ እይታ"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock ተሰናክሏል"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ምስል ተልኳል"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ቅጽበታዊ ገጽ እይታ በማስቀመጥ ላይ..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"ቅጽበታዊ ገጽ እይታን ወደ የስራ መገለጫ በማስቀመጥ ላይ…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"በሚቀጥለው ሙከራ ላይ ትክክል ያልሆነ ፒን ካስገቡ የእርስዎ የሥራ መገለጫ እና ውሂቡ ይሰረዛሉ።"</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"በሚቀጥለው ሙከራ ላይ ትክክል ያልሆነ የይለፍ ቃል ካስገቡ የእርስዎ የሥራ መገለጫ እና ውሂቡ ይሰረዛሉ።"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"የጣት አሻራ ዳሳሹን ይንኩ"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"የጣት አሻራ አዶ"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"መልክን መለየት አልተቻለም። በምትኩ የጣት አሻራ ይጠቀሙ።"</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"የማሳወቂያ ጥላ።"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ፈጣን ቅንብሮች።"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ፈጣን ቅንብሮች እና የማሳወቂያ ጥላ።"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ማያ ገጽ ቆልፍ።"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"የስራ ማያ ገጽ ቁልፍ"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"ዝጋ"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ሙሉ ገጽ እይታን ያጉሉ"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"የማያ ገጹን ክፍል አጉላ"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"ማብሪያ/ማጥፊያ"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"መጠን ለመቀየር ጠርዙን ይዘው ይጎትቱ"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"ሰያፍ ሽብለላን ፍቀድ"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"መጠን ቀይር"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"የግራ መያዣ"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"የቀኝ መያዣ"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"የታች መያዣ"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"የማጉያ መጠን"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"አጉላ"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"መካከለኛ"</string>
@@ -870,7 +873,10 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# ቁጥጥር ታክሏል።}one{# ቁጥጥር ታክሏል።}other{# ቁጥጥሮች ታክለዋል።}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"ተወግዷል"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> ይታከል?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g>ን ሲያክሉ መቆጣጠሪያዎችን እና ይዘትን ወደዚህ ፓነል ሊያክል ይችላል። በአንዳንድ መተግበሪያዎች ውስጥ የትኛዎቹ መቆጣጠሪያዎች እዚህ ላይ እንደሚታዩ መምረጥ ይችላሉ።"</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <!-- no translation found for controls_panel_remove_app_authorization (5920442084735364674) -->
+    <skip />
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"ተወዳጅ የተደረገ"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"ተወዳጅ ተደርጓል፣ አቋም <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ተወዳጅ አልተደረገም"</string>
@@ -888,12 +894,15 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ሌላ"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"ወደ የመሣሪያ መቆጣጠሪያዎች ያክሉ"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"አክል"</string>
+    <!-- no translation found for controls_dialog_remove (3775288002711561936) -->
+    <skip />
     <string name="controls_dialog_message" msgid="342066938390663844">"በ<xliff:g id="APP">%s</xliff:g> የተጠቆመ"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"መሣሪያ ተቆልፏል"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"ከማያ ገጽ ቆልፍ ላይ መሳሪያዎች ይታዩ እና ይቆጣጠሩ?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"ለውጫዊ መሳሪያዎችዎ መቆጣጠሪያዎችን ወደ ማያ ገጽ ቆልፍ ማከል ይችላሉ።\n\nየእርስዎ መሣሪያ መተግበሪያ የእርስዎን ስልክ ወይም ጡባዊ ሳይከፍቱ አንዳንድ መሣሪያዎችን እንዲቆጣጠሩ ሊፈቅድልዎ ይችላል።\n\nበቅንብሮች ውስጥ በማንኛውም ጊዜ ለውጦችን ማድረግ ይችላሉ።"</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"መሳሪያዎች ከማያ ገጽ ቆልፍ ይቆጣጠሩ?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"የእርስዎን ስልክ ወይም ጡባዊ ሳይከፍቱ አንዳንድ መሳሪያዎችን መቆጣጠር ይችላሉ።\n\nየእርስዎ መሣሪያ መተግበሪያ የትኞቹ መሣሪያዎች በዚህ መንገድ ሊቆጣጠሩ እንደሚችሉ ይወስናል።"</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"አይ፣ አመሰግናለሁ"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"አዎ"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"ፒን ፊደሎችን ወይም ምልክቶችን ይይዛል"</string>
@@ -941,6 +950,8 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"መቆጣጠሪያዎችን አክል"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"መቆጣጠሪያዎችን ያርትዑ"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"መተግበሪያ አክል"</string>
+    <!-- no translation found for controls_menu_remove (3006525275966023468) -->
+    <skip />
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"ውጽዓቶችን ያክሉ"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"ቡድን"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 መሣሪያ ተመርጧል"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 03925f7..d6a7a9a 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"‏تفعيل USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"مزيد من المعلومات"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"لقطة شاشة"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"‏تم إيقاف Smart Lock."</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"أرسَل صورة"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"جارٍ حفظ لقطة الشاشة..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"جارٍ حفظ لقطة الشاشة في الملف الشخصي للعمل…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"عند إدخال رقم تعريف شخصي غير صحيح في المحاولة التالية، سيتم حذف ملفك الشخصي للعمل وبياناته."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"عند إدخال كلمة مرور غير صحيحة في المحاولة التالية، سيتم حذف ملفك الشخصي للعمل وبياناته."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"المس أداة استشعار بصمة الإصبع"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"رمز بصمة الإصبع"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"يتعذّر التعرّف على الوجه. استخدِم بصمة الإصبع بدلاً من ذلك."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"مركز الإشعارات."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"الإعدادات السريعة."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"\"الإعدادات السريعة\" و\"مركز الإشعارات\""</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"شاشة القفل."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"شاشة قفل بيانات العمل"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"إغلاق"</string>
@@ -240,8 +239,8 @@
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"التدوير التلقائي للشاشة"</string>
     <string name="quick_settings_location_label" msgid="2621868789013389163">"الموقع الجغرافي"</string>
     <string name="quick_settings_screensaver_label" msgid="1495003469366524120">"شاشة الاستراحة"</string>
-    <string name="quick_settings_camera_label" msgid="5612076679385269339">"الوصول إلى الكاميرا"</string>
-    <string name="quick_settings_mic_label" msgid="8392773746295266375">"الوصول إلى الميكروفون"</string>
+    <string name="quick_settings_camera_label" msgid="5612076679385269339">"الكاميرا"</string>
+    <string name="quick_settings_mic_label" msgid="8392773746295266375">"الميكروفون"</string>
     <string name="quick_settings_camera_mic_available" msgid="1453719768420394314">"متاح"</string>
     <string name="quick_settings_camera_mic_blocked" msgid="4710884905006788281">"محظور"</string>
     <string name="quick_settings_media_device_label" msgid="8034019242363789941">"جهاز الوسائط"</string>
@@ -695,7 +694,7 @@
     <string name="right_keycode" msgid="2480715509844798438">"رمز مفتاح اليمين"</string>
     <string name="left_icon" msgid="5036278531966897006">"رمز اليسار"</string>
     <string name="right_icon" msgid="1103955040645237425">"رمز اليمين"</string>
-    <string name="drag_to_add_tiles" msgid="8933270127508303672">"اضغط باستمرار مع السحب لإضافة الميزات."</string>
+    <string name="drag_to_add_tiles" msgid="8933270127508303672">"اضغط باستمرار مع السحب لإضافة المربّعات"</string>
     <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"اضغط باستمرار مع السحب لإعادة ترتيب الميزات."</string>
     <string name="drag_to_remove_tiles" msgid="4682194717573850385">"اسحب هنا للإزالة"</string>
     <string name="drag_to_remove_disabled" msgid="933046987838658850">"الحدّ الأدنى من عدد المربعات الذي تحتاج إليه هو <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g>"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"تكبير الشاشة كلها"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"تكبير جزء من الشاشة"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"تبديل"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"اسحب الزاوية لتغيير الحجم."</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"السماح بالتمرير القطري"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"تغيير الحجم"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"المقبض الأيسر"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"المقبض الأيمن"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"المقبض السفلي"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"حجم مكبّر الشاشة"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"تكبير/تصغير"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"متوسط"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{تمت إضافة عنصر تحكّم واحد.}zero{تمت إضافة # عنصر تحكّم.}two{تمت إضافة عنصرَي تحكّم.}few{تمت إضافة # عناصر تحكّم.}many{تمت إضافة # عنصر تحكّم.}other{تمت إضافة # عنصر تحكّم.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"تمت الإزالة"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"هل تريد إضافة \"<xliff:g id="APPNAME">%s</xliff:g>\"؟"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"عند إضافة تطبيق \"<xliff:g id="APPNAME">%s</xliff:g>\"، يمكنه إضافة عناصر تحكّم ومحتوى إلى هذه اللوحة. في بعض التطبيقات، يمكنك اختيار عناصر التحكّم التي تظهر هنا."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"هل تريد إزالة عناصر التحكّم في \"<xliff:g id="APPNAME">%s</xliff:g>\"؟"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"تمت الإضافة إلى المفضّلة"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"تمت الإضافة إلى المفضّلة، الموضع <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"تمت الإزالة من المفضّلة"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"غير ذلك"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"إضافة إلى أدوات التحكم بالجهاز"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"إضافة"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"إزالة"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"اقتراح من <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"الجهاز مُقفل."</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"هل تريد عرض أجهزتك والتحكم فيها من شاشة القفل؟"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"يمكنك إضافة عناصر تحكم لشاشة القفل الخاصة بأجهزتك الخارجية.\n\nقد يسمح لك تطبيق الجهاز بالتحكم في بعض الأجهزة بدون فتح قفل هاتفك أو جهازك اللوحي.\n\nيمكنك إجراء التغييرات في أي وقت من الإعدادات."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"هل تريد التحكم في الأجهزة من شاشة القفل؟"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"يمكنك التحكم في بعض الأجهزة بدون فتح قفل هاتفك أو جهازك اللوحي.\n\nيحدِّد تطبيق الجهاز أيًا من الأجهزة يمكن التحكم فيه على هذا النحو."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"لا، شكرًا"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"نعم"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"يشتمل رقم التعريف الشخصي على أحرف أو رموز."</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"إضافة عناصر تحكّم"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"تعديل عناصر التحكّم"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"إضافة تطبيق"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"إزالة التطبيق"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"إضافة مخرجات"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"مجموعة"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"تم اختيار جهاز واحد."</string>
@@ -1111,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"التبديل إلى الملف الشخصي للعمل"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"إغلاق"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"إعدادات شاشة القفل"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"‏لا يتوفّر اتصال Wi-Fi."</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"استخدام الكاميرا محظور."</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"استخدام الكاميرا والميكروفون محظور."</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"استخدام الميكروفون محظور."</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"وضع الأولوية مفعّل."</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"‏ميزة لفت انتباه \"مساعد Google\" مفعّلة."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 9507cda..c90abb7 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USB সক্ষম কৰক"</string>
     <string name="learn_more" msgid="4690632085667273811">"অধিক জানক"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"স্ক্ৰীনশ্বট"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock অক্ষম কৰা হৈছে"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"এখন প্ৰতিচ্ছবি পঠিয়াইছে"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"স্ক্ৰীণশ্বট ছেভ কৰি থকা হৈছে…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"কৰ্মস্থানৰ প্ৰ’ফাইলত স্ক্ৰীনশ্বট ছেভ কৰি থকা হৈছে…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"আপুনি পৰৱৰ্তী প্ৰয়াসত এটা ভুল পিন দিলে, আপোনাৰ কৰ্মস্থানৰ প্ৰ’ফাইল আৰু ইয়াৰ ডেটা মচি পেলোৱা হ’ব।"</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"আপুনি পৰৱৰ্তী প্ৰয়াসত এটা ভুল পাছৱৰ্ড দিলে, আপোনাৰ কৰ্মস্থানৰ প্ৰ’ফাইল আৰু ইয়াৰ ডেটা মচি পেলোৱা হ’ব।"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ফিংগাৰপ্ৰিণ্ট ছেন্সৰটো স্পৰ্শ কৰক"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"ফিংগাৰপ্ৰিণ্ট আইকন"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"মুখাৱয়ব চিনিব নোৱাৰি। ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰক।"</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"জাননী পেনেল।"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ক্ষিপ্ৰ ছেটিং।"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ক্ষিপ্ৰ ছেটিং জাননী পেনেল।"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"বন্ধ স্ক্ৰীন।"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"কৰ্মস্থানৰ প্ৰ\'ফাইলৰ লক স্ক্ৰীন"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"বন্ধ কৰক"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"পূৰ্ণ স্ক্ৰীন বিবৰ্ধন কৰক"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"স্ক্ৰীনৰ কিছু অংশ বিবৰ্ধন কৰক"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"ছুইচ"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"আকাৰ সলনি কৰিবলৈ চুককেইটা টানি আনি এৰক"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"কৰ্ণডালৰ দিশত স্ক্ৰ’ল কৰাৰ সুবিধা"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"আকাৰ সলনি কৰক"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"বাওঁফালৰ হেণ্ডেল"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"সোঁফালৰ হেণ্ডেল"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"তলৰ হেণ্ডেল"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"বিবৰ্ধকৰ আকাৰ"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"জুম কৰক"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"মধ্যমীয়া"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# টা নিয়ন্ত্ৰণ যোগ দিয়া হৈছে।}one{# টা নিয়ন্ত্ৰণ যোগ দিয়া হৈছে।}other{# টা নিয়ন্ত্ৰণ যোগ দিয়া হৈছে।}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"আঁতৰোৱা হ’ল"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> যোগ দিবনে?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"আপুনি <xliff:g id="APPNAME">%s</xliff:g> যোগ দিলে, ই এই পেনেলত নিয়ন্ত্ৰণ আৰু সমল যোগ দিব পাৰে। কিছুমান এপত আপুনি কোনবোৰ নিয়ন্ত্ৰণ ইয়াত দেখা পোৱা যাব সেয়া বাছনি কৰিব পাৰে।"</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g>ৰ নিয়ন্ত্ৰণ আঁতৰাবনে?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"প্ৰিয় হিচাপে চিহ্নিত কৰা হ’ল"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"প্ৰিয় হিচাপে চিহ্নিত কৰা হ’ল, স্থান <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"অপ্ৰিয় হিচাপে চিহ্নিত কৰা হ’ল"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"অন্য"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"ডিভাইচৰ নিয়ন্ত্ৰণসমূহত যোগ দিয়ক"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"যোগ দিয়ক"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"আঁতৰাওক"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g>এ পৰামৰ্শ হিচাপে আগবঢ়োৱা"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"ডিভাইচ লক হৈ আছে"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"লক স্ক্ৰীনৰ পৰা ডিভাইচসমূহ লক আৰু নিয়ন্ত্ৰণ কৰিবনে?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"আপুনি লক স্ক্ৰীনত আপোনাৰ বাহ্যিক ডিভাইচৰ বাবে নিয়ন্ত্ৰণ যোগ দিব পাৰে।\n\nআপোনাৰ ডিভাইচ এপে আপোনাক আপোনাৰ ফ’ন অথবা টেবলেট আনলক নকৰাকৈ কিছুমান ডিভাইচ নিয়ন্ত্ৰণ কৰাৰ অনুমতি দিব পাৰে। \n\nআপুনি যিকোনো সময়তে ছেটিঙত সালসলনি কৰিব পাৰে।"</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"লক স্ক্ৰীনৰ পৰা ডিভাইচসমূহ নিয়ন্ত্ৰণ কৰিবনে?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"আপুনি আপোনাৰ ফ’ন অথবা টেবলেট আনলক নকৰাকৈ কিছুমান ডিভাইচ নিয়ন্ত্ৰণ কৰিব পাৰে।\n\nএইধৰণে কোনবোৰ ডিভাইচ নিয়ন্ত্ৰণ কৰিব পাৰি সেয়া আপোনাৰ ডিভাইচ এপে নিৰ্ধাৰণ কৰে।"</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"নালাগে, ধন্যবাদ"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"হয়"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"পিনত বৰ্ণ অথবা প্ৰতীকসমূহ থাকে"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"নিয়ন্ত্ৰণসমূহ যোগ দিয়ক"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"নিয়ন্ত্ৰণসমূহ সম্পাদনা কৰক"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"এপ্‌ যোগ দিয়ক"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"এপ্‌টো আঁতৰাওক"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"আউটপুটসমূহ যোগ দিয়ক"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"গোট"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"১ টা ডিভাইচ বাছনি কৰা হৈছে"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index fcee2e1..8970642 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USB-ni aktiv edin"</string>
     <string name="learn_more" msgid="4690632085667273811">"Ətraflı məlumat"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Skrinşot"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock deaktivdir"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"şəkil göndərdi"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Skrinşot yadda saxlanır..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"İş profili skrinşotu saxlanılır…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Növbəti cəhddə yanlış PIN daxil etsəniz, iş profili və datası silinəcək."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Növbəti cəhddə yanlış parol daxil etsəniz, iş profili və datası silinəcək."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Barmaq izi sensoruna klikləyin"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Barmaq izi ikonası"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Tanımaq olmur. Barmaq izini işlədin."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bildiriş kölgəsi."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Tez ayarlar."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Sürətli ayarlar və Bildiriş göstərişi."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Kilid ekranı."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ekran kilidi"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Qapadın"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Tam ekranı böyüdün"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ekran hissəsinin böyüdülməsi"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Dəyişdirici"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Ölçüsünü dəyişmək üçün küncündən sürüşdürün"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Diaqonal sürüşdürməyə icazə verin"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Ölçüsünü dəyişin"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Sol tutacaq"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Sağ tutacaq"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Alt tutacaq"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Böyüdücü ölçüsü"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoom"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Orta"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# nizamlayıcı əlavə edilib.}other{# nizamlayıcı əlavə edilib.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Silinib"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> əlavə edilsin?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> əlavə etdiyiniz zaman, o, bu panelə nizamlayıcılar və məzmun əlavə edə bilər. Bəzi tətbiqlərdə burada hansı nizamlayıcıların göstərilməsini seçə bilərsiniz."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> nizamlayıcıları silinsin?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Sevimlilərə əlavə edilib"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Sevimlilərə əlavə edilib, sıra: <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Sevimlilərdən silinib"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Digər"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Cihaz idarəetmələrinə əlavə edin"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Əlavə edin"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Silin"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> tərəfindən təklif edilib"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Cihaz kilidlənib"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Kilid ekranından cihazlar göstərilsin və idarə edilsin?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Xarici cihazlarınız üçün kilid ekranına nizamlayıcılar əlavə edə bilərsiniz.\n\nCihaz tətbiqiniz sizə telefon və ya planşetinizin kilidini açmadan bəzi cihazları idarə etməyə imkan verə bilər.\n\nİstənilən vaxt Ayarlarda dəyişiklik edə bilərsiniz."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Cihazları kilid ekranından idarə etmək istəyirsiniz?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Telefon və ya planşetinizin kilidini açmadan bəzi cihazları idarə edə bilərsiniz.\n\nCihaz tətbiqiniz hansı cihazların bu şəkildə idarə oluna biləcəyini müəyyən edir."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Xeyr, təşəkkür"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Bəli"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN hərflər və ya simvollar ehtiva edir"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Vidcet əlavə edin"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Vidcetlərə düzəliş edin"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Tətbiq əlavə edin"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Tətbiqi silin"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Nəticələri əlavə edin"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Qrup"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 cihaz seçilib"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 82c9bbd..6dbe85b 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Omogući USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Saznajte više"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Snimak ekrana"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock je onemogućen"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"je poslao/la sliku"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Čuvanje snimka ekrana..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Snimak ekrana se čuva na poslovnom profilu…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Ako unesete netačan PIN pri sledećem pokušaju, izbrisaćemo poslovni profil i njegove podatke."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Ako unesete netačnu lozinku pri sledećem pokušaju, izbrisaćemo poslovni profil i njegove podatke."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Dodirnite senzor za otisak prsta"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikona otiska prsta"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Lice nije prepoznato. Koristite otisak prsta."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -407,7 +407,7 @@
     <string name="media_projection_action_text" msgid="3634906766918186440">"Započni"</string>
     <string name="empty_shade_text" msgid="8935967157319717412">"Nema obaveštenja"</string>
     <string name="no_unseen_notif_text" msgid="395512586119868682">"Nema novih obaveštenja"</string>
-    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Otključajte da vidite starija obaveštenja"</string>
+    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Otključajte za starija obaveštenja"</string>
     <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Ovim uređajem upravlja roditelj"</string>
     <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Organizacija je vlasnik uređaja i može da nadgleda mrežni saobraćaj"</string>
     <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> je vlasnik ovog uređaja i može da nadgleda mrežni saobraćaj"</string>
@@ -834,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Uvećajte ceo ekran"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Uvećajte deo ekrana"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Pređi"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Prevucite ugao da biste promenili veličinu"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Dozvoli dijagonalno skrolovanje"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Promeni veličinu"</string>
@@ -843,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Leva ručica"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Desna ručica"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Donja ručica"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Veličina lupe"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zumiranje"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Srednje"</string>
@@ -869,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kontrola je dodata.}one{# kontrola je dodata.}few{# kontrole su dodate.}other{# kontrola je dodato.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Uklonjeno"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Želite li da dodate <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Kada dodate aplikaciju <xliff:g id="APPNAME">%s</xliff:g>, ona može da dodaje kontrole i sadržaj u ovo okno. U nekim aplikacijama možete da izaberete koje će se kontrole ovde prikazivati."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Želite da uklonite kontrole za <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Označeno je kao omiljeno"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Označeno je kao omiljeno, <xliff:g id="NUMBER">%d</xliff:g>. pozicija"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Uklonjeno je iz omiljenih"</string>
@@ -887,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Drugo"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Dodajte u kontrole uređaja"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Dodaj"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Ukloni"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Predlaže <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Uređaj je zaključan"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Želite li da prikazujete i kontrolišete uređaje sa zaključanog ekrana?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Možete da dodate kontrole za spoljne uređaje na zaključani ekran.\n\nAplikacija na uređaju može da vam omogući da kontrolišete neke uređaje bez otključavanja telefona ili tableta.\n\nTo možete da promenite kad god želite u Podešavanjima."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Želite li da kontrolišete uređaje sa zaključanog ekrana?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Neke uređaje možete da kontrolišete bez otključavanja telefona ili tableta.\n\nAplikacija na uređaju određuje koji uređaji mogu da se kontrolišu na ovaj način."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Ne, hvala"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Da"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN sadrži slova ili simbole"</string>
@@ -940,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Dodaj kontrole"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Izmeni kontrole"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Dodaj aplikaciju"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Ukloni aplikaciju"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Dodajte izlaze"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupa"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Izabran je 1 uređaj"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 12ce259..8ff9fc2 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Уключыць USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Даведацца больш"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Здымак экрана"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Функцыя \"Smart Lock\" адключана"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"адпраўлены відарыс"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Захаванне скрыншота..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Захаванне здымка экрана ў працоўны профіль…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Калі вы ўведзяце няправільны PIN-код яшчэ раз, ваш працоўны профіль і звязаныя з ім даныя будуць выдалены."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Калі вы ўведзяце няправільны пароль яшчэ раз, ваш працоўны профіль і звязаныя з ім даныя будуць выдалены."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Дакраніцеся да сканера адбіткаў пальцаў"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Значок адбіткаў пальцаў"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Твар не распазнаны. Скарыстайце адбітак пальца."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Цень апавяшчэння.."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Хуткія налады."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Хуткія налады і шчыток апавяшчэнняў."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Экран блакіроўкі."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Экран блакіроўкі дзейнасці"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Закрыць"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Павялічыць увесь экран"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Павялічыць частку экрана"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Пераключальнік"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Каб змяніць памер, перацягніце вугал"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Дазволіць прагортванне па дыяганалі"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Змяніць памер"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Левы маркер"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Правы маркер"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Ніжні маркер"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Памер лупы"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Маштаб"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Сярэдні"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Дададзены # элемент кіравання.}one{Дададзена # элемента кіравання.}few{Дададзена # элементы кіравання.}many{Дададзена # элементаў кіравання.}other{Дададзена # элемента кіравання.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Выдалена"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Дадаць праграму \"<xliff:g id="APPNAME">%s</xliff:g>\"?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Калі вы дадасце праграму \"<xliff:g id="APPNAME">%s</xliff:g>\", яна зможа дадаваць на гэту панэль налады і змесціва. Для некаторых праграм вы зможаце выбраць, якія налады будуць тут паказвацца."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Выдаліць налады для <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Дададзена ў абранае"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Дададзена ў абранае, пазіцыя <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Выдалена з абранага"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Іншае"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Дадаць у элементы кіравання прыладай"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Дадаць"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Выдаліць"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Прапанавана праграмай \"<xliff:g id="APP">%s</xliff:g>\""</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Прылада блакіравана"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Паказваць прылады і кіраваць імі з экрана блакіроўкі?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Вы можаце дадаць на экран блакіроўкі элементы кіравання знешнімі прыладамі.\n\nДзякуючы праграме на вашай прыладзе вы можаце кіраваць некаторымі прыладамі без разблакіроўкі тэлефона ці планшэта.\n\nУнесці змяненні можна ў любы час у Наладах."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Кіраваць прыладамі з экрана блакіроўкі?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Вы можаце кіраваць некаторымі прыладамі без разблакіроўкі тэлефона ці планшэта.\n\nПраграма на вашай прыладзе вызначае, якімі прыладамі можна кіраваць такім спосабам."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Не, дзякуй"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Так"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN-код складаецца з літар або знакаў"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Дадаць элементы кіравання"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Змяніць элементы кіравання"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Дадаць праграму"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Выдаліць праграму"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Дадайце прылады вываду"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Група"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Выбрана 1 прылада"</string>
@@ -1111,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Пераключыцца на працоўны профіль"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Закрыць"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Налады экрана блакіроўкі"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Сетка Wi-Fi недаступная"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камера заблакіравана"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камера і мікрафон заблакіраваны"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Мікрафон заблакіраваны"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Прыярытэтны рэжым уключаны"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Памочнік гатовы выконваць каманды"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 9ba041e..efa4113d 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Активиране на USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Научете повече"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Екранна снимка"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Функцията Smart Lock е деактивирана"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"изпратено изображение"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Екранната снимка се запазва..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Екранната снимка се запазва в служебния профил…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Ако въведете неправилен ПИН код при следващия опит, служебният ви потребителски профил и данните в него ще бъдат изтрити."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Ако въведете неправилна парола при следващия опит, служебният ви потребителски профил и данните в него ще бъдат изтрити."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Докоснете сензора за отпечатъци"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Икона за отпечатък"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Лицето не е разпознато. Използвайте отпечатък."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Падащ панел с известия."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Бързи настройки."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Падащ панел с бързи настройки и известия."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Заключване на екрана."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Заключен екран на служебния профил"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Затваряне"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Увеличаване на целия екран"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Увеличаване на част от екрана"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Превключване"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Плъзнете ъгъла за преоразмеряване"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Разрешаване на диагонално превъртане"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Преоразмеряване"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Манипулатор вляво"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Манипулатор вдясно"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Манипулатор в долната част"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Размер на лупата"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Промяна на мащаба"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Среден"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Добавена е # контрола.}other{Добавени са # контроли.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Премахнато"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Да се добави ли <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Когато добавите <xliff:g id="APPNAME">%s</xliff:g>, приложението може да добави контроли и съдържание към този панел. Някои приложения ви дават възможност да избирате кои контроли да се показват тук."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Да се премахнат ли контролите за <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Означено като любимо"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Означено като любимо – позиция <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Не е означено като любимо"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Друго"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Добавяне към контролите за устройството"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Добавяне"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Премахване"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Предложено от <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"У-вото е заключено"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Да се показват ли устройствата на заключения екран и да се контролират ли оттам?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Можете да добавите към заключения екран контроли за външните си устройства.\n\nПриложението на устройството ви може да ви дава възможност да управлявате някои устройства, без да отключвате телефона или таблета си.\n\nПо всяко време можете да правите промени в „Настройки“."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Да се контролират ли устройствата от заключения екран?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Имате възможност да контролирате някои устройства, без да отключвате телефона или таблета си.\n\nПриложението на устройството ви определя кои устройства могат да бъдат контролирани по този начин."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Не, благодаря"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Да"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"ПИН кодът съдържа букви или символи"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Добавяне на контроли"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Редактиране на контролите"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Добавяне на приложение"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Премахване на приложението"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Добавяне на изходящи устройства"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Група"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 избрано устройство"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index dbc3a52..87e0a1d 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"ইউএসবি চালু করুন"</string>
     <string name="learn_more" msgid="4690632085667273811">"আরও জানুন"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"স্ক্রিনশট নিন"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock বন্ধ করা হয়েছে"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"একটি ছবি পাঠানো হয়েছে"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"স্ক্রিনশট সেভ করা হচ্ছে..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"অফিস প্রোফাইলে স্ক্রিনশট সেভ করা হচ্ছে…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"আপনি পরের বারও ভুল পিন দিলে আপনার অফিস প্রোফাইল এবং তার ডেটা মুছে দেওয়া হবে।"</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"আপনি পরের বারও ভুল পাসওয়ার্ড দিলে আপনার অফিস প্রোফাইল এবং তার ডেটা মুছে দেওয়া হবে।"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"আঙ্গুলের ছাপের সেন্সর স্পর্শ করুন"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"আঙ্গুলের ছাপের আইকন"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"মুখ শনাক্ত করতে পারছি না। পরিবর্তে আঙ্গুলের ছাপ ব্যবহার করুন।"</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"বিজ্ঞপ্তি শেড৷"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"দ্রুত সেটিংস৷"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"দ্রুত সেটিংস এবং বিজ্ঞপ্তি শেড।"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"লক স্ক্রিন।"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"কর্মস্থলের স্ক্রিন লক"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"বন্ধ করুন"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"সম্পূর্ণ স্ক্রিন বড় করে দেখা"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"স্ক্রিনের কিছুটা অংশ বড় করুন"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"বদল করুন"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"ছোট বড় করার জন্য কোণ টেনে আনুন"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"কোণাকুণি স্ক্রল করার অনুমতি দেওয়া"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"ছোট বড় করা"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"বাঁদিকের হ্যান্ডেল"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"ডানদিকের হ্যান্ডেল"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"নিচের হ্যান্ডেল"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"ম্যাগনিফায়ার সাইজ"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"জুম"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"মাঝারি"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{#টি কন্ট্রোল যোগ করা হয়েছে।}one{#টি কন্ট্রোল যোগ করা হয়েছে।}other{#টি কন্ট্রোল যোগ করা হয়েছে।}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"সরানো হয়েছে"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> যোগ করবেন?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"আপনি <xliff:g id="APPNAME">%s</xliff:g> যোগ করলে, এই প্যানেলে এটি কন্ট্রোল ও কন্টেন্ট যোগ করতে পারবে। কিছু অ্যাপের ক্ষেত্রে, এখানে কোন কোন কন্ট্রোল দেখা যাবে আপনি তা নিয়ন্ত্রণ করতে পারবেন।"</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g>-এর জন্য নিয়ন্ত্রণ সরিয়ে দেবেন?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"পছন্দসই হিসেবে চিহ্নিত করেছেন"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"পছন্দসই হিসেবে চিহ্নিত করেছেন, অবস্থান <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"পছন্দসই থেকে সরিয়ে দিয়েছেন"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"অন্য"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"ডিভাইস কন্ট্রোলে যোগ করুন"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"যোগ করুন"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"সরিয়ে দিন"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> সাজেস্ট করেছে"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"ডিভাইস লক করা আছে"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"লক স্ক্রিন থেকে ডিভাইস দেখতে এবং নিয়ন্ত্রণ করতে চান?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"লক স্ক্রিনে আপনার বাইরের ডিভাইসের জন্য কন্ট্রোল যোগ করা যাবে।\n\nআপনার ফোন বা ট্যাবলেট আনলক না করেই আপনার ডিভাইস অ্যাপ হয়ত কিছু ডিভাইস নিয়ন্ত্রণ করার সুবিধা দেবে\n\nসেটিংস থেকে যেকোনও সময়ে আপনি পরিবর্তন করতে পারবেন।"</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"লক স্ক্রিন থেকে ডিভাইস নিয়ন্ত্রণ করতে চান?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"আপনি ফোন বা ট্যাবলেট আনলক না করেই কিছু ডিভাইস নিয়ন্ত্রণ করতে পারবেন।\n\nএইভাবে কোন ডিভাইস নিয়ন্ত্রণ করা হবে সেটি আপনার ডিভাইস অ্যাপ ঠিক করে।"</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"না থাক"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"হ্যাঁ"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"পিন-এ অক্ষর বা চিহ্ন রয়েছে"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"কন্ট্রোল যোগ করুন"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"কন্ট্রোল এডিট করুন"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"অ্যাপ যোগ করুন"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"অ্যাপটি সরিয়ে দিন"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"আউটপুট যোগ করুন"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"গ্রুপ"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"১টি ডিভাইস বেছে নেওয়া হয়েছে"</string>
@@ -1111,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"অফিস প্রোফাইলে পাল্টে নিন"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"বন্ধ করুন"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"লক স্ক্রিন সেটিংস"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ওয়াই-ফাই উপলভ্য নয়"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ক্যামেরার অ্যাক্সেস ব্লক করা আছে"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ক্যামেরা এবং মাইক্রোফোনের অ্যাক্সেস ব্লক করা আছে"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"মাইক্রোফোনের অ্যাক্সেস ব্লক করা আছে"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"\'প্রায়োরিটি\' মোড চালু করা আছে"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"অ্যাসিস্ট্যান্ট আপনার কথা শোনার জন্য চালু করা আছে"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 8d4a0dd..1dfaa98 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Omogući USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Saznajte više"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Snimak ekrana"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock je onemogućen"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"je poslao/la sliku"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Spašavanje snimka ekrana..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Pohranjivanje snimka ekrana na radni profil…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Ako u sljedećem pokušaju unesete neispravan PIN, vaš radni profil i njegovi podaci će se izbrisati."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Ako u sljedećem pokušaju unesete neispravnu lozinku, vaš radni profil i njegovi podaci će se izbrisati."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Dodirnite senzor za otisak prsta"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikona za otisak prsta"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nije moguće prepoznati lice. Koristite otisak prsta."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,7 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Obavještenja sa sjenčenjem."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Brze postavke."</string>
-    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Brze postavke i zaslon obavijesti."</string>
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Brze postavke i lokacija za obavještenja."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Zaključan ekran."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Zaključan ekran radnog profila"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Zatvori"</string>
@@ -834,6 +834,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Uvećavanje prikaza preko cijelog ekrana"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Uvećavanje dijela ekrana"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Prekidač"</string>
+    <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Otvori postavke povećavanja"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Prevucite ugao da promijenite veličinu"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Dozvoli dijagonalno klizanje"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Promijeni veličinu"</string>
@@ -843,6 +844,7 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Lijeva ručica"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Desna ručica"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Donja ručica"</string>
+    <string name="accessibility_magnification_settings_panel_description" msgid="8174187340747846953">"Postavke povećavanja"</string>
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Veličina povećala"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zumiranje"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Srednje"</string>
@@ -869,7 +871,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Dodana je # kontrola.}one{Dodana je # kontrola.}few{Dodane su # kontrole.}other{Dodano je # kontrola.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Uklonjeno"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Dodati aplikaciju <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Kada dodate aplikaciju <xliff:g id="APPNAME">%s</xliff:g>, ona može dodavati kontrole i sadržaj na ovu ploču. U nekim aplikacijama možete odabrati koje kontrole se prikazuju ovdje."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Ukloniti kontrole za aplikaciju <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Dodano u omiljeno"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Dodano u omiljeno, pozicija <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Uklonjeno iz omiljenog"</string>
@@ -887,12 +891,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Drugo"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Dodajte u kontrole uređaja"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Dodaj"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Uklanjanje"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Predlaže <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Uređaj je zaključan"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Prikazati uređaje i kontrolirati njima sa zaključanog ekrana?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Na zaključani ekran možete dodati kontrole za eksterne uređaje.\n\nAplikacija vašeg uređaja vam može omogućiti da kontrolirate određene uređaje bez otključavanja telefona ili tableta.\n\nPromjene možete izvršiti bilo kada u Postavkama."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Kontrolirati uređaje sa zaključanog ekrana?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Neke uređaje možete kontrolirati bez otključavanja telefona ili tableta.\n\nAplikacija vašeg uređaja određuje koji uređaji se mogu kontrolirati na ovaj način."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Ne, hvala"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Da"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN sadrži slova ili simbole"</string>
@@ -940,6 +946,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Dodaj kontrole"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Uredi kontrole"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Dodaj aplikaciju"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Ukloni aplikaciju"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Dodajte izlaze"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupa"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Odabran je 1 uređaj"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index cc87895..47876fe 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Activa l\'USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Més informació"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Captura de pantalla"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock desactivat"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ha enviat una imatge"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"S\'està desant la captura de pantalla..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"S\'està desant la captura al perfil de treball…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Si tornes a introduir un PIN incorrecte, se suprimirà el perfil de treball i les dades que contingui."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Si tornes a introduir una contrasenya incorrecta, se suprimirà el perfil de treball i les dades que contingui."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Toca el sensor d\'empremtes digitals"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Icona d\'empremta digital"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"No podem detectar la cara. Usa l\'empremta digital."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Àrea de notificacions"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configuració ràpida"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configuració ràpida i àrea de notificacions."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Pantalla de bloqueig"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Pantalla de bloqueig per a la feina"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Tanca"</string>
@@ -408,7 +407,7 @@
     <string name="media_projection_action_text" msgid="3634906766918186440">"Comença ara"</string>
     <string name="empty_shade_text" msgid="8935967157319717412">"No hi ha cap notificació"</string>
     <string name="no_unseen_notif_text" msgid="395512586119868682">"No hi ha cap notificació nova"</string>
-    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloq. per veure notificacions antigues"</string>
+    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloqueja per veure notif. anteriors"</string>
     <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Els teus pares gestionen aquest dispositiu"</string>
     <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"La teva organització és propietària del dispositiu i és possible que supervisi el trànsit de xarxa"</string>
     <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> és propietària d\'aquest dispositiu i és possible que supervisi el trànsit de xarxa"</string>
@@ -716,7 +715,7 @@
     <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"suprimir el mosaic"</string>
     <string name="accessibility_qs_edit_tile_add_action" msgid="5051211910345301833">"afegir un mosaic al final"</string>
     <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Mou el mosaic"</string>
-    <string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Afegeix un mosaic"</string>
+    <string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Afegeix una icona"</string>
     <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mou a la posició <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Afegeix a la posició <xliff:g id="POSITION">%1$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Posició <xliff:g id="POSITION">%1$d</xliff:g>"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Amplia la pantalla completa"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Amplia una part de la pantalla"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Canvia"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Arrossega el cantó per canviar la mida"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Permet el desplaçament en diagonal"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Canvia la mida"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Ansa esquerra"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Ansa dreta"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Ansa inferior"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Mida de la lupa"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoom"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Normal"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{S\'ha afegit # control.}many{S\'han afegit # controls.}other{S\'han afegit # controls.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Suprimit"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Vols afegir <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"En afegir <xliff:g id="APPNAME">%s</xliff:g>, podrà afegir controls i contingut en aquest tauler. En algunes aplicacions, pots triar quins controls es mostren aquí."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Vols suprimir els controls per a <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Afegit als preferits"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Afegit als preferits, posició <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Suprimit dels preferits"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Altres"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Afegeix als controls de dispositius"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Afegeix"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Suprimeix"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Suggerit per <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Dispositiu bloquejat"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Vols mostrar i controlar dispositius a la pantalla de bloqueig?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Pots afegir controls dels teus dispositius externs a la pantalla de bloqueig.\n\nL\'aplicació del dispositiu et pot permetre controlar alguns dispositius sense desbloquejar el telèfon o la tauleta.\n\nPots fer canvis en qualsevol moment a Configuració."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Vols controlar dispositius des de la pantalla de bloqueig?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Pots controlar alguns dispositius sense desbloquejar el telèfon o la tauleta.\n\nL\'aplicació del dispositiu determina quins dispositius es poden controlar d\'aquesta manera."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"No, gràcies"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Sí"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"El PIN conté lletres o símbols"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Afegeix controls"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Edita els controls"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Afegeix una aplicació"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Suprimeix l\'aplicació"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Afegeix sortides"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grup"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositiu seleccionat"</string>
@@ -1111,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Canvia al perfil de treball"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Tanca"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Configuració pantalla de bloqueig"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"No hi ha cap Wi‑Fi disponible"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"La càmera està bloquejada"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"La càmera i el micròfon estan bloquejats"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"El micròfon està bloquejat"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"El mode Prioritat està activat"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"L\'Assistent està activat"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index e07a892..763d7f0 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Aktivovat USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Další informace"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Snímek obrazovky"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Funkce Smart Lock je deaktivována"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"odesílá obrázek"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Ukládání snímku obrazovky..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Ukládání snímku obrazovky do pracovního profilu…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Pokud při příštím pokusu zadáte nesprávný PIN, váš pracovní profil a přidružená data budou smazána."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Pokud při příštím pokusu zadáte nesprávné heslo, váš pracovní profil a přidružená data budou smazána."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Dotkněte se snímače otisků prstů"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikona otisku prstu"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Obličej se nepodařilo rozpoznat. Použijte místo něj otisk prstu."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Panel oznámení."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Rychlé nastavení."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Rychlé nastavení a panel oznámení"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Obrazovka uzamčení"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Obrazovka uzamčení pracovního profilu"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Zavřít"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Zvětšit celou obrazovku"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Zvětšit část obrazovky"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Přepnout"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Velikost změníte přetažením rohu"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Povolit diagonální posouvání"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Změnit velikost"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Levý úchyt"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Pravý úchyt"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Spodní úchyt"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Velikost lupy"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Změna velikosti zobrazení"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Střední"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Byl přidán # ovládací prvek.}few{Byly přidány # ovládací prvky.}many{Bylo přidáno # ovládacího prvku.}other{Bylo přidáno # ovládacích prvků.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Odstraněno"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Přidat aplikaci <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Když přidáte aplikaci <xliff:g id="APPNAME">%s</xliff:g>, může do tohoto panelu přidat ovládací prvky a obsah. V některých aplikacích si můžete vybrat, které ovládací prvky se zde zobrazí."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Odstranit ovládací prvky aplikace <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Přidáno do oblíbených"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Přidáno do oblíbených na pozici <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Odebráno z oblíbených"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Jiné"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Přidání ovládání zařízení"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Přidat"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Odstranit"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Návrh z aplikace <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Zařízení uzamčeno"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Zobrazovat a ovládat zařízení z obrazovky uzamčení?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Na obrazovku uzamčení můžete přidat ovládací prvky pro svá externí zařízení.\n\nAplikace zařízení vám může umožnit ovládat některá zařízení bez odemykání telefonu nebo tabletu.\n\nZměny můžete kdykoli provést v Nastavení."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Ovládat zařízení z obrazovky uzamčení?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Některá zařízení můžete ovládat bez odemykání telefonu nebo tabletu.\n\nAplikace zařízení určuje, která zařízení lze tímto způsobem ovládat."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Ne, díky"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ano"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Kód PIN obsahuje písmena nebo symboly"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Přidat ovládací prvky"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Upravit ovládací prvky"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Přidat aplikaci"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Odstranit aplikaci"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Přidání výstupů"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Skupina"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Je vybráno 1 zařízení"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 4b10ddf..bcd44ea 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Aktivér USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Få flere oplysninger"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock er deaktiveret"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"sendte et billede"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Gemmer screenshot..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Gemmer screenshot på din arbejdsprofil…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Hvis du angiver en forkert pinkode i næste forsøg, slettes din arbejdsprofil og de tilhørende data."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Hvis du angiver en forkert adgangskode i næste forsøg, slettes din arbejdsprofil og de tilhørende data."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Sæt fingeren på fingeraftrykssensoren"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikon for fingeraftryk"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ansigtet kan ikke genkendes. Brug fingeraftryk i stedet."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Notifikationspanel."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Kvikmenu."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Kvikmenu og notifikationspanel."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Låseskærm."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Låseskærm til arbejde"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Luk"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Forstør hele skærmen"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Forstør en del af skærmen"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Skift"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Træk i hjørnet for at justere størrelsen"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Tillad diagonal rulning"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Juster"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Venstre håndtag"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Højre håndtag"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Nedre håndtag"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Lupstørrelse"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoom"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Mellem"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# styringselement er tilføjet.}one{# styringselement er tilføjet.}other{# styringselementer er tilføjet.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Fjernet"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Vil du tilføje <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Når du tilføjer <xliff:g id="APPNAME">%s</xliff:g>, kan den føje styringselementer og indhold til dette panel. I nogle apps kan du vælge, hvilke styringselementer der vises her."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Vil du fjerne styringselementerne for <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Angivet som favorit"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Angivet som favorit. Position <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Fjernet fra favoritter"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Andre"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Føj til enhedsstyring"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Tilføj"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Fjern"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Foreslået af <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Enheden er låst"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Vil du se og styre enheder via låseskærmen?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Du kan tilføje styringselementer til dine eksterne enheder på låseskærmen.\n\nMed din enhedsapp kan du muligvis styre visse enheder uden at låse op for din telefon eller tablet.\n\nDu kan til enhver tid foretage ændringer i Indstillinger."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Vil du styre enheder via låseskærmen?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Du kan styre visse enheder uden at låse op for din telefon eller tablet.\n\nDin enhedsapp bestemmer, hvilke enheder der kan styres på denne måde."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Nej tak"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ja"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Pinkoden indeholder bogstaver eller symboler"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Tilføj styring"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Rediger styring"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Tilføj app"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Fjern app"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Tilføj medieudgange"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Gruppe"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Der er valgt 1 enhed"</string>
@@ -1111,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Skift til arbejdsprofil"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Luk"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Indstillinger for låseskærm"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi er ikke tilgængeligt"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kameraet er blokeret"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Der er blokeret for kameraet og mikrofonen"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofonen er blokeret"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritetstilstand er aktiveret"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistent lytter"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index f8c02e3..b8d0a96 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USB aktivieren"</string>
     <string name="learn_more" msgid="4690632085667273811">"Weitere Informationen"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock deaktiviert"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"Bild gesendet"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Screenshot wird gespeichert..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Screenshot wird in Arbeitsprofil gespeichert…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Wenn du beim nächsten Versuch eine falsche PIN eingibst, werden dein Arbeitsprofil und die zugehörigen Daten gelöscht."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Wenn du beim nächsten Versuch ein falsches Passwort eingibst, werden dein Arbeitsprofil und die zugehörigen Daten gelöscht."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Berühre den Fingerabdrucksensor"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Fingerabdruck-Symbol"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Gesicht wurde nicht erkannt. Verwende stattdessen den Fingerabdruck."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Benachrichtigungsleiste"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Schnelleinstellungen"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Schnelleinstellungen und Benachrichtigungsleiste."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Sperrbildschirm"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Sperrbildschirm für Arbeitsprofil"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Schließen"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ganzen Bildschirm vergrößern"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Teil des Bildschirms vergrößern"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Schalter"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Zum Anpassen der Größe Ecke ziehen"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Diagonales Scrollen erlauben"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Größe ändern"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Linker Ziehpunkt"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Rechter Ziehpunkt"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Unterer Ziehpunkt"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Lupengröße"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoom"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Mittel"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# Steuerelement hinzugefügt.}other{# Steuerelemente hinzugefügt.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Entfernt"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> hinzufügen?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Wenn du <xliff:g id="APPNAME">%s</xliff:g> hinzufügst, kann diese App Einstellungen und Inhalte zu diesem Bereich hinzufügen. In einigen Apps kannst du festlegen, welche Einstellungen hier angezeigt werden sollen."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Einstellungen für <xliff:g id="APPNAME">%s</xliff:g> entfernen?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Zu Favoriten hinzugefügt"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Zu Favoriten hinzugefügt, Position <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Aus Favoriten entfernt"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Andere"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Zur Gerätesteuerung hinzufügen"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Hinzufügen"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Entfernen"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Vorgeschlagen von <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Gerät gesperrt"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Geräte auf Sperrbildschirm anzeigen und steuern?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Du kannst dem Sperrbildschirm Steuerelemente für deine externen Geräte hinzufügen.\n\nDie App deines Geräts ermöglicht dir eventuell, einige Geräte zu steuern, ohne dein Smartphone oder Tablet zu entsperren.\n\nDu kannst jederzeit Änderungen in den Einstellungen vornehmen."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Geräte über den Sperrbildschirm steuern?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Du kannst einige Geräte steuern, ohne das Smartphone oder Tablet zu entsperren.\n\nDie App deines Geräts bestimmt, welche Geräte auf diese Weise gesteuert werden können."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Nein danke"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ja"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Die PIN enthält Buchstaben oder Symbole"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Steuerelemente hinzufügen"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Steuerelemente bearbeiten"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"App hinzufügen"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"App entfernen"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Ausgabegeräte hinzufügen"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Gruppe"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Ein Gerät ausgewählt"</string>
@@ -1111,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Zum Arbeitsprofil wechseln"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Schließen"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Sperrbildschirm-Einstellungen"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Kein WLAN verfügbar"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera blockiert"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera und Mikrofon blockiert"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon blockiert"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritätsmodus an"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant-Aktivierung an"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index f2fb5b8..d648682 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Ενεργοποίηση USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Μάθετε περισσότερα"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Στιγμιότυπο οθόνης"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Το Smart Lock έχει απενεργοποιηθεί"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"έστειλε μια εικόνα"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Αποθήκευση στιγμιότυπου οθόνης..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Αποθήκευση στιγμιότ. οθόνης στο προφίλ εργασίας…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Εάν εισαγάγετε εσφαλμένο PIN στην επόμενη προσπάθεια, το προφίλ εργασίας σας και τα δεδομένα του θα διαγραφούν."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Εάν εισαγάγετε εσφαλμένο κωδικό πρόσβασης στην επόμενη προσπάθεια, το προφίλ εργασίας σας και τα δεδομένα του θα διαγραφούν."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Αγγίξτε τον αισθητήρα δακτυλικού αποτυπώματος"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Εικονίδιο δακτυλικών αποτυπωμάτων"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Το πρόσωπο δεν αναγνωρίζεται. Χρησιμ. δακτ. αποτ."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Πλαίσιο σκίασης ειδοποιήσεων."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Γρήγορες ρυθμίσεις."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Γρήγορες ρυθμίσεις και πλαίσιο σκίασης ειδοποιήσεων."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Οθόνη κλειδώματος"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Οθόνη κλειδωμένης εργασίας"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Κλείσιμο"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Μεγέθυνση πλήρους οθόνης"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Μεγέθυνση μέρους της οθόνης"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Εναλλαγή"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Σύρετε τη γωνία για αλλαγή μεγέθους"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Να επιτρέπεται η διαγώνια κύλιση"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Αλλαγή μεγέθους"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Αριστερή λαβή"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Δεξιά λαβή"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Κάτω λαβή"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Μέγεθος μεγεθυντικού φακού"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Εστίαση"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Μέτριο"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Προστέθηκε # στοιχείο ελέγχου.}other{Προστέθηκαν # στοιχεία ελέγχου.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Καταργήθηκε"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Προσθήκη <xliff:g id="APPNAME">%s</xliff:g>;"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Όταν προσθέσετε την εφαρμογή <xliff:g id="APPNAME">%s</xliff:g>, μπορεί να προσθέσει στοιχεία ελέγχου και περιεχόμενο σε αυτό το πλαίσιο. Σε ορισμένες εφαρμογές, μπορείτε να επιλέξετε ποια στοιχεία ελέγχου θα εμφανίζονται εδώ."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Κατάργηση στοιχείων ελέγχου για την εφαρμογή <xliff:g id="APPNAME">%s</xliff:g>;"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Προστέθηκε στα αγαπημένα"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Προστέθηκε στα αγαπημένα, στη θέση <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Αφαιρέθηκε από τα αγαπημένα"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Άλλο"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Προσθήκη στα στοιχεία ελέγχου συσκευής"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Προσθήκη"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Κατάργηση"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Προτείνεται από <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Η συσκευή κλειδώθηκε"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Εμφάνιση και έλεγχος συσκευών από την οθόνη κλειδώματος;"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Μπορείτε να προσθέσετε στοιχεία ελέγχου για τις εξωτερικές συσκευές σας στην οθόνη κλειδώματος.\n\nΗ εφαρμογή της συσκευής σας μπορεί να σας παρέχει τη δυνατότητα ελέγχου ορισμένων συσκευών χωρίς να ξεκλειδώσετε το τηλέφωνο ή το tablet.\n\nΜπορείτε να κάνετε αλλαγές στις Ρυθμίσεις ανά πάσα στιγμή."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Έλεγχος συσκευών από την οθόνη κλειδώματος;"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Μπορείτε να ελέγχετε ορισμένες συσκευές χωρίς να ξεκλειδώσετε το τηλέφωνο ή το tablet σας.\n\nΗ εφαρμογή της συσκευής σας καθορίζει ποιες συσκευές μπορούν να ελέγχονται με αυτόν τον τρόπο."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Όχι, ευχαριστώ"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ναι"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Το PIN περιέχει γράμματα ή σύμβολα"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Προσθήκη στοιχείων ελέγχου"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Επεξεργασία στοιχείων ελέγχου"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Προσθήκη εφαρμογής"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Κατάργηση εφαρμογής"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Προσθήκη εξόδων"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Ομάδα"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Επιλέχτηκε 1 συσκευή"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index dc3c8e4..ffe67fa 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Enable USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Learn more"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock disabled"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"sent an image"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Saving screenshot to work profile…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"If you enter an incorrect PIN on the next attempt, your work profile and its data will be deleted."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"If you enter an incorrect password on the next attempt, your work profile and its data will be deleted."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Touch the fingerprint sensor"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Fingerprint icon"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Can’t recognise face. Use fingerprint instead."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -834,6 +834,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Magnify full screen"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Magnify part of screen"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Switch"</string>
+    <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Open magnification settings"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Drag corner to resize"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Allow diagonal scrolling"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Resize"</string>
@@ -843,6 +844,7 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Left handle"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Right handle"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Bottom handle"</string>
+    <string name="accessibility_magnification_settings_panel_description" msgid="8174187340747846953">"Magnification settings"</string>
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Magnifier size"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoom"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Medium"</string>
@@ -869,7 +871,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# control added.}other{# controls added.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Removed"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Add <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"When you add <xliff:g id="APPNAME">%s</xliff:g>, it can add controls and content to this panel. In some apps, you can choose which controls show up here."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Remove controls for <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Favourited"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Favourited, position <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Unfavourited"</string>
@@ -887,12 +891,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Other"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Add to device controls"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Add"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Remove"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Suggested by <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Device locked"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Show and control devices from the lock screen?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"You can add controls for your external devices to the lock screen.\n\nYour device app may allow you to control some devices without unlocking your phone or tablet.\n\nYou can make changes at any time in Settings."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Control devices from the lock screen?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"You can control some devices without unlocking your phone or tablet.\n\nYour device app determines which devices can be controlled in this way."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"No, thanks"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Yes"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN contains letters or symbols"</string>
@@ -940,6 +946,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Add controls"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Edit controls"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Add app"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Remove app"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Add outputs"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Group"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"One device selected"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 9c31722..da91052 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Enable USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Learn more"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock disabled"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"sent an image"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Saving screenshot to work profile…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"If you enter an incorrect PIN on the next attempt, your work profile and its data will be deleted."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"If you enter an incorrect password on the next attempt, your work profile and its data will be deleted."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Touch the fingerprint sensor"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Fingerprint icon"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Can’t recognize face. Use fingerprint instead."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -834,6 +834,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Magnify full screen"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Magnify part of screen"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Switch"</string>
+    <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Open magnification settings"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Drag corner to resize"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Allow diagonal scrolling"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Resize"</string>
@@ -843,6 +844,7 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Left handle"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Right handle"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Bottom handle"</string>
+    <string name="accessibility_magnification_settings_panel_description" msgid="8174187340747846953">"Magnification settings"</string>
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Magnifier size"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoom"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Medium"</string>
@@ -869,7 +871,8 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# control added.}other{# controls added.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Removed"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Add <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"When you add <xliff:g id="APPNAME">%s</xliff:g>, it can add controls and content to this panel. In some apps, you can choose which controls show up here."</string>
+    <string name="controls_panel_authorization" msgid="4665218066461350247">"<xliff:g id="APPNAME">%s</xliff:g>can choose which controls and content show here."</string>
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Remove controls for <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Favorited"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Favorited, position <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Unfavorited"</string>
@@ -887,12 +890,13 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Other"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Add to device controls"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Add"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Remove"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Suggested by <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Device locked"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Show and control devices from lock screen?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"You can add controls for your external devices to the lock screen.\n\nYour device app may allow you to control some devices without unlocking your phone or tablet.\n\nYou can make changes any time in Settings."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Control devices from lock screen?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"You can control some devices without unlocking your phone or tablet.\n\nYour device app determines which devices can be controlled in this way."</string>
+    <string name="controls_settings_trivial_controls_dialog_message" msgid="397178734990952575">"You can control some devices without unlocking your phone or tablet. Your device app determines which devices can be controlled in this way."</string>
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"No thanks"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Yes"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN contains letters or symbols"</string>
@@ -940,6 +944,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Add controls"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Edit controls"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Add app"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Remove app"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Add outputs"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Group"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 device selected"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index dc3c8e4..ffe67fa 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Enable USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Learn more"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock disabled"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"sent an image"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Saving screenshot to work profile…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"If you enter an incorrect PIN on the next attempt, your work profile and its data will be deleted."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"If you enter an incorrect password on the next attempt, your work profile and its data will be deleted."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Touch the fingerprint sensor"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Fingerprint icon"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Can’t recognise face. Use fingerprint instead."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -834,6 +834,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Magnify full screen"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Magnify part of screen"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Switch"</string>
+    <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Open magnification settings"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Drag corner to resize"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Allow diagonal scrolling"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Resize"</string>
@@ -843,6 +844,7 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Left handle"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Right handle"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Bottom handle"</string>
+    <string name="accessibility_magnification_settings_panel_description" msgid="8174187340747846953">"Magnification settings"</string>
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Magnifier size"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoom"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Medium"</string>
@@ -869,7 +871,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# control added.}other{# controls added.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Removed"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Add <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"When you add <xliff:g id="APPNAME">%s</xliff:g>, it can add controls and content to this panel. In some apps, you can choose which controls show up here."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Remove controls for <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Favourited"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Favourited, position <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Unfavourited"</string>
@@ -887,12 +891,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Other"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Add to device controls"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Add"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Remove"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Suggested by <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Device locked"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Show and control devices from the lock screen?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"You can add controls for your external devices to the lock screen.\n\nYour device app may allow you to control some devices without unlocking your phone or tablet.\n\nYou can make changes at any time in Settings."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Control devices from the lock screen?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"You can control some devices without unlocking your phone or tablet.\n\nYour device app determines which devices can be controlled in this way."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"No, thanks"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Yes"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN contains letters or symbols"</string>
@@ -940,6 +946,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Add controls"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Edit controls"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Add app"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Remove app"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Add outputs"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Group"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"One device selected"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index dc3c8e4..ffe67fa 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Enable USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Learn more"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock disabled"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"sent an image"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Saving screenshot to work profile…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"If you enter an incorrect PIN on the next attempt, your work profile and its data will be deleted."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"If you enter an incorrect password on the next attempt, your work profile and its data will be deleted."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Touch the fingerprint sensor"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Fingerprint icon"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Can’t recognise face. Use fingerprint instead."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -834,6 +834,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Magnify full screen"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Magnify part of screen"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Switch"</string>
+    <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Open magnification settings"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Drag corner to resize"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Allow diagonal scrolling"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Resize"</string>
@@ -843,6 +844,7 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Left handle"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Right handle"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Bottom handle"</string>
+    <string name="accessibility_magnification_settings_panel_description" msgid="8174187340747846953">"Magnification settings"</string>
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Magnifier size"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoom"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Medium"</string>
@@ -869,7 +871,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# control added.}other{# controls added.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Removed"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Add <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"When you add <xliff:g id="APPNAME">%s</xliff:g>, it can add controls and content to this panel. In some apps, you can choose which controls show up here."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Remove controls for <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Favourited"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Favourited, position <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Unfavourited"</string>
@@ -887,12 +891,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Other"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Add to device controls"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Add"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Remove"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Suggested by <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Device locked"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Show and control devices from the lock screen?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"You can add controls for your external devices to the lock screen.\n\nYour device app may allow you to control some devices without unlocking your phone or tablet.\n\nYou can make changes at any time in Settings."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Control devices from the lock screen?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"You can control some devices without unlocking your phone or tablet.\n\nYour device app determines which devices can be controlled in this way."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"No, thanks"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Yes"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN contains letters or symbols"</string>
@@ -940,6 +946,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Add controls"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Edit controls"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Add app"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Remove app"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Add outputs"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Group"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"One device selected"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index bc46af1..a577537 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎‏‏‏‎‎‏‎‎‎‎‏‏‎‏‏‏‏‏‎‎‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‎‏‏‏‎‏‏‏‏‏‎‎‏‎‎‎‏‎Enable USB‎‏‎‎‏‎"</string>
     <string name="learn_more" msgid="4690632085667273811">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‎‎‏‏‎‎‎‎‏‏‏‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‎‎‏‏‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‏‎‏‎‎‏‏‎Learn more‎‏‎‎‏‎"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‎‏‏‏‎‎‏‏‏‎‎‎‎‏‎‏‏‏‎‏‎‎‏‏‎‎‏‏‎‎‏‏‎‏‎‎‏‏‏‎‏‎‎‎‏‏‎‎‎‎‏‏‎‎Screenshot‎‏‎‎‏‎"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‎‏‎‎‎‎‏‏‏‎‏‎‏‎‎‏‏‎‏‎‏‎‏‏‎‎‏‎‏‏‏‏‎‎‎‏‎‎‎‎Smart Lock disabled‎‏‎‎‏‎"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‏‏‏‏‎‎‏‎‎‎‏‏‎‎‎‎‎‎‏‏‎‏‎‎‏‎‏‎‎‎‏‏‎sent an image‎‏‎‎‏‎"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‏‎‎‎‎‏‏‎‏‎‏‏‎‏‎‎‎‎‏‏‎‎‎‏‎‏‎‎‏‎‏‎Saving screenshot…‎‏‎‎‏‎"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎‎‎‎‏‎‎‎‎‎‎‏‎‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‏‎‎‏‎‏‏‏‎‎‎‏‎‎‎‎‎‎‎Saving screenshot to work profile…‎‏‎‎‏‎"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‎‎‏‎‎‏‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‏‎‏‏‏‎‏‏‎‏‏‏‏‎‎‏‎‎‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‎If you enter an incorrect PIN on the next attempt, your work profile and its data will be deleted.‎‏‎‎‏‎"</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‎‏‎‎‏‎‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎If you enter an incorrect password on the next attempt, your work profile and its data will be deleted.‎‏‎‎‏‎"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‎‏‏‎‏‏‎‎‏‎‎‏‎‏‎‏‏‎‎‏‎‏‎‎‎‏‏‏‎‎‎‏‎‏‎‏‎‏‎‏‎‏‏‏‏‏‏‏‎‏‏‏‏‏‎Touch the fingerprint sensor‎‏‎‎‏‎"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‏‏‎‎‏‎‎‏‏‏‎‏‎‎‏‎‎‏‏‎‏‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‎‏‎‏‎Fingerprint icon‎‏‎‎‏‎"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‏‏‏‎‏‎‏‏‏‏‎‏‎‎‏‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‎‏‎‏‎‎‏‏‎‎‎‏‎‎‎‏‎‎‎Can’t recognize face. Use fingerprint instead.‎‏‎‎‏‎"</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -834,6 +834,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‎‏‎‎‏‏‎‏‏‏‎‏‏‎‎‎‏‎‏‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‎‎‏‎‏‎‏‏‏‎‏‎‎‎‎‎‏‎Magnify full screen‎‏‎‎‏‎"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‏‏‎‎‎‎‏‎‎‏‎‎‏‎‎‎‎‎‏‎‏‎‏‎‏‏‎‏‏‏‏‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‎‏‎Magnify part of screen‎‏‎‎‏‎"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‏‎‏‎‏‎‏‎‏‎‎‏‎‏‎‏‎‏‎‏‎‎‏‏‏‎‎‏‏‎‏‏‏‎‎‎‎‎‏‎‎‎‏‏‎‎‎‏‏‏‎‏‎‏‏‏‎Switch‎‏‎‎‏‎"</string>
+    <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‏‎‎‏‎‏‏‏‎‎‎‏‏‏‎‎‎‏‎‎‎‏‏‎Open magnification settings‎‏‎‎‏‎"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‎‏‎‏‏‎‎‎‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‏‏‏‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‎‎‎‏‎‏‎‎‏‎‎Drag corner to resize‎‏‎‎‏‎"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‏‎‏‏‎‏‏‏‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‏‎‏‏‎‎‎‎‎‏‎‏‏‎‎‏‏‏‎‎Allow diagonal scrolling‎‏‎‎‏‎"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‎‏‎‎‏‎‎‏‏‎‎‏‏‏‏‎‎‎‏‏‏‎‎‏‎‏‎‏‎‎‏‎‏‏‏‎‏‎‏‏‎‏‏‎‏‎‏‏‎‏‏‏‏‏‎Resize‎‏‎‎‏‎"</string>
@@ -843,6 +844,7 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‏‎‎‏‎‏‎‎‎‎‎‎‏‏‏‏‎‎‏‎‏‏‏‏‎‎‏‏‎‏‎‏‎‏‏‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‎‎Left handle‎‏‎‎‏‎"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‎‏‎‏‎‏‎‏‎‏‎‏‎‎‏‎‎‎‏‏‎‏‏‏‏‎‎‎‏‎‎‏‏‏‏‎‎‎‎‎‏‏‏‎‎‏‎‏‎Right handle‎‏‎‎‏‎"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‎‎‏‎‏‎‎‎‏‎‎‏‎‎‏‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‏‎‏‎‎Bottom handle‎‏‎‎‏‎"</string>
+    <string name="accessibility_magnification_settings_panel_description" msgid="8174187340747846953">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‏‎‎‎‎‏‎‎‎‏‏‎‎‎‎‎‏‎‎‏‏‏‏‏‎‎‏‎‎‏‏‎‎‎‏‎‏‎‎‏‏‎‏‎‏‎‎‏‎‏‎‎‏‎Magnification settings‎‏‎‎‏‎"</string>
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‏‎‏‎‏‏‏‏‎‏‎‏‎‎‎‎‎‏‏‏‏‎‎‏‎‎‎‎‏‏‎‎‎‎‏‎‏‎‏‏‎‏‎‏‎‏‎‎‏‏‏‏‏‎‎Magnifier size‎‏‎‎‏‎"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‎‏‎‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‏‏‏‏‎‏‏‎‎‏‎‎‎‏‏‏‏‎‎‎‎‏‏‏‏‎‏‎‎‏‏‎‏‎‏‏‎Zoom‎‏‎‎‏‎"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‏‎‎‎‏‏‏‏‎‏‏‎‏‎‏‎‎‏‏‏‎‎‏‎‎‏‏‏‏‏‏‎‎‎‎‏‏‏‏‏‎‏‎‏‎‏‏‎‎‎‎‎‏‎Medium‎‏‎‎‏‎"</string>
@@ -869,7 +871,8 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‏‎‎‏‎‏‎‎‏‎‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‏‎‎‏‎‎‏‏‎‎‏‎‎‏‎‎‏‎‏‎‎‏‎‎‎‎‏‏‎# control added.‎‏‎‎‏‎}other{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‏‎‎‏‎‏‎‎‏‎‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‏‎‎‏‎‎‏‏‎‎‏‎‎‏‎‎‏‎‏‎‎‏‎‎‎‎‏‏‎# controls added.‎‏‎‎‏‎}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‏‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‏‏‎‎‏‎‎‏‏‎‏‎‏‏‏‎‏‎‎‏‎‏‏‏‎‏‏‏‏‏‏‏‏‎Removed‎‏‎‎‏‎"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‏‎‏‏‎‏‏‎‎‎‎‏‏‎‎‏‏‎‎‏‎‎‎‏‎‎‎‏‎‏‎‎‏‏‎‏‏‎‎‏‎‏‎‏‏‏‎‎‏‎‎‎‏‎‏‎‎Add ‎‏‎‎‏‏‎<xliff:g id="APPNAME">%s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‎‎‎‏‎‏‏‏‏‏‎‎‏‏‎‏‏‎‏‎‎‏‏‎‏‎‎‎‎‏‎‏‏‏‎‎‏‏‎‏‏‏‎‏‎‏‎‏‎‏‏‏‎When you add ‎‏‎‎‏‏‎<xliff:g id="APPNAME">%s</xliff:g>‎‏‎‎‏‏‏‎, it can add controls and content to this panel. In some apps, you can choose which controls show up here.‎‏‎‎‏‎"</string>
+    <string name="controls_panel_authorization" msgid="4665218066461350247">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‏‏‏‏‏‎‎‎‏‎‏‏‏‏‎‎‎‏‏‏‎‏‎‎‏‏‎‎‏‏‎‎‏‎‏‎‎‏‏‏‎‏‏‎‎‏‎‏‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="APPNAME">%s</xliff:g>‎‏‎‎‏‏‏‎can choose which controls and content show here.‎‏‎‎‏‎"</string>
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‎‏‎‎‏‏‎‏‎‎‎‏‎‏‎‏‏‎‏‎‏‎‏‎‎‏‏‎‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‏‎‎‏‎‎‎‎‏‎‎Remove controls for ‎‏‎‎‏‏‎<xliff:g id="APPNAME">%s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‎‎‏‎‎‏‎‏‎‎‏‏‎‎‏‏‎‏‏‎‏‏‏‏‎‎‎‎‏‏‎‏‎‏‎‎‎‏‏‎‏‏‎‎‎‎‎‎‎‏‎Favorited‎‏‎‎‏‎"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‎‏‏‎‎‎‎‎‎‏‎‏‎‎‎‎‏‎‎‎‎‏‎‎‏‏‎‎‏‎‏‎‎‏‎‏‎‎‎‏‎‏‏‏‎‏‏‎‏‏‏‎‎‎‏‎‏‎Favorited, position ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‏‏‏‎‏‏‎‏‎‏‎‎‎‎‎‏‎‎‎‏‏‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‎‏‎‏‏‏‎‏‏‎‎‎‎‏‏‏‎Unfavorited‎‏‎‎‏‎"</string>
@@ -887,12 +890,13 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‎‎‏‏‎‎‏‎‏‏‎‎‎‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‎‎‎‏‎‏‏‎‎‎‎‏‎‎‎Other‎‏‎‎‏‎"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‎‏‏‎‎‎‎‎‎‏‎‎‎‎‏‏‎‎‎‏‏‎‏‎‏‎‎‎‏‏‎‎‎‏‏‎‎‏‏‎‏‎‏‎‏‎‏‏‏‎‏‎‎Add to device controls‎‏‎‎‏‎"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‏‎‎‎‏‏‏‎‏‎‏‎‏‏‎‎‎‎‏‎‎‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‏‎‎‎‏‎‏‎‎‏‏‎‏‏‏‏‎‎Add‎‏‎‎‏‎"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‏‎‎‏‎‎‏‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‎‏‎‏‎‏‎‏‎‎‏‏‎‏‏‎‏‎‎‎‎‎Remove‎‏‎‎‏‎"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‏‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‏‏‏‎‎‏‎‏‎‎‏‎‏‎‏‎‎‏‎‎‎Suggested by ‎‏‎‎‏‏‎<xliff:g id="APP">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‎‏‎‎‏‏‎‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‏‏‎‏‏‏‎‏‎‏‏‎‎‎‏‎‎‎‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‎Device locked‎‏‎‎‏‎"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‏‎‎‏‏‎‎‏‎‏‏‏‏‏‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‏‎‎‎‏‏‏‎‎‏‎‎‏‎‎‏‎‎Show and control devices from lock screen?‎‏‎‎‏‎"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‎‎‎‏‏‏‏‎‏‏‎‏‎‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‎‏‏‎‏‏‎‎‎‎‏‏‎‏‏‏‏‎‎‎‎‎‏‎You can add controls for your external devices to the lock screen.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Your device app may allow you to control some devices without unlocking your phone or tablet.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎You can make changes any time in Settings.‎‏‎‎‏‎"</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‎‎‎‎‎‏‏‎‏‏‎‎‎‏‏‎‎‏‏‎‎‎‏‎‎‎‎‏‏‎‏‏‏‎‏‏‎‎‏‏‎‎‏‏‎‎‎‎‎‏‎‏‎Control devices from lock screen?‎‏‎‎‏‎"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‏‎‏‎‏‎‎‏‎‏‎‏‏‎‎‏‎‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‏‏‎‎‎‎‏‎‎‏‎‎‏‎‎‏‎‎You can control some devices without unlocking your phone or tablet.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Your device app determines which devices can be controlled in this way.‎‏‎‎‏‎"</string>
+    <string name="controls_settings_trivial_controls_dialog_message" msgid="397178734990952575">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‎‎‎‎‎‏‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‏‎‎‏‏‎‎‎‏‎‎‎‎‏‏‏‏‏‏‏‎You can control some devices without unlocking your phone or tablet. Your device app determines which devices can be controlled in this way.‎‏‎‎‏‎"</string>
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‏‎‎‏‏‎‏‎‎‎‏‎‎‏‎‎‎‎‏‎‏‎‏‎‎‎‎‏‏‏‎‎‎‎‎‎‎‎‎‏‎‏‎‎‎‏‎‎‏‎‏‏‎‎‎No thanks‎‏‎‎‏‎"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‎‎‎‏‏‎‏‎‎‏‏‏‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎‏‎‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎Yes‎‏‎‎‏‎"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‎‎‏‎‎‏‏‏‎‏‎‎‏‎‎‏‎‎‏‏‎‎‎‏‎‎‏‏‏‏‏‎‎‏‎‎‏‎‎‎‎‏‎‏‏‎‏‏‏‏‎‎PIN contains letters or symbols‎‏‎‎‏‎"</string>
@@ -940,6 +944,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‏‎‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‏‎‎‎‎‏‏‎‏‏‎‏‎‏‏‎‏‏‏‏‎‎‎‏‎‎‏‏‎‎‏‏‎‎‏‎‎Add controls‎‏‎‎‏‎"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‏‎‏‏‏‎‎‎‎‏‎‎‎‎‏‏‏‎‎‏‏‎‎‎‎‏‎‎‎‏‎‏‎‏‎‏‏‎‏‎‏‎‏‏‎‏‏‎‏‏‏‎‏‏‎‎Edit controls‎‏‎‎‏‎"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‎‏‎‏‎‏‎‏‎‏‎‎‏‎‏‎‎‏‎‎‏‏‏‏‏‎‏‎‎‏‎‏‎‎‏‎‏‎‏‎‏‏‏‏‎‎‏‎‎‎‏‎Add app‎‏‎‎‏‎"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‏‎‏‏‏‎‎‏‎‏‎‏‎‎‏‎‏‏‎‎‏‏‏‏‎‎‏‎‏‎‏‎‎‎‏‏‎‎‎‎‎‎‏‎‎‏‏‏‎‎‏‎‏‏‎‎‎Remove app‎‏‎‎‏‎"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎‏‏‏‎‏‏‏‎‏‎‎‎‏‎‏‏‎‎‏‏‎‎‎‎‏‏‏‎‎‎‏‏‏‎‏‎‏‎‏‏‏‎‎‎‎‏‏‎‏‏‏‎‎Add outputs‎‏‎‎‏‎"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‎‏‎‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‎‏‎‎‏‎‎‎‏‎‏‎‎‏‏‎‏‏‎‏‏‎‎‏‏‎‏‏‎‏‎‎‎Group‎‏‎‎‏‎"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‎‎‏‏‏‏‎‎‏‏‎‏‏‎‏‏‎‏‏‎‏‎‏‎‎‏‎‎‎‎‏‏‏‎‎‏‏‎‎‏‏‎‏‎‏‎‎‎‎‏‎‎‏‎‎1 device selected‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 81682b5..c00024c 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Habilitar USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Más información"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Captura de pantalla"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Se inhabilitó Smart Lock"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"envió una imagen"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Guardando la captura de pantalla..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Guardando cap. de pantalla en perfil de trabajo…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Si ingresas un PIN incorrecto en el próximo intento, se borrarán tu perfil de trabajo y sus datos."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Si ingresas una contraseña incorrecta en el próximo intento, se borrarán tu perfil de trabajo y sus datos."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Toca el sensor de huellas dactilares"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ícono de huella dactilar"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"No se reconoce el rostro. Usa la huella dactilar."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Pantalla de notificaciones"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configuración rápida"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configuración rápida y panel de notificaciones."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Pantalla de bloqueo"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Pantalla bloqueada del perfil de trabajo"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Cerrar"</string>
@@ -408,7 +407,7 @@
     <string name="media_projection_action_text" msgid="3634906766918186440">"Comenzar ahora"</string>
     <string name="empty_shade_text" msgid="8935967157319717412">"No hay notificaciones"</string>
     <string name="no_unseen_notif_text" msgid="395512586119868682">"No hay notificaciones nuevas"</string>
-    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloquea para ver notif. anteriores"</string>
+    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloquea para ver notificaciones anteriores"</string>
     <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Tu padre o madre administra este dispositivo"</string>
     <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Tu organización es propietaria de este dispositivo y podría controlar el tráfico de red"</string>
     <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> es la organización propietaria de este dispositivo y podría controlar el tráfico de red"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ampliar pantalla completa"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ampliar parte de la pantalla"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Interruptor"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Arrastra la esquina para cambiar el tamaño"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Permitir desplazamiento en diagonal"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Cambiar tamaño"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Controlador izquierdo"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Controlador derecho"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Controlador inferior"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Tamaño de ampliación"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoom"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Mediano"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Se agregó # control.}many{Se agregaron # controles.}other{Se agregaron # controles.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Quitados"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"¿Quieres agregar <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Si agregas la app de <xliff:g id="APPNAME">%s</xliff:g>, se incluirán controles y contenido en este panel. Algunas apps te permiten elegir qué controles mostrar aquí."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"¿Quieres quitar los controles para <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Está en favoritos"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Está en favoritos en la posición <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"No está en favoritos"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Otros"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Agregar a controles de dispositivos"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Agregar"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Quitar"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Sugerido por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Dispos. bloqueado"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"¿Quieres mostrar y controlar dispositivos desde la pantalla de bloqueo?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Puedes agregar controles para dispositivos externos a la pantalla de bloqueo.\n\nLa app de tu dispositivo podría permitirte controlar algunos dispositivos sin desbloquear el teléfono o la tablet.\n\nPuedes realizar cambios en cualquier momento en Configuración."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"¿Quieres controlar dispositivos desde la pantalla de bloqueo?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Puedes controlar algunos dispositivos sin desbloquear el teléfono o la tablet.\n\nLa app de tu dispositivo determina los que se pueden controlar de esa manera."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"No, gracias"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Sí"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"El PIN contiene letras o símbolos"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Agregar controles"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Editar controles"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Agregar app"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Quitar app"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Agregar salidas"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Se seleccionó 1 dispositivo"</string>
@@ -1096,9 +1104,9 @@
     <string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Mantener presionado atajo"</string>
     <string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancelar"</string>
     <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Cambiar de pantalla ahora"</string>
-    <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Desplegar teléfono"</string>
+    <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Despliega el teléfono"</string>
     <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"¿Quieres cambiar de pantalla?"</string>
-    <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Para obtener una resolución más alta, usa la cámara posterior"</string>
+    <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Para obtener una resolución más alta, usa la cámara posterior."</string>
     <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Para obtener una resolución más alta, gira el teléfono"</string>
     <string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo plegable siendo desplegado"</string>
     <string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo plegable siendo girado"</string>
@@ -1111,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Cambiar al perfil de trabajo"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Cerrar"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Config. de pantalla de bloqueo"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi no disponible"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"La cámara está bloqueada"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"La cámara y el micrófono están bloqueados"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"El micrófono está bloqueado"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"El modo de prioridad está activado"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Asistente está prestando atención"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 526743a..35f55c0 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -51,7 +51,7 @@
     <string name="usb_debugging_message" msgid="5794616114463921773">"La huella digital de tu clave RSA es:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="4003121804294739548">"Permitir siempre desde este ordenador"</string>
     <string name="usb_debugging_allow" msgid="1722643858015321328">"Permitir"</string>
-    <string name="usb_debugging_secondary_user_title" msgid="7843050591380107998">"Depuración USB no permitida"</string>
+    <string name="usb_debugging_secondary_user_title" msgid="7843050591380107998">"Depuración por USB no permitida"</string>
     <string name="usb_debugging_secondary_user_message" msgid="1888835696965417845">"El usuario con el que se ha iniciado sesión en este dispositivo no puede activar la depuración por USB. Para usar esta función, inicia sesión con la cuenta de un usuario administrador."</string>
     <string name="hdmi_cec_set_menu_language_title" msgid="1259765420091503742">"¿Quieres cambiar el idioma del sistema a <xliff:g id="LANGUAGE">%1$s</xliff:g>?"</string>
     <string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Otro dispositivo ha solicitado un cambio en el idioma del sistema"</string>
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Habilitar USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Más información"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Captura de pantalla"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock inhabilitado"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ha enviado una imagen"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Guardando captura..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Guardando captura en el perfil de trabajo…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Si vuelves a introducir un PIN incorrecto, tu perfil de trabajo y sus datos se eliminarán."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Si vuelves a introducir una contraseña incorrecta, tu perfil de trabajo y sus datos se eliminarán."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Toca el sensor de huellas digitales"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Icono de huella digital"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"No se reconoce la cara. Usa la huella digital."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Pantalla de notificaciones"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Ajustes rápidos"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Ajustes rápidos y pantalla de notificaciones."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Pantalla de bloqueo."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Pantalla de bloqueo para el perfil de trabajo"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Cerrar"</string>
@@ -408,7 +407,7 @@
     <string name="media_projection_action_text" msgid="3634906766918186440">"Empezar ahora"</string>
     <string name="empty_shade_text" msgid="8935967157319717412">"No hay notificaciones"</string>
     <string name="no_unseen_notif_text" msgid="395512586119868682">"No hay notificaciones nuevas"</string>
-    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloquea para ver notif. anteriores"</string>
+    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloquea para ver notificaciones anteriores"</string>
     <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo lo gestionan tu padre o tu madre"</string>
     <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"El dispositivo pertenece a tu organización, que puede monitorizar su tráfico de red"</string>
     <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"El dispositivo pertenece a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>, que puede monitorizar su tráfico de red"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ampliar pantalla completa"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ampliar parte de la pantalla"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Cambiar"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Arrastra la esquina para cambiar el tamaño"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Permitir desplazamiento en diagonal"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Cambiar tamaño"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Controlador izquierdo"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Controlador derecho"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Controlador inferior"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Tamaño de la lupa"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoom"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Mediano"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# control añadido.}many{# controles añadidos.}other{# controles añadidos.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Quitado"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"¿Añadir <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Si añades <xliff:g id="APPNAME">%s</xliff:g>, podrá añadir controles y contenido a este panel. En algunas aplicaciones, puedes elegir qué controles aparecen aquí."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"¿Quitar los controles de <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Añadido a favoritos"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Añadido a favoritos (posición <xliff:g id="NUMBER">%d</xliff:g>)"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Quitado de favoritos"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Otros"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Añadir a control de dispositivos"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Añadir"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Quitar"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Sugerido por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Dispositivo bloqueado"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"¿Mostrar y controlar otros dispositivos en la pantalla de bloqueo?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Puedes añadir controles de tus dispositivos externos a la pantalla de bloqueo.\n\nPuede que la aplicación de tu dispositivo permita que controles algunos dispositivos sin desbloquear tu teléfono o tablet.\n\nPuedes hacer cambios en cualquier momento en Ajustes."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"¿Controlar dispositivos desde la pantalla de bloqueo?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Puedes controlar algunos dispositivos sin desbloquear tu teléfono o tablet.\n\nLa aplicación de tu dispositivo determina qué dispositivos se pueden controlar de esta forma."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"No, gracias"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Sí"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"El PIN contiene letras o símbolos"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Añadir controles"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Editar controles"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Añadir aplicación"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Quitar aplicación"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Añadir dispositivos de salida"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo seleccionado"</string>
@@ -1019,7 +1027,7 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Datos móviles"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectado"</string>
-    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectada temporalmente"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectado temporalmente"</string>
     <string name="mobile_data_poor_connection" msgid="819617772268371434">"Conexión inestable"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Los datos móviles no se conectarán automáticamente"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Sin conexión"</string>
@@ -1111,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Cambiar al perfil de trabajo"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Cerrar"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Ajustes de pantalla de bloqueo"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Red Wi-Fi no disponible"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Cámara bloqueada"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Cámara y micrófono bloqueados"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Micrófono bloqueado"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modo Prioridad activado"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"El Asistente está activado"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 9388a14..9b5bc7e 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Luba USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Lisateave"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Ekraanipilt"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock on keelatud"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"saatis kujutise"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Kuvatõmmise salvestamine ..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Ekraanipildi salvestamine tööprofiilile …"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Kui sisestate järgmisel katsel vale PIN-koodi, kustutatakse teie tööprofiil ja selle andmed."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Kui sisestate järgmisel katsel vale parooli, kustutatakse teie tööprofiil ja selle andmed."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Puudutage sõrmejäljeandurit"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Sõrmejälje ikoon"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nägu ei õnnestu tuvastada. Kasutage sõrmejälge."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Märguande vari."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Kiirseaded."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Kiirseaded ja märguandeala."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Kuva lukustamine."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Töö lukustuskuva"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Sulgemine"</string>
@@ -408,7 +407,7 @@
     <string name="media_projection_action_text" msgid="3634906766918186440">"Alusta kohe"</string>
     <string name="empty_shade_text" msgid="8935967157319717412">"Märguandeid pole"</string>
     <string name="no_unseen_notif_text" msgid="395512586119868682">"Uusi märguandeid ei ole"</string>
-    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Uute märguannete nägemiseks avage"</string>
+    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Vanemate märguannete nägemiseks avage"</string>
     <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Seda seadet haldab sinu vanem"</string>
     <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Teie organisatsioon on selle seadme omanik ja võib jälgida võrguliiklust"</string>
     <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> on selle seadme omanik ja võib jälgida võrguliiklust"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Täisekraani suurendamine"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ekraanikuva osa suurendamine"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Vaheta"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Suuruse muutmiseks lohistage nurka"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Luba diagonaalne kerimine"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Muuda suurust"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Vasak käepide"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Parem käepide"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Alumine käepide"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Luubi suurus"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Suumi"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Keskmine"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Lisati # juhtnupp.}other{Lisati # juhtnuppu.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Eemaldatud"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Kas lisada <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Kui lisate rakenduse <xliff:g id="APPNAME">%s</xliff:g>, saab see sellele paneelile lisada juhtelemendid ja sisu. Mõnes rakenduses saate valida, millised juhtelemendid siin kuvatakse."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Kas soovite rakenduse <xliff:g id="APPNAME">%s</xliff:g> juhtelemendid eemaldada?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Lisatud lemmikuks"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Lisatud lemmikuks, positsioon <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Eemaldatud lemmikute hulgast"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Muu"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Seadmete juhtimisvidinate hulka lisamine"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Lisa"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Eemalda"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Soovitas <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Seade on lukustatud"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Kas soovite seadmete juhtelemente lukustuskuval kuvada ja kasutada?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Võite lukustuskuvale oma väliste seadmete juhtelemendid lisada.\n\nTeie seadmerakendus võib võimaldada teil teatud seadmeid ilma telefoni või tahvelarvutit avamata hallata.\n\nSaate igal ajal seadetes muudatusi teha."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Kas soovite seadmeid lukustuskuva kaudu hallata?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Võite teatud seadmeid ilma telefoni või tahvelarvutit avamata hallata.\n\nTeie seadmerakendus määrab, milliseid seadmeid saab sel viisil hallata."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Tänan, ei"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Jah"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN-kood sisaldab tähti või sümboleid"</string>
@@ -940,7 +947,8 @@
     <string name="controls_error_failed" msgid="960228639198558525">"Ilmnes viga, proovige uuesti"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Lisa juhtelemente"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Muuda juhtelemente"</string>
-    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Rakenduse lisamine"</string>
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Lisa rakendus"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Eemalda rakendus"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Väljundite lisamine"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupp"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 seade on valitud"</string>
@@ -1111,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Lülitu tööprofiilile"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Sule"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Lukustuskuva seaded"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"WiFi pole saadaval"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kaamera on blokeeritud"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kaamera ja mikrofon on blokeeritud"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon on blokeeritud"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioriteetne režiim on sisse lülitatud"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistent on aktiveeritud"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 84f2d0c..653504a 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Gaitu USB ataka"</string>
     <string name="learn_more" msgid="4690632085667273811">"Lortu informazio gehiago"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Pantaila-argazkia"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Desgaitu da Smart Lock"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"erabiltzaileak irudi bat bidali du"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Pantaila-argazkia gordetzen…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Pantaila-argazkia laneko profilean gordetzen…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Hurrengo saiakeran PINa oker idazten baduzu, laneko profila eta bertako datuak ezabatuko dira."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Hurrengo saiakeran pasahitza oker idazten baduzu, laneko profila eta bertako datuak ezabatuko dira."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Sakatu hatz-marken sentsorea"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Hatz-markaren ikonoa"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ezin da hauteman aurpegia. Erabili hatz-marka."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Jakinarazpenen panela."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Ezarpen bizkorrak."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Ezarpen bizkorrak eta jakinarazpenen panela."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Pantaila blokeatzeko aukera."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Laneko pantaila blokeatua"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Itxi"</string>
@@ -616,84 +615,48 @@
     <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_clear_text (4679927133259287577) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_list_title (1156178106617830429) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_list_hint (5982623262974326746) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_list_no_result (6819302191660875501) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_category_system (1151182120757052669) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_category_input (5440558509904296233) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_category_open_apps (1450959949739257562) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_category_current_app (2011953559133734491) -->
-    <skip />
-    <!-- no translation found for group_system_access_notification_shade (7116898151485382275) -->
-    <skip />
-    <!-- no translation found for group_system_full_screenshot (7389040853798023211) -->
-    <skip />
-    <!-- no translation found for group_system_access_system_app_shortcuts (4421497579210445641) -->
-    <skip />
-    <!-- no translation found for group_system_go_back (8838454003680364227) -->
-    <skip />
-    <!-- no translation found for group_system_access_home_screen (1857344316928441909) -->
-    <skip />
-    <!-- no translation found for group_system_overview_open_apps (6897128761003265350) -->
-    <skip />
-    <!-- no translation found for group_system_cycle_forward (9202444850838205990) -->
-    <skip />
-    <!-- no translation found for group_system_cycle_back (5163464503638229131) -->
-    <skip />
-    <!-- no translation found for group_system_access_all_apps_search (488070738028991753) -->
-    <skip />
-    <!-- no translation found for group_system_hide_reshow_taskbar (3809304065624351131) -->
-    <skip />
-    <!-- no translation found for group_system_access_system_settings (7961639365383008053) -->
-    <skip />
-    <!-- no translation found for group_system_access_google_assistant (1186152943161483864) -->
-    <skip />
-    <!-- no translation found for group_system_lock_screen (7391191300363416543) -->
-    <skip />
-    <!-- no translation found for group_system_quick_memo (2914234890158583919) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_group_system_multitasking (1065232949510862593) -->
-    <skip />
-    <!-- no translation found for system_multitasking_rhs (6593269428880305699) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (8839380725557952846) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (1962084334200006297) -->
-    <skip />
-    <!-- no translation found for system_multitasking_replace (844285282472557186) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_group_input (6888282716546625610) -->
-    <skip />
-    <!-- no translation found for input_switch_input_language_next (3394291576873633793) -->
-    <skip />
-    <!-- no translation found for input_switch_input_language_previous (8823659252918609216) -->
-    <skip />
-    <!-- no translation found for input_access_emoji (8105642858900406351) -->
-    <skip />
-    <!-- no translation found for input_access_voice_typing (7291201476395326141) -->
-    <skip />
+    <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Garbitu testua"</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>
+    <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string>
+    <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>
+    <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Atzitu jakinarazpenen panela"</string>
+    <string name="group_system_full_screenshot" msgid="7389040853798023211">"Atera pantaila osoaren argazki bat"</string>
+    <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Atzitu sistemaren edo aplikazioetarako lasterbideen zerrenda"</string>
+    <string name="group_system_go_back" msgid="8838454003680364227">"Atzera: itzuli aurreko egoerara (atzera egiteko botoia)"</string>
+    <string name="group_system_access_home_screen" msgid="1857344316928441909">"Atzitu hasierako pantaila"</string>
+    <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Ikusi irekitako aplikazioen ikuspegi orokorra"</string>
+    <string name="group_system_cycle_forward" msgid="9202444850838205990">"Joan azken aplikazioetako batetik bestera (aurrera)"</string>
+    <string name="group_system_cycle_back" msgid="5163464503638229131">"Joan azken aplikazioetako batetik bestera (atzera)"</string>
+    <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Atzitu aplikazio guztien zerrenda eta bilatu (adibidez, bilatzeko aukeraren edo Exekutatzeko tresna aplikazioaren bidez)"</string>
+    <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Ezkutatu eta erakutsi (berriro) zereginen barra"</string>
+    <string name="group_system_access_system_settings" msgid="7961639365383008053">"Atzitu sistemaren ezarpenak"</string>
+    <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Atzitu Google-ren Laguntzailea"</string>
+    <string name="group_system_lock_screen" msgid="7391191300363416543">"Blokeatu pantaila"</string>
+    <string name="group_system_quick_memo" msgid="2914234890158583919">"Ireki Oharrak aplikazioa oharrak bizkor idazteko"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Zereginen aldibereko sistemaren exekuzioa"</string>
+    <string name="system_multitasking_rhs" msgid="6593269428880305699">"Sartu pantaila zatituaren eskuineko aldean uneko aplikazioarekin"</string>
+    <string name="system_multitasking_lhs" msgid="8839380725557952846">"Sartu pantaila zatituaren ezkerreko aldean uneko aplikazioarekin"</string>
+    <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Aldatu pantaila zatitutik pantaila osora"</string>
+    <string name="system_multitasking_replace" msgid="844285282472557186">"Pantaila zatituan zaudela: ordeztu aplikazio bat beste batekin"</string>
+    <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Sarrera"</string>
+    <string name="input_switch_input_language_next" msgid="3394291576873633793">"Aldatu idazteko hizkuntza (hurrengo hizkuntza)"</string>
+    <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Aldatu idazteko hizkuntza (aurreko hizkuntza)"</string>
+    <string name="input_access_emoji" msgid="8105642858900406351">"Atzitu emojiak"</string>
+    <string name="input_access_voice_typing" msgid="7291201476395326141">"Atzitu ahozko idazketa"</string>
     <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplikazioak"</string>
     <string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Laguntzailea"</string>
-    <!-- no translation found for keyboard_shortcut_group_applications_browser (7328131901589876868) -->
-    <skip />
+    <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Ireki arakatzailea (Chrome, modu lehenetsian)"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kontaktuak"</string>
-    <!-- no translation found for keyboard_shortcut_group_applications_email (7480359963463803511) -->
-    <skip />
+    <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Ireki posta elektronikoa (Gmail, modu lehenetsian)"</string>
     <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMSak"</string>
     <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Musika"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
-    <!-- no translation found for keyboard_shortcut_group_applications_calculator (6316043911946540137) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_group_applications_maps (7312554713993114342) -->
-    <skip />
+    <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Ireki Kalkulagailua"</string>
+    <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Ireki Maps"</string>
     <string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ez molestatzeko modua"</string>
     <string name="volume_dnd_silent" msgid="4154597281458298093">"Bolumen-botoietarako lasterbidea"</string>
     <string name="battery" msgid="769686279459897127">"Bateria"</string>
@@ -856,12 +819,9 @@
     <string name="privacy_type_media_projection" msgid="8136723828804251547">"pantaila-grabaketa"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Ez du izenik"</string>
     <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Egonean"</string>
-    <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
-    <skip />
-    <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
-    <skip />
-    <!-- no translation found for font_scaling_larger (5476242157436806760) -->
-    <skip />
+    <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Letraren tamaina"</string>
+    <string name="font_scaling_smaller" msgid="1012032217622008232">"Txikitu"</string>
+    <string name="font_scaling_larger" msgid="5476242157436806760">"Handitu"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"Lupa-leihoa"</string>
     <string name="magnification_controls_title" msgid="8421106606708891519">"Lupa-leihoaren aukerak"</string>
     <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Handitu"</string>
@@ -874,6 +834,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Handitu pantaila osoa"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Handitu pantailaren zati bat"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Botoia"</string>
+    <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Ireki luparen ezarpenak"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Arrastatu izkina bat tamaina aldatzeko"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Eman diagonalki gora eta behera egiteko aukera erabiltzeko baimena"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Aldatu tamaina"</string>
@@ -883,6 +844,7 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Ezkerreko kontrol-puntua"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Eskuineko kontrol-puntua"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Beheko kontrol-puntua"</string>
+    <string name="accessibility_magnification_settings_panel_description" msgid="8174187340747846953">"Luparen ezarpenak"</string>
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Luparen tamaina"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zooma"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Ertaina"</string>
@@ -909,7 +871,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Kontrolatzeko # aukera gehitu da.}other{Kontrolatzeko # aukera gehitu dira.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Kenduta"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> gehitu nahi duzu?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> gehitzen duzunean, kontrolatzeko aukerak eta edukia gehi ditzake panelean. Aplikazio batzuetan, hemen zein kontrolatzeko aukera agertzen diren aukera dezakezu."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> kontrolatzeko aukerak kendu nahi dituzu?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Gogokoetan dago"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"<xliff:g id="NUMBER">%d</xliff:g>. gogokoa da"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Ez dago gogokoetan"</string>
@@ -927,12 +891,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Beste bat"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Gehitu gailuak kontrolatzeko widgetetan"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Gehitu"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Kendu"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> aplikazioak iradoki du"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Gailua blokeatuta"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Gailuak pantaila blokeatuan ikusi eta kontrolatu nahi dituzu?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Kanpoko gailuak kontrolatzeko aukerak gehi ditzakezu pantaila blokeatuan.\n\nBaliteke telefonoa edo tableta desblokeatu gabe gailu batzuk kontrolatzeko baimena ematea gailuaren aplikazioak.\n\nAldaketak egiteko, joan Ezarpenak atalera."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Gailuak pantaila blokeatuan kontrolatu nahi dituzu?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Gailu batzuk telefonoa edo tableta desblokeatu gabe kontrola ditzakezu.\n\nGailuaren aplikazioak zehaztuko du zer gailu kontrola daitezkeen modu horretan."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Ez, eskerrik asko"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Bai"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN kodeak hizkiak edo ikurrak ditu"</string>
@@ -980,6 +946,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Gehitu aukerak"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Editatu aukerak"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Gehitu aplikazio bat"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Kendu aplikazioa"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Gehitu irteerak"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Taldea"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 gailu hautatu da"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index bafee64..0474b28 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"‏فعال کردن USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"بیشتر بدانید"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"نماگرفت"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"‏Smart Lock غیرفعال شد"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"تصویری ارسال کرد"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"درحال ذخیره نماگرفت…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"درحال ذخیره کردن نماگرفت در نمایه کاری…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"اگر در تلاش بعدی‌ پین نادرستی وارد کنید، نمایه کاری شما و داده‌های آن حذف خواهند شد."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"اگر در تلاش بعدی‌ گذرواژه نادرستی وارد کنید، نمایه کاری شما و داده‌های آن حذف خواهند شد."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"حسگر اثر انگشت را لمس کنید"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"نماد اثر انگشت"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"چهره شناسایی نشد. درعوض از اثر انگشت استفاده کنید."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"مجموعه اعلان."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"تنظیمات سریع."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"تنظیمات فوری و کشوی اعلانات."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"صفحه قفل."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"صفحه قفل کاری"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"بستن"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"درشت‌نمایی تمام‌صفحه"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"درشت‌نمایی بخشی از صفحه"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"کلید"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"برای تغییر اندازه، گوشه را بکشید"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"مجاز کردن پیمایش قطری"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"تغییر اندازه"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"دستگیره چپ"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"دستگیره راست"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"دستگیره پایین"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"اندازه ذره‌بین"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"بزرگ‌نمایی"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"متوسط"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# کنترل اضافه شد.}one{# کنترل اضافه شد.}other{# کنترل اضافه شد.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"حذف شد"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> افزوده شود؟"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"وقتی <xliff:g id="APPNAME">%s</xliff:g> را اضافه می‌کنید، می‌تواند کنترل‌ها و محتوا را به این پانل اضافه کند. در برخی‌از برنامه‌ها می‌توانید انتخاب کنید چه کنترل‌هایی در اینجا نشان داده شود."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"کنترل‌های <xliff:g id="APPNAME">%s</xliff:g> برداشته شود؟"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"به موارد دلخواه اضافه شد"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"اضافه‌شده به موارد دلخواه، جایگاه <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"حذف‌شده از موارد دلخواه"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"موارد دیگر"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"افزودن به کنترل‌های دستگاه"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"افزودن"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"برداشتن"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"پیشنهاد <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"دستگاه قفل است"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"امکان دیدن و کنترل دستگاه‌ها از صفحه قفل وجود داشته باشد؟"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"می‌توانید کنترل‌هایی برای دستگاه‌های خارجی به صفحه قفل اضافه کنید.\n\nبرنامه دستگاهتان ممکن است به شما اجازه دهد بعضی‌از دستگاه‌ها را بدون باز کردن قفل تلفن یا رایانه لوحی‌تان کنترل کنید.\n\nهرزمان بخواهید می‌توانید در «تنظیمات» تغییراتی اعمال کنید."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"امکان کنترل دستگاه‌ها از صفحه قفل وجود داشته باشد؟"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"می‌توانید بعضی‌از دستگاه‌ها را بدون باز کردن قفل تلفن یا رایانه لوحی‌تان کنترل کنید.\n\nبرنامه دستگاهتان تعیین می‌کند کدام دستگاه‌ها را می‌توان به این روش کنترل کرد."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"نه متشکرم"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"بله"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"پین شامل حروف یا نماد است"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"افزودن کنترل‌ها"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"ویرایش کنترل‌ها"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"افزودن برنامه"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"برداشتن برنامه"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"افزودن خروجی"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"گروه"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"۱ دستگاه انتخاب شد"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 4097e76..6620ac6 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Ota USB käyttöön"</string>
     <string name="learn_more" msgid="4690632085667273811">"Lue lisää"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Kuvakaappaus"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock poistettu käytöstä"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"lähetti kuvan"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Tallennetaan kuvakaappausta..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Kuvakaappausta tallennetaan työprofiiliin…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Jos annat väärän PIN-koodin seuraavalla yrityskerralla, työprofiilisi ja sen data poistetaan."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Jos annat väärän salasanan seuraavalla yrityskerralla, työprofiilisi ja sen data poistetaan."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Kosketa sormenjälkitunnistinta"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Sormenjälkikuvake"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Kasvoja ei voi tunnistaa. Käytä sormenjälkeä."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Ilmoitusalue."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Pika-asetukset."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Pika-asetukset ja ilmoitusalue"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lukitse näyttö."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Työlukitusnäyttö"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Sulje"</string>
@@ -408,7 +407,7 @@
     <string name="media_projection_action_text" msgid="3634906766918186440">"Aloita nyt"</string>
     <string name="empty_shade_text" msgid="8935967157319717412">"Ei ilmoituksia"</string>
     <string name="no_unseen_notif_text" msgid="395512586119868682">"Ei uusia ilmoituksia"</string>
-    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Avaa lukitus uusia ilmoituksia varten"</string>
+    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Avaa lukitus niin näet ilmoituksia"</string>
     <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Vanhempasi ylläpitää tätä laitetta"</string>
     <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Organisaatiosi omistaa laitteen ja voi valvoa verkkoliikennettä"</string>
     <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> omistaa laitteen ja voi valvoa verkkoliikennettä"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Koko näytön suurennus"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Suurenna osa näytöstä"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Vaihda"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Muuta kokoa vetämällä kulmaa"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Diagonaalisen vierittämisen salliminen"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Muuta kokoa"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Vasen kahva"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Oikea kahva"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Alakahva"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Suurennuksen koko"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoomaus"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Keskitaso"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# säädin lisätty.}other{# säädintä lisätty.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Poistettu"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Lisätäänkö <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Kun <xliff:g id="APPNAME">%s</xliff:g> lisätään, se voi lisätä asetuksia ja sisältöä tähän paneeliin. Joissakin sovelluksissa voit valita, mitä asetukset näkyvät täällä."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Poistetaanko säätimet: <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Lisätty suosikkeihin"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Lisätty suosikkeihin sijalle <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Poistettu suosikeista"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Muu"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Lisää laitteiden hallintaan"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Lisää"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Poista"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Ehdottaja: <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Laite lukittu"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Haluatko nähdä ja hallita laitteita lukitusnäytöltä?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Voit lisätä lukitusnäytölle ohjaimia ulkoisia laitteita varten.\n\nLaitteen sovellus voi sallia joidenkin laitteiden ohjaamisen avaamatta puhelimen tai tabletin lukitusta.\n\nVoit milloin tahansa tehdä muutoksia asetuksissa."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Haluatko ohjata laitteita lukitusnäytöllä?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Voit ohjata joitakin laitteita avaamatta puhelimen tai tabletin lukitusta.\n\nRiippuu laitteen sovelluksesta, mitä laitteita voi ohjata näin."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Ei kiitos"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Kyllä"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN-koodi sisältää kirjaimia tai symboleja"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Lisää säätimiä"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Muokkaa säätimiä"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Lisää sovellus"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Poista sovellus"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Lisää toistotapoja"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Ryhmä"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 laite valittu"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 47974b2..cfd5614 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Activer l\'USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"En savoir plus"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Capture d\'écran"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Fonctionnalité Smart Lock désactivée"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"a envoyé une image"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Enregistrement capture écran…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Sauv. de la capture dans le profil prof. en cours…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Si vous entrez un NIP incorrect à la prochaine tentative, votre profil professionnel et ses données seront supprimés."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Si vous entrez un mot de passe incorrect à la prochaine tentative suivante, votre profil professionnel et ses données seront supprimés."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Touchez le capteur d\'empreintes digitales"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Icône d\'empreinte digitale"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Visage non reconnu. Utilisez plutôt l\'empreinte digitale."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Volet des notifications"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Paramètres rapides"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Paramètres rapides et volet des notifications."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Écran de verrouillage"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Verrouillage de l\'écran du profil professionnel"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Fermer"</string>
@@ -616,84 +615,48 @@
     <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_clear_text (4679927133259287577) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_list_title (1156178106617830429) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_list_hint (5982623262974326746) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_list_no_result (6819302191660875501) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_category_system (1151182120757052669) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_category_input (5440558509904296233) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_category_open_apps (1450959949739257562) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_category_current_app (2011953559133734491) -->
-    <skip />
-    <!-- no translation found for group_system_access_notification_shade (7116898151485382275) -->
-    <skip />
-    <!-- no translation found for group_system_full_screenshot (7389040853798023211) -->
-    <skip />
-    <!-- no translation found for group_system_access_system_app_shortcuts (4421497579210445641) -->
-    <skip />
-    <!-- no translation found for group_system_go_back (8838454003680364227) -->
-    <skip />
-    <!-- no translation found for group_system_access_home_screen (1857344316928441909) -->
-    <skip />
-    <!-- no translation found for group_system_overview_open_apps (6897128761003265350) -->
-    <skip />
-    <!-- no translation found for group_system_cycle_forward (9202444850838205990) -->
-    <skip />
-    <!-- no translation found for group_system_cycle_back (5163464503638229131) -->
-    <skip />
-    <!-- no translation found for group_system_access_all_apps_search (488070738028991753) -->
-    <skip />
-    <!-- no translation found for group_system_hide_reshow_taskbar (3809304065624351131) -->
-    <skip />
-    <!-- no translation found for group_system_access_system_settings (7961639365383008053) -->
-    <skip />
-    <!-- no translation found for group_system_access_google_assistant (1186152943161483864) -->
-    <skip />
-    <!-- no translation found for group_system_lock_screen (7391191300363416543) -->
-    <skip />
-    <!-- no translation found for group_system_quick_memo (2914234890158583919) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_group_system_multitasking (1065232949510862593) -->
-    <skip />
-    <!-- no translation found for system_multitasking_rhs (6593269428880305699) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (8839380725557952846) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (1962084334200006297) -->
-    <skip />
-    <!-- no translation found for system_multitasking_replace (844285282472557186) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_group_input (6888282716546625610) -->
-    <skip />
-    <!-- no translation found for input_switch_input_language_next (3394291576873633793) -->
-    <skip />
-    <!-- no translation found for input_switch_input_language_previous (8823659252918609216) -->
-    <skip />
-    <!-- no translation found for input_access_emoji (8105642858900406351) -->
-    <skip />
-    <!-- no translation found for input_access_voice_typing (7291201476395326141) -->
-    <skip />
+    <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Effacer le texte"</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>
+    <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Système"</string>
+    <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>
+    <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Accéder au volet de notification"</string>
+    <string name="group_system_full_screenshot" msgid="7389040853798023211">"Prendre une capture d\'écran complète"</string>
+    <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Accéder à la liste des raccourcis du système/des applications"</string>
+    <string name="group_system_go_back" msgid="8838454003680364227">"Retour : retour à l\'état précédent (bouton précédent)"</string>
+    <string name="group_system_access_home_screen" msgid="1857344316928441909">"Accéder à l\'écran d\'accueil"</string>
+    <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Aperçu des applications ouvertes"</string>
+    <string name="group_system_cycle_forward" msgid="9202444850838205990">"Parcourir les applications récentes (avancer)"</string>
+    <string name="group_system_cycle_back" msgid="5163464503638229131">"Parcourir les applications récentes (retour)"</string>
+    <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Accéder à la liste des applis et à la recherche (recherche/lanceur)"</string>
+    <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Masquer et (ré)afficher la barre des tâches"</string>
+    <string name="group_system_access_system_settings" msgid="7961639365383008053">"Accéder aux paramètres système"</string>
+    <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Accéder à l\'Assistant Google"</string>
+    <string name="group_system_lock_screen" msgid="7391191300363416543">"Écran de verrouillage"</string>
+    <string name="group_system_quick_memo" msgid="2914234890158583919">"Ouvrir l\'application de prise de notes pour prendre des notes rapides"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitâche du système"</string>
+    <string name="system_multitasking_rhs" msgid="6593269428880305699">"Passer à l\'écran partagé avec l\'application actuelle à droite"</string>
+    <string name="system_multitasking_lhs" msgid="8839380725557952846">"Passer à l\'écran partagé avec l\'application actuelle à gauche"</string>
+    <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Passer de l\'écran partagé au plein écran"</string>
+    <string name="system_multitasking_replace" msgid="844285282472557186">"En mode d\'écran partagé : remplacer une application par une autre"</string>
+    <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Entrée"</string>
+    <string name="input_switch_input_language_next" msgid="3394291576873633793">"Changer la langue d\'entrée (langue suivante)"</string>
+    <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Changer la langue d\'entrée (langue précédente)"</string>
+    <string name="input_access_emoji" msgid="8105642858900406351">"Accéder aux émojis"</string>
+    <string name="input_access_voice_typing" msgid="7291201476395326141">"Accéder à l\'entrée vocale"</string>
     <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Applications"</string>
     <string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Assistance"</string>
-    <!-- no translation found for keyboard_shortcut_group_applications_browser (7328131901589876868) -->
-    <skip />
+    <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Navigateur (Chrome par défaut)"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Contacts"</string>
-    <!-- no translation found for keyboard_shortcut_group_applications_email (7480359963463803511) -->
-    <skip />
+    <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Courriel (Gmail par défaut)"</string>
     <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"Messages texte"</string>
     <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Musique"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Agenda"</string>
-    <!-- no translation found for keyboard_shortcut_group_applications_calculator (6316043911946540137) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_group_applications_maps (7312554713993114342) -->
-    <skip />
+    <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculatrice"</string>
+    <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
     <string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ne pas déranger"</string>
     <string name="volume_dnd_silent" msgid="4154597281458298093">"Raccourci des boutons de volume"</string>
     <string name="battery" msgid="769686279459897127">"Pile"</string>
@@ -856,12 +819,9 @@
     <string name="privacy_type_media_projection" msgid="8136723828804251547">"enregistrement d\'écran"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Sans titre"</string>
     <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Veille"</string>
-    <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
-    <skip />
-    <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
-    <skip />
-    <!-- no translation found for font_scaling_larger (5476242157436806760) -->
-    <skip />
+    <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Taille de police"</string>
+    <string name="font_scaling_smaller" msgid="1012032217622008232">"Rapetisser"</string>
+    <string name="font_scaling_larger" msgid="5476242157436806760">"Agrandir"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"Fenêtre d\'agrandissement"</string>
     <string name="magnification_controls_title" msgid="8421106606708891519">"Commandes pour la fenêtre d\'agrandissement"</string>
     <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Effectuer un zoom avant"</string>
@@ -874,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Agrandir la totalité de l\'écran"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Agrandir une partie de l\'écran"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Commutateur"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Faire glisser le coin pour redimensionner"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Autoriser le défilement en diagonale"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Redimensionner"</string>
@@ -883,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Poignée gauche"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Poignée droite"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Poignée inférieure"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Taille de loupe"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoom"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Moyenne"</string>
@@ -909,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# commande ajoutée.}one{# commande ajoutée.}many{# de commandes ajoutées.}other{# commandes ajoutées.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Supprimé"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Ajouter <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Lorsque vous ajoutez <xliff:g id="APPNAME">%s</xliff:g>, elle peut ajouter des commandes et du contenu à ce panneau. Dans certaines applications, vous pouvez choisir les commandes qui s\'affichent ici."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Retirer les commandes pour <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Ajouté aux favoris"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Ajouté aux favoris, en position <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Supprimé des favoris"</string>
@@ -927,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Autre"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Ajouter aux commandes des appareils"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Ajouter"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Retirer"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Suggestion de <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Appareil verrouillé"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Afficher et contrôler les appareils à partir de l\'écran de verrouillage?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Vous pouvez ajouter des commandes pour vos appareils externes à l\'écran de verrouillage.\n\nL\'application de votre appareil peut vous permettre de contrôler certains appareils sans déverrouiller votre téléphone ou votre tablette.\n\nVous pouvez apporter des modifications à tout moment dans les paramètres."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Contrôler les appareils à partir de l\'écran de verrouillage?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Vous pouvez contrôler certains appareils sans déverrouiller votre téléphone ou votre tablette.\n\nL\'application de votre appareil détermine quels appareils peuvent être contrôlés de cette manière."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Non merci"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Oui"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Le NIP contient des lettres ou des symboles"</string>
@@ -980,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Ajouter des commandes"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Modifier des commandes"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Ajouter une application"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Retirer l\'application"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Ajouter des sorties"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Groupe"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Un appareil sélectionné"</string>
@@ -1150,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Passer au profil professionnel"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Fermer"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Paramètres écran de verrouillage"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi non accessible"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Appareil photo bloqué"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Appareil photo et microphone bloqués"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microphone bloqué"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Mode Priorité activé"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant à l\'écoute"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 7e2bada..995e218 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Activer le port USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"En savoir plus"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Capture d\'écran"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock désactivé"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"a envoyé une image"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Enregistrement de la capture d\'écran…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Enregistrement de capture d\'écran dans profil pro…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Si vous saisissez un code incorrect lors de la prochaine tentative, votre profil professionnel et les données associées seront supprimés."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Si vous saisissez un mot de passe incorrect lors de la prochaine tentative, votre profil professionnel et les données associées seront supprimés."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Appuyez sur le lecteur d\'empreinte digitale"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Icône d\'empreinte digitale"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Visage non reconnu. Utilisez votre empreinte."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Volet des notifications"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Réglages rapides"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Réglages rapides et volet des notifications."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Écran de verrouillage"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Écran de verrouillage du profil professionnel"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Fermer"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Agrandir tout l\'écran"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Agrandir une partie de l\'écran"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Changer"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Faire glisser le coin pour redimensionner"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Autoriser le défilement diagonal"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Redimensionner"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Poignée gauche"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Poignée droite"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Poignée inférieure"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Taille de l\'agrandissement"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoom"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Moyen"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# commande ajoutée.}one{# commande ajoutée.}many{# commandes ajoutées.}other{# commandes ajoutées.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Supprimé"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Ajouter <xliff:g id="APPNAME">%s</xliff:g> ?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Lorsque vous ajoutez l\'appli <xliff:g id="APPNAME">%s</xliff:g>, elle peut ajouter des commandes et contenus dans ce panneau. Dans certaines applis, vous pouvez choisir les commandes à afficher ici."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Supprimer les commandes pour <xliff:g id="APPNAME">%s</xliff:g> ?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Ajouté aux favoris"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Ajouté aux favoris, en position <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Supprimé des favoris"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Autre"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Ajouter aux commandes des appareils"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Ajouter"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Supprimer"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Suggérée par <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Appareil verrouillé"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Afficher et contrôler les appareils depuis l\'écran de verrouillage ?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Vous pouvez ajouter des commandes pour vos appareils externes sur l\'écran de verrouillage.\n\nL\'appli de votre appareil peut vous autoriser à contrôler certains appareils sans déverrouiller votre téléphone ou tablette.\n\nVous pouvez apporter des modifications à tout moment dans les paramètres."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Contrôler des appareils depuis l\'écran de verrouillage ?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Vous pouvez contrôler certains appareils sans déverrouiller votre téléphone ou tablette.\n\nL\'appli de votre appareil détermine les appareils qui peuvent être contrôlés de cette manière."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Non, merci"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Oui"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Le code contient des lettres ou des symboles"</string>
@@ -935,12 +942,13 @@
     <string name="controls_error_removed" msgid="6675638069846014366">"Introuvable"</string>
     <string name="controls_error_removed_title" msgid="1207794911208047818">"Commande indisponible"</string>
     <string name="controls_error_removed_message" msgid="2885911717034750542">"Impossible d\'accéder à \"<xliff:g id="DEVICE">%1$s</xliff:g>\". Vérifiez l\'application <xliff:g id="APPLICATION">%2$s</xliff:g> pour vous assurer que la commande est toujours disponible et que les paramètres de l\'application n\'ont pas changé."</string>
-    <string name="controls_open_app" msgid="483650971094300141">"Ouvrir l\'application"</string>
+    <string name="controls_open_app" msgid="483650971094300141">"Ouvrir l\'appli"</string>
     <string name="controls_error_generic" msgid="352500456918362905">"Impossible de charger l\'état"</string>
     <string name="controls_error_failed" msgid="960228639198558525">"Erreur. Veuillez réessayer."</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Ajouter des commandes"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Modifier des commandes"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Ajouter une appli"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Supprimer l\'application"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Ajouter des sorties"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Groupe"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 appareil sélectionné"</string>
@@ -1019,7 +1027,7 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Données mobiles"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Connecté"</string>
-    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Connectée temporairement"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Connexion temporaire"</string>
     <string name="mobile_data_poor_connection" msgid="819617772268371434">"Connexion médiocre"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Pas de connexion automatique des données mobiles"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Aucune connexion"</string>
@@ -1111,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Passer au profil professionnel"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Fermer"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Paramètres écran de verrouillage"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi non disponible"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Caméra bloquée"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Caméra et micro bloqués"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Micro bloqué"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Mode Prioritaire activé"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant à l\'écoute"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 8ff9b06..74d9f9a 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Activar USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Máis información"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Facer captura"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock está desactivado"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"enviou unha imaxe"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Gardando captura de pantalla…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Gardando captura de pantalla no perfil de traballo"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Se indicas un PIN incorrecto no seguinte intento, eliminaranse o teu perfil de traballo e os datos asociados."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Se indicas un contrasinal incorrecto no seguinte intento, eliminaranse o teu perfil de traballo e os datos asociados."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Toca o sensor de impresión dixital"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Icona de impresión dixital"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Non se recoñeceu a cara. Usa a impresión dixital."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Panel despregable"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configuración rápida"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configuración rápida e panel despregable."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Pantalla de bloqueo."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Pantalla de bloqueo do perfil de traballo"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Pechar"</string>
@@ -408,7 +407,7 @@
     <string name="media_projection_action_text" msgid="3634906766918186440">"Iniciar agora"</string>
     <string name="empty_shade_text" msgid="8935967157319717412">"Non hai notificacións"</string>
     <string name="no_unseen_notif_text" msgid="395512586119868682">"Non hai notificacións novas"</string>
-    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloquea para ver notificacións"</string>
+    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloquea para ver máis notificacións"</string>
     <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"O teu pai ou nai xestiona este dispositivo"</string>
     <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"A túa organización é propietaria deste dispositivo e pode controlar o tráfico de rede"</string>
     <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> é a organización propietaria deste dispositivo e pode controlar o tráfico de rede"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ampliar pantalla completa"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Amplía parte da pantalla"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Cambiar"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Arrastrar a esquina para cambiar o tamaño"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Permitir desprazamento diagonal"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Cambiar tamaño"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Controlador esquerdo"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Controlador dereito"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Controlador inferior"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Tamaño da lupa"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoom"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Mediano"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Engadiuse # control.}other{Engadíronse # controis.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Quitouse"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Queres engadir <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Cando engadas a aplicación <xliff:g id="APPNAME">%s</xliff:g>, poderá incluír controis e contido neste panel Nalgunhas aplicacións, podes escoller os controis que se mostrarán aquí."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Queres quitar os controis de <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Está entre os controis favoritos"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Está entre os controis favoritos (posición: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Non está entre os controis favoritos"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Outra"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Engadir ao control de dispositivos"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Engadir"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Quitar"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Control suxerido por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Disposit. bloqueado"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Queres que se mostren dispositivos na pantalla de bloqueo e poder controlalos desde ela?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Podes engadir á pantalla de bloqueo controis para os dispositivos externos.\n\nÉ posible que a aplicación do dispositivo che permita controlar algúns dispositivos sen desbloquear o teléfono ou a tableta.\n\nPodes realizar cambios cando queiras en Configuración."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Queres controlar dispositivos desde a pantalla de bloqueo?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Podes controlar algúns dispositivos sen desbloquear o teléfono ou a tableta.\n\nA aplicación do dispositivo determina os dispositivos que se poden controlar deste xeito."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Non, grazas"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Si"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"O PIN contén letras ou símbolos"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Engadir controis"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Editar controis"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Engadir aplicación"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Quitar aplicación"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Engadir saídas"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Seleccionouse 1 dispositivo"</string>
@@ -1111,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Cambiar ao perfil de traballo"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Pechar"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Configuración pantalla bloqueo"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wifi non dispoñible"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"A cámara está bloqueada"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"A cámara e o micrófono están bloqueados"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"O micrófono está bloqueado"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"O modo de prioridade está activado"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"A atención do Asistente está activada"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index d1422ba..50aadc7 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USB ચાલુ કરો"</string>
     <string name="learn_more" msgid="4690632085667273811">"વધુ જાણો"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"સ્ક્રીનશૉટ"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock બંધ કરેલું છે"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"છબી મોકલી"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"સ્ક્રીનશોટ સાચવી રહ્યું છે…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"ઑફિસની પ્રોફાઇલમાં સ્ક્રીનશૉટ સાચવી રહ્યાં છીએ…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"જો તમે આગલા પ્રયત્નમાં ખોટો પિન દાખલ કરશો, તો તમારી કાર્યાલયની પ્રોફાઇલ અને તેનો ડેટા ડિલીટ કરવામાં આવશે."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"જો તમે આગલા પ્રયત્નમાં ખોટો પાસવર્ડ દાખલ કરશો, તો તમારી કાર્યાલયની પ્રોફાઇલ અને તેનો ડેટા ડિલીટ કરવામાં આવશે."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ફિંગરપ્રિન્ટના સેન્સરને સ્પર્શ કરો"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"ફિંગરપ્રિન્ટનું આઇકન"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ચહેરો ઓળખી શકતા નથી. તેને બદલે ફિંગરપ્રિન્ટ વાપરો."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"નોટિફિકેશન શેડ."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ઝડપી સેટિંગ."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ઝડપી સેટિંગ અને નોટિફિકેશન શેડ."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"લૉક સ્ક્રીન."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"કાર્ય લૉક સ્ક્રીન"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"બંધ કરો"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"પૂર્ણ સ્ક્રીનને મોટી કરો"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"સ્ક્રીનનો કોઈ ભાગ મોટો કરો"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"સ્વિચ"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"કદ બદલવા માટે ખૂણો ખેંચો"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"ડાયગોનલ સ્ક્રોલિંગને મંજૂરી આપો"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"કદ બદલો"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"ડાબું હૅન્ડલ"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"જમણું હૅન્ડલ"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"નીચેનું હૅન્ડલ"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"મેગ્નિફાયરનું કદ"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"નાનું-મોટું કરો"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"મધ્યમ"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# નિયંત્રણ ઉમેર્યું.}one{# નિયંત્રણ ઉમેર્યું.}other{# નિયંત્રણ ઉમેર્યા.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"કાઢી નાખ્યું"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> ઉમેરીએ?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"જ્યારે તમે <xliff:g id="APPNAME">%s</xliff:g> ઉમેરો, ત્યારે તે આ પૅનલમાં નિયંત્રણો અને કન્ટેન્ટ ઉમેરી શકે છે. કેટલીક ઍપમાં, અહીં કયા નિયંત્રણો દેખાય તે તમે પસંદ કરી શકો છો."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> માટે નિયંત્રણો કાઢી નાખીએ?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"મનપસંદમાં ઉમેર્યું"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"મનપસંદમાં ઉમેર્યું, સ્થાન <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"મનપસંદમાંથી કાઢી નાખ્યું"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"અન્ય"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"ડિવાઇસનાં નિયંત્રણોમાં ઉમેરો"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"ઉમેરો"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"કાઢી નાખો"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> દ્વારા સૂચવેલા"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"ડિવાઇસ લૉક કરેલું છે"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"લૉક સ્ક્રીનમાંથી ડિવાઇસ બતાવીએ અને નિયંત્રિત કરીએ?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"તમે તમારા બાહ્ય ડિવાઇસ માટેના નિયંત્રણો લૉક સ્ક્રીન પર ઉમેરી શકો છો.\n\nતમારી ડિવાઇસ ઍપ કદાચ તમને તમારો ફોન કે ટૅબ્લેટ અનલૉક કર્યા વિના અમુક ડિવાઇસ નિયંત્રિત કરવાની મંજૂરી આપી શકે.\n\nતમે ગમે ત્યારે સેટિંગમાં જઈને ફેરફાર કરી શકો છો."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"લૉક સ્ક્રીનમાંથી ડિવાઇસ નિયંત્રિત કરીએ?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"તમે તમારા ફોન કે ટૅબ્લેટને અનલૉક કર્યા વિના અમુક ડિવાઇસ નિયંત્રિત કરી શકો છો.\n\nતમારી ડિવાઇસ ઍપ નક્કી કરે છે કે આ રીતે કયા ડિવાઇસને નિયંત્રિત કરવા."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"ના, આભાર"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"હા"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"પિનમાં અક્ષરો અથવા પ્રતીકોનો સમાવેશ થાય છે"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"નિયંત્રણો ઉમેરો"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"નિયંત્રણોમાં ફેરફાર કરો"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"ઍપ ઉમેરો"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"ઍપ કાઢી નાખો"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"આઉટપુટ ઉમેરો"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"ગ્રૂપ"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 ડિવાઇસ પસંદ કર્યું"</string>
@@ -1111,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"ઑફિસની પ્રોફાઇલ પર સ્વિચ કરો"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"બંધ કરો"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"લૉક સ્ક્રીનના સેટિંગ"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"વાઇ-ફાઇ ઉપલબ્ધ નથી"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"કૅમેરા બ્લૉક કરેલો છે"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"કૅમેરા અને માઇક્રોફોન બ્લૉક કરેલા છે"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"માઇક્રોફોન બ્લૉક કરેલો છે"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"પ્રાધાન્યતા મોડ ચાલુ છે"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant સક્રિય છે"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 0d08dcd..046f554 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"यूएसबी चालू करें"</string>
     <string name="learn_more" msgid="4690632085667273811">"ज़्यादा जानें"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"स्क्रीनशॉट"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock की सुविधा बंद कर दी गई है"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"एक इमेज भेजी गई"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"स्क्रीनशॉट सहेजा जा रहा है..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"स्क्रीनशॉट, वर्क प्रोफ़ाइल में सेव किया जा रहा है…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"अगर आप फिर से गलत पिन डालते हैं, तो आपकी वर्क प्रोफ़ाइल और उसका डेटा मिटा दिया जाएगा."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"अगर आप फिर से गलत पासवर्ड डालते हैं, तो आपकी वर्क प्रोफ़ाइल और उसका डेटा मिटा दिया जाएगा."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"फ़िंगरप्रिंट सेंसर को छुएं"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"फ़िंगरप्रिंट आइकॉन"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"चेहरे की पहचान नहीं हुई. फ़िंगरप्रिंट इस्तेमाल करें."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"सूचना शेड."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"त्वरित सेटिंग."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"क्विक सेटिंग और नोटिफ़िकेशन शेड."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"लॉक स्क्रीन."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"वर्क लॉक स्‍क्रीन"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"बंद करें"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"फ़ुल स्क्रीन को ज़ूम करें"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"स्क्रीन के किसी हिस्से को ज़ूम करें"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"स्विच"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"साइज़ बदलने के लिए, कोने को खींचें और छोड़ें"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"तिरछी दिशा में स्क्रोल करने की अनुमति दें"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"साइज़ बदलें"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"बायां हैंडल"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"दायां हैंडल"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"नीचे का हैंडल"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"ज़ूम करने की सुविधा का साइज़"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"ज़ूम करें"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"मध्यम"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# कंट्रोल जोड़ा गया.}one{# कंट्रोल जोड़ा गया.}other{# कंट्रोल जोड़े गए.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"हटाया गया"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> को जोड़ना है?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> को जोड़ने पर, वह इस पैनल पर कुछ कंट्रोल और कॉन्टेंट दिखा सकता है. कुछ ऐप्लिकेशन के लिए यह चुना जा सकता है कि वे इस पैनल पर कौनसे कंट्रोल दिखाएं."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> के लिए कंट्रोल हटाने हैं?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"पसंदीदा बनाया गया"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"पसंदीदा बनाया गया, क्रम संख्या <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"पसंदीदा से हटाया गया"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"अन्य"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"डिवाइस कंट्रोल में जोड़ें"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"जोड़ें"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"हटाएं"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> से मिला सुझाव"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"डिवाइस लॉक है"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"क्या डिवाइसों को लॉक स्क्रीन पर देखना है और उन्हें वहीं से कंट्रोल करना है?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"लॉक स्क्रीन पर अपने बाहरी डिवाइसों के लिए कंट्रोल जोड़े जा सकते हैं.\n\nअपने डिवाइस के ऐप्लिकेशन से कुछ डिवाइसों को कंट्रोल किया जा सकता है. इसके लिए, फ़ोन या टैबलेट को अनलॉक नहीं करना पड़ता.\n\nकिसी भी समय सेटिंग में जाकर बदलाव किए जा सकते हैं."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"क्या लॉक स्क्रीन से डिवाइसों को कंट्रोल करना है?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"फ़ोन या टैबलेट को अनलॉक किए बिना, कुछ डिवाइसों को कंट्रोल किया जा सकता है.\n\nआपके डिवाइस के ऐप्लिकेशन से यह तय किया जाता है कि किन डिवाइसों को इस तरह कंट्रोल किया जा सकता है."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"नहीं, रहने दें"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"हां"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"पिन में अक्षर या चिह्न शामिल होते हैं"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"कंट्राेल जोड़ें"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"कंट्रोल में बदलाव करें"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"ऐप्लिकेशन जोड़ें"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"ऐप्लिकेशन हटाएं"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"आउटपुट जोड़ें"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"ग्रुप"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"एक डिवाइस चुना गया"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 9c94f7b..6d8b24b 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Omogući USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Saznajte više"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Snimka zaslona"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock onemogućen"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"šalje sliku"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Spremanje snimke zaslona..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Spremanje snimke zaslona na poslovni profil…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Ako pri sljedećem pokušaju unesete netočan PIN, izbrisat će se vaš poslovni profil i njegovi podaci."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Ako pri sljedećem pokušaju unesete netočnu zaporku, izbrisat će se vaš poslovni profil i njegovi podaci."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Dodirnite senzor otiska prsta"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikona otiska prsta"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Prepoznavanje lica nije uspjelo. Upotrijebite otisak prsta."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -834,6 +834,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Povećajte cijeli zaslon"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Povećaj dio zaslona"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Prebacivanje"</string>
+    <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Otvori postavke povećavanja"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Povucite kut da biste promijenili veličinu"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Dopusti dijagonalno pomicanje"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Promijeni veličinu"</string>
@@ -843,6 +844,7 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Lijevi marker"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Desni marker"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Donji marker"</string>
+    <string name="accessibility_magnification_settings_panel_description" msgid="8174187340747846953">"Postavke povećavanja"</string>
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Veličina povećala"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zumiranje"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Srednja"</string>
@@ -869,7 +871,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Dodana je # kontrola.}one{Dodana je # kontrola.}few{Dodane su # kontrole.}other{Dodano je # kontrola.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Uklonjeno"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Želite li dodati aplikaciju <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Kada dodate aplikaciju <xliff:g id="APPNAME">%s</xliff:g>, može dodati kontrole i sadržaj na ovu ploču. U nekim aplikacijama možete odabrati koje se kontrole prikazuju ovdje."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Ukloniti kontrole za aplikaciju <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Dodano u favorite"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Dodano u favorite, položaj <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Uklonjeno iz favorita"</string>
@@ -887,12 +891,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Drugo"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Dodavanje kontrolama uređaja"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Dodaj"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Ukloni"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Preporuka s kanala <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Uređaj je zaključan"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Prikazati uređaje i omogućiti upravljanje njima na zaključanom zaslonu?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Na zaključan zaslon možete dodati kontrole za svoje vanjske uređaje.\n\nAplikacija vašeg uređaja može vam dopustiti upravljanje nekim uređajima bez otključavanja telefona ili tableta.\n\nPromjene uvijek možete unijeti u Postavkama."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Upravljati uređajima na zaključanom zaslonu?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Nekim uređajima možete upravljati bez otključavanja telefona ili tableta.\n\nAplikacija vašeg uređaja odlučuje kojim se uređajima može upravljati na taj način."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Ne, hvala"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Da"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN sadrži slova ili simbole"</string>
@@ -934,12 +940,13 @@
     <string name="controls_error_removed" msgid="6675638069846014366">"Nije pronađeno"</string>
     <string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrola nije dostupna"</string>
     <string name="controls_error_removed_message" msgid="2885911717034750542">"Nije moguće pristupiti uređaju: <xliff:g id="DEVICE">%1$s</xliff:g>. U aplikaciji <xliff:g id="APPLICATION">%2$s</xliff:g> provjerite je li kontrola i dalje dostupna te potvrdite da se postavke aplikacije nisu promijenile."</string>
-    <string name="controls_open_app" msgid="483650971094300141">"Otvori apl."</string>
+    <string name="controls_open_app" msgid="483650971094300141">"Otvori aplikaciju"</string>
     <string name="controls_error_generic" msgid="352500456918362905">"Status se ne može učitati"</string>
     <string name="controls_error_failed" msgid="960228639198558525">"Pogreška, pokušajte ponovo"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"Dodaj kontrole"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Uredi kontrole"</string>
-    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Dodavanje aplikacije"</string>
+    <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Dodaj aplikaciju"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Ukloni aplikaciju"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Dodavanje izlaza"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupa"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Odabran je jedan uređaj"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index fadc88d..dcb7d72 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USB engedélyezése"</string>
     <string name="learn_more" msgid="4690632085667273811">"Részletek"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Képernyőkép"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock kikapcsolva"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"képet küldött"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Képernyőkép mentése..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Képernyőkép mentése a munkaprofilba…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Amennyiben helytelen PIN-kódot ad meg a következő kísérletnél, a rendszer törli munkaprofilját és a kapcsolódó adatokat."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Amennyiben helytelen jelszót ad meg a következő kísérletnél, a rendszer törli munkaprofilját és a kapcsolódó adatokat."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Érintse meg az ujjlenyomat-érzékelőt"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ujjlenyomat ikonja"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Az arc nem felismerhető. Használjon ujjlenyomatot."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Értesítési felület."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Gyorsbeállítások."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Gyorsbeállítások és értesítési terület"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lezárási képernyő."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Munka lezárási képernyővel"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Bezárás"</string>
@@ -835,6 +834,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"A teljes képernyő felnagyítása"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Képernyő bizonyos részének nagyítása"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Váltás"</string>
+    <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Nagyítási beállítások megnyitása"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Az átméretezéshez húzza a kívánt sarkot"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Átlós görgetés engedélyezése"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Átméretezés"</string>
@@ -844,6 +844,7 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Bal oldali fogópont"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Jobb oldali fogópont"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Alsó fogópont"</string>
+    <string name="accessibility_magnification_settings_panel_description" msgid="8174187340747846953">"Nagyítási beállítások"</string>
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Nagyító mérete"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Nagyítás/kicsinyítés"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Közepes"</string>
@@ -870,7 +871,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# vezérlő hozzáadva.}other{# vezérlő hozzáadva.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Eltávolítva"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Hozzáadja a(z) <xliff:g id="APPNAME">%s</xliff:g> alkalmazást?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"A(z) <xliff:g id="APPNAME">%s</xliff:g> hozzáadását követően az alkalmazás vezérlőelemeket és tartalmakat adhat hozzá ehhez a panelhez. Egyes alkalmazásokban kiválasztható, hogy mely vezérlőelemek jelenjenek meg itt."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Eltávolítja a(z) <xliff:g id="APPNAME">%s</xliff:g> vezérlőit?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Hozzáadva a kedvencekhez"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Hozzáadva a kedvencekhez <xliff:g id="NUMBER">%d</xliff:g>. helyen"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Eltávolítva a kedvencek közül"</string>
@@ -888,12 +891,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Más"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Hozzáadás az eszközvezérlőkhöz"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Hozzáadás"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Eltávolítás"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> javasolta"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Az eszköz zárolva van"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Szeretne megtekinteni és vezérelni eszközöket a lezárási képernyőn?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Hozzáadhatja külső eszközök vezérlőit a lezárási képernyőhöz.\n\nAz eszközön lévő alkalmazás segítségével telefonja vagy táblagépe feloldása nélkül is vezérelhet néhány eszközt.\n\nA Beállításokban bármikor módosíthatja ezt a funkciót."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Szeretne eszközöket vezérelni a lezárási képernyőn?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Telefonja vagy táblagépe feloldása nélkül is vezérelhet néhány eszközt.\n\nAz eszközön lévő alkalmazással határozhatja meg, hogy mely eszközöket kívánja ilyen módon vezérelni."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Most nem"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Igen"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"A PIN-kód betűket vagy szimbólumokat tartalmaz"</string>
@@ -941,6 +946,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Vezérlők hozzáadása"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Vezérlők szerkesztése"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Alkalmazás hozzáadása"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Alkalmazás eltávolítása"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Kimenetek hozzáadása"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Csoport"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 eszköz kiválasztva"</string>
@@ -1111,16 +1117,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Váltás munkaprofilra"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Bezárás"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Lezárási képernyő beállításai"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Nem áll rendelkezésre Wi-Fi"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera letiltva"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera és mikrofon letiltva"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon letiltva"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritás mód bekapcsolva"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"A Segéd figyel"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 22877cf..1b21230 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Միացնել USB-ն"</string>
     <string name="learn_more" msgid="4690632085667273811">"Իմանալ ավելին"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Սքրինշոթ"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock-ն անջատված է"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"պատկեր է ուղարկվել"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Սքրինշոթը պահվում է..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Սքրինշոթը պահվում է աշխատանքային պրոֆիլում…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Հաջորդ փորձի ժամանակ սխալ PIN կոդ մուտքագրելու դեպքում աշխատանքային պրոֆիլը և դրա տվյալները կջնջվեն։"</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Հաջորդ փորձի ժամանակ սխալ գաղտնաբառ մուտքագրելու դեպքում աշխատանքային պրոֆիլը և դրա տվյալները կջնջվեն։"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Հպեք մատնահետքի սկաներին"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Մատնահետքի պատկերակ"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Դեմքը չի հաջողվում ճանաչել։ Օգտագործեք մատնահետքը։"</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Ծանուցումների վահանակ:"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Արագ կարգավորումներ:"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Արագ կարգավորումներ և ծանուցումների վահանակ։"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Էկրանի կողպում:"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Աշխատանքային պրոֆիլի կողպէկրան"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Փակել"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Խոշորացնել ամբողջ էկրանը"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Խոշորացնել էկրանի որոշակի հատվածը"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Փոխել"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Քաշեք անկյունը՝ չափը փոխելու համար"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Թույլատրել անկյունագծով ոլորումը"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Փոխել չափը"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Ձախ բռնակ"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Աջ բռնակ"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Ներքևի բռնակ"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Խոշորացույցի չափսը"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Մասշտաբ"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Միջին"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Ավելացվեց կառավարման # տարր։}one{Ավելացվեց կառավարման # տարր։}other{Ավելացվեց կառավարման # տարր։}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Հեռացված է"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Ավելացնե՞լ <xliff:g id="APPNAME">%s</xliff:g> հավելվածը"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Եթե ավելացնեք <xliff:g id="APPNAME">%s</xliff:g> հավելվածը, այն կարող է կարգավորումներ և բովանդակություն ավելացնել այս վահանակում։ Որոշ հավելվածներում դուք կարող եք ընտրել, թե որ կարգավորումները ցուցադրվեն այստեղ։"</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Հեռացնե՞լ <xliff:g id="APPNAME">%s</xliff:g> հավելվածի համար կարգավորումները։"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Ավելացված է ընտրանիում"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Ավելացված է ընտրանիում, դիրքը՝ <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Հեռացված է ընտրանուց"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Այլ"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Ավելացրեք սարքերի կառավարման տարրերում"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Ավելացնել"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Հեռացնել"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Առաջարկվել է <xliff:g id="APP">%s</xliff:g> հավելվածի կողմից"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Սարքը կողպված է"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Ցույց տա՞լ և կառավարել սարքերը կողպէկրանից"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Դուք կարող եք կարգավորումներ ավելացնել ձեր արտաքին սարքերի համար կողպէկրանին։\n\nՁեր սարքի հավելվածը կարող է ձեզ թույլ տալ որոշ սարքեր կառավարել առանց ապակողպելու հեռախոսը կամ պլանշետը։\n\nՑանկացած ժամանակ փոփոխություններ կատարեք Կարգավորումներում։"</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Կառավարե՞լ սարքերը կողպէկրանից"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Դուք կարող եք կառավարել որոշ սարքեր՝ առանց ապակողպելու ձեր հեռախոսը կամ պլանշետը։\n\nՁեր սարքի հավելվածը որոշում է, թե որ սարքերը կարելի է կառավարել այս եղանակով։"</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Ոչ, շնորհակալություն"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Այո"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN կոդը տառեր և նշաններ է պարունակում"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Ավելացնել կառավարման տարրեր"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Փոփոխել կառավարման տարրերը"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Ավելացնել հավելված"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Հեռացնել հավելվածը"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Ավելացրեք մուտքագրման սարքեր"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Խումբ"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Ընտրված է 1 սարք"</string>
@@ -1111,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Անցնել աշխատանքային պրոֆիլ"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Փակել"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Կողպէկրանի կարգավորումներ"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ցանց հասանելի չէ"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Տեսախցիկն արգելափակված է"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Տեսախցիկն ու խոսափողը արգելափակված են"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Խոսափողն արգելափակված է"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Առաջնահերթության ռեժիմը միացված է"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Օգնականը լսում է"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 262d0e1..055479e 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Aktifkan USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Pelajari lebih lanjut"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock dinonaktifkan"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"mengirim gambar"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Menyimpan screenshot..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Menyimpan screenshot ke profil kerja …"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Jika Anda memasukkan PIN yang salah saat mencoba lagi, profil kerja dan datanya akan dihapus."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Jika Anda memasukkan sandi yang salah saat mencoba lagi, profil kerja dan datanya akan dihapus."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Sentuh sensor sidik jari"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikon sidik jari"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Tidak dapat mengenali wajah. Gunakan sidik jari."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bayangan pemberitahuan."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Setelan cepat."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Setelan cepat dan Menu notifikasi."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Layar kunci."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Layar kunci kantor"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Tutup"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Memperbesar tampilan layar penuh"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Perbesar sebagian layar"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Alihkan"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Tarik pojok persegi untuk mengubah ukuran"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Izinkan scrolling diagonal"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Ubah ukuran"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Tuas kiri"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Tuas kanan"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Tuas bawah"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Ukuran kaca pembesar"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoom"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Sedang"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kontrol ditambahkan.}other{# kontrol ditambahkan.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Dihapus"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Tambahkan <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Jika Anda menambahkannya, <xliff:g id="APPNAME">%s</xliff:g> dapat menambahkan kontrol dan konten ke panel ini. Di beberapa aplikasi, Anda dapat memilih kontrol yang akan muncul di sini."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Hapus kontrol untuk <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Difavoritkan"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Difavoritkan, posisi <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Batal difavoritkan"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Lainnya"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Tambahkan ke kontrol perangkat"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Tambahkan"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Hapus"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Disarankan oleh <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Perangkat terkunci"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Tampilkan dan kontrol perangkat dari layar kunci?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Anda dapat menambahkan kontrol untuk perangkat eksternal ke layar kunci.\n\nAplikasi perangkat Anda mungkin mengizinkan Anda mengontrol beberapa perangkat tanpa membuka kunci ponsel atau tablet.\n\nAnda dapat melakukan perubahan kapan saja di Setelan."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Kontrol perangkat dari layar kunci?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Anda dapat mengontrol beberapa perangkat eksternal tanpa membuka kunci ponsel atau tablet.\n\nAplikasi perangkat Anda menentukan perangkat yang dapat dikontrol dengan cara ini."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Lain kali"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ya"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN berisi huruf atau simbol"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Tambahkan kontrol"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Edit kontrol"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Tambahkan aplikasi"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Hapus aplikasi"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Tambahkan output"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grup"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 perangkat dipilih"</string>
@@ -1111,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Beralih ke profil kerja"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Tutup"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Setelan layar kunci"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi tidak tersedia"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera diblokir"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera dan mikrofon diblokir"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon diblokir"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Mode prioritas diaktifkan"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Asisten sedang memerhatikan"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 7bdc66c..553e0e4 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Virkja USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Frekari upplýsingar"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Skjámynd"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Slökkt á Smart Lock"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"sendi mynd"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Vistar skjámynd…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Vistar skjámynd á vinnusnið…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Ef þú slærð inn rangt PIN-númer í næstu tilraun verður vinnusniðinu þínu og gögnum þess eytt."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Ef þú slærð inn rangt aðgangsorð í næstu tilraun verður vinnusniðinu þínu og gögnum þess eytt."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Snertu fingrafaralesarann"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Fingrafaratákn"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Andlit þekkist ekki. Notaðu fingrafar í staðinn."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Tilkynningasvæði."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Flýtistillingar."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Flýtistillingar og tilkynningagluggi."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lásskjár."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Vinnulásskjár"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Loka"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Stækka allan skjáinn"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Stækka hluta skjásins"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Rofi"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Dragðu horn til að breyta stærð"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Leyfa skáflettingu"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Breyta stærð"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Vinstra handfang"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Hægra handfang"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Handfang neðst"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Stærð stækkunarglers"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Stækka/minnka"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Miðlungs"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# stýringu bætt við.}one{# stýringu bætt við.}other{# stýringum bætt við.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Fjarlægt"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Viltu bæta <xliff:g id="APPNAME">%s</xliff:g> við?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Þegar þú bætir <xliff:g id="APPNAME">%s</xliff:g> við getur það bætt stýringum og efni við þetta svæði. Í sumum forritum geturðu valið hvaða stýringar birtast hér."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Fjarlægja stýringar fyrir <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Eftirlæti"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Eftirlæti, staða <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Fjarlægt úr eftirlæti"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Annað"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Bæta við tækjastjórnun"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Bæta við"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Fjarlægja"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Tillaga frá <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Tækið er læst"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Sjá og stjórna tækjum á lásskjánum?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Þú getur bætt við stýringum fyrir ytri tæki á lásskjáinn.\n\nForrit tækisins kann að leyfa þér að stjórna sumum tækjum án þess að taka símann eða spjaldtölvuna úr lás.\n\nÞú getur gert breytingar hvenær sem er í stillingunum."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Stjórna tækjum á lásskjá?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Þú getur stjórnað sumum tækjum án þess að taka símann eða spjaldtölvuna úr lás.\n\nForrit tækisins ákvarðar hvaða tækjum er hægt að stjórna á þennan hátt."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Nei, takk"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Já"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN inniheldur bókstafi eða tákn"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Bæta við stýringum"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Breyta stýringum"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Bæta við forriti"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Fjarlægja forrit"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Bæta við úttaki"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Hópur"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 tæki valið"</string>
@@ -1111,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Skipta yfir í vinnusnið"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Loka"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Stillingar fyrir lásskjá"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi er ekki til staðar"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Lokað fyrir myndavél"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Lokað fyrir myndavél og hljóðnema"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Lokað fyrir hljóðnema"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Kveikt er á forgangsstillingu"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Hjálparinn er að hlusta"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index bc983ff..f3876ce 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Attiva USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Scopri di più"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Funzionalità Smart Lock disattivata"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"è stata inviata un\'immagine"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Salvataggio screenshot…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Salvataggio screenshot nel profilo di lavoro…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Se al prossimo tentativo inserirai un PIN sbagliato, il tuo profilo di lavoro e i relativi dati verranno eliminati."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Se al prossimo tentativo inserirai una password sbagliata, il tuo profilo di lavoro e i relativi dati verranno eliminati."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Tocca il sensore di impronte"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Icona dell\'impronta"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Impossibile riconoscere il volto. Usa l\'impronta."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -407,7 +407,7 @@
     <string name="media_projection_action_text" msgid="3634906766918186440">"Avvia adesso"</string>
     <string name="empty_shade_text" msgid="8935967157319717412">"Nessuna notifica"</string>
     <string name="no_unseen_notif_text" msgid="395512586119868682">"Nessuna nuova notifica"</string>
-    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Sblocca per notifiche meno recenti"</string>
+    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Sblocca per vedere le notifiche meno recenti"</string>
     <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Questo dispositivo è gestito dai tuoi genitori"</string>
     <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Questo dispositivo appartiene alla tua organizzazione, che potrebbe monitorare il traffico di rete"</string>
     <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Questo dispositivo appartiene a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>, che potrebbe monitorare il traffico di rete"</string>
@@ -834,6 +834,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ingrandisci l\'intero schermo"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ingrandisci parte dello schermo"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Opzione"</string>
+    <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Apri le impostazioni di ingrandimento"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Trascina l\'angolo per ridimensionare"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Consenti lo scorrimento diagonale"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Ridimensiona"</string>
@@ -843,6 +844,7 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Punto di manipolazione sinistro"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Punto di manipolazione destro"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Punto di manipolazione inferiore"</string>
+    <string name="accessibility_magnification_settings_panel_description" msgid="8174187340747846953">"Impostazioni di ingrandimento"</string>
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Dimensione dell\'ingrandimento"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoom"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Medio"</string>
@@ -869,7 +871,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# controllo aggiunto.}many{# controlli aggiunti.}other{# controlli aggiunti.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Rimosso"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Vuoi aggiungere <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Se la aggiungi, l\'app <xliff:g id="APPNAME">%s</xliff:g> può aggiungere controlli e contenuti a questo riquadro. In alcune app puoi scegliere quali controlli visualizzare qui."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Vuoi rimuovere i controlli per l\'app <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Aggiunto ai preferiti"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Preferito, posizione <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Rimosso dai preferiti"</string>
@@ -887,12 +891,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Altro"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Aggiungi al controllo dei dispositivi"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Aggiungi"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Rimuovi"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Suggerito da <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Dispositivo bloccato"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Vuoi visualizzare e controllare i dispositivi dalla schermata di blocco?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Puoi aggiungere impostazioni alla schermata di blocco per i tuoi dispositivi esterni.\n\nL\'app del tuo dispositivo potrebbe consentirti di controllare alcuni dispositivi senza dover sbloccare il tuo telefono o tablet.\n\nPuoi apportare modifiche in qualsiasi momento in Impostazioni."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Vuoi controllare i dispositivi dalla schermata di blocco?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Puoi controllare alcuni dispositivi senza dover sbloccare il tuo telefono o tablet.\n\nL\'app del tuo dispositivo determina quali dispositivi possono essere controllati in questo modo."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"No, grazie"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Sì"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Il PIN contiene lettere o simboli"</string>
@@ -940,6 +946,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Aggiungi controlli"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Modifica controlli"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Aggiungi app"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Rimuovi l\'app"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Aggiungi uscite"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Gruppo"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo selezionato"</string>
@@ -1017,7 +1024,7 @@
     <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefonata in corso"</string>
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dati mobili"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
-    <string name="mobile_data_connection_active" msgid="944490013299018227">"Connessione attiva"</string>
+    <string name="mobile_data_connection_active" msgid="944490013299018227">"Connessa"</string>
     <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Connessa temporaneamente"</string>
     <string name="mobile_data_poor_connection" msgid="819617772268371434">"Connessione debole"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Nessuna connessione dati mobili automatica"</string>
@@ -1107,19 +1114,13 @@
     <string name="video_camera" msgid="7654002575156149298">"Videocamera"</string>
     <string name="call_from_work_profile_title" msgid="6991157106804289643">"Impossibile chiamare da questo profilo"</string>
     <string name="call_from_work_profile_text" msgid="3458704745640229638">"Le norme di lavoro ti consentono di fare telefonate soltanto dal profilo di lavoro"</string>
-    <string name="call_from_work_profile_action" msgid="2937701298133010724">"Passa a profilo di lavoro"</string>
+    <string name="call_from_work_profile_action" msgid="2937701298133010724">"Passa al profilo di lavoro"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Chiudi"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Impostazioni schermata di blocco"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi non disponibile"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Videocamera bloccata"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Videocamera e microfono bloccati"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microfono bloccato"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modalità priorità attivata"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"L\'assistente è attivo"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 859435f..4dcafa1 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"‏הפעלת USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"מידע נוסף"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"צילום מסך"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"‏השבתת את Smart Lock"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"נשלחה תמונה"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"המערכת שומרת את צילום המסך..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"צילום המסך נשמר בפרופיל העבודה…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"הזנה של קוד אימות שגוי בניסיון הבא תגרום למחיקת פרופיל העבודה והנתונים המשויכים אליו."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"הזנת סיסמה שגויה בניסיון הבא תגרום למחיקת פרופיל העבודה והנתונים המשויכים אליו."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"יש לגעת בחיישן טביעות האצבע"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"סמל טביעת אצבע"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"לא ניתן לזהות את הפנים. יש להשתמש בטביעת אצבע במקום."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"לוח התראות."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"הגדרות מהירות."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"הגדרות מהירות ולוח ההתראות."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"מסך נעילה."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"מסך נעילה של עבודה"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"סגירה"</string>
@@ -835,6 +834,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"הגדלה של המסך המלא"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"הגדלת חלק מהמסך"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"מעבר"</string>
+    <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"פתיחת הגדרות ההגדלה"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"צריך לגרור את הפינה כדי לשנות את הגודל"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"הפעלת גלילה באלכסון"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"שינוי גודל"</string>
@@ -844,6 +844,7 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"נקודת אחיזה שמאלית"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"נקודת אחיזה ימנית"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"נקודת אחיזה תחתונה"</string>
+    <string name="accessibility_magnification_settings_panel_description" msgid="8174187340747846953">"הגדרות ההגדלה"</string>
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"גודל חלון ההגדלה"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"זום"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"בינוני"</string>
@@ -870,7 +871,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{נוסף אמצעי בקרה אחד (#).}one{נוספו # אמצעי בקרה.}two{נוספו # אמצעי בקרה.}other{נוספו # אמצעי בקרה.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"הוסר"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"להוסיף את <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"כשמוסיפים את האפליקציה <xliff:g id="APPNAME">%s</xliff:g>, היא תוכל להוסיף אמצעי בקרה ותוכן לחלונית הזו. חלק מהאפליקציות מאפשרות לבחור אילו אמצעי בקרה יוצגו כאן."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"להסיר את אמצעי הבקרה של <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"סומן כמועדף"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"סומן כמועדף, במיקום <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"הוסר מהמועדפים"</string>
@@ -888,12 +891,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"אחר"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"הוספה לפקדי המכשירים"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"הוספה"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"הסרה"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"הוצע על-ידי <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"המכשיר נעול"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"להציג מכשירים ולאפשר שליטה בהם במסך הנעילה?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"ניתן להוסיף למסך הנעילה אמצעי בקרה למכשירים החיצוניים.\n\nיכול להיות שהאפליקציה של המכשיר תאפשר לך לשלוט בחלק מהמכשירים בלי לבטל את הנעילה של הטלפון או הטאבלט.\n\nאפשר לבצע שינויים בכל שלב בהגדרות."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"לאפשר שליטה במכשירים במסך הנעילה?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"אפשר לשלוט בחלק מהמכשירים בלי לבטל את הנעילה של הטלפון או הטאבלט.\n\nהמכשירים שניתן לשלוט בהם באופן הזה נקבעים באפליקציה של המכשיר."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"לא תודה"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"כן"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"קוד האימות מכיל אותיות או סמלים"</string>
@@ -935,12 +940,13 @@
     <string name="controls_error_removed" msgid="6675638069846014366">"לא נמצא"</string>
     <string name="controls_error_removed_title" msgid="1207794911208047818">"הפקד לא זמין"</string>
     <string name="controls_error_removed_message" msgid="2885911717034750542">"לא ניתן להתחבר אל <xliff:g id="DEVICE">%1$s</xliff:g>. יש לבדוק את האפליקציה <xliff:g id="APPLICATION">%2$s</xliff:g> כדי לוודא שהפקד עדיין זמין ושהגדרות האפליקציה לא השתנו."</string>
-    <string name="controls_open_app" msgid="483650971094300141">"לפתיחת האפליקציה"</string>
+    <string name="controls_open_app" msgid="483650971094300141">"פתיחת האפליקציה"</string>
     <string name="controls_error_generic" msgid="352500456918362905">"לא ניתן לטעון את הסטטוס"</string>
     <string name="controls_error_failed" msgid="960228639198558525">"שגיאה, יש לנסות שוב"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"הוספת פקדים"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"עריכת פקדים"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"הוספת אפליקציה"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"הסרת האפליקציה"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"הוספת מכשירי פלט"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"קבוצה"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"נבחר מכשיר אחד"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index ca29664..0b7b469 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USB を有効にする"</string>
     <string name="learn_more" msgid="4690632085667273811">"詳細"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"スクリーンショット"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock は無効です"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"画像を送信しました"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"スクリーンショットを保存しています..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"スクリーンショットを仕事用プロファイルに保存中…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"PIN をあと 1 回間違えると、仕事用プロファイルと関連データが削除されます。"</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"パスワードをあと 1 回間違えると、仕事用プロファイルと関連データが削除されます。"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"指紋認証センサーをタッチ"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"指紋アイコン"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"顔を認識できません。指紋認証を使用してください。"</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"通知シェード"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"クイック設定"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"クイック設定と通知シェード。"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ロック画面"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"仕事用プロファイルのロック画面"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"閉じる"</string>
@@ -835,6 +834,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"画面全体を拡大します"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"画面の一部を拡大します"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"スイッチ"</string>
+    <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"画面の拡大設定を開く"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"サイズを変更するには角をドラッグ"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"斜めスクロールを許可"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"サイズ変更"</string>
@@ -844,6 +844,7 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"左ハンドル"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"右ハンドル"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"下ハンドル"</string>
+    <string name="accessibility_magnification_settings_panel_description" msgid="8174187340747846953">"画面の拡大設定"</string>
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"拡大鏡のサイズ"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"ズーム"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"中"</string>
@@ -870,7 +871,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# 件のコントロールを追加しました。}other{# 件のコントロールを追加しました。}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"削除済み"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> を追加しますか?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> を追加することで、コントロールやコンテンツをこのパネルに追加できます。一部のアプリでは、ここに表示されるコントロールを選択できます。"</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> のコントロールを削除しますか?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"お気に入りに追加済み"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"お気に入りに追加済み、位置: <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"お気に入りから削除済み"</string>
@@ -888,12 +891,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"その他"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"デバイス コントロールに追加"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"追加"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"削除"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> によるおすすめ"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"デバイス: ロック状態"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"ロック画面にデバイスを表示して操作しますか?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"ロック画面に外部デバイスのコントロールを追加できます。\n\nスマートフォンやタブレットのロックを解除しなくても、デバイスアプリによって一部のデバイスを操作できる可能性があります。\n\n設定でいつでも変更できます。"</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"ロック画面でデバイスを操作しますか?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"スマートフォンやタブレットのロックを解除しなくても一部のデバイスを操作できます。\n\nこの方法でどのデバイスを操作できるかは、デバイスアプリが判断します。"</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"いいえ"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"はい"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN に英字や記号を含める"</string>
@@ -941,6 +946,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"コントロールを追加"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"コントロールを編集"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"アプリを追加"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"アプリを削除"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"出力の追加"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"グループ"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"選択したデバイス: 1 台"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 4e40a73..2bdf163 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USB-ის ჩართვა"</string>
     <string name="learn_more" msgid="4690632085667273811">"შეიტყვეთ მეტი"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ეკრანის ანაბეჭდი"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock გათიშულია"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"გაიგზავნა სურათი"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ეკრანის სურათის შენახვა…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"მიმდინარეობს ეკრანის ანაბეჭდის შენახვა სამუშაო პროფილში…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"შემდეგი მცდელობისას PIN-კოდის არასწორად შეყვანის შემთხვევაში, თქვენი სამსახურის პროფილი და მისი მონაცემები წაიშლება."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"შემდეგი მცდელობისას პაროლის არასწორად შეყვანის შემთხვევაში, თქვენი სამსახურის პროფილი და მისი მონაცემები წაიშლება."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"შეეხეთ თითის ანაბეჭდის სენსორს"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"თითის ანაბეჭდის ხატულა"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"სახის ამოცნობა ვერ ხერხდება. სანაცვლოდ თითის ანაბეჭდი გამოიყენეთ."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"შეტყობინებების ფარდა"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"სწრაფი პარამეტრები"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"სწრაფი პარამეტრები და შეტყობინებების ფარდა"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ეკრანის დაბლოკვა."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"სამსახურის ჩაკეტილი ეკრანი"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"დახურვა"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"გაადიდეთ სრულ ეკრანზე"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ეკრანის ნაწილის გადიდება"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"გადართვა"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"ჩავლებით გადაიტანეთ კუთხე ზომის შესაცვლელად"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"დიაგონალური გადახვევის დაშვება"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"ზომის შეცვლა"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"მარცხენა სახელური"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"მარჯვენა სახელური"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"ქვედა სახელური"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"გადიდების ზომა"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"გადიდება"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"საშუალო"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{დაემატა მართვის # საშუალება.}other{დაემატა მართვის # საშუალება.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"ამოიშალა"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"გსურთ <xliff:g id="APPNAME">%s</xliff:g>-ის დამატება?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"როდესაც <xliff:g id="APPNAME">%s</xliff:g>-ს ამატებთ, მან შეიძლება დაამატოს მართვის საშუალებები და კონტენტი მოცემულ არეში. ზოგიერთ აპში შეგიძლიათ აირჩიოთ, რომელი მართვის საშუალებები უნდა გამოჩნდეს აქ."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"ამოიშალოს <xliff:g id="APPNAME">%s</xliff:g>-ის მართვის საშუალებები?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"რჩეულებშია"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"რჩეულებშია, პოზიციაზე <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"რჩეულებიდან ამოღებულია"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"სხვა"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"მოწყობილ. მართვის საშუალებებში დამატება"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"დამატება"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"ამოშლა"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"შემოთავაზებულია <xliff:g id="APP">%s</xliff:g>-ის მიერ"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"მოწყობილ. ჩაკეტილია"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"გსურთ მოწყობილობების ჩვენება და მართვა ჩაკეტილი ეკრანიდან?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"შეგიძლიათ დაამატოთ მართვის საშუალებები გარე მოწყობილობებისთვის, ჩაკეტილ ეკრანზე.\n\nთქვენი მოწყობილობის აპმა შეიძლება მოგცეთ საშუალება, მართოთ ზოგიერთი მოწყობილობა თქვენი ტელეფონის ან ტაბლეტის განბლოკვის გარეშე.\n\nცვლილებების შეტანა ნებისმიერ დროს შეგიძლიათ პარამეტრებიდან."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"გსურთ მოწყობილობების მართვა ჩაკეტილი ეკრანიდან?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"შეგიძლიათ ზოგიერთი მოწყობილობის მართვა ტელეფონის ან ტაბლეტის განბლოკვის გარეშე.\n\nთქვენი მოწყობილობის აპი განსაზღვრავს, რომელი მოწყობილობა იმართება ამგვარად."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"არა, გმადლობთ"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"დიახ"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN-კოდი შეიცავს ასოებს ან სიმბოლოებს"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"მართვის საშუალებების დამატება"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"მართვის საშუალებათა რედაქტირება"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"აპის დამატება"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"აპის ამოშლა"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"მედია-გამოსავლების დამატება"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"ჯგუფი"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"არჩეულია 1 მოწყობილობა"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 459237b..2a2b307 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USB қосу"</string>
     <string name="learn_more" msgid="4690632085667273811">"Толығырақ"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Скриншот"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock өшірілді"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"сурет жіберілді"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Скриншотты сақтауда…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Скриншот жұмыс профиліне сақталып жатыр…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Келесі әрекет кезінде қате PIN кодын енгізсеңіз, жұмыс профиліңіз бен оның деректері жойылады."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Келесі әрекет кезінде қате құпия сөз енгізсеңіз, жұмыс профиліңіз бен оның деректері жойылады."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Саусақ ізін оқу сканерін түртіңіз"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Саусақ ізі белгішесі"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Бет танылмады. Орнына саусақ ізін пайдаланыңыз."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Хабарландыру тақтасы"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Жылдам параметрлер."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Жылдам параметрлер мен хабарландыру тақтасы."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Бекіту экраны."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Әрекетті құлыптау экраны"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Жабу"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Толық экранды ұлғайту"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Экранның бөлігін ұлғайту"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Ауысу"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Өлшемін өзгерту үшін бұрышынан сүйреңіз."</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Диагональ бойынша айналдыруға рұқсат беру"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Өлшемін өзгерту"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Сол жақ маркер"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Оң жақ маркер"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Төменгі маркер"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Ұлғайтқыш көлемі"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Масштабтау"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Орташа"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# басқару элементі қосылды.}other{# басқару элементі қосылды.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Өшірілді"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> қолданбасын қосу керек пе?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> қолданбасын қосқан кезде, басқару элементтері мен контент осы панельге енгізіледі. Кейбір қолданбада басқару элементтерінің қайсысы осы жерде көрсетілетінін таңдай аласыз."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> қолданбасының басқару элементтері жойылсын ба?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Таңдаулыларға қосылды"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Таңдаулыларға қосылды, <xliff:g id="NUMBER">%d</xliff:g>-позиция"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Таңдаулылардан алып тасталды"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Басқа"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Құрылғы басқару элементтеріне қосу"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Енгізу"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Өшіру"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ұсынған"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Құрылғы құлыпталды."</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Құрылғыларды құлып экранынан көрсетуге және басқаруға рұқсат берілсін бе?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Сыртқы құрылғылардың басқару элементтерін құлып экранына қоса аласыз.\n\nҚұрылғы қолданбасы кейбір құрылғыларды телефонның немесе планшеттің құлпын ашпастан басқаруға мүмкіндік береді.\n\n\"Параметрлер\" бөлімінде кез келген уақытта өзгерістер енгізуге болады."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Құрылғылар құлып экранынан басқарылсын ба?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Кейбір құрылғыларды телефонның немесе планшеттің құлпын ашпастан басқара аласыз.\n\nҚұрылғы қолданбасы осылай басқаруға болатын құрылғыларды анықтайды."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Жоқ, рақмет"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Иә"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN коды әріптерден не таңбалардан құралады."</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Басқару элементтерін қосу"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Басқару элементтерін өзгерту"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Қолданба қосу"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Қолданбаны өшіру"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Шығыс сигналдарды қосу"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Топ"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 құрылғы таңдалды."</string>
@@ -1111,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Жұмыс профиліне ауысу"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Жабу"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Экран құлпының параметрлері"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi қолжетімсіз."</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камера бөгелген."</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камера мен микрофон бөгелген."</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Микрофон бөгелген."</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"\"Маңызды\" режимі қосулы."</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant қосулы."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index f345283..b396538 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"បើក USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"ស្វែងយល់​បន្ថែម"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"រូបថតអេក្រង់"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"បានបិទ Smart Lock"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"បាន​ផ្ញើរូបភាព"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"កំពុង​រក្សាទុក​រូបថត​អេក្រង់..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"កំពុងរក្សាទុករូបថតអេក្រង់ទៅកម្រងព័ត៌មានការងារ…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"ប្រសិនបើអ្នក​បញ្ចូលកូដ PIN មិនត្រឹមត្រូវ នៅពេលព្យាយាមបញ្ចូល​លើកក្រោយ កម្រងព័ត៌មានការងាររបស់អ្នក និងទិន្នន័យរបស់កម្រងព័ត៌មាននេះ​នឹងត្រូវបានលុប។"</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"ប្រសិនបើអ្នក​បញ្ចូលពាក្យសម្ងាត់មិន​ត្រឹមត្រូវ នៅពេលព្យាយាមបញ្ចូល​លើកក្រោយ កម្រងព័ត៌មាន​ការងាររបស់អ្នក និងទិន្នន័យ​របស់កម្រងព័ត៌មាននេះនឹងត្រូវបានលុប។"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ប៉ះ​ឧបករណ៍​ចាប់ស្នាម​ម្រាមដៃ"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"រូប​ស្នាម​ម្រាមដៃ"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"មិនអាចសម្គាល់មុខបានទេ។ សូមប្រើស្នាមម្រាមដៃជំនួសវិញ។"</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ពណ៌​ការ​ជូន​ដំណឹង"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ការ​កំណត់​រហ័ស។"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ការកំណត់រហ័ស និងផ្ទាំងជូនដំណឹង។"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ចាក់​សោ​អេក្រង់។"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"អេក្រង់​ចាក់​សោ​លក្ខណៈ​ការងារ"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"បិទ"</string>
@@ -835,6 +834,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ពង្រីក​ពេញអេក្រង់"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ពង្រីក​ផ្នែកនៃ​អេក្រង់"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"ប៊ូតុងបិទបើក"</string>
+    <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"បើកការកំណត់​ការពង្រីក"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"អូសជ្រុងដើម្បីប្ដូរទំហំ"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"អនុញ្ញាត​ការរំកិលបញ្ឆិត"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"ប្ដូរ​ទំហំ"</string>
@@ -844,6 +844,7 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"ដង​ខាងឆ្វេង"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"ដង​ខាងស្ដាំ"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"ដង​ខាងក្រោម"</string>
+    <string name="accessibility_magnification_settings_panel_description" msgid="8174187340747846953">"ការកំណត់​ការពង្រីក"</string>
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"ទំហំកម្មវិធីពង្រីក"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"ពង្រីកបង្រួម"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"មធ្យម"</string>
@@ -870,7 +871,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{បានបញ្ចូល​ការគ្រប់គ្រង #។}other{បានបញ្ចូល​ការគ្រប់គ្រង #។}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"បានដកចេញ"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"បញ្ចូល <xliff:g id="APPNAME">%s</xliff:g> ឬ?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"នៅពេលអ្នកបញ្ចូល <xliff:g id="APPNAME">%s</xliff:g> កម្មវិធីនេះអាចបញ្ចូលការគ្រប់គ្រង និងខ្លឹមសារទៅផ្ទាំងនេះបាន។ ក្នុងកម្មវិធីមួយចំនួន អ្នកអាចជ្រើសរើសឱ្យការគ្រប់គ្រងណាខ្លះបង្ហាញនៅទីនេះបាន។"</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"ដកការគ្រប់គ្រងសម្រាប់ <xliff:g id="APPNAME">%s</xliff:g> ចេញឬ?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"បានដាក់ជា​សំណព្វ"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"បានដាក់ជា​សំណព្វ ទីតាំង​ទី <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"បានដកចេញ​ពី​សំណព្វ"</string>
@@ -888,12 +891,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ផ្សេងៗ"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"បញ្ចូល​ទៅក្នុងផ្ទាំងគ្រប់គ្រងឧបករណ៍"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"បញ្ចូល"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"ដកចេញ"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"បាន​ណែនាំដោយ <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"បានចាក់សោ​ឧបករណ៍"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"បង្ហាញ និង​គ្រប់គ្រង​ឧបករណ៍ពី​អេក្រង់ចាក់សោឬ?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"អ្នកអាចបញ្ចូល​ការគ្រប់គ្រង​សម្រាប់ឧបករណ៍​ខាងក្រៅ​របស់អ្នក​ទៅក្នុងអេក្រង់​ចាក់សោបាន។\n\nកម្មវិធី​ឧបករណ៍​របស់អ្នក​អាចអនុញ្ញាតឱ្យអ្នក​គ្រប់គ្រង​ឧបករណ៍​មួយចំនួន ដោយមិនចាំបាច់​ដោះសោ​ទូរសព្ទ ឬ​ថេប្លេត​របស់អ្នក។\n\nអ្នកអាចធ្វើការផ្លាស់ប្ដូរ​បានគ្រប់ពេល​នៅក្នុង​ការកំណត់។"</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"គ្រប់គ្រង​ឧបករណ៍ពី​អេក្រង់ចាក់សោឬ?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"អ្នកអាចគ្រប់គ្រង​ឧបករណ៍​មួយចំនួន ដោយមិនចាំបាច់​ដោះសោ​ទូរសព្ទ ឬថេប្លេត​របស់អ្នក។\n\nកម្មវិធី​ឧបករណ៍​របស់អ្នក​កំណត់ឧបករណ៍​ដែលអាចត្រូវបានគ្រប់គ្រង​តាមវិធីនេះ។"</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"ទេ អរគុណ"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"បាទ/ចាស"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"កូដ PIN មាន​អក្សរ ឬនិមិត្តសញ្ញា"</string>
@@ -941,6 +946,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"បញ្ចូល​ផ្ទាំងគ្រប់គ្រង"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"កែ​ផ្ទាំងគ្រប់គ្រង"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"បញ្ចូល​កម្មវិធី"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"ដក​កម្មវិធី​ចេញ"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"បញ្ចូល​ឧបករណ៍​មេឌៀ"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"ក្រុម"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"បានជ្រើសរើស​ឧបករណ៍ 1"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 6e22f36..cfe6268 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USB ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
     <string name="learn_more" msgid="4690632085667273811">"ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ಚಿತ್ರವನ್ನು ಕಳುಹಿಸಲಾಗಿದೆ"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಉಳಿಸಲಾಗುತ್ತಿದೆ…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌ಗೆ ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ಉಳಿಸಲಾಗುತ್ತಿದೆ…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"ಮುಂದಿನ ಪ್ರಯತ್ನದಲ್ಲಿ ನೀವು ತಪ್ಪಾದ ಪಿನ್ ನಮೂದಿಸಿದರೆ, ನಿಮ್ಮ ಉದ್ಯೋಗದ ಪ್ರೊಫೈಲ್ ಮತ್ತು ಅದರ ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"ಮುಂದಿನ ಪ್ರಯತ್ನದಲ್ಲಿ ನೀವು ತಪ್ಪಾದ ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿದರೆ, ನಿಮ್ಮ ಉದ್ಯೋಗದ ಪ್ರೊಫೈಲ್ ಮತ್ತು ಅದರ ಡೇಟಾವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್‌‌ ಅನ್ನು ಸ್ಪರ್ಶಿಸಿ"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಐಕಾನ್"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ಮುಖ ಗುರುತಿಸಲಾಗುತ್ತಿಲ್ಲ ಬದಲಿಗೆ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಬಳಸಿ."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ಅಧಿಸೂಚನೆಯ ಛಾಯೆ."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‍ಗಳು."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‍ಗಳು ಮತ್ತು ಅಧಿಸೂಚನೆಯ ಪರದೆ."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ಲಾಕ್‌ ಸ್ಕ್ರೀನ್."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ಕೆಲಸದ ಲಾಕ್ ಪರದೆ"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"ಮುಚ್ಚು"</string>
@@ -835,6 +834,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ಪೂರ್ಣ ಸ್ಕ್ರೀನ್‌ ಅನ್ನು ಹಿಗ್ಗಿಸಿ"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ಸ್ಕ್ರೀನ್‌ನ ಅರ್ಧಭಾಗವನ್ನು ಝೂಮ್ ಮಾಡಿ"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"ಸ್ವಿಚ್"</string>
+    <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"ಹಿಗ್ಗಿಸುವಿಕೆ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ತೆರೆಯಿರಿ"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"ಮರುಗಾತ್ರಗೊಳಿಸಲು ಮೂಲೆಯನ್ನು ಡ್ರ್ಯಾಗ್ ಮಾಡಿ"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"ಡಯಾಗನಲ್ ಸ್ಕ್ರೋಲಿಂಗ್ ಅನ್ನು ಅನುಮತಿಸಿ"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"ಮರುಗಾತ್ರಗೊಳಿಸಿ"</string>
@@ -844,6 +844,7 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"ಎಡ ಹ್ಯಾಂಡಲ್"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"ಬಲ ಹ್ಯಾಂಡಲ್"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"ಕೆಳಗಿನ ಹ್ಯಾಂಡಲ್"</string>
+    <string name="accessibility_magnification_settings_panel_description" msgid="8174187340747846953">"ಹಿಗ್ಗಿಸುವಿಕೆ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"ಮ್ಯಾಗ್ನಿಫೈರ್ ಗಾತ್ರ"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoom"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"ಮಧ್ಯಮ"</string>
@@ -870,7 +871,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# ನಿಯಂತ್ರಣವನ್ನು ಸೇರಿಸಲಾಗಿದೆ.}one{# ನಿಯಂತ್ರಣಗಳನ್ನು ಸೇರಿಸಲಾಗಿದೆ.}other{# ನಿಯಂತ್ರಣಗಳನ್ನು ಸೇರಿಸಲಾಗಿದೆ.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> ಅನ್ನು ಸೇರಿಸಬೇಕೆ?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"ನೀವು <xliff:g id="APPNAME">%s</xliff:g> ಅನ್ನು ಸೇರಿಸಿದಾಗ, ಅದು ಈ ಪ್ಯಾನೆಲ್‌ಗೆ ನಿಯಂತ್ರಣಗಳು ಮತ್ತು ವಿಷಯವನ್ನು ಸೇರಿಸಬಹುದು. ಕೆಲವು ಆ್ಯಪ್‌ಗಳಲ್ಲಿ, ಇಲ್ಲಿ ಯಾವ ನಿಯಂತ್ರಣಗಳು ಕಾಣಿಸಬೇಕು ಎಂಬುದನ್ನು ನೀವು ಆಯ್ಕೆಮಾಡಬಹುದು."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> ಗಾಗಿ ನಿಯಂತ್ರಣಗಳನ್ನು ತೆಗೆದುಹಾಕಬೇಕೆ?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"ಮೆಚ್ಚಲಾಗಿರುವುದು"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"ಮೆಚ್ಚಲಾಗಿರುವುದು, ಸ್ಥಾನ <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ಮೆಚ್ಚಿನದಲ್ಲದ್ದು"</string>
@@ -888,12 +891,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ಇತರ"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"ಸಾಧನ ನಿಯಂತ್ರಣಗಳಿಗೆ ಸೇರಿಸಿ"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"ಸೇರಿಸಿ"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"ತೆಗೆದುಹಾಕಿ"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ಆ್ಯಪ್ ಸೂಚಿಸಿದೆ"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"ಸಾಧನ ಲಾಕ್ ಆಗಿದೆ"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"ಲಾಕ್ ಸ್ಕ್ರೀನ್‌ನಿಂದ ಸಾಧನಗಳನ್ನು ತೋರಿಸಬೇಕೇ ಹಾಗೂ ನಿಯಂತ್ರಿಸಬೇಕೇ?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"ಲಾಕ್ ಸ್ಕ್ರೀನ್‌ನಲ್ಲಿ ನಿಮ್ಮ ಬಾಹ್ಯ ಸಾಧನಗಳಿಗಾಗಿ ನೀವು ನಿಯಂತ್ರಣಗಳನ್ನು ಸೇರಿಸಬಹುದು.\n\nನಿಮ್ಮ ಫೋನ್ ಅಥವಾ ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡದೆಯೇ ನಿಮ್ಮ ಕೆಲವು ಸಾಧನಗಳನ್ನು ನಿಯಂತ್ರಿಸಲು ನಿಮ್ಮ ಸಾಧನ ಆ್ಯಪ್ ಅನುಮತಿಸಬಹುದು.\n\nಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ನೀವು ಯಾವಾಗ ಬೇಕಾದರೂ ಬದಲಾವಣೆಗಳನ್ನು ಮಾಡಬಹುದು."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"ಲಾಕ್ ಸ್ಕ್ರೀನ್‌ನಿಂದ ಸಾಧನಗಳನ್ನು ನಿಯಂತ್ರಿಸಬೇಕೇ?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"ನಿಮ್ಮ ಫೋನ್ ಅಥವಾ ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡದೆಯೇ ನಿಮ್ಮ ಕೆಲವು ಸಾಧನಗಳನ್ನು ನೀವು ನಿಯಂತ್ರಿಸಬಹುದು.\n\nಈ ವಿಧಾನದ ಮೂಲಕ ಯಾವ ಸಾಧನಗಳನ್ನು ನಿಯಂತ್ರಿಸಬಹುದು ಎಂಬುದನ್ನು ನಿಮ್ಮ ಸಾಧನದ ಆ್ಯಪ್ ನಿರ್ಧರಿಸುತ್ತದೆ."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"ಬೇಡ"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"ಹೌದು"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"ಪಿನ್ ಅಕ್ಷರಗಳು ಅಥವಾ ಸಂಕೇತಗಳನ್ನು ಒಳಗೊಂಡಿದೆ"</string>
@@ -941,6 +946,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"ನಿಯಂತ್ರಣಗಳನ್ನು ಸೇರಿಸಿ"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"ನಿಯಂತ್ರಣಗಳನ್ನು ಎಡಿಟ್ ಮಾಡಿ"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"ಆ್ಯಪ್ ಅನ್ನು ಸೇರಿಸಿ"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"ಆ್ಯಪ್ ತೆಗೆದುಹಾಕಿ"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"ಔಟ್‌ಪುಟ್‌ಗಳನ್ನು ಸೇರಿಸಿ"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"ಗುಂಪು"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 ಸಾಧನವನ್ನು ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index f7a6dfb..f131402 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USB 사용"</string>
     <string name="learn_more" msgid="4690632085667273811">"자세히 알아보기"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"스크린샷"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock 사용 중지됨"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"이미지 보냄"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"캡쳐화면 저장 중..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"직장 프로필에 스크린샷 저장 중…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"다음번 시도에서 잘못된 PIN을 입력하면 직장 프로필 및 관련 데이터가 삭제됩니다."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"다음번 시도에서 잘못된 비밀번호를 입력하면 직장 프로필 및 관련 데이터가 삭제됩니다."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"지문 센서를 터치하세요."</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"지문 아이콘"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"얼굴을 인식할 수 없습니다. 대신 지문을 사용하세요."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"알림 세부정보"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"빠른 설정"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"빠른 설정 및 알림 창입니다."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"화면을 잠급니다."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"업무용 잠금 화면"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"닫기"</string>
@@ -616,84 +615,48 @@
     <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_clear_text (4679927133259287577) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_list_title (1156178106617830429) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_list_hint (5982623262974326746) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_list_no_result (6819302191660875501) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_category_system (1151182120757052669) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_category_input (5440558509904296233) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_category_open_apps (1450959949739257562) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_category_current_app (2011953559133734491) -->
-    <skip />
-    <!-- no translation found for group_system_access_notification_shade (7116898151485382275) -->
-    <skip />
-    <!-- no translation found for group_system_full_screenshot (7389040853798023211) -->
-    <skip />
-    <!-- no translation found for group_system_access_system_app_shortcuts (4421497579210445641) -->
-    <skip />
-    <!-- no translation found for group_system_go_back (8838454003680364227) -->
-    <skip />
-    <!-- no translation found for group_system_access_home_screen (1857344316928441909) -->
-    <skip />
-    <!-- no translation found for group_system_overview_open_apps (6897128761003265350) -->
-    <skip />
-    <!-- no translation found for group_system_cycle_forward (9202444850838205990) -->
-    <skip />
-    <!-- no translation found for group_system_cycle_back (5163464503638229131) -->
-    <skip />
-    <!-- no translation found for group_system_access_all_apps_search (488070738028991753) -->
-    <skip />
-    <!-- no translation found for group_system_hide_reshow_taskbar (3809304065624351131) -->
-    <skip />
-    <!-- no translation found for group_system_access_system_settings (7961639365383008053) -->
-    <skip />
-    <!-- no translation found for group_system_access_google_assistant (1186152943161483864) -->
-    <skip />
-    <!-- no translation found for group_system_lock_screen (7391191300363416543) -->
-    <skip />
-    <!-- no translation found for group_system_quick_memo (2914234890158583919) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_group_system_multitasking (1065232949510862593) -->
-    <skip />
-    <!-- no translation found for system_multitasking_rhs (6593269428880305699) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (8839380725557952846) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (1962084334200006297) -->
-    <skip />
-    <!-- no translation found for system_multitasking_replace (844285282472557186) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_group_input (6888282716546625610) -->
-    <skip />
-    <!-- no translation found for input_switch_input_language_next (3394291576873633793) -->
-    <skip />
-    <!-- no translation found for input_switch_input_language_previous (8823659252918609216) -->
-    <skip />
-    <!-- no translation found for input_access_emoji (8105642858900406351) -->
-    <skip />
-    <!-- no translation found for input_access_voice_typing (7291201476395326141) -->
-    <skip />
+    <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"텍스트 삭제"</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>
+    <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"시스템"</string>
+    <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>
+    <string name="group_system_access_notification_shade" msgid="7116898151485382275">"알림 창에 액세스"</string>
+    <string name="group_system_full_screenshot" msgid="7389040853798023211">"전체 스크린샷 촬영"</string>
+    <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"시스템/앱 단축키 목록에 액세스"</string>
+    <string name="group_system_go_back" msgid="8838454003680364227">"뒤로: 이전 상태로 되돌아가기(뒤로 버튼)"</string>
+    <string name="group_system_access_home_screen" msgid="1857344316928441909">"홈 화면에 액세스"</string>
+    <string name="group_system_overview_open_apps" msgid="6897128761003265350">"열린 앱 개요"</string>
+    <string name="group_system_cycle_forward" msgid="9202444850838205990">"최근 앱 간 순환(앞으로)"</string>
+    <string name="group_system_cycle_back" msgid="5163464503638229131">"최근 앱 간 순환(뒤로)"</string>
+    <string name="group_system_access_all_apps_search" msgid="488070738028991753">"모든 앱 및 검색 목록(예: 검색/런처)에 액세스"</string>
+    <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"태스크 바 숨김 및 다시 표시"</string>
+    <string name="group_system_access_system_settings" msgid="7961639365383008053">"시스템 설정에 액세스"</string>
+    <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google 어시스턴트에 액세스"</string>
+    <string name="group_system_lock_screen" msgid="7391191300363416543">"잠금 화면"</string>
+    <string name="group_system_quick_memo" msgid="2914234890158583919">"빠른 메모를 위해 노트 앱 불러오기"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"시스템 멀티태스킹"</string>
+    <string name="system_multitasking_rhs" msgid="6593269428880305699">"현재 앱을 오른쪽으로 보내는 화면 분할 입력"</string>
+    <string name="system_multitasking_lhs" msgid="8839380725557952846">"현재 앱을 왼쪽으로 보내는 화면 분할 입력"</string>
+    <string name="system_multitasking_full_screen" msgid="1962084334200006297">"화면 분할에서 전체 화면으로 전환"</string>
+    <string name="system_multitasking_replace" msgid="844285282472557186">"화면 분할 중: 다른 앱으로 바꾸기"</string>
+    <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"입력"</string>
+    <string name="input_switch_input_language_next" msgid="3394291576873633793">"입력 언어 전환(다음 언어)"</string>
+    <string name="input_switch_input_language_previous" msgid="8823659252918609216">"입력 언어 전환(이전 언어)"</string>
+    <string name="input_access_emoji" msgid="8105642858900406351">"이모티콘에 액세스"</string>
+    <string name="input_access_voice_typing" msgid="7291201476395326141">"음성 입력에 액세스"</string>
     <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"애플리케이션"</string>
     <string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"지원"</string>
-    <!-- no translation found for keyboard_shortcut_group_applications_browser (7328131901589876868) -->
-    <skip />
+    <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"브라우저(Chrome을 기본값으로 설정)"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"연락처"</string>
-    <!-- no translation found for keyboard_shortcut_group_applications_email (7480359963463803511) -->
-    <skip />
+    <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"이메일(Gmail을 기본값으로 설정)"</string>
     <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
     <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"음악"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"캘린더"</string>
-    <!-- no translation found for keyboard_shortcut_group_applications_calculator (6316043911946540137) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_group_applications_maps (7312554713993114342) -->
-    <skip />
+    <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"계산기"</string>
+    <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"지도"</string>
     <string name="volume_and_do_not_disturb" msgid="502044092739382832">"방해 금지 모드"</string>
     <string name="volume_dnd_silent" msgid="4154597281458298093">"볼륨 버튼 단축키"</string>
     <string name="battery" msgid="769686279459897127">"배터리"</string>
@@ -856,12 +819,9 @@
     <string name="privacy_type_media_projection" msgid="8136723828804251547">"화면 녹화"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"제목 없음"</string>
     <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"대기"</string>
-    <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
-    <skip />
-    <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
-    <skip />
-    <!-- no translation found for font_scaling_larger (5476242157436806760) -->
-    <skip />
+    <string name="font_scaling_dialog_title" msgid="6273107303850248375">"글꼴 크기"</string>
+    <string name="font_scaling_smaller" msgid="1012032217622008232">"축소"</string>
+    <string name="font_scaling_larger" msgid="5476242157436806760">"확대"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"확대 창"</string>
     <string name="magnification_controls_title" msgid="8421106606708891519">"확대 창 컨트롤"</string>
     <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"확대"</string>
@@ -874,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"전체 화면 확대"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"화면 일부 확대"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"전환"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"모서리를 드래그하여 크기 조절"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"대각선 스크롤 허용"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"크기 조절"</string>
@@ -883,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"왼쪽 핸들"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"오른쪽 핸들"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"하단 핸들"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"돋보기 크기"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"확대/축소"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"보통"</string>
@@ -909,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{설정이 #개 추가되었습니다.}other{설정이 #개 추가되었습니다.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"삭제됨"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g>을(를) 추가할까요?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> 앱을 추가하면 이 패널에 컨트롤과 콘텐츠가 추가됩니다. 일부 앱에서는 여기 표시되는 컨트롤을 선택할 수 있습니다."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> 컨트롤을 삭제할까요?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"즐겨찾기에 추가됨"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"즐겨찾기에 추가됨, 위치 <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"즐겨찾기에서 삭제됨"</string>
@@ -927,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"기타"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"기기 컨트롤에 추가"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"추가"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"삭제"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g>에서 제안"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"기기 잠김"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"잠금 화면에서 기기를 표시하고 제어하시겠습니까?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"외부 기기에 대한 제어 권한을 잠금 화면에 추가할 수 있습니다.\n\n기기 앱을 사용하여 휴대전화나 태블릿의 잠금을 해제하지 않고 해당 기기를 제어할 수도 있습니다.\n\n언제든지 설정에서 옵션을 변경할 수 있습니다."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"잠금 화면에서 기기를 제어하시겠습니까?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"휴대전화나 태블릿의 화면을 잠금 해제하지 않고 해당 기기를 제어할 수 있습니다.\n\n기기 앱에 이러한 방식으로 어떤 기기를 제어할 수 있는지 표시됩니다."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"아니요"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"예"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN에 문자나 기호가 포함됨"</string>
@@ -978,8 +946,9 @@
     <string name="controls_error_generic" msgid="352500456918362905">"통계를 로드할 수 없음"</string>
     <string name="controls_error_failed" msgid="960228639198558525">"오류. 다시 시도하세요."</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"컨트롤 추가"</string>
-    <string name="controls_menu_edit" msgid="890623986951347062">"컨트롤 수정"</string>
+    <string name="controls_menu_edit" msgid="890623986951347062">"제어 설정 수정"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"앱 추가"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"앱 삭제"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"출력 추가"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"그룹"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"기기 1대 선택됨"</string>
@@ -1150,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"직장 프로필로 전환"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"닫기"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"잠금 화면 설정"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi를 사용할 수 없음"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"카메라 차단됨"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"카메라 및 마이크 차단됨"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"마이크 차단됨"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"우선순위 모드 설정됨"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"어시스턴트가 대기 중임"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 3d6a949..a53542b 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USB’ни иштетүү"</string>
     <string name="learn_more" msgid="4690632085667273811">"Кененирээк"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Скриншот"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock өчүрүлдү"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"сүрөт жөнөттү"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Скриншот сакталууда..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Скриншот жумуш профилине сакталууда…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Эгер PIN кодду дагы бир жолу туура эмес киргизсеңиз, жумуш профилиңиз жана андагы маалыматтын баары өчөт."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Эгер сырсөздү дагы бир жолу туура эмес киргизсеңиз, жумуш профилиңиз жана андагы маалыматтын баары өчөт."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Манжа изинин сенсорун басыңыз"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Манжа изинин сүрөтчөсү"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Жүз таанылбай жатат. Манжа изин колдонуңуз."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Билдирмелер тактасы."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Тез тууралоолор."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Ыкчам параметрлер жана билдирмелер тактасы."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Кулпуланган экран."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Жумуштун кулпуланган экраны"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Жабуу"</string>
@@ -633,7 +632,7 @@
     <string name="group_system_cycle_forward" msgid="9202444850838205990">"Соңку колдонмолорду көрүү (кадимки тартипте)"</string>
     <string name="group_system_cycle_back" msgid="5163464503638229131">"Соңку колдонмолорду көрүү (тескери тартипте)"</string>
     <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Бардык колдонмолордун тизмесин ачуу жана издөө (Издөө/Жүргүзгүч)"</string>
-    <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Тапшырмалар панелин жашыруу жана көрсөтүү"</string>
+    <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Тапшырмалар тактасын жашыруу жана көрсөтүү"</string>
     <string name="group_system_access_system_settings" msgid="7961639365383008053">"Тутум параметрлерине кирүү"</string>
     <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google Жардамчыны иштетүү"</string>
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Экранды кулпулоо"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Толук экранда ачуу"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Экрандын бир бөлүгүн чоңойтуу"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Которулуу"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Өлчөмүн өзгөртүү үчүн бурчун сүйрөңүз"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Диагональ боюнча сыдырууга уруксат берүү"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Өлчөмүн өзгөртүү"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Сол маркер"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Оң маркер"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Ылдыйкы маркер"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Чоңойткучтун өлчөмү"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Чоңойтуп/кичирейтүү"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Орто"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# көзөмөл кошулду.}other{# көзөмөл кошулду.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Өчүрүлдү"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> кошулсунбу?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> колдонмосун кошсоңуз, ал бул панелге башкаруу элементтерин жана контентти кошо алат. Айрым колдонмолордо бул жерде көрүнүүчү башкаруу элементтерин тандай аласыз."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> башкаруу элементтери өчүрүлсүнбү?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Сүйүктүүлөргө кошулду"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Сүйүктүүлөргө <xliff:g id="NUMBER">%d</xliff:g>-позицияга кошулду"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Сүйүктүүлөрдөн чыгарылды"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Башка"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Түзмөктү башкаруу элементтерине кошуу"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Кошуу"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Өчүрүү"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> сунуштайт"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Түзмөк кулпуланды"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Түзмөктөрдү кулпуланган экрандан көрүп, көзөмөлдөйсүзбү?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Тышкы түзмөктөрүңүздү көзөмөлдөө каражаттарын кулпу экранына кошо аласыз.\n\nТүзмөгүңүздүн колдонмосу айрым түзмөктөрдү телефонуңуздун же планшетиңиздин кулпусун ачпастан көзөмөлдөөгө уруксат бериши мүмкүн.\n\nКаалаган убакта Жөндөөлөрдөн өзгөртүүлөрдү жасай аласыз."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Түзмөктөрдү кулпуланган экрандан көзөмөлдөйсүзбү?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Айрым түзмөктөрдү телефонуңуздун же планшетиңиздин кулпусун ачпастан көзөмөлдөй аласыз.\n\nКайсы түзмөктөрдү ушул жол менен көзөмөлдөөгө болорун түзмөгүңүздүн колдонмосу аныктайт."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Жок, рахмат"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ооба"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN код тамгалардан же символдордон турат"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Башкаруу элементтерин кошуу"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Башкаруу элементтерин түзөтүү"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Колдонмо кошуу"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Колдонмону алып салуу"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Медиа түзмөктөрдү кошуу"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Топ"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 түзмөк тандалды"</string>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index bc63c9f..908aac4 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -64,5 +64,10 @@
 
     <dimen name="qs_panel_padding_top">@dimen/qqs_layout_margin_top</dimen>
 
-    <dimen name="controls_padding_horizontal">16dp</dimen>
+    <dimen name="controls_header_horizontal_padding">12dp</dimen>
+    <dimen name="controls_content_margin_horizontal">16dp</dimen>
+
+    <!-- Bouncer user switcher margins -->
+    <dimen name="bouncer_user_switcher_view_mode_user_switcher_bottom_margin">0dp</dimen>
+    <dimen name="bouncer_user_switcher_view_mode_view_flipper_bottom_margin">0dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 0b5b5de..205d66d 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"ເປີດໃຊ້ USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"ສຶກສາເພີ່ມເຕີມ"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ພາບໜ້າຈໍ"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"ປິດການນຳໃຊ້ Smart Lock ແລ້ວ"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ສົ່ງຮູບແລ້ວ"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ກຳລັງບັນທຶກພາບໜ້າຈໍ..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"ກຳລັງບັນທຶກຮູບໜ້າຈໍໃສ່ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກ…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"ຫາກທ່ານໃສ່ລະຫັດ PIN ຜິດໃນຄວາມພະຍາຍາມເທື່ອຕໍ່ໄປ, ໂປຣໄຟລ໌ບ່ອນເຣັດວຽກຂອງທ່ານ ແລະ ຂໍ້ມູນຂອງມັນຈະຖືກລຶບອອກ."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"ຫາກທ່ານໃສ່ລະຫັດຜິດໃນຄວາມພະຍາຍາມເທື່ອຕໍ່ໄປ, ໂປຣໄຟລ໌ບ່ອນເຣັດວຽກຂອງທ່ານ ແລະ ຂໍ້ມູນຂອງມັນຈະຖືກລຶບອອກ."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ແຕະໃສ່ເຊັນເຊີລາຍນິ້ວມື"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"ໄອຄອນລາຍນິ້ວມື"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ບໍ່ສາມາດຈຳແນກໜ້າໄດ້. ກະລຸນາໃຊ້ລາຍນິ້ວມືແທນ."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ໜ້າຈໍແຈ້ງເຕືອນ."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ການຕັ້ງຄ່າດ່ວນ."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ການຕັ້ງຄ່າດ່ວນ ແລະ ເງົາການແຈ້ງເຕືອນ."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ລັອກ​ໜ້າ​ຈໍ."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ໜ້າຈໍລັອກວຽກ"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"ປິດ"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ຂະຫຍາຍເຕັມຈໍ"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ຂະຫຍາຍບາງສ່ວນຂອງໜ້າຈໍ"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"ສະຫຼັບ"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"ລາກຢູ່ມຸມເພື່ອປັບຂະໜາດ"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"ອະນຸຍາດໃຫ້ເລື່ອນທາງຂວາງ"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"ປ່ຽນຂະໜາດ"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"ດ້າມຈັບຊ້າຍມື"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"ດ້າມຈັບຂວາມື"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"ດ້າມຈັບທາງລຸ່ມ"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"ຂະໜາດການຂະຫຍາຍ"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"ຊູມ"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"ປານກາງ"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{ເພີ່ມ # ການຄວບຄຸມແລ້ວ.}other{ເພີ່ມ # ການຄວບຄຸມແລ້ວ.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"ລຶບອອກແລ້ວ"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"ເພີ່ມ <xliff:g id="APPNAME">%s</xliff:g> ບໍ?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"ເມື່ອທ່ານເພີ່ມ <xliff:g id="APPNAME">%s</xliff:g>, ມັນຈະສາມາດເພີ່ມການຄວບຄຸມ ແລະ ເນື້ອຫາໃສ່ແຜງນີ້ໄດ້. ໃນບາງແອັບ, ທ່ານສາມາດເລືອກວ່າຈະໃຫ້ສ່ວນຄວບຄຸມໃດສະແດງຂຶ້ນຢູ່ບ່ອນນີ້ໄດ້."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"ລຶບການຄວບຄຸມສຳລັບ <xliff:g id="APPNAME">%s</xliff:g> ອອກບໍ?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"ເພີ່ມລາຍການທີ່ມັກແລ້ວ"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"ເພີ່ມລາຍການທີ່ມັກແລ້ວ, ຕຳແໜ່ງ <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ຍົກເລີກລາຍການທີ່ມັກແລ້ວ"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ອື່ນໆ"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"ເພີ່ມໃສ່ການຄວບຄຸມອຸປະກອນ"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"ເພີ່ມ"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"ລຶບອອກ"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"ແນະນຳໂດຍ <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"ອຸປະກອນຖືກລັອກໄວ້"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"ສະແດງ ແລະ ຄວບຄຸມອຸປະກອນຈາກໜ້າຈໍລັອກບໍ?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"ທ່ານສາມາດເພີ່ມການຄວບຄຸມສຳລັບອຸປະກອນພາຍນອກຂອງທ່ານໄປໃສ່ໜ້າຈໍລັອກໄດ້.\n\nແອັບອຸປະກອນຂອງທ່ານອາດອະນຸຍາດໃຫ້ທ່ານຄວບຄຸມອຸປະກອນບາງຢ່າງໄດ້ໂດຍບໍ່ຕ້ອງປົດລັອກໂທລະສັບ ຫຼື ແທັບເລັດຂອງທ່ານ.\n\nທ່ານສາມາດປ່ຽນແປງຕອນໃດກໍໄດ້ໃນການຕັ້ງຄ່າ."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"ຄວບຄຸມອຸປະກອນຈາກໜ້າຈໍລັອກບໍ?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"ທ່ານສາມາດຄວບຄຸມອຸປະກອນບາງຢ່າງໄດ້ໂດຍບໍ່ຕ້ອງປົດລັອກໂທລະສັບ ຫຼື ແທັບເລັດຂອງທ່ານ.\n\nແອັບອຸປະກອນຂອງທ່ານຈະກຳນົດວ່າອຸປະກອນໃດສາມາດຖືກຄວບຄຸມດ້ວຍວິທີນີ້ໄດ້."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"ບໍ່, ຂອບໃຈ"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"ແມ່ນແລ້ວ"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN ປະກອບມີຕົວອັກສອນ ຫຼື ສັນຍາລັກ"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"ເພີ່ມການຄວບຄຸມ"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"ແກ້ໄຂການຄວບຄຸມ"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"ເພີ່ມແອັບ"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"ລຶບແອັບອອກ"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"ເພີ່ມເອົ້າພຸດ"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"ກຸ່ມ"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"ເລືອກ 1 ອຸປະກອນແລ້ວ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index d607b17..ca52f06 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Įgalinti USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Sužinokite daugiau"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Ekrano kopija"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"„Smart Lock“ išjungta"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"išsiuntė vaizdą"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Išsaugoma ekrano kopija..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Išsaugoma ekrano kopija darbo profilyje…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Jei kitu bandymu įvesite netinkamą PIN kodą, darbo profilis ir jo duomenys bus ištrinti."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Jei kitu bandymu įvesite netinkamą slaptažodį, darbo profilis ir jo duomenys bus ištrinti."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Palieskite piršto antspaudo jutiklį"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Piršto antspaudo piktograma"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Veidas neatpažintas. Naudokite kontrolinį kodą."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Pranešimų gaubtas."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Spartieji nustatymai."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Spartieji nustatymai ir pranešimų skydelis."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Užrakinimo ekranas."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Darbo profilio užrakinimo ekranas"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Uždaryti"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Viso ekrano didinimas"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Didinti ekrano dalį"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Perjungti"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Norėdami keisti dydį, vilkite kampą"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Slinkimo įstrižai leidimas"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Pakeisti dydį"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Rankenėlė kairėje"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Rankenėlė dešinėje"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Rankenėlė apačioje"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Didinimo dydis"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Mastelio keitimas"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Vidutinis"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Pridėtas # valdiklis.}one{Pridėtas # valdiklis.}few{Pridėti # valdikliai.}many{Pridėta # valdiklio.}other{Pridėta # valdiklių.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Pašalinta"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Pridėti „<xliff:g id="APPNAME">%s</xliff:g>“?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Pridėjus programą „<xliff:g id="APPNAME">%s</xliff:g>“, ji gali pridėti valdiklių ir turinio prie šio skydelio. Kai kuriose programose galite pasirinkti, kurie valdikliai čia rodomi."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Pašalinti „<xliff:g id="APPNAME">%s</xliff:g>“ valdiklius?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Įtraukta į mėgstamiausius"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Įtraukta į mėgstamiausius, padėtis: <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Pašalinta iš mėgstamiausių"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Kita"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Pridėjimas prie įrenginio valdiklių"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Pridėti"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Pašalinti"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Siūlo „<xliff:g id="APP">%s</xliff:g>“"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Įrenginys užrakintas"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Rodyti ir valdyti įrenginius užrakinimo ekrane?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Galite pridėti išorinių įrenginių valdiklių užrakinimo ekrane.\n\nĮrenginio programoje gali būti leidžiama valdyti tam tikrus įrenginius neatrakinus telefono ar planšetinio kompiuterio.\n\nGalite bet kada pakeisti „Nustatymų“ skiltyje."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Valdyti įrenginius užrakinimo ekrane?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Galite valdyti tam tikrus išorinius įrenginius neatrakinę telefono ar planšetinio kompiuterio.\n\nĮrenginio programoje nustatoma, kuriuos įrenginius galima valdyti tokiu būdu."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Ne, ačiū"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Taip"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN kodą sudaro raidės arba simboliai"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Pridėti valdiklių"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Redaguoti valdiklius"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Pridėti programą"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Pašalinti programą"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Išvesčių pridėjimas"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupė"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Pasirinktas 1 įrenginys"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 30ffd4b..34628f6 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Iespējot USB portu"</string>
     <string name="learn_more" msgid="4690632085667273811">"Uzzināt vairāk"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Ekrānuzņēmums"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Sistēma Smart Lock ir atspējota"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"nosūtīts attēls"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Notiek ekrānuzņēmuma saglabāšana..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Notiek ekrānuzņēmuma saglabāšana darba profilā…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Ja nākamajā mēģinājumā ievadīsiet nepareizu PIN, jūsu darba profils un ar to saistītie dati tiks dzēsti."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Ja nākamajā mēģinājumā ievadīsiet nepareizu paroli, jūsu darba profils un ar to saistītie dati tiks dzēsti."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Pieskarieties pirksta nospieduma sensoram"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Pirksta nospieduma ikona"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nevar atpazīt seju. Lietojiet pirksta nospiedumu."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Paziņojumu panelis"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Ātrie iestatījumi"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Ātrie iestatījumi un paziņojumu panelis."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Bloķēšanas ekrāns."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Darba profila bloķēšanas ekrāns"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Aizvērt"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Palielināt visu ekrānu"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Palielināt ekrāna daļu"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Pārslēgt"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Velciet stūri, lai mainītu izmērus"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Atļaut ritināšanu pa diagonāli"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Mainīt lielumu"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Kreisais turis"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Labais turis"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Apakšdaļas turis"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Lupas lielums"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Tālummainīt"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Vidējs"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Pievienota # vadīkla.}zero{Pievienotas # vadīklas.}one{Pievienota # vadīkla.}other{Pievienotas # vadīklas.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Noņemta"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Vai pievienot lietotni <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Ja pievienosiet lietotni <xliff:g id="APPNAME">%s</xliff:g>, tā varēs pievienot vadīklas un saturu šim panelim. Dažās lietotnēs varat izvēlēties, kuras vadīklas šeit rādīt."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Vai noņemt vadīklas lietotnei <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Pievienota izlasei"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Pievienota izlasei, <xliff:g id="NUMBER">%d</xliff:g>. pozīcija"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Noņemta no izlases"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Cita"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Pievienošana ierīču vadīklām"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Pievienot"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Noņemt"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Ieteica: <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Ierīce ir bloķēta"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Vai skatīt un kontrolēt ierīces no bloķēšanas ekrāna?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Varat pievienot bloķēšanas ekrānam vadīklas, ar kurām kontrolēt savas ārējās ierīces.\n\nJūsu ierīces lietotne var ļaut jums kontrolēt dažas ierīces, neatbloķējot tālruni vai planšetdatoru.\n\nVarat jebkurā laikā veikt izmaiņas iestatījumos."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Vai kontrolēt ierīces no bloķēšanas ekrāna?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Varat kontrolēt dažas ierīces, neatbloķējot tālruni vai planšetdatoru.\n\nJūsu ierīces lietotne nosaka, kuras ierīces var šādi kontrolēt."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Nē, paldies"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Jā"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN ietver burtus vai simbolus."</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Pievienot vadīklas"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Rediģēt vadīklas"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Pievienot lietotni"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Noņemt lietotni"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Izejas ierīču pievienošana"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupa"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Atlasīta viena ierīce"</string>
@@ -1111,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Pārslēgties uz darba profilu"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Aizvērt"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Bloķēšanas ekrāna iestatījumi"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi nav pieejams"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera ir bloķēta"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kameras un mikrofona lietošana ir bloķēta"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofons ir bloķēts"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritātes režīms ir ieslēgts"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Asistents klausās"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index cda4a85..175ef74 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Овозможи USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Дознајте повеќе"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Слика од екранот"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Оневозможено е Smart Lock"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"испрати слика"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Сликата на екранот се зачувува..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Се зачувува слика од екранот на вашиот работен профил…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Ако внесете погрешен PIN при следниот обид, работниот профил и неговите податоци ќе се избришат."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Ако внесете погрешна лозинка при следниот обид, работниот профил и неговите податоци ќе се избришат."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Допрете го сензорот за отпечатоци"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Икона за отпечаток"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Не се препознава ликот. Користете отпечаток."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Панел за известување"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Брзи поставки."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"„Брзи поставки“ и „Панел со известувања“."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Заклучи екран."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Работен заклучен екран"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Затвори"</string>
@@ -835,6 +834,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Зголемете го целиот екран"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Зголемувајте дел од екранот"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Префрли"</string>
+    <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Отвори поставки за зголемување"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Повлечете на аголот за да ја промените големината"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Дозволете дијагонално лизгање"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Промени големина"</string>
@@ -844,6 +844,7 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Лева рачка"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Десна рачка"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Долна рачка"</string>
+    <string name="accessibility_magnification_settings_panel_description" msgid="8174187340747846953">"Поставки за зголемување"</string>
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Големина на лупа"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Зум"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Средно"</string>
@@ -870,7 +871,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Додадена е # контрола.}one{Додадени се # контрола.}other{Додадени се # контроли.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Отстранета"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Да се додаде <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Кога ќе ја додадете <xliff:g id="APPNAME">%s</xliff:g>, таа ќе може да додава контроли и содржини на таблава. Кај некои апликации, може да изберете кои контроли ќе се прикажуваат тука."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Да се отстранат контролите за <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Омилена"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Омилена, позиција <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Неомилена"</string>
@@ -888,12 +891,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Друга"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Додајте во контроли за уредите"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Додај"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Отстрани"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Предложено од <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Уредот е заклучен"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Да се прикажуваат и контролираат уреди од заклучениот екран?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Може да додадете контроли за надворешните уреди на заклучениот екран.\n\nАпликацијата на уредот може да ви дозволи да контролирате одредени уреди без да го отклучувате телефонот или таблетот.\n\nМоже да извршите промени во секое време во „Поставки“."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Да се контролираат уреди од заклучен екран?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Може да контролирате одредени уреди без отклучување на телефонот или таблетот.\n\nАпликацијата на вашиот уред одредува кои уреди може да се контролираат вака."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Не, фала"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Да"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN-кодот содржи букви или симболи"</string>
@@ -941,6 +946,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Додајте контроли"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Изменете ги контролите"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Додајте апликација"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Отстранете ја апликацијата"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Додајте излези"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Група"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Избран е 1 уред"</string>
@@ -1111,16 +1117,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Префрли се на работен профил"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Затвори"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Поставки за заклучен екран"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi не е достапно"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камерата е блокирана"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камерата и микрофонот се блокирани"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Микрофонот е блокиран"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Приоритетниот режим е вклучен"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Вниманието на „Помошникот“ е вклучено"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 5802410..a25aa2c 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USB പ്രവർത്തനക്ഷമമാക്കുക"</string>
     <string name="learn_more" msgid="4690632085667273811">"കൂടുതലറിയുക"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"സ്ക്രീൻഷോട്ട്"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock പ്രവർത്തനരഹിതമാക്കി"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ചിത്രം അയച്ചു"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"സ്‌ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നു..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"ഔദ്യോഗിക പ്രൊഫൈലിലേക്ക് സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നു…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"അടുത്ത തവണയും നിങ്ങൾ തെറ്റായ പിൻ നൽകിയാൽ, നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫൈലും അതിന്റെ ഡാറ്റയും ഇല്ലാതാക്കപ്പെടും."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"അടുത്ത തവണയും നിങ്ങൾ തെറ്റായ പാസ്‌വേഡ് നൽകിയാൽ, നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫൈലും അതിന്റെ ഡാറ്റയും ഇല്ലാതാക്കപ്പെടും."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ഫിംഗർപ്രിന്റ് സെൻസർ സ്‌പർശിക്കുക"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"ഫിംഗർപ്രിന്റ് ഐക്കൺ"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"മുഖം തിരിച്ചറിയാനായില്ല. പകരം ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കൂ."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"അറിയിപ്പ് ഷെയ്‌ഡ്."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ദ്രുത ക്രമീകരണങ്ങൾ."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"അറിയിപ്പ് ഷെയ്‌ഡിനുള്ള ദ്രുത ക്രമീകരണം."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ലോക്ക് സ്‌ക്രീൻ."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ഔദ്യോഗിക ലോക്ക് സ്ക്രീൻ"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"അവസാനിപ്പിക്കുക"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"സ്ക്രീൻ പൂർണ്ണമായും മാഗ്നിഫൈ ചെയ്യുക"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"സ്‌ക്രീനിന്റെ ഭാഗം മാഗ്നിഫൈ ചെയ്യുക"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"മാറുക"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"വലുപ്പം മാറ്റാൻ മൂല വലിച്ചിടുക"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"ഡയഗണൽ സ്‌ക്രോളിംഗ് അനുവദിക്കുക"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"വലുപ്പം മാറ്റുക"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"ഇടത് ഹാൻഡിൽ"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"വലത് ഹാൻഡിൽ"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"ചുവടെയുള്ള ഹാൻഡിൽ"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"മാഗ്നിഫയർ വലുപ്പം"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"സൂം ചെയ്യുക"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"ഇടത്തരം"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# നിയന്ത്രണം ചേർത്തു.}other{# നിയന്ത്രണങ്ങൾ ചേർത്തു.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"നീക്കം ചെയ്‌തു"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> ചേർക്കണോ?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"നിങ്ങൾ <xliff:g id="APPNAME">%s</xliff:g> ചേർത്താൽ, അതിന് ഈ പാനലിലേക്ക് നിയന്ത്രണങ്ങളും ഉള്ളടക്കവും ചേർക്കാനാകും. ചില ആപ്പുകളിൽ, ഇവിടെ ഏത് നിയന്ത്രണങ്ങൾ ദൃശ്യമാകണമെന്ന് നിങ്ങൾക്ക് തിരഞ്ഞെടുക്കാനാകും."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> എന്നതിനുള്ള നിയന്ത്രണങ്ങൾ നീക്കം ചെയ്യണോ?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"പ്രിയപ്പെട്ടതാക്കി"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"പ്രിയപ്പെട്ടതാക്കി, സ്ഥാനം <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"പ്രിയപ്പെട്ടതല്ലാതാക്കി"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"മറ്റുള്ളവ"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"ഉപകരണ നിയന്ത്രണങ്ങളിലേക്ക് ചേർക്കുക"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"ചേർക്കുക"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"നീക്കം ചെയ്യുക"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> നിർദ്ദേശിച്ചത്"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"ഉപകരണം ലോക്ക് ചെയ്തു"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"ലോക്ക് സ്‌ക്രീനിൽ നിന്ന് ഉപകരണങ്ങൾ കാണിക്കുകയും നിയന്ത്രിക്കുകയും ചെയ്യണോ?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"നിങ്ങളുടെ ബാഹ്യ ഉപകരണങ്ങൾക്കുള്ള നിയന്ത്രണങ്ങൾ ലോക്ക് സ്‌ക്രീനിലേക്ക് ചേർക്കാനാകും.\n\nനിങ്ങളുടെ ഫോണോ ടാബ്‌ലെറ്റോ അൺലോക്ക് ചെയ്യാതെ ചില ഉപകരണങ്ങൾ നിയന്ത്രിക്കാൻ നിങ്ങളുടെ ഉപകരണ ആപ്പ് അനുവദിച്ചേക്കും.\n\nനിങ്ങൾക്ക് ക്രമീകരണത്തിൽ ഏതുസമയത്തും മാറ്റങ്ങൾ വരുത്താം."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"ലോക്ക് സ്‌ക്രീനിൽ നിന്ന് ഉപകരണങ്ങൾ നിയന്ത്രിക്കണോ?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"നിങ്ങളുടെ ഫോണോ ടാബ്‌ലെറ്റോ അൺലോക്ക് ചെയ്യാതെ ചില ഉപകരണങ്ങൾ നിയന്ത്രിക്കാം.\n\nഏതൊക്കെ ഉപകരണങ്ങൾ ഈ രീതിയിൽ നിയന്ത്രിക്കാൻ കഴിയുമെന്ന് നിങ്ങളുടെ ഉപകരണ ആപ്പ് നിർണ്ണയിക്കുന്നു."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"വേണ്ട, നന്ദി"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"ഉവ്വ്"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"പിന്നിൽ അക്ഷരങ്ങളോ ചിഹ്നങ്ങളോ അടങ്ങിയിരിക്കുന്നു"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"നിയന്ത്രണങ്ങൾ ചേർക്കുക"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"നിയന്ത്രണങ്ങൾ എഡിറ്റ് ചെയ്യുക"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"ആപ്പ് ചേർക്കുക"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"ആപ്പ് നീക്കം ചെയ്യുക"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"ഔട്ട്പുട്ടുകൾ ചേർക്കുക"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"ഗ്രൂപ്പ്"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"ഒരു ഉപകരണം തിരഞ്ഞെടുത്തു"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 3e6405c..73a4b75 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USB-г идэвхжүүлэх"</string>
     <string name="learn_more" msgid="4690632085667273811">"Нэмэлт мэдээлэл авах"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Дэлгэцийн зураг дарах"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Ухаалаг түгжээг идэвхгүй болгосон"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"зураг илгээсэн"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Дэлгэцийн агшинг хадгалж байна…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Дэлгэцийн агшныг ажлын профайлд хадгалж байна…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Та дараагийн оролдлогоор буруу ПИН оруулбал таны ажлын профайлыг өгөгдөлтэй нь цуг устгах болно."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Та дараагийн оролдлогоор буруу нууц үг оруулбал таны ажлын профайлыг өгөгдөлтэй нь цуг устгах болно."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Хурууны хээ мэдрэгчид хүрэх"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Хурууны хээний дүрс тэмдэг"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Царай таних боломжгүй. Оронд нь хурууны хээ ашигла"</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Мэдэгдлийн хураангуй самбар"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Шуурхай тохиргоо."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Шуурхай тохиргоо болон мэдэгдлийн хураангуй самбар."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Дэлгэц түгжих."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ажлын түгжигдсэн дэлгэц"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Хаах"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Бүтэн дэлгэцийг томруулах"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Дэлгэцийн нэг хэсгийг томруулах"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Сэлгэх"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Хэмжээг өөрчлөхийн тулд булангаас чирнэ үү"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Хөндлөн гүйлгэхийг зөвшөөрнө үү"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Хэмжээг өөрчлөх"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Зүүн бариул"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Баруун бариул"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Доод бариул"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Томруулагчийн хэмжээ"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Томруулалт"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Дунд зэрэг"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# хяналт нэмсэн.}other{# хяналт нэмсэн.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Хассан"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g>-г нэмэх үү?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Та <xliff:g id="APPNAME">%s</xliff:g>-г нэмэх үед энэ нь уг түр зуурын самбарт тохиргоо болон контент нэмэх боломжтой. Зарим аппад та энд ямар тохиргоог харуулахыг сонгох боломжтой."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g>-н тохиргоог хасах уу?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Дуртай гэж тэмдэглэсэн"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"<xliff:g id="NUMBER">%d</xliff:g>-р байршилд дуртай гэж тэмдэглэсэн"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Дургүй гэж тэмдэглэсэн"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Бусад"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Төхөөрөмжийн хяналт руу нэмэх"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Нэмэх"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Хасах"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g>-н санал болгосон"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Төхөөрөмжийг түгжсэн"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Түгжигдсэн дэлгэцээс төхөөрөмжүүдийг харуулж, хянах уу?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Та түгжигдсэн дэлгэцэд гадаад төхөөрөмжүүдийнхээ хяналтыг нэмэх боломжтой.\n\nТаны төхөөрөмжийн апп танд утас эсвэл таблетынхаа түгжээг тайлахгүйгээр зарим төхөөрөмжийг хянах боломжийг олгож магадгүй.\n\nТа хүссэн үедээ Тохиргоонд өөрчлөлт хийж болно."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Төхөөрөмжүүдийг түгжигдсэн дэлгэцээс хянах уу?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Та утас эсвэл таблетынхаа түгжээг тайлахгүйгээр зарим төхөөрөмжийг хянах боломжтой.\n\nТаны төхөөрөмжийн апп энэ аргаар ямар төхөөрөмжүүдийг хянах боломжтойг тодорхойлно."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Үгүй, баярлалаа"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Тийм"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"ПИН нь үсэг эсвэл дүрс тэмдэгт агуулдаг"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Хяналт нэмэх"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Хяналтыг өөрчлөх"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Апп нэмэх"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Аппыг хасах"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Гаралт нэмэх"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Бүлэг"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 төхөөрөмж сонгосон"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index f582a9f..fea5b63 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USB सुरू करा"</string>
     <string name="learn_more" msgid="4690632085667273811">"अधिक जाणून घ्या"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"स्क्रीनशॉट"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock बंद केले"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"इमेज पाठवली आहे"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"स्क्रीनशॉट सेव्ह करत आहे…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"कार्य प्रोफाइलवर स्क्रीनशॉट सेव्ह करत आहे…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"तुम्‍ही पुढील प्रयत्‍नात चुकीचा पिन एंटर केल्यास, तुमची कार्य प्रोफाइल आणि तिचा डेटा हटवला जाईल."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"तुम्‍ही पुढील प्रयत्‍नात चुकीचा पासवर्ड एंटर केल्यास, तुमची कार्य प्रोफाइल आणि तिचा डेटा हटवला जाईल."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"फिंगरप्रिंट सेन्सरला स्पर्श करा"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"फिंगरप्रिंट आयकन"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"चेहरा ओळखू शकत नाही. त्याऐवजी फिंगरप्रिंट वापरा."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"सूचना शेड."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"क्विक सेटिंग्ज."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"क्विक सेटिंग्ज आणि सूचना शेड."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"लॉक स्क्रीन."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"कार्य लॉक स्क्रीन"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"बंद करा"</string>
@@ -408,7 +407,7 @@
     <string name="media_projection_action_text" msgid="3634906766918186440">"आता सुरू करा"</string>
     <string name="empty_shade_text" msgid="8935967157319717412">"सूचना नाहीत"</string>
     <string name="no_unseen_notif_text" msgid="395512586119868682">"नवीन सूचना नाहीत"</string>
-    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"जुन्या सूचना पहाण्यासाठी अनलॉक करा"</string>
+    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"जुन्या सूचना पाहण्यासाठी अनलॉक करा"</string>
     <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"हे डिव्हाइस तुमच्या पालकाने व्यवस्थापित केले आहे"</string>
     <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"तुमच्‍या संस्‍थेकडे या डिव्हाइसची मालकी आहे आणि ती नेटवर्क ट्रॅफिकचे परीक्षण करू शकते"</string>
     <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"हे डिव्हाइस <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> च्या मालकीचे आहे आणि ती नेटवर्क ट्रॅफिकचे परीक्षण करू शकते"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"फुल स्क्रीन मॅग्निफाय करा"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"स्क्रीनचा काही भाग मॅग्निफाय करा"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"स्विच करा"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"आकार बदलण्यासाठी कोपरा ड्रॅग करा"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"तिरपे स्क्रोल करण्याची अनुमती द्या"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"आकार बदला"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"डावीकडील हँडल"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"उजवीकडील हँडल"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"तळाकडील हँडल"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"मॅग्निफायरचा आकार"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"झूम करा"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"मध्‍यम"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# नियंत्रण जोडले आहे.}other{# नियंत्रणे जोडली आहेत.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"काढून टाकले"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> जोडायचे आहे का?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"तुम्ही <xliff:g id="APPNAME">%s</xliff:g> जोडता, तेव्हा ते या पॅनलमध्ये नियंत्रणे आणि आशय जोडू शकते. येथे कोणती नियंत्रणे दाखवावीत ते तुम्ही काही अ‍ॅप्समध्ये निवडू शकता."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> साठी नियंत्रणे काढून टाकायची आहेत का?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"आवडले"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"आवडले, स्थान <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"नावडले"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"इतर"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"डिव्हाइस नियंत्रणांमध्ये जोडा"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"जोडा"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"काढून टाका"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ने सुचवले आहे"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"डिव्हाइस लॉक आहे"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"लॉक स्क्रीनवरून डिव्हाइस दाखवायचे आणि नियंत्रित करायचे का?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"तुम्ही तुमच्या बाह्य डिव्हाइससाठी लॉक स्क्रीनवर नियंत्रणे जोडू शकता.\n\nतुमचे डिव्हाइस अ‍ॅप तुम्हाला तुमचा फोन किंवा टॅबलेट अनलॉक न करता काही डिव्हाइस नियंत्रित करण्याची अनुमती देऊ शकते.\n\nतुम्ही सेटिंग्ज मध्ये कधीही बदल करू शकता."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"लॉक स्क्रीनवरून डिव्हाइस नियंत्रित करायची का?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"तुमचा फोन किंवा टॅबलेट अनलॉक न करता तुम्ही काही डिव्हाइस नियंत्रित करू शकता.\n\nतुमचे डिव्हाइस अ‍ॅप अशा प्रकारे कोणते डिव्हाइस नियंत्रित केले जाऊ शकतात हे निर्धारित करते."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"नाही, नको"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"होय"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"पिनमध्ये अक्षरे किंवा चिन्हे आहेत"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"नियंत्रणे जोडा"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"नियंत्रणे संपादित करा"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"अ‍ॅप जोडा"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"ॲप काढून टाका"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"आउटपुट जोडा"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"गट"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"एक डिव्हाइस निवडले"</string>
@@ -1111,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"कार्य प्रोफाइलवर स्विच करा"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"बंद करा"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"लॉक स्क्रीन सेटिंग्ज"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"वाय-फाय उपलब्ध नाही"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"कॅमेरा ब्लॉक केला"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"कॅमेरा आणि मायक्रोफोन ब्लॉक केले आहेत"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"मायक्रोफोन ब्लॉक केला"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"प्राधान्य मोड सुरू आहे"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant चे लक्ष हे आता अ‍ॅक्टिव्ह आहे"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 4624a4ba..202d66f 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Dayakan USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Ketahui lebih lanjut"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Tangkapan skrin"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock dilumpuhkan"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"menghantar imej"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Menyimpan tangkapan skrin..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Menyimpan tangkapan skrin ke profil kerja…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Jika anda memasukkan PIN yang salah pada percubaan seterusnya, profil kerja anda dan data profil itu akan dipadamkan."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Jika anda memasukkan kata laluan yang salah pada percubaan seterusnya, profil kerja anda dan data profil itu akan dipadamkan."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Sentuh penderia cap jari"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikon cap jari"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Tidak mengenali wajah. Gunakan cap jari."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bidai pemberitahuan."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Tetapan pantas."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Tetapan pantas dan Bidai pemberitahuan."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Kunci skrin."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Skrin kunci kerja"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Tutup"</string>
@@ -835,6 +834,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Besarkan skrin penuh"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Besarkan sebahagian skrin"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Tukar"</string>
+    <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Buka tetapan pembesaran"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Seret sudut untuk mengubah saiz"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Benarkan penatalan pepenjuru"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Ubah saiz"</string>
@@ -844,6 +844,7 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Pemegang kiri"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Pemegang kanan"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Pemegang bawah"</string>
+    <string name="accessibility_magnification_settings_panel_description" msgid="8174187340747846953">"Tetapan pembesaran"</string>
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Saiz penggadang"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zum"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Sederhana"</string>
@@ -870,7 +871,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kawalan ditambah.}other{# kawalan ditambah.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Dialih keluar"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Tambahkan <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Apabila anda menambahkan <xliff:g id="APPNAME">%s</xliff:g>, apl ini boleh menambahkan kawalan dan kandungan pada panel ini. Dalam sesetengah apl, anda boleh memilih kawalan yang muncul di sini."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Alih keluar kawalan untuk <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Digemari"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Digemari, kedudukan <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Dinyahgemari"</string>
@@ -888,12 +891,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Lain-lain"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Tambahkan pada kawalan peranti"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Tambah"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Alih keluar"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Dicadangkan oleh <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Peranti dikunci"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Tunjukkan dan kawal peranti daripada skrin kunci?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Anda boleh menambah kawalan untuk peranti luaran anda pada skrin kunci.\n\nApl peranti anda mungkin membenarkan anda mengawal sesetengah peranti tanpa membuka kunci telefon atau tablet anda.\n\nAnda boleh membuat perubahan pada bila-bila masa dalam Tetapan."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Kawal peranti daripada skrin kunci?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Anda boleh mengawal sesetengah peranti tanpa membuka kunci telefon atau tablet anda.\n\nApl peranti anda menentukan peranti yang boleh dikawal dengan cara ini."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Tidak perlu"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ya"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN mengandungi huruf atau simbol"</string>
@@ -941,6 +946,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Tambah kawalan"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Edit kawalan"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Tambahkan apl"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Alih keluar apl"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Tambah output"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Kumpulan"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 peranti dipilih"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 6463480..bb1bba9 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USB ကို ဖွင့်ရန်"</string>
     <string name="learn_more" msgid="4690632085667273811">"ပိုမိုလေ့လာရန်"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ဖန်သားပြင်ဓာတ်ပုံ"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock ပိတ်ထားသည်"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ပုံပို့ထားသည်"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ဖန်သားပြင်ဓါတ်ပုံရိုက်ခြင်းအား သိမ်းဆည်းပါမည်"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"အလုပ်ပရိုဖိုင်တွင် ဖန်သားပြင်ဓာတ်ပုံ သိမ်းနေသည်…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"မှားယွင်းသည့် ပင်နံပါတ်ကို နောက်တစ်ကြိမ်ထည့်သွင်းပါက သင်၏အလုပ်ပရိုဖိုင်နှင့် ၎င်း၏ဒေတာများကို ဖျက်လိုက်ပါမည်။"</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"မှားယွင်းသည့် စကားဝှက်ကို နောက်တစ်ကြိမ်ထည့်သွင်းပါက သင်၏အလုပ်ပရိုဖိုင်နှင့် ၎င်း၏ ဒေတာများကို ဖျက်လိုက်ပါမည်။"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"လက်ဗွေအာရုံခံကိရိယာကို တို့ပါ"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"လက်ဗွေ သင်္ကေတ"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"မျက်နှာကို မမှတ်မိပါ။ လက်ဗွေကို အစားထိုးသုံးပါ။"</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"အ​ကြောင်းကြားစာအကွက်"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"အမြန်လုပ် အပြင်အဆင်"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"‘အမြန်ဆက်တင်များ’ နှင့် ‘အကြောင်းကြားစာအကွက်’။"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"မျက်နှာပြင် သော့ပိတ်ရန်"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"အလုပ်သုံး လော့ခ်မျက်နှာပြင်"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"ပိတ်ရန်"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ဖန်သားပြင်အပြည့် ချဲ့သည်"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ဖန်သားပြင် တစ်စိတ်တစ်ပိုင်းကို ချဲ့ပါ"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"ခလုတ်"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"အရွယ်အစားပြန်ပြုပြင်ရန် ထောင့်စွန်းကို ဖိဆွဲပါ"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"ထောင့်ဖြတ် လှိမ့်ခွင့်ပြုရန်"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"အရွယ်အစားပြန်ပြုပြင်ရန်"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"ဘယ်ဘက်အထိန်း"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"ညာဘက်အထိန်း"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"အောက်ခြေအထိန်း"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"မှန်ဘီလူး အရွယ်အစား"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"ဇူးမ်"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"အလတ်"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{ထိန်းချုပ်ခလုတ် # ခု ထည့်ထားသည်။}other{ထိန်းချုပ်ခလုတ် # ခု ထည့်ထားသည်။}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"ဖယ်ရှားထားသည်"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> ထည့်မလား။"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> ထည့်သောအခါ ၎င်းသည် ဤအကန့်တွင် သတ်မှတ်ချက်များနှင့် အကြောင်းအရာကို ထည့်နိုင်သည်။ အက်ပ်အချို့၌ မြင်ရမည့် သတ်မှတ်ချက်များကို ဤနေရာတွင် ရွေးနိုင်သည်။"</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> အတွက် သတ်မှတ်ချက်များ ဖယ်ရှားမလား။"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"အကြိုက်ဆုံးတွင် ထည့်ထားသည်"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"အကြိုက်ဆုံးတွင် ထည့်ထားသည်၊ အဆင့် <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"အကြိုက်ဆုံးမှ ဖယ်ရှားထားသည်"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"အခြား"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"စက်ထိန်းစနစ်သို့ ထည့်ရန်"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"ထည့်ရန်"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"ဖယ်ရှားရန်"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> က အကြံပြုထားသည်"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"စက်ကိုလော့ခ်ချထားသည်"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"လော့ခ်မျက်နှာပြင်တွင် စက်ပစ္စည်းများကြည့်ရှုပြီး ထိန်းချုပ်မလား။"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"လော့ခ်မျက်နှာပြင်တွင် ပြင်ပစက်များအတွက် ထိန်းချုပ်မှုများ ထည့်နိုင်သည်။\n\nသင့်စက်ပစ္စည်းအက်ပ်က အချို့စက်များကို ဖုန်း (သို့) တက်ဘလက် လော့ခ်ဖွင့်ရန်မလိုဘဲ သုံးခွင့်ပေးနိုင်သည်။\n\nဆက်တင်များ၌ အချိန်မရွေး ပြောင်းလဲပြင်ဆင်နိုင်သည်။"</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"လော့ခ်မျက်နှာပြင်တွင် စက်ပစ္စည်းများ ထိန်းချုပ်မလား။"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"အချို့စက်များကို ဖုန်း (သို့) တက်ဘလက် လော့ခ်ဖွင့်ရန်မလိုဘဲ ထိန်းချုပ်နိုင်သည်။\n\nဤနည်းလမ်းအတိုင်း ထိန်းချုပ်နိုင်မည့်စက်များကို သင့်စက်ပစ္စည်းအက်ပ်က ဆုံးဖြတ်သည်။"</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"မလိုပါ"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Yes"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"ပင်နံပါတ်တွင် စာလုံး သို့မဟုတ် သင်္ကေတများပါဝင်သည်"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"ထိန်းချုပ်မှုများ ထည့်ရန်"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"ထိန်းချုပ်မှုများ ပြင်ရန်"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"အက်ပ်ထည့်ရန်"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"အက်ပ်ဖယ်ရှားရန်"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"မီဒီယာအထွက်များ ထည့်ရန်"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"အုပ်စု"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"စက်ပစ္စည်း ၁ ခုကို ရွေးချယ်ထားသည်"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 94ebf2b..1618f73 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Slå på USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Finn ut mer"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Skjermdump"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock er slått av"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"har sendt et bilde"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Lagrer skjermdumpen …"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Lagrer skjermdumpen i jobbprofilen …"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Hvis du skriver inn feil PIN-kode på neste forsøk, slettes jobbprofilen din og tilknyttede data."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Hvis du skriver inn feil passord på neste forsøk, slettes jobbprofilen din og tilknyttede data."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Trykk på fingeravtrykkssensoren"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikon for fingeravtrykk"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ansiktet gjenkjennes ikke. Bruk fingeravtrykk."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Varselskygge."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Hurtiginnstillinger."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Hurtiginnstillinger og varselpanelet"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Låseskjerm."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Låseskjerm for arbeid"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Lukk"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Forstørr hele skjermen"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Forstørr en del av skjermen"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Bytt"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Dra hjørnet for å endre størrelse"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Tillat diagonal rulling"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Endre størrelse"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Venstre håndtak"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Høyre håndtak"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Nedre håndtak"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Forstørringsstørrelse"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoom"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Middels"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kontroll er lagt til.}other{# kontroller er lagt til.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Fjernet"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Vil du legge til <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Når du legger til <xliff:g id="APPNAME">%s</xliff:g>, kan den legge til kontroller og innhold i dette panelet. I noen apper kan du velge hvilke kontroller som vises her."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Vil du fjerne kontrollene for <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Favoritt"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Favoritt, posisjon <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Fjernet som favoritt"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Annet"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Legg til i enhetsstyring"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Legg til"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Fjern"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Foreslått av <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Enheten er låst"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Vil du se og kontrollere enheter fra låseskjermen?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Du kan legge til kontroller for de eksterne enhetene dine på låseskjermen.\n\nEnhetsappen kan la deg kontrollere noen enheter uten å låse opp telefonen eller nettbrettet.\n\nDu kan når som helst endre innstillingene."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Vil du kontrollere enheter fra låseskjermen?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Du kan kontrollere enkelte enheter uten å låse opp telefonen eller nettbrettet.\n\nEnhetsappen fastslår hvilke enheter som kan kontrolleres på denne måten."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Nei takk"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ja"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN-koden inneholder bokstaver eller symboler"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Legg til kontroller"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Endre kontroller"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Legg til app"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Fjern appen"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Legg til utenheter"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Gruppe"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 enhet er valgt"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index d16e91f..eafca69 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USB सक्षम पार्नुहोस्"</string>
     <string name="learn_more" msgid="4690632085667273811">"थप जान्नुहोस्"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"स्क्रिनसट"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"स्मार्ट लक अफ गरिएको छ"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"कुनै छवि पठाइयो"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"स्क्रिनसट बचत गर्दै…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"कार्य प्रोफाइलमा स्क्रिनसट सेभ गरिँदै छ…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"तपाईंले अर्को पटक पनि गलत PIN प्रविष्टि गर्नुभयो भने तपाईंको कार्य प्रोफाइल र त्यहाँको डेटा मेटाइने छ।"</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"तपाईंले अर्को पटक पनि गलत पासवर्ड प्रविष्टि गर्नुभयो भने तपाईंको कार्य प्रोफाइल र त्यहाँको डेटा मेटाइने छ।"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"फिंगरप्रिन्ट सेन्सरमा छुनुहोस्‌"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"फिंगरप्रिन्ट जनाउने आइकन"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"अनुहार पहिचान गर्न सकिएन। बरु फिंगरप्रिन्ट प्रयोग गर्नुहोस्।"</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"सूचना कक्ष।"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"द्रुत सेटिङहरू"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"द्रुत सेटिङ तथा सूचना कक्ष।"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"स्क्रीन बन्द गर्नुहोस्।"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"कार्य प्रोफाइलको लक स्क्रिन"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"बन्द गर्नुहोस्"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"पूरै स्क्रिन जुम इन गर्नुहोस्"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"स्क्रिनको केही भाग म्याग्निफाइ गर्नुहोस्"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"बदल्नुहोस्"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"आकार बदल्न कुनाबाट ड्र्याग गर्नुहोस्"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"डायगोनल तरिकाले स्क्रोल गर्ने अनुमति दिनुहोस्"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"आकार बदल्नुहोस्"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"बायाँतिरको ह्यान्डल"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"दायाँतिरको ह्यान्डल"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"पुछारको ह्यान्डल"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"म्याग्निफायरको आकार"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"जुम"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"मध्यम"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# कन्ट्रोल हालियो।}other{# वटा कन्ट्रोल हालियो।}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"हटाइएको"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> हाल्ने हो?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"तपाईंले <xliff:g id="APPNAME">%s</xliff:g> हाल्नुभयो भने यसले यो प्यानलमा सेटिङ र सामग्री हाल्न सक्छ। तपाईं केही एपहरूमा यहाँ कुन कुन सेटिङ देखाउने भन्ने कुरा छनौट गर्न सक्नुहुन्छ।"</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> का सेटिङ हटाउने हो?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"मनपराइएको"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"मन पराइएका कुराहरूको <xliff:g id="NUMBER">%d</xliff:g> औँ स्थानमा"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"मन पर्ने कुराहरूको सूचीमा नराखिएको"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"अन्य"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"डिभाइस नियन्त्रण गर्ने विजेटहरूको सूचीमा थप्नुहोस्"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"थप्नुहोस्"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"हटाउनुहोस्"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ले सिफारिस गरेको"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"यन्त्र लक गरिएको छ"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"लक स्क्रिनमै डिभाइसहरू देखाउने र लक स्क्रिनबाटै ती डिभाइसहरू नियन्त्रण गर्ने हो?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"तपाईं आफ्ना बाह्य डिभाइसहरूका कन्ट्रोलहरू लक स्क्रिनमा हाल्न सक्नुहुन्छ।\n\nतपाईंको डिभाइसको एपले तपाईंलाई आफ्नो फोन वा ट्याब्लेट अनलक नगरिकनै केही डिभाइसहरू नियन्त्रण गर्ने अनुमति दिन सक्छ।\n\nतपाईं जुनसुकै बेला सेटिङमा गई यी कुराहरू बदल्न सक्नुहुन्छ।"</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"लक स्क्रिनबाटै डिभाइसहरू नियन्त्रण गर्ने हो?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"तपाईं आफ्नो फोन वा ट्याब्लेट अनलक नगरिकनै केही डिभाइसहरू नियन्त्रण गर्न सक्नुहुन्छ।\n\nतपाईंको डिभाइस एपले यस तरिकाले कुन कुन डिभाइस नियन्त्रण गर्न सकिन्छ भन्ने कुरा निर्धारण गर्छ।"</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"पर्दैन"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"अँ"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN मा अक्षर वा चिन्हहरू समाविष्ट हुन्छन्"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"कन्ट्रोल थप्नुहोस्"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"कन्ट्रोल सम्पादन गर्नुहोस्"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"एप हाल्नुहोस्"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"यो एप हटाउनुहोस्"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"आउटपुट यन्त्रहरू थप्नुहोस्"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"समूह"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"१ यन्त्र चयन गरियो"</string>
@@ -1019,7 +1027,7 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"मोबाइल डेटा"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"इन्टरनेटमा कनेक्ट गरिएको छ"</string>
-    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"केही समयका लागि मोबाइल डेटामा कनेक्ट गरिएको छ"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"यसमा केही समयका लागि कनेक्ट गरिएको हो"</string>
     <string name="mobile_data_poor_connection" msgid="819617772268371434">"इन्टरनेट राम्री चलेको छैन"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"मोबाइल डेटा स्वतः कनेक्ट हुँदैन"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"इन्टरनेट छैन"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 995abb0..4427571 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USB aanzetten"</string>
     <string name="learn_more" msgid="4690632085667273811">"Meer informatie"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock staat uit"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"heeft een afbeelding gestuurd"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Screenshot opslaan..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Screenshot opslaan in werkprofiel…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Als je bij de volgende poging een onjuiste pincode opgeeft, worden je werkprofiel en de bijbehorende gegevens verwijderd."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Als je bij de volgende poging een onjuist wachtwoord opgeeft, worden je werkprofiel en de bijbehorende gegevens verwijderd."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Raak de vingerafdruksensor aan"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Vingerafdrukpictogram"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Gezicht niet herkend. Gebruik je vingerafdruk."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Meldingenpaneel."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Snelle instellingen."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Snelle instellingen en meldingenpaneel."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Vergrendelscherm."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Vergrendelscherm voor werk"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Sluiten"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Volledig scherm vergroten"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Deel van het scherm vergroten"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Schakelen"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Sleep een hoek om het formaat te wijzigen"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Diagonaal scrollen toestaan"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Formaat aanpassen"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Handgreep links"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Handgreep rechts"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Handgreep onderaan"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Vergrotingsgrootte"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoomen"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Normaal"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# bedieningselement toegevoegd.}other{# bedieningselementen toegevoegd.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Verwijderd"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> toevoegen?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Als je <xliff:g id="APPNAME">%s</xliff:g> toevoegt, kan deze app bedieningselementen en content aan dit deelvenster toevoegen. In sommige apps kun je kiezen welke bedieningselementen hier worden getoond."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Bedieningselementen voor <xliff:g id="APPNAME">%s</xliff:g> verwijderen?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Gemarkeerd als favoriet"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Gemarkeerd als favoriet, positie <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Verwijderd als favoriet"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Overig"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Toevoegen aan apparaatbediening"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Toevoegen"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Verwijderen"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Voorgesteld door <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Apparaat vergrendeld"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Apparaten tonen en bedienen via het vergrendelscherm?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Je kunt bedieningselementen voor je externe apparaten toevoegen aan het vergrendelscherm.\n\nMet je apparaat-app kun je misschien bepaalde apparaten bedienen zonder je telefoon of tablet te ontgrendelen.\n\nJe kunt op elk moment wijzigingen aanbrengen via Instellingen."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Apparaten bedienen via vergrendelscherm?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Je kunt bepaalde apparaten bedienen zonder je telefoon of tablet te ontgrendelen.\n\nJe apparaat-app bepaalt welke apparaten op deze manier kunnen worden bediend."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Nee, bedankt"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ja"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Pincode bevat letters of symbolen"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Bedieningselementen toevoegen"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Bedieningselementen bewerken"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"App toevoegen"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"App verwijderen"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Uitvoer toevoegen"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Groep"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Eén apparaat geselecteerd"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index f1b69b4..fb036f3 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USB ସକ୍ଷମ କରନ୍ତୁ"</string>
     <string name="learn_more" msgid="4690632085667273811">"ଅଧିକ ଜାଣନ୍ତୁ"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ସ୍କ୍ରିନ୍‌ସଟ୍ ନିଅନ୍ତୁ"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"ସ୍ମାର୍ଟ ଲକ୍ ଅକ୍ଷମ କରାଯାଇଛି"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ଏକ ଛବି ପଠାଯାଇଛି"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ସ୍କ୍ରୀନଶଟ୍‍ ସେଭ୍‍ କରାଯାଉଛି…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"ୱାର୍କ ପ୍ରୋଫାଇଲରେ ସ୍କ୍ରିନସଟ ସେଭ କରାଯାଉଛି…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"ଆପଣ ପରବର୍ତ୍ତୀ ପ୍ରଚେଷ୍ଟାରେ ଏକ ଭୁଲ PIN ଲେଖିଲେ, ଆପଣଙ୍କ ୱାର୍କ ପ୍ରୋଫାଇଲ୍ ଏବଂ ଏହାର ଡାଟାକୁ ଡିଲିଟ୍ କରିଦିଆଯିବ।"</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"ଆପଣ ପରବର୍ତ୍ତୀ ପ୍ରଚେଷ୍ଟାରେ ଏକ ଭୁଲ ପାସୱାର୍ଡ ଲେଖିଲେ, ଆପଣଙ୍କ ୱାର୍କ ପ୍ରୋଫାଇଲ୍ ଓ ଏହାର ଡାଟାକୁ ଡିଲିଟ୍ କରିଦିଆଯିବ।"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ଟିପଚିହ୍ନ ସେନସର୍‌କୁ ଛୁଅଁନ୍ତୁ"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"ଟିପଚିହ୍ନ ଆଇକନ୍"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ଫେସ୍ ଚିହ୍ନଟ କରିହେବ ନାହିଁ। ଟିପଚିହ୍ନ ବ୍ୟବହାର କରନ୍ତୁ।"</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ବିଜ୍ଞପ୍ତି ଶେଡ୍‍।"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"କ୍ୱିକ୍ ସେଟିଂସ୍।"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"କୁଇକ ସେଟିଂସ ଏବଂ ବିଜ୍ଞପ୍ତି ସେଡ।"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ଲକ୍‌ ସ୍କ୍ରୀନ୍‌।"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ୱର୍କ ଲକ୍‍ ସ୍କ୍ରୀନ୍‍"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"ବନ୍ଦ କରନ୍ତୁ"</string>
@@ -407,8 +406,8 @@
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"\"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\" ବିକଳ୍ପ ଦ୍ୱାରା ବିଜ୍ଞପ୍ତି ପଜ୍‍ ହୋଇଛି"</string>
     <string name="media_projection_action_text" msgid="3634906766918186440">"ବର୍ତ୍ତମାନ ଆରମ୍ଭ କରନ୍ତୁ"</string>
     <string name="empty_shade_text" msgid="8935967157319717412">"କୌଣସି ବିଜ୍ଞପ୍ତି ନାହିଁ"</string>
-    <string name="no_unseen_notif_text" msgid="395512586119868682">"କୌଣସି ନୂଆ ବିଜ୍ଞପ୍ତି ନାହିଁ"</string>
-    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"ପୁରୁଣା ବିଜ୍ଞପ୍ତି ଦେଖିବାକୁ ଅନଲକ କରନ୍ତୁ"</string>
+    <string name="no_unseen_notif_text" msgid="395512586119868682">"କୌଣସି ନୂଆ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ନାହିଁ"</string>
+    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"ପୁରୁଣା ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ଦେଖିବାକୁ ଅନଲକ କରନ୍ତୁ"</string>
     <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ଏହି ଡିଭାଇସ୍ ଆପଣଙ୍କ ବାପାମାଙ୍କ ଦ୍ୱାରା ପରିଚାଳିତ"</string>
     <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ଏହି ଡିଭାଇସର ମାଲିକାନା ଆପଣଙ୍କ ସଂସ୍ଥା ପାଖରେ ଅଛି ଏବଂ ଏହା ନେଟୱାର୍କ ଟ୍ରାଫିକର ନିରୀକ୍ଷଣ କରିପାରେ"</string>
     <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"ଏହି ଡିଭାଇସଟି <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>ର ଅଟେ ଏବଂ ଏହା ନେଟୱାର୍କ ଟ୍ରାଫିକକୁ ନିରୀକ୍ଷଣ କରିପାରେ"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ସମ୍ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନକୁ ମ୍ୟାଗ୍ନିଫାଏ କରନ୍ତୁ"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ସ୍କ୍ରିନର ଅଂଶ ମାଗ୍ନିଫାଏ କରନ୍ତୁ"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"ସ୍ୱିଚ୍ କରନ୍ତୁ"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"ରିସାଇଜ କରିବା ପାଇଁ କୋଣକୁ ଡ୍ରାଗ କରନ୍ତୁ"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"ଡାଏଗୋନାଲ ସ୍କ୍ରୋଲିଂକୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"ରିସାଇଜ କରନ୍ତୁ"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"ବାମ ହ୍ୟାଣ୍ଡେଲ"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"ଡାହାଣ ହ୍ୟାଣ୍ଡେଲ"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"ନିମ୍ନର ହ୍ୟାଣ୍ଡେଲ"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"ମ୍ୟାଗ୍ନିଫାୟରର ଆକାର"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"ଜୁମ କରନ୍ତୁ"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"ମଧ୍ୟମ"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{#ଟି ନିୟନ୍ତ୍ରଣ ଯୋଗ କରାଯାଇଛି।}other{#ଟି ନିୟନ୍ତ୍ରଣ ଯୋଗ କରାଯାଇଛି।}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"କାଢ଼ି ଦିଆଯାଇଛି"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g>କୁ ଯୋଗ କରିବେ?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"ଯେତେବେଳେ ଆପଣ <xliff:g id="APPNAME">%s</xliff:g>କୁ ଯୋଗ କରନ୍ତି, ସେତେବେଳେ ଏହି ପେନେଲରେ ଏହା ନିୟନ୍ତ୍ରଣ ଏବଂ ବିଷୟବସ୍ତୁ ଯୋଗ କରିପାରିବ। କିଛି ଆପ୍ସରେ, ଏଠାରେ କେଉଁ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ଦେଖାଯିବ ତାହା ଆପଣ ବାଛିପାରିବେ।"</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> ପାଇଁ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକୁ କାଢ଼ି ଦେବେ?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"ପସନ୍ଦ କରାଯାଇଛି"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"ପସନ୍ଦ କରାଯାଇଛି, ସ୍ଥିତି <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ନାପସନ୍ଦ କରାଯାଇଛି"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ଅନ୍ୟ"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"ଡିଭାଇସ୍ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକରେ ଯୋଗ କରନ୍ତୁ"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"ଯୋଗ କରନ୍ତୁ"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"କାଢ଼ି ଦିଅନ୍ତୁ"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ଦ୍ଵାରା ପ୍ରସ୍ତାବିତ"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"ଡିଭାଇସ୍ ଲକ୍ ହୋଇଯାଇଛି"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"ଲକ ସ୍କ୍ରିନରୁ ଡିଭାଇସଗୁଡ଼ିକୁ ଦେଖାଇବେ ଏବଂ ନିୟନ୍ତ୍ରଣ କରିବେ?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"ଆପଣ ଲକ ସ୍କ୍ରିନରେ ଆପଣଙ୍କ ଏକ୍ସଟର୍ନଲ ଡିଭାଇସଗୁଡ଼ିକ ପାଇଁ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ଯୋଗ କରିପାରିବେ।\n\nଆପଣଙ୍କ ଫୋନ କିମ୍ବା ଟାବଲେଟକୁ ଅନଲକ ନକରି କିଛି ଡିଭାଇସକୁ ନିୟନ୍ତ୍ରଣ କରିବା ପାଇଁ ଆପଣଙ୍କ ଡିଭାଇସର ଆପ ଆପଣଙ୍କୁ ଅନୁମତି ଦେଇପାରେ।\n\nଆପଣ ଯେ କୌଣସି ସମୟରେ ସେଟିଂସରେ ପରିବର୍ତ୍ତନ କରିପାରିବେ।"</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"ଲକ ସ୍କ୍ରିନରୁ ଡିଭାଇସଗୁଡ଼ିକୁ ନିୟନ୍ତ୍ରଣ କରିବେ?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"ଆପଣ ଆପଣଙ୍କ ଫୋନ କିମ୍ବା ଟାବଲେଟକୁ ଅନଲକ ନକରି କିଛି ଡିଭାଇସକୁ ନିୟନ୍ତ୍ରଣ କରିପାରିବେ।\n\nଏହି ଉପାୟରେ କେଉଁ ଡିଭାଇସଗୁଡ଼ିକୁ ନିୟନ୍ତ୍ରଣ କରାଯାଇପାରିବ ତାହା ଆପଣଙ୍କ ଡିଭାଇସର ଆପ ସ୍ଥିର କରେ।"</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"ନା, ଧନ୍ୟବାଦ"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"ହଁ"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PINରେ ଅକ୍ଷର କିମ୍ୱା ପ୍ରତୀକଗୁଡ଼ିକ ଥାଏ"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ଯୋଗ କରନ୍ତୁ"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକୁ ଏଡିଟ କରନ୍ତୁ"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"ଆପ ଯୋଗ କରନ୍ତୁ"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"ଆପକୁ କାଢ଼ି ଦିଅନ୍ତୁ"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"ଆଉଟପୁଟ୍ ଯୋଗ କରନ୍ତୁ"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"ଗୋଷ୍ଠୀ"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1ଟି ଡିଭାଇସ୍ ଚୟନ କରାଯାଇଛି"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 0c7708f..6aea323 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USB ਚਾਲੂ ਕਰੋ"</string>
     <string name="learn_more" msgid="4690632085667273811">"ਹੋਰ ਜਾਣੋ"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock ਬੰਦ ਕੀਤਾ ਗਿਆ"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ਚਿੱਤਰ ਭੇਜਿਆ ਗਿਆ"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ \'ਤੇ ਰੱਖਿਅਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"ਜੇ ਤੁਸੀਂ ਅਗਲੀ ਕੋਸ਼ਿਸ਼ ਵਿੱਚ ਕੋਈ ਗਲਤ ਪਿੰਨ ਦਾਖਲ ਕਰਦੇ ਹੋ, ਤਾਂ ਤੁਹਾਡਾ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਅਤੇ ਇਸ ਦਾ ਡਾਟਾ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ।"</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"ਜੇ ਤੁਸੀਂ ਅਗਲੀ ਕੋਸ਼ਿਸ਼ ਵਿੱਚ ਕੋਈ ਗਲਤ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰਦੇ ਹੋ, ਤਾਂ ਤੁਹਾਡਾ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਅਤੇ ਇਸ ਦਾ ਡਾਟਾ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ।"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਨੂੰ ਸਪੱਰਸ਼ ਕਰੋ"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਾ ਪ੍ਰਤੀਕ"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ਚਿਹਰਾ ਨਹੀਂ ਪਛਾਣ ਸਕਦੇ। ਇਸਦੀ ਬਜਾਏ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤੋ।"</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ਸੂਚਨਾ ਸ਼ੇਡ।"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ।"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸੂਚਨਾ ਸ਼ੇਡ।"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">" ਲਾਕ  ਸਕ੍ਰੀਨ।"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ਕਾਰਜ-ਸਥਾਨ  ਲਾਕ  ਸਕ੍ਰੀਨ"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"ਬੰਦ ਕਰੋ"</string>
@@ -407,7 +406,7 @@
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"\'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਵੱਲੋਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਰੋਕਿਆ ਗਿਆ"</string>
     <string name="media_projection_action_text" msgid="3634906766918186440">"ਹੁਣੇ ਸ਼ੁਰੂ ਕਰੋ"</string>
     <string name="empty_shade_text" msgid="8935967157319717412">"ਕੋਈ ਸੂਚਨਾਵਾਂ ਨਹੀਂ"</string>
-    <string name="no_unseen_notif_text" msgid="395512586119868682">"ਕੋਈ ਨਵੀਂ ਸੂਚਨਾ ਨਹੀਂ"</string>
+    <string name="no_unseen_notif_text" msgid="395512586119868682">"ਕੋਈ ਨਵੀਂ ਸੂਚਨਾ ਨਹੀਂ ਹੈ"</string>
     <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"ਪੁਰਾਣੀਆਂ ਸੂਚਨਾਵਾਂ ਦੇਖਣ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string>
     <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ਇਸ ਡੀਵਾਈਸ ਦਾ ਪ੍ਰਬੰਧਨ ਤੁਹਾਡੇ ਮਾਂ-ਪਿਓ ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ"</string>
     <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ਤੁਹਾਡੀ ਸੰਸਥਾ ਕੋਲ ਇਸ ਡੀਵਾਈਸ ਦੀ ਮਲਕੀਅਤ ਹੈ ਅਤੇ ਇਹ ਨੈੱਟਵਰਕ ਟਰੈਫ਼ਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ਪੂਰੀ ਸਕ੍ਰੀਨ ਨੂੰ ਵੱਡਦਰਸ਼ੀ ਕਰੋ"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ਸਕ੍ਰੀਨ ਦੇ ਹਿੱਸੇ ਨੂੰ ਵੱਡਾ ਕਰੋ"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"ਸਵਿੱਚ"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"ਆਕਾਰ ਬਦਲਣ ਲਈ ਕੋਨਾ ਘਸੀਟੋ"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"ਟੇਡੀ ਦਿਸ਼ਾ ਵਿੱਚ ਸਕ੍ਰੋਲ ਕਰਨ ਦਿਓ"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"ਆਕਾਰ ਬਦਲੋ"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"ਖੱਬਾ ਹੈਂਡਲ"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"ਸੱਜਾ ਹੈਂਡਲ"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"ਹੇਠਲਾਂ ਹੈਂਡਲ"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"ਵੱਡਦਰਸ਼ੀ ਦਾ ਆਕਾਰ"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"ਜ਼ੂਮ"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"ਦਰਮਿਆਨਾ"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# ਕੰਟਰੋਲ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ।}one{# ਕੰਟਰੋਲ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ।}other{# ਕੰਟਰੋਲ ਸ਼ਾਮਲ ਕੀਤੇ ਗਏ।}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"ਹਟਾਇਆ ਗਿਆ"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"ਕੀ <xliff:g id="APPNAME">%s</xliff:g> ਸ਼ਾਮਲ ਕਰਨਾ ਹੈ?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"ਜਦੋਂ ਤੁਸੀਂ <xliff:g id="APPNAME">%s</xliff:g> ਸ਼ਾਮਲ ਕਰਦੇ ਹੋ, ਤਾਂ ਇਹ ਇਸ ਪੈਨਲ ਵਿੱਚ ਕੰਟਰੋਲਾਂ ਅਤੇ ਸਮੱਗਰੀ ਨੂੰ ਸ਼ਾਮਲ ਕਰ ਸਕਦੀ ਹੈ। ਕੁਝ ਐਪਾਂ ਲਈ, ਤੁਸੀਂ ਇਹ ਚੁਣ ਸਕਦੇ ਹੋ ਕਿ ਇੱਥੇ ਕਿਹੜੇ ਕੰਟਰੋਲ ਦਿਸਣ।"</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"ਕੀ <xliff:g id="APPNAME">%s</xliff:g> ਲਈ ਕੰਟਰੋਲਾਂ ਨੂੰ ਹਟਾਉਣਾ ਹੈ?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"ਮਨਪਸੰਦ ਵਿੱਚ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"ਮਨਪਸੰਦ ਵਿੱਚ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ, ਸਥਾਨ <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ਮਨਪਸੰਦ ਵਿੱਚੋਂ ਹਟਾਇਆ ਗਿਆ"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ਹੋਰ"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"ਡੀਵਾਈਸ ਕੰਟਰੋਲਾਂ ਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"ਸ਼ਾਮਲ ਕਰੋ"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"ਹਟਾਓ"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ਵੱਲੋਂ ਸੁਝਾਇਆ ਗਿਆ"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"ਡੀਵਾਈਸ ਲਾਕ ਹੈ"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"ਕੀ ਲਾਕ ਸਕ੍ਰੀਨ ਤੋਂ ਡੀਵਾਈਸਾਂ ਨੂੰ ਦੇਖਣਾ ਅਤੇ ਕੰਟਰੋਲ ਕਰਨਾ ਹੈ?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"ਤੁਸੀਂ ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਆਪਣੇ ਬਾਹਰੀ ਡੀਵਾਈਸਾਂ ਲਈ ਕੰਟਰੋਲ ਸ਼ਾਮਲ ਕਰ ਸਕਦੇ ਹੋ।\n\nਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਮੌਜੂਦ ਐਪ ਤੁਹਾਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ ਜਾਂ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕੀਤੇ ਬਿਨਾਂ ਕੁਝ ਡੀਵਾਈਸਾਂ ਨੂੰ ਕੰਟਰੋਲ ਕਰਨ ਦੇ ਸਕਦੀ ਹੈ।\n\nਤੁਸੀਂ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਜਾ ਕੇ ਕਿਸੇ ਵੇਲੇ ਵੀ ਤਬਦੀਲੀਆਂ ਕਰ ਸਕਦੇ ਹੋ।"</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"ਕੀ ਲਾਕ ਸਕ੍ਰੀਨ ਤੋਂ ਡੀਵਾਈਸਾਂ ਨੂੰ ਕੰਟਰੋਲ ਕਰਨਾ ਹੈ?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"ਤੁਸੀਂ ਆਪਣੇ ਫ਼ੋਨ ਜਾਂ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕੀਤੇ ਬਿਨਾਂ ਕੁਝ ਡੀਵਾਈਸਾਂ ਨੂੰ ਕੰਟਰੋਲ ਕਰ ਸਕਦੇ ਹੋ।\n\nਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਮੌਜੂਦ ਐਪ ਇਹ ਨਿਰਧਾਰਿਤ ਕਰਦੀ ਹੈ ਕਿ ਇਸ ਤਰੀਕੇ ਨਾਲ ਕਿਹੜੇ ਡੀਵਾਈਸਾਂ ਨੂੰ ਕੰਟਰੋਲ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ।"</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"ਨਹੀਂ ਧੰਨਵਾਦ"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"ਹਾਂ"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"ਪਿੰਨ ਵਿੱਚ ਅੱਖਰ ਜਾਂ ਚਿੰਨ੍ਹ ਸ਼ਾਮਲ ਹਨ"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"ਕੰਟਰੋਲ ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"ਕੰਟਰੋਲਾਂ ਦਾ ਸੰਪਾਦਨ ਕਰੋ"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"ਐਪ ਸ਼ਾਮਲ ਕਰੋ"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"ਐਪ ਹਟਾਓ"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"ਆਊਟਪੁੱਟ ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"ਗਰੁੱਪ"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 ਡੀਵਾਈਸ ਨੂੰ ਚੁਣਿਆ ਗਿਆ"</string>
@@ -1111,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ \'ਤੇ ਜਾਓ"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"ਬੰਦ ਕਰੋ"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"ਲਾਕ ਸਕ੍ਰੀਨ ਸੈਟਿੰਗਾਂ"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ਵਾਈ-ਫਾਈ ਉਪਲਬਧ ਨਹੀਂ"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ਕੈਮਰਾ ਬਲਾਕ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ਕੈਮਰਾ ਅਤੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਬਲਾਕ ਕੀਤੇ ਗਏ"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਬਲਾਕ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ਤਰਜੀਹ ਮੋਡ ਚਾਲੂ ਹੈ"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant ਧਿਆਨ ਸੁਵਿਧਾ ਨੂੰ ਚਾਲੂ ਹੈ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 611e996..583259e 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Włącz USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Więcej informacji"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Zrzut ekranu"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Wyłączono Smart Lock"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"wysłano obraz"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Zapisywanie zrzutu ekranu..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Zapisuję zrzut ekranu w profilu służbowym…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Jeśli następnym razem podasz nieprawidłowy kod PIN, profil służbowy oraz powiązane z nim dane zostaną usunięte."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Jeśli następnym razem podasz nieprawidłowe hasło, profil służbowy oraz powiązane z nim dane zostaną usunięte."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Dotknij czytnika linii papilarnych"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikona odcisku palca"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nie rozpoznaję twarzy. Użyj odcisku palca."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Obszar powiadomień."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Szybkie ustawienia."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Szybkie ustawienia i obszar powiadomień."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Ekran blokady."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ekran blokady wyświetlany podczas działania"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Zamknij"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Powiększanie pełnego ekranu"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Powiększ część ekranu"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Przełącz"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Przeciągnij róg, aby zmienić rozmiar"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Zezwalaj na przewijanie poprzeczne"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Zmień rozmiar"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Lewy uchwyt"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Prawy uchwyt"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Dolny uchwyt"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Rozmiar powiększania"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Powiększenie"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Średni"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Dodano # element sterujący.}few{Dodano # elementy sterujące.}many{Dodano # elementów sterujących.}other{Dodano # elementu sterującego.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Usunięto"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Dodać aplikację <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Gdy dodasz aplikację <xliff:g id="APPNAME">%s</xliff:g>, będzie ona mogła dodawać elementy sterujące i treści do tego panelu. W niektórych aplikacjach można wybrać elementy sterujące, które się tu pojawią."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Usunąć elementy sterujące aplikacji <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Dodano do ulubionych"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Dodano do ulubionych, pozycja <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Usunięto z ulubionych"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Inne"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Dodaj do sterowania urządzeniami"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Dodaj"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Usuń"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Sugestia: <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Urządzenie zablokowane"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Pokazywać urządzenia i umożliwiać sterowanie nimi na ekranie blokady?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Możesz dodać do ekranu blokady elementy sterujące dotyczące urządzeń zewnętrznych.\n\nMożesz mieć możliwość sterowania niektórymi urządzeniami za pomocą aplikacji na telefonie lub tablecie bez odblokowywania tych urządzeń.\n\nW dowolnej chwili możesz wprowadzić zmiany w Ustawieniach."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Sterować urządzeniami na ekranie blokady?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Możesz sterować niektórymi urządzeniami bez odblokowywania telefonu lub tabletu.\n\nTo, którymi urządzeniami możesz sterować w ten sposób, określa aplikacja na urządzeniu."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Nie, dziękuję"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Tak"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Kod PIN zawiera litery lub symbole"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Dodaj elementy sterujące"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Edytuj elementy sterujące"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Dodaj aplikację"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Usuń aplikację"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Dodaj urządzenia wyjściowe"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupa"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Wybrano 1 urządzenie"</string>
@@ -1111,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Przełącz na profil służbowy"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Zamknij"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Ustawienia ekranu blokady"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Sieć Wi-Fi jest niedostępna"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera jest zablokowana"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera i mikrofon są zablokowane"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon jest zablokowany"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Tryb priorytetowy jest włączony"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Asystent jest aktywny"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 105031c..616e007 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Ativar USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Saiba mais"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Capturar tela"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"O Smart Lock foi desativado"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"enviou uma imagem"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Salvando captura de tela..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Salvando captura de tela no perfil de trabalho…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Se você informar um PIN incorreto na próxima tentativa, seu perfil de trabalho e os dados dele serão excluídos."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Se você informar uma senha incorreta na próxima tentativa, seu perfil de trabalho e os dados dele serão excluídos."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Toque no sensor de impressão digital"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ícone de impressão digital"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Não foi possível reconhecer o rosto Use a impressão digital."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Aba de notificações."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configurações rápidas."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configurações rápidas e aba de notificações."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Tela de bloqueio."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Tela de bloqueio de trabalho"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Fechar"</string>
@@ -408,7 +407,7 @@
     <string name="media_projection_action_text" msgid="3634906766918186440">"Iniciar agora"</string>
     <string name="empty_shade_text" msgid="8935967157319717412">"Sem notificações"</string>
     <string name="no_unseen_notif_text" msgid="395512586119868682">"Nenhuma notificação nova"</string>
-    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloqueie para conferir as notificações antigas"</string>
+    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloqueie p/ acessar notificações antigas"</string>
     <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo é gerenciado pelo seu familiar responsável"</string>
     <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Sua organização é dona deste dispositivo e pode monitorar o tráfego de rede"</string>
     <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"A organização <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> é dona deste dispositivo e pode monitorar o tráfego de rede"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ampliar toda a tela"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ampliar parte da tela"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Trocar"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Arraste o canto para redimensionar"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Permitir rolagem diagonal"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Redimensionar"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Alça esquerda"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Alça direita"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Alça de baixo"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Tamanho da lupa"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoom"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Médio"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# controle adicionado.}one{# controle adicionado.}many{# de controles adicionados.}other{# controles adicionados.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Removido"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Adicionar o app <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Quando você adiciona o app <xliff:g id="APPNAME">%s</xliff:g>, ele pode incluir controles e conteúdo neste painel. Em alguns casos, é possível escolher quais controles aparecem aqui."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Remover controles do app <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Adicionado como favorito"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Adicionado como favorito (posição <xliff:g id="NUMBER">%d</xliff:g>)"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Removido dos favoritos"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Outro"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Adicionar aos controles do dispositivo"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Adicionar"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Remover"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Sugerido por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Dispositivo bloq."</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Mostrar e controlar dispositivos na tela de bloqueio?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Você pode adicionar à tela de bloqueio controles para dispositivos externos.\n\nO app do dispositivo pode permitir que você controle alguns dispositivos sem desbloquear o smartphone ou tablet.\n\nÉ possível fazer mudanças a qualquer momento nas Configurações."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Controlar dispositivos na tela de bloqueio?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"É possível controle alguns dispositivos sem desbloquear o smartphone ou tablet.\n\nO app do dispositivo determina quais dispositivos podem ser controlados dessa maneira."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Agora não"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Sim"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"O PIN contém letras ou símbolos"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Adicionar controles"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Editar controles"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Adicionar app"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Remover o app"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Adicionar saídas"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo selecionado"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 8145483..c1fb700 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Ativar USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Saiba mais"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Captura de ecrã"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock desativado"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"enviou uma imagem"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"A guardar captura de ecrã..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"A guardar captura de ecrã no perfil de trabalho…"</string>
@@ -151,8 +152,8 @@
     <string name="biometric_dialog_tap_confirm_with_face_alt_3" msgid="2192670471930606539">"Rosto reconhecido. Prima ícone de desbloqueio para continuar"</string>
     <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Autenticado"</string>
     <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Usar PIN"</string>
-    <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Utilizar padrão"</string>
-    <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Utilizar palavra-passe"</string>
+    <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Usar padrão"</string>
+    <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Usar palavra-passe"</string>
     <string name="biometric_dialog_wrong_pin" msgid="1878539073972762803">"PIN incorreto."</string>
     <string name="biometric_dialog_wrong_pattern" msgid="8954812279840889029">"Padrão incorreto."</string>
     <string name="biometric_dialog_wrong_password" msgid="69477929306843790">"Palavra-passe incorreta."</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Se introduzir um PIN incorreto na tentativa seguinte, o seu perfil de trabalho e os respetivos dados serão eliminados."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Se introduzir uma palavra-passe incorreta na tentativa seguinte, o seu perfil de trabalho e os respetivos dados serão eliminados."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Toque no sensor de impressões digitais."</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ícone de impressão digital"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Impos. reconh. rosto. Utilize a impressão digital."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Painel de notificações."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Definições rápidas."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Definições rápidas e painel de notificações."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Ecrã de bloqueio."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ecrã de bloqueio de trabalho"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Fechar"</string>
@@ -737,7 +736,7 @@
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Ecrã de bloqueio"</string>
     <string name="thermal_shutdown_title" msgid="2702966892682930264">"Telem. deslig. devido ao calor"</string>
     <string name="thermal_shutdown_message" msgid="6142269839066172984">"O seu telemóvel já está a funcionar normalmente.\nToque para obter mais informações."</string>
-    <string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"O telemóvel estava muito quente, por isso desligou-se para arrefecer. Agora funciona normalmente.\n\nO telemóvel pode sobreaquecer se:\n	• Utilizar aplicações que utilizam mais recursos (jogos, vídeo ou aplicações de navegação)\n	• Transferir ou carregar ficheiros grandes\n	• Utilizar em altas temperaturas"</string>
+    <string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"O telemóvel estava muito quente, por isso desligou-se para arrefecer. Agora funciona normalmente.\n\nO telemóvel pode sobreaquecer se:\n	• Usar aplicações que utilizam mais recursos (jogos, vídeo ou aplicações de navegação)\n	• Transferir ou carregar ficheiros grandes\n	• Usar em altas temperaturas"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Veja os passos de manutenção"</string>
     <string name="high_temp_title" msgid="2218333576838496100">"O telemóvel está a aquecer"</string>
     <string name="high_temp_notif_message" msgid="1277346543068257549">"Algumas funcionalidades são limitadas enquanto o telemóvel arrefece.\nToque para obter mais informações."</string>
@@ -835,6 +834,7 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ampliar o ecrã inteiro"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ampliar parte do ecrã"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Mudar"</string>
+    <string name="magnification_open_settings_click_label" msgid="6151849212725923363">"Abrir definições de ampliação"</string>
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Arrastar o canto para redimensionar"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Permitir deslocamento da página na diagonal"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Redimensionar"</string>
@@ -844,6 +844,7 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Indicador esquerdo"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Indicador direito"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Indicador inferior"</string>
+    <string name="accessibility_magnification_settings_panel_description" msgid="8174187340747846953">"Definições de ampliação"</string>
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Tipo de lupa"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoom"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Médio"</string>
@@ -870,7 +871,8 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# controlo adicionado.}many{# controlos adicionados.}other{# controlos adicionados.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Removido"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Adicionar <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Quando adicionar a app <xliff:g id="APPNAME">%s</xliff:g>, esta pode adicionar controlos e conteúdos a este painel. Em algumas apps, pode escolher que controlos são apresentados aqui."</string>
+    <string name="controls_panel_authorization" msgid="4665218066461350247">"A app <xliff:g id="APPNAME">%s</xliff:g> pode escolher que controlos e conteúdos são apresentados aqui."</string>
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Remover controlos para a app <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Adicionado aos favoritos"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Adicionados aos favoritos, posição <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Removido dos favoritos"</string>
@@ -888,12 +890,13 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Outro"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Adicione aos controlos de dispositivos"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Adicionar"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Remover"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Sugerido por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Dispositivo bloq."</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Mostrar e controlar dispositivos a partir do ecrã de bloqueio?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Pode adicionar controlos para os seus dispositivos externos ao ecrã de bloqueio.\n\nA app do dispositivo pode permitir controlar alguns dispositivos sem desbloquear o seu telemóvel ou tablet.\n\nPode fazer alterações em qualquer altura nas Definições."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Controlar dispositivos a partir do ecrã de bloqueio?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Pode controlar alguns dispositivos sem desbloquear o seu telemóvel ou tablet.\n\nA app do dispositivo determina que dispositivos podem ser controlados desta forma."</string>
+    <string name="controls_settings_trivial_controls_dialog_message" msgid="397178734990952575">"Pode controlar alguns dispositivos sem desbloquear o seu telemóvel ou tablet. A app do dispositivo determina que dispositivos podem ser controlados desta forma."</string>
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Não"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Sim"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"O PIN contém letras ou símbolos."</string>
@@ -941,6 +944,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Adicionar controlos"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Editar controlos"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Adicionar app"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Remover app"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Adicione saídas"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo selecionado"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 105031c..616e007 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Ativar USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Saiba mais"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Capturar tela"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"O Smart Lock foi desativado"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"enviou uma imagem"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Salvando captura de tela..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Salvando captura de tela no perfil de trabalho…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Se você informar um PIN incorreto na próxima tentativa, seu perfil de trabalho e os dados dele serão excluídos."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Se você informar uma senha incorreta na próxima tentativa, seu perfil de trabalho e os dados dele serão excluídos."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Toque no sensor de impressão digital"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ícone de impressão digital"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Não foi possível reconhecer o rosto Use a impressão digital."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Aba de notificações."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configurações rápidas."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configurações rápidas e aba de notificações."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Tela de bloqueio."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Tela de bloqueio de trabalho"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Fechar"</string>
@@ -408,7 +407,7 @@
     <string name="media_projection_action_text" msgid="3634906766918186440">"Iniciar agora"</string>
     <string name="empty_shade_text" msgid="8935967157319717412">"Sem notificações"</string>
     <string name="no_unseen_notif_text" msgid="395512586119868682">"Nenhuma notificação nova"</string>
-    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloqueie para conferir as notificações antigas"</string>
+    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Desbloqueie p/ acessar notificações antigas"</string>
     <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo é gerenciado pelo seu familiar responsável"</string>
     <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Sua organização é dona deste dispositivo e pode monitorar o tráfego de rede"</string>
     <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"A organização <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> é dona deste dispositivo e pode monitorar o tráfego de rede"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ampliar toda a tela"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ampliar parte da tela"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Trocar"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Arraste o canto para redimensionar"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Permitir rolagem diagonal"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Redimensionar"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Alça esquerda"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Alça direita"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Alça de baixo"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Tamanho da lupa"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoom"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Médio"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# controle adicionado.}one{# controle adicionado.}many{# de controles adicionados.}other{# controles adicionados.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Removido"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Adicionar o app <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Quando você adiciona o app <xliff:g id="APPNAME">%s</xliff:g>, ele pode incluir controles e conteúdo neste painel. Em alguns casos, é possível escolher quais controles aparecem aqui."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Remover controles do app <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Adicionado como favorito"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Adicionado como favorito (posição <xliff:g id="NUMBER">%d</xliff:g>)"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Removido dos favoritos"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Outro"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Adicionar aos controles do dispositivo"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Adicionar"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Remover"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Sugerido por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Dispositivo bloq."</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Mostrar e controlar dispositivos na tela de bloqueio?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Você pode adicionar à tela de bloqueio controles para dispositivos externos.\n\nO app do dispositivo pode permitir que você controle alguns dispositivos sem desbloquear o smartphone ou tablet.\n\nÉ possível fazer mudanças a qualquer momento nas Configurações."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Controlar dispositivos na tela de bloqueio?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"É possível controle alguns dispositivos sem desbloquear o smartphone ou tablet.\n\nO app do dispositivo determina quais dispositivos podem ser controlados dessa maneira."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Agora não"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Sim"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"O PIN contém letras ou símbolos"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Adicionar controles"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Editar controles"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Adicionar app"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Remover o app"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Adicionar saídas"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 dispositivo selecionado"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 0303e64..7f531e7 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Activează USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Mai multe"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Captură de ecran"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock dezactivat"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"a trimis o imagine"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Se salvează captura de ecran..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Se salvează captura în profilul de serviciu…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Dacă la următoarea încercare introduci un cod PIN incorect, profilul de serviciu și datele sale vor fi șterse."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Dacă la următoarea încercare introduci o parolă incorectă, profilul de serviciu și datele sale vor fi șterse."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Atinge senzorul de amprente"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Pictograma amprentă"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Chipul nu a fost recunoscut. Folosește amprenta."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Fereastră pentru notificări."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Setări rapide."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Fereastră de Setări rapide și notificări."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Ecranul de blocare."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ecran de blocare pentru serviciu"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Închide"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Mărește tot ecranul"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Mărește o parte a ecranului"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Comutator"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Trage de colț pentru a redimensiona"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Permite derularea pe diagonală"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Redimensionează"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Ghidajul din stânga"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Ghidajul din dreapta"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Ghidajul de jos"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Dimensiunea lupei"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoom"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Mediu"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{S-a adăugat # comandă.}few{S-au adăugat # comenzi.}other{S-au adăugat # de comenzi.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Eliminată"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Adaugi <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Când adaugi <xliff:g id="APPNAME">%s</xliff:g>, aplicația poate să adauge comenzi și conținut pe acest panou. În anumite aplicații, poți să alegi comenzile care se afișează aici."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Elimini comenzile pentru <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Marcată ca preferată"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Marcată ca preferată, poziția <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"S-a anulat marcarea ca preferată"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Altul"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Adaugă la comenzile dispozitivelor"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Adaugă"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Exclude"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Sugerat de <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Dispozitiv blocat"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Afișezi și controlezi dispozitivele de pe ecranul de blocare?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Poți adăuga comenzi pentru dispozitivele externe pe ecranul de blocare.\n\nAplicația de pe dispozitiv îți poate permite să controlezi unele dispozitive fără să deblochezi telefonul.\n\nPoți face modificări oricând în setări."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Controlezi dispozitivele de pe ecranul de blocare?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Poți controla unele dispozitive fără să deblochezi telefonul sau tableta.\n\nAplicația de pe dispozitiv stabilește dispozitivele care pot fi controlate astfel."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Nu, mulțumesc"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Da"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Codul PIN conține litere sau simboluri"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Adaugă comenzi"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Editează comenzile"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Adaugă o aplicație"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Elimină aplicația"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Adaugă ieșiri"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grup"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"S-a selectat un dispozitiv"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 9a71eea..79f2abf 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Включить USB-порт"</string>
     <string name="learn_more" msgid="4690632085667273811">"Подробнее"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Скриншот"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Функция Smart Lock отключена."</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"отправлено изображение"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Сохранение..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Сохранение скриншота в рабочем профиле…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Если вы неправильно введете PIN-код ещё раз, ваш рабочий профиль и его данные будут удалены."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Если вы неправильно введете пароль ещё раз, ваш рабочий профиль и его данные будут удалены."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Прикоснитесь к сканеру отпечатков пальцев."</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Значок отпечатка пальца"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Не удалось распознать лицо. Используйте отпечаток."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Панель уведомлений"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Быстрые настройки"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Быстрые настройки и панель уведомлений."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Экран блокировки."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Заблокировано"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Закрыть"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Увеличение всего экрана"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Увеличить часть экрана"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Переключить"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Потяните за угол, чтобы изменить размер"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Разрешить прокручивать по диагонали"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Изменить размер"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Левый маркер"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Правый маркер"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Нижний маркер"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Размер лупы"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Масштаб"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Средняя"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Добавлен # элемент управления.}one{Добавлен # элемент управления.}few{Добавлено # элемента управления.}many{Добавлено # элементов управления.}other{Добавлено # элемента управления.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Удалено"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Добавить приложение \"<xliff:g id="APPNAME">%s</xliff:g>\"?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Приложение \"<xliff:g id="APPNAME">%s</xliff:g>\" может добавить на эту панель элементы управления и контент. Некоторые приложения позволяют выбирать, какие элементы будут здесь показаны."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Удалить приложение \"<xliff:g id="APPNAME">%s</xliff:g>\" с панели управления устройствами?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Добавлено в избранное"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Добавлено в избранное на позицию <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Не добавлено в избранное"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Другое"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Добавьте виджеты управления устройствами"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Добавить"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Удалить"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Предложено приложением \"<xliff:g id="APP">%s</xliff:g>\""</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Устройство заблокировано"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Разрешить показывать устройства и управлять ими на заблокированном экране?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Вы можете добавить элементы управления внешними устройствами на заблокированный экран.\n\nПриложение на вашем устройстве может разрешать управление некоторыми устройствами с заблокированного экрана.\n\nИзменить параметры можно в любое время в настройках."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Управлять устройствами на заблокированном экране?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Вы можете управлять некоторыми устройствами с заблокированного телефона или планшета.\n\nКакими именно устройствами можно управлять, зависит от приложения на вашем устройстве."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Не сейчас"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Да"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN-код содержит буквы или символы"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Добавить виджеты"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Изменить виджеты"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Добавить приложение"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Удалить приложение"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Добавление устройств вывода"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Группа"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Выбрано 1 устройство"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index ba04fab..92c9a3f 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USB සබල කරන්න"</string>
     <string name="learn_more" msgid="4690632085667273811">"තවත් දැන ගන්න"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"තිර රුව"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock අබලයි"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"රූපයක් එවන ලදී"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"තිර රුව සුරැකෙමින් පවතී…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"කාර්යාල පැතිකඩ වෙත තිර රුව සුරකිමින්…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"ඔබ ඊළඟ උත්සාහයේදී වැරදි PIN එකක් ඇතුළු කළහොත්, ඔබේ කාර්යාල පැතිකඩ සහ එහි දත්ත මකනු ඇත."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"ඔබ ඊළඟ උත්සාහයේදී වැරදි මුරපදයක් ඇතුළු කළහොත්, ඔබේ කාර්යාල පැතිකඩ සහ එහි දත්ත මකනු ඇත."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ඇඟිලි සලකුණු සංවේදකය ස්පර්ශ කරන්න"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"ඇඟිලි සලකුණු නිරූපකය"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"මුහුණ හැඳිනිය නොහැක. ඒ වෙනුවට ඇඟිලි සලකුණ භාවිත ක."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"දැනුම්දීම් ආවරණය."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ක්ෂණික සැකසීම්."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ඉක්මන් සැකසීම් සහ දැනුම්දීම් ඡායිතය."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"අගුළු තිරය."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"කාර්යාල අගුලු තිරය"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"වසන්න"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"පූර්ණ තිරය විශාලනය කරන්න"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"තිරයේ කොටසක් විශාලනය කරන්න"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"ස්විචය"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"ප්‍රමාණය වෙනස් කිරීමට කොන අදින්න"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"විකර්ණ අනුචලනයට ඉඩ දෙන්න"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"ප්‍රතිප්‍රමාණය කරන්න"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"වම් හසුරුව"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"දකුණු හසුරුව"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"පහළ හසුරුව"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"විශාලන තරම"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"විශාලනය කරන්න"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"මධ්‍යම"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# පාලනයක් එක් කර ඇත.}one{පාලන #ක් එක් කර ඇත.}other{පාලන #ක් එක් කර ඇත.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"ඉවත් කළා"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> එක් කරන්න ද?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"ඔබ <xliff:g id="APPNAME">%s</xliff:g> එක් කළ විට, එයට මෙම පැනලයට පාලන සහ අන්තර්ගතය එක් කළ හැක. සමහර යෙදුම්වල, ඔබට මෙහි පෙන්වන්නේ කුමන පාලන ද යන්න තෝරා ගැනීමට හැක."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> සඳහා පාලන ඉවත් කරන්න ද?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"ප්‍රියතම කළා"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"ප්‍රියතම කළා, තත්ත්ව <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ප්‍රියතම වෙතින් ඉවත් කළා"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"වෙනත්"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"උපාංග පාලන වෙත එක් කරන්න"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"එක් කරන්න"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"ඉවත් කරන්න"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"යෝජනා කළේ <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"උපාංගය අගුලු දමා ඇත"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"අගුලු තිරයෙන් උපාංග පෙන්වීම සහ පාලනය සිදු කරන්නද?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"ඔබට ඔබගේ බාහිර උපාංග සඳහා පාලන අගුලු තිරයට එක් කළ හැකිය.\n\nඔබගේ උපාංග යෙදුම ඔබගේ දුරකථනය හෝ ටැබ්ලටය අගුලු හැරීමෙන් තොරව සමහර උපාංග පාලනය කිරීමට ඉඩ ලබා දේ.\n\nඔබට සැකසීම් තුළ ඕනෑම වේලාවක වෙනස් කිරීම් සිදු කළ හැකිය."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"අගුලු තිරයෙන් උපාංග පාලනය කරන්නද?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"ඔබගේ දුරකථනය හෝ ටැබ්ලටය අගුලු හැරීමෙන් තොරව ඔබට සමහර උපාංග පාලනය කළ හැකිය.\n\nඔබගේ උපාංග යෙදුම මේ ආකාරයෙන් පාලනය කළ හැකි උපාංග තීරණය කරයි."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"එපා ස්තුතියි"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"ඔව්"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN හි අකුරු හෝ සංකේත අඩංගු වේ"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"පාලන එක් කරන්න"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"පාලන සංස්කරණය කරන්න"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"යෙදුම එක් කරන්න"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"යෙදුම ඉවත් කරන්න"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"ප්‍රතිදාන එක් කරන්න"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"සමූහය"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"උපාංග 1ක් තෝරන ලදී"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 36058de..090a82b 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Povoliť USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Ďalšie informácie"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Snímka obrazovky"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Funkcia Smart Lock je deaktivovaná"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"odoslal(a) obrázok"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Prebieha ukladanie snímky obrazovky..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Ukladá sa snímka obrazovky do pracovného profilu…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Ak pri ďalšom pokuse zadáte nesprávny PIN, váš pracovný profil a jeho dáta budú odstránené."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Ak pri ďalšom pokuse zadáte nesprávne heslo, váš pracovný profil a jeho dáta budú odstránené."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Dotknite sa senzora odtlačkov prstov"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikona odtlačku prsta"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Tvár sa nedá rozpoznať. Použite odtlačok prsta."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Panel upozornení."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Rýchle nastavenia."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Rýchle nastavenia a panel upozornení"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Uzamknutá obrazovka"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Uzamknutá obrazovka pracovného profilu"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Zavrieť"</string>
@@ -408,7 +407,7 @@
     <string name="media_projection_action_text" msgid="3634906766918186440">"Spustiť"</string>
     <string name="empty_shade_text" msgid="8935967157319717412">"Žiadne upozornenia"</string>
     <string name="no_unseen_notif_text" msgid="395512586119868682">"Žiadne nové upozornenia"</string>
-    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Odomknutím si zobrazte staršie upozor."</string>
+    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Odomknutím zobrazíte staršie upozornenia"</string>
     <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Toto zariadenie spravuje tvoj rodič"</string>
     <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Vaša organizácia spravuje toto zariadenie a môže sledovať sieťovú premávku"</string>
     <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> vlastní toto zariadenie a môže sledovať sieťovú premávku"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Zväčšenie celej obrazovky"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Zväčšiť časť obrazovky"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Prepnúť"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Veľkosť zmeníte presunutím rohu"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Povoliť diagonálne posúvanie"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Zmeniť veľkosť"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Ľavá rukoväť"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Pravá rukoväť"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Dolná rukoväť"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Veľkosť zväčšenia"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Lupa"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Stredný"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Bol pridaný # ovládací prvok.}few{Boli pridané # ovládacie prvky.}many{# controls added.}other{Bolo pridaných # ovládacích prvkov.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Odstránené"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Chcete pridať aplikáciu <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Keď pridáte aplikáciu <xliff:g id="APPNAME">%s</xliff:g>, bude môcť pridať ovládanie a obsah na tento panel. V prípade niektorých aplikácií môžete vybrať, ktoré ovládacie prvky sa tu majú zobraziť."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Chcete odstrániť ovládanie aplikácie <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Pridané medzi obľúbené"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Pridané medzi obľúbené, pozícia <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Odstránené z obľúbených"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Iné"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Pridanie do ovládania zariadení"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Pridať"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Odstrániť"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Navrhuje <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Uzamknuté zariadenie"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Chcete zobrazovať a ovládať zariadenia na uzamknutej obrazovke?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Na uzamknutú obrazovku si môžete pridať ovládanie externých zariadení.\n\nAplikácia zariadenia vám môže umožniť ovládať niektoré zariadenia bez odomknutia telefónu či tabletu.\n\nZmeny môžete vykonať kedykoľvek v Nastaveniach."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Chcete ovládať zariadenia na uzamknutej obrazovke?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Niektoré zariadenia môžete ovládať bez odomknutia telefónu či tabletu.\n\nAplikácia zariadenia určuje, ktoré zariadenia sa dajú týmto spôsobom ovládať."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Nie, vďaka"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Áno"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN obsahuje písmená či symboly"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Pridať ovládače"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Upraviť ovládače"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Pridať aplikáciu"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Odstrániť aplikáciu"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Pridanie výstupov"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Skupina"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 vybrané zariadenie"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index f4ae067..84fd7c5 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Omogoči USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Več o tem"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Posnetek zaslona"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Storitev Smart Lock je onemogočena."</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"je poslal(-a) sliko"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Shranjevanje posnetka zaslona ..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Shranjevanje posnetka zaslona v delovni profil …"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Če pri naslednjem poskusu vnesete napačno kodo PIN, bodo delovni profil in podatki v njem izbrisani."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Če pri naslednjem poskusu vnesete napačno geslo, bodo delovni profil in podatki v njem izbrisani."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Dotaknite se tipala prstnih odtisov"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikona prstnih odtisov"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Obraza ni mogoče prepoznati. Uporabite prstni odtis."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Zaslon z obvestili."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Hitre nastavitve."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Hitre nastavitve in zaslon z obvestili"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Zaklenjen zaslon"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Zaklenjen zaslon delovnega profila"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Zapri"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Povečanje celotnega zaslona"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Povečava dela zaslona"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Stikalo"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Povlecite vogal, da spremenite velikost."</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Dovoli diagonalno pomikanje"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Spremeni velikost"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Ročica levo"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Ročica desno"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Ročica spodaj"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Velikost povečevalnika"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Povečava/pomanjšava"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Srednja"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kontrolnik je dodan.}one{# kontrolnik je dodan.}two{# kontrolnika sta dodana.}few{# kontrolniki so dodani.}other{# kontrolnikov je dodanih.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Odstranjeno"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Želite dodati aplikacijo <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Ko dodate aplikacijo <xliff:g id="APPNAME">%s</xliff:g>, lahko ta doda kontrolnike in vsebino v to podokno. V nekaterih aplikacijah lahko izberete, kateri kontrolniki so prikazani tukaj."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Želite odstraniti kontrolnike za aplikacijo <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Dodano med priljubljene"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Dodano med priljubljene, položaj <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Odstranjeno iz priljubljenih"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Drugo"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Dodajanje med kontrolnike naprave"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Dodaj"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Odstrani"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Predlagala aplikacija <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Naprava je zaklenjena"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Želite prikazati in upravljati naprave na zaklenjenem zaslonu?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Kontrolnike za zunanje naprave lahko dodate na zaklenjen zaslon.\n\nAplikacija v napravi vam bo morda omogočala upravljanje nekaterih naprav brez odklepanja telefona ali tabličnega računalnika.\n\nTe spremembe lahko kadar koli izvedete v nastavitvah."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Želite upravljati naprave na zaklenjenem zaslonu?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Nekatere naprave lahko upravljate brez odklepanja telefona ali tabličnega računalnika.\n\nAplikacija v napravi določa, katere naprave je mogoče upravljati na ta način."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Ne, hvala"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Da"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Koda PIN vsebuje črke ali simbole"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Dodajte kontrolnike"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Uredite kontrolnike"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Dodaj aplikacijo"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Odstrani aplikacijo"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Dodajanje izhodov"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Skupina"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Izbrana je ena naprava"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index f69221a..4cf4346 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Aktivizo USB-në"</string>
     <string name="learn_more" msgid="4690632085667273811">"Mëso më shumë"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Pamja e ekranit"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock është çaktivizuar"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"dërgoi një imazh"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Po ruan pamjen e ekranit…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Pamja e ekranit po ruhet te profili i punës…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Nëse fut një kod PIN të pasaktë në tentativën tjetër, profili yt i punës dhe të dhënat e tij do të fshihen."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Nëse fut një fjalëkalim të pasaktë në tentativën tjetër, profili yt i punës dhe të dhënat e tij do të fshihen."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Prek sensorin e gjurmës së gishtit"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikona e gjurmës së gishtit"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nuk mund ta dallojë fytyrën. Përdor më mirë gjurmën e gishtit."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Streha e njoftimeve."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Cilësimet e shpejta."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"\"Cilësimet e shpejta\" dhe \"Streha e njoftimeve\"."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Ekrani i kyçjes."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ekrani i kyçjes së punës"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Mbylle"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Zmadho ekranin e plotë"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Zmadho një pjesë të ekranit"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Ndërro"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Zvarrit këndin për të ndryshuar përmasat"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Lejo lëvizjen diagonale"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Ndrysho përmasat"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Doreza e majtë"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Doreza e djathtë"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Doreza e poshtme"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Përmasa e zmadhimit"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zmadho"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Mesatar"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{U shtua # kontroll.}other{U shtuan # kontrolle.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"E hequr"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Të shtohet <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Kur shton <xliff:g id="APPNAME">%s</xliff:g>, ai mund t\'i shtojë kontrolle dhe përmbajtje këtij paneli. Në disa aplikacione, mund të zgjedhësh se cilat kontrolle shfaqen këtu."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Të hiqen kontrollet për <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"E shtuar te të preferuarat"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"E shtuar te të preferuarat, pozicioni <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"E hequr nga të preferuarat"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Tjetër"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Shto te kontrollet e pajisjes"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Shto"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Hiq"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Sugjeruar nga <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Pajisja është e kyçur"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Të shfaqen dhe të kontrollohen pajisjet nga ekrani i kyçjes?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Mund të shtosh kontrolle për pajisjet e tua të jashtme në ekranin e kyçjes.\n\nAplikacioni në pajisjen tënde mund të të lejojë të kontrollosh disa pajisje pa shkyçur telefonin apo tabletin.\n\nMund të bësh ndryshime në çdo kohë te \"Cilësimet\"."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Të kontrollohen pajisjet nga ekrani i kyçjes?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Mund të kontrollosh disa pajisje pa shkyçur telefonin apo tabletin.\n\nAplikacioni në pajisjen tënde përcakton se cilat pajisje mund të kontrollohen në këtë mënyrë."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Jo, faleminderit"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Po"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Kodi PIN përmban shkronja ose simbole"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Shto kontrollet"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Modifiko kontrollet"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Shto një aplikacion"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Hiqe aplikacionin"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Shto daljet"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupi"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 pajisje e zgjedhur"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index fb4f455..987f5f5 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Омогући USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Сазнајте више"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Снимак екрана"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock је онемогућен"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"је послао/ла слику"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Чување снимка екрана..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Снимак екрана се чува на пословном профилу…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Ако унесете нетачан PIN при следећем покушају, избрисаћемо пословни профил и његове податке."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Ако унесете нетачну лозинку при следећем покушају, избрисаћемо пословни профил и његове податке."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Додирните сензор за отисак прста"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Икона отиска прста"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Лице није препознато. Користите отисак прста."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -407,7 +407,7 @@
     <string name="media_projection_action_text" msgid="3634906766918186440">"Започни"</string>
     <string name="empty_shade_text" msgid="8935967157319717412">"Нема обавештења"</string>
     <string name="no_unseen_notif_text" msgid="395512586119868682">"Нема нових обавештења"</string>
-    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Откључајте да видите старија обавештења"</string>
+    <string name="unlock_to_see_notif_text" msgid="7439033907167561227">"Откључајте за старија обавештења"</string>
     <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Овим уређајем управља родитељ"</string>
     <string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Организација је власник уређаја и може да надгледа мрежни саобраћај"</string>
     <string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> је власник овог уређаја и може да надгледа мрежни саобраћај"</string>
@@ -834,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Увећајте цео екран"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Увећајте део екрана"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Пређи"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Превуците угао да бисте променили величину"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Дозволи дијагонално скроловање"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Промени величину"</string>
@@ -843,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Лева ручица"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Десна ручица"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Доња ручица"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Величина лупе"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Зумирање"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Средње"</string>
@@ -869,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# контрола је додата.}one{# контрола је додата.}few{# контроле су додате.}other{# контрола је додато.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Уклоњено"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Желите ли да додате <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Када додате апликацију <xliff:g id="APPNAME">%s</xliff:g>, она може да додаје контроле и садржај у ово окно. У неким апликацијама можете да изаберете које ће се контроле овде приказивати."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Желите да уклоните контроле за <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Означено је као омиљено"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Означено је као омиљено, <xliff:g id="NUMBER">%d</xliff:g>. позиција"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Уклоњено је из омиљених"</string>
@@ -887,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Друго"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Додајте у контроле уређаја"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Додај"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Уклони"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Предлаже <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Уређај је закључан"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Желите ли да приказујете и контролишете уређаје са закључаног екрана?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Можете да додате контроле за спољне уређаје на закључани екран.\n\nАпликација на уређају може да вам омогући да контролишете неке уређаје без откључавања телефона или таблета.\n\nТо можете да промените кад год желите у Подешавањима."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Желите ли да контролишете уређаје са закључаног екрана?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Неке уређаје можете да контролишете без откључавања телефона или таблета.\n\nАпликација на уређају одређује који уређаји могу да се контролишу на овај начин."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Не, хвала"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Да"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN садржи слова или симболе"</string>
@@ -940,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Додај контроле"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Измени контроле"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Додај апликацију"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Уклони апликацију"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Додајте излазе"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Група"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Изабран је 1 уређај"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 19e5952..bffb743 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Aktivera USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Läs mer"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Skärmbild"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock har inaktiverats"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"har skickat en bild"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Skärmbilden sparas ..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Sparar skärmbild i jobbprofilen …"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Jobbprofilen och dess data raderas om du anger fel pinkod vid nästa försök."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Din jobbprofil och dess data raderas om du anger fel lösenord vid nästa försök."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Tryck på fingeravtryckssensorn"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Ikon för fingeravtryck"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ansiktet kändes inte igen. Använd fingeravtryck."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Meddelandepanel."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Snabbinställningar."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Snabbinställningar och meddelandepanel."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Låsskärm."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Låsskärm för arbete"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Stäng"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Förstora hela skärmen"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Förstora en del av skärmen"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Reglage"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Dra i hörnet för att ändra storlek"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Tillåt diagonal scrollning"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Ändra storlek"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Vänster handtag"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Höger handtag"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Nedre handtag"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Förstoringsstorlek"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoom"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Medel"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kontroll har lagts till.}other{# kontroller har lagts till.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Har tagits bort"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Vill du lägga till <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"När du lägger till <xliff:g id="APPNAME">%s</xliff:g> kan den lägga till kontroller och innehåll i den här panelen. I vissa appar kan du styra vilka kontroller som visas här."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Vill du ta bort inställningarna för <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Har lagts till som favorit"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Har lagts till som favorit, plats <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Har tagits bort från favoriter"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Övrigt"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Lägg till i enhetsstyrning"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Lägg till"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Ta bort"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Förslag från <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Enheten är låst"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Vill du se och styra enheter på låsskärmen?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Du kan lägga till reglage att styra externa enheter med på låsskärmen.\n\nVissa enheter kan gå att styra med appen på enheten utan att du behöver låsa upp telefonen eller surfplattan.\n\nDu kan när som helst ändra detta i inställningarna."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Vill du styra enheter på låsskärmen?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Du kan styra vissa enheter utan att låsa upp telefonen eller surfplattan.\n\nVilka enheter som går att styra på det här sättet beror på appen på enheten."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Nej tack"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ja"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Pinkoden innehåller bokstäver eller symboler"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Lägg till snabbkontroller"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Redigera snabbkontroller"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Lägg till app"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Ta bort app"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Lägg till utgångar"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupp"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 enhet har valts"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 1cfa514..269d0a7 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Washa kipengele cha USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Pata maelezo zaidi"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Picha ya skrini"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Kipengele cha Smart Lock kimezimwa"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"imetuma picha"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Inahifadhi picha ya skrini..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Inahifadhi picha ya skrini kwenye wasifu wa kazini…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Ukiweka PIN isiyo sahihi utakapojaribu tena, wasifu wako wa kazini utafutwa pamoja na data yake."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Ukiweka nenosiri lisilo sahihi utakapojaribu tena, wasifu wako wa kazini utafutwa pamoja na data yake."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Gusa kitambua alama ya kidole"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Aikoni ya alama ya kidole"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Imeshindwa kutambua uso. Tumia alama ya kidole."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Kivuli cha arifa."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Mipangilio ya haraka."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Mipangilio ya haraka na Sehemu ya arifa."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Skrini iliyofungwa."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Skrini iliyofungwa ya kazini"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Funga"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Kuza skrini nzima"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Kuza sehemu ya skrini"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Swichi"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Buruta kona ili ubadilishe ukubwa"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Ruhusu usogezaji wa kimshazari"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Badilisha ukubwa"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Ncha ya kushoto"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Ncha ya kulia"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Ncha ya chini"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Ukubwa wa kikuzaji"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Kuza"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Wastani"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Umeweka kidhibiti #.}other{Umeweka vidhibiti #.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Kimeondolewa"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Ungependa kuweka <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Unapoweka <xliff:g id="APPNAME">%s</xliff:g>, inaweza kuweka vidhibiti na maudhui kwenye kidirisha hiki. Katika baadhi ya programu, unaweza kuchagua ni vidhibiti vipi vionekane hapa."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Ungependa kuondoa vidhibiti vya <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Kimewekwa kwenye vipendwa"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Kimewekwa kwenye vipendwa, nafasi ya <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Kimeondolewa kwenye vipendwa"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Nyingine"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Weka kwenye vidhibiti vya vifaa"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Weka"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Ondoa"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Kimependekezwa na <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Kifaa kimefungwa"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Ungependa kuonyesha na udhibiti vifaa kwenye skrini iliyofungwa?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Unaweza kuweka vidhibiti kwa ajili ya vifaa vyako vya nje kwenye skrini iliyofungwa.\n\nProgramu ya kifaa chako huenda ikakuruhusu udhibiti baadhi ya vifaa bila kufungua simu au kompyuta kibao yako.\n\nUnaweza kufanya mabadiliko muda wowote kwenye Mipangilio."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Ungependa kudhibiti vifaa kwenye skrini iliyofungwa?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Unaweza kudhibiti baadhi ya vifaa bila kufungua simu au kompyuta kibao yako.\n\nProgramu ya kifaa chako hubainisha ni vifaa vipi vinaweza kudhibitiwa kwa njia hii."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Hapana"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ndiyo"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN ina herufi au alama"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Weka vidhibiti"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Badilisha vidhibiti"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Weka programu"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Ondoa programu"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Weka vifaa vya kutoa sauti"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Kikundi"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Umechagua kifaa 1"</string>
@@ -1111,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Tumia wasifu wa kazini"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Funga"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Mipangilio ya skrini iliyofungwa"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi haipatikani"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera imezuiwa"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera na maikrofoni zimezuiwa"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Maikrofoni imezuiwa"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Hali ya kipaumbele imewashwa"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Programu ya Mratibu imewashwa"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 7cd1470..59becc6 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -87,4 +87,7 @@
 
     <!-- Biometric Auth pattern view size, better to align keyguard_security_width -->
     <dimen name="biometric_auth_pattern_view_size">348dp</dimen>
+
+    <dimen name="controls_header_horizontal_padding">12dp</dimen>
+    <dimen name="controls_content_margin_horizontal">24dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-sw720dp-h1000dp/dimens.xml b/packages/SystemUI/res/values-sw720dp-h1000dp/dimens.xml
index b98165f..ca62d28 100644
--- a/packages/SystemUI/res/values-sw720dp-h1000dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp-h1000dp/dimens.xml
@@ -21,6 +21,6 @@
     <!-- Space between status view and notification shelf -->
     <dimen name="keyguard_status_view_bottom_margin">70dp</dimen>
     <dimen name="keyguard_clock_top_margin">80dp</dimen>
-    <dimen name="bouncer_user_switcher_view_mode_user_switcher_bottom_margin">186dp</dimen>
-    <dimen name="bouncer_user_switcher_view_mode_view_flipper_bottom_margin">110dp</dimen>
+    <dimen name="bouncer_user_switcher_view_mode_user_switcher_bottom_margin">155dp</dimen>
+    <dimen name="bouncer_user_switcher_view_mode_view_flipper_bottom_margin">85dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-sw720dp-land/dimens.xml b/packages/SystemUI/res/values-sw720dp-land/dimens.xml
index 9ed9360..8583f05 100644
--- a/packages/SystemUI/res/values-sw720dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp-land/dimens.xml
@@ -37,6 +37,8 @@
     <dimen name="qs_media_rec_album_size">112dp</dimen>
     <dimen name="qs_media_rec_album_side_margin">16dp</dimen>
 
+    <dimen name="controls_panel_corner_radius">40dp</dimen>
+
     <dimen name="lockscreen_shade_max_over_scroll_amount">42dp</dimen>
 
     <!-- Roughly the same distance as media on LS to media on QS. We will translate by this value
diff --git a/packages/SystemUI/res/values-sw720dp-port/dimens.xml b/packages/SystemUI/res/values-sw720dp-port/dimens.xml
index 8b41a44..9248d58 100644
--- a/packages/SystemUI/res/values-sw720dp-port/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp-port/dimens.xml
@@ -33,5 +33,7 @@
      side -->
     <dimen name="qs_tiles_page_horizontal_margin">60dp</dimen>
 
+    <dimen name="controls_panel_corner_radius">46dp</dimen>
+
     <dimen name="notification_section_divider_height">16dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-sw720dp/dimens.xml b/packages/SystemUI/res/values-sw720dp/dimens.xml
index 8f59df6..2086459 100644
--- a/packages/SystemUI/res/values-sw720dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp/dimens.xml
@@ -19,7 +19,8 @@
     <!-- gap on either side of status bar notification icons -->
     <dimen name="status_bar_icon_padding">1dp</dimen>
 
-    <dimen name="controls_padding_horizontal">40dp</dimen>
+    <dimen name="controls_header_horizontal_padding">28dp</dimen>
+    <dimen name="controls_content_margin_horizontal">40dp</dimen>
 
     <dimen name="large_screen_shade_header_height">56dp</dimen>
 
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index f62029a..ba38c98 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USBயை இயக்கு"</string>
     <string name="learn_more" msgid="4690632085667273811">"மேலும் அறிக"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ஸ்கிரீன்ஷாட்"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock முடக்கப்பட்டது"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"படம் அனுப்பப்பட்டது"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ஸ்க்ரீன் ஷாட்டைச் சேமிக்கிறது…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"பணிக் கணக்கில் ஸ்கிரீன்ஷாட் சேமிக்கப்படுகிறது…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"அடுத்த முறை தவறான பின்னை உள்ளிட்டால் உங்கள் பணிக் கணக்கும் அதன் தரவும் நீக்கப்படும்."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"அடுத்த முறை தவறான கடவுச்சொல்லை உள்ளிட்டால் உங்கள் பணிக் கணக்கும் அதன் தரவும் நீக்கப்படும்."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"கைரேகை சென்சாரைத் தொடவும்"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"கைரேகை ஐகான்"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"முகத்தை அடையாளம் காண முடியவில்லை. கைரேகையைப் பயன்படுத்தவும்."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"அறிவிப்பு விவரம்."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"உடனடி அமைப்பு."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"விரைவு அமைப்புகளும் அறிவிப்பு விவரமும்."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"லாக் ஸ்கிரீன்."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"பணி லாக் ஸ்கிரீன்"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"மூடு"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"முழுத்திரையைப் பெரிதாக்கும்"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"திரையின் ஒரு பகுதியைப் பெரிதாக்கும்"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"ஸ்விட்ச்"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"அளவை மாற்ற மூலையை இழுக்கவும்"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"குறுக்கே ஸ்க்ரோல் செய்வதை அனுமதி"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"அளவை மாற்று"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"இடது ஹேண்டில்"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"வலது ஹேண்டில்"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"கீழ்ப்புற ஹேண்டில்"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"பெரிதாக்கும் கருவியின் அளவு"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"அளவை மாற்று"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"நடுத்தரமானது"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# கட்டுப்பாடு சேர்க்கப்பட்டது.}other{# கட்டுப்பாடுகள் சேர்க்கப்பட்டன.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"அகற்றப்பட்டது"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> ஆப்ஸைச் சேர்க்கவா?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"இந்தப் பேனலில் <xliff:g id="APPNAME">%s</xliff:g> ஆப்ஸைச் சேர்க்கும்போது கட்டுப்பாடுகளையும் உள்ளடக்கத்தையும் அது சேர்க்கலாம். இருப்பினும், சில ஆப்ஸில் எந்தெந்தக் கட்டுப்பாடுகள் இங்கே காட்டப்பட வேண்டும் என்பதை நீங்களே தேர்வுசெய்யலாம்."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> ஆப்ஸுக்கான கட்டுப்பாடுகளை அகற்றவா?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"பிடித்தவற்றில் சேர்க்கப்பட்டது"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"பிடித்தவற்றில் சேர்க்கப்பட்டது, நிலை <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"பிடித்தவற்றிலிருந்து நீக்கப்பட்டது"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"பிற"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"சாதனக் கட்டுப்பாடுகளில் சேர்த்தல்"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"சேர்"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"அகற்று"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ஆப்ஸால் பரிந்துரைக்கப்பட்டது"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"சாதனம் பூட்டப்பட்டது"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"பூட்டுத் திரையிலிருந்தே சாதனங்களைப் பார்க்கவும் கட்டுப்படுத்தவும் அனுமதிக்கவா?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"வெளிப்புறச் சாதனங்களுக்கான கட்டுப்பாடுகளை உங்கள் பூட்டுத் திரையில் சேர்க்கலாம்.\n\nஉங்கள் மொபைலையோ டேப்லெட்டையோ அன்லாக் செய்யாமலேயே சில சாதனங்களைக் கட்டுப்படுத்த சாதன ஆப்ஸ் உங்களை அனுமதிக்கக்கூடும்.\n\nஅமைப்புகளுக்குச் சென்று எப்போது வேண்டுமானாலும் மாற்றங்களைச் செய்யலாம்."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"பூட்டுத் திரையிலிருந்தே சாதனங்களைக் கட்டுப்படுத்தவா?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"உங்கள் மொபைலையோ டேப்லெட்டையோ அன்லாக் செய்யாமலேயே சில சாதனங்களை நீங்கள் கட்டுப்படுத்தலாம்.\n\nஎந்தெந்தச் சாதனங்களை இவ்வாறு கட்டுப்படுத்தலாம் என்பதை உங்கள் சாதன ஆப்ஸ் தீர்மானிக்கும்."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"வேண்டாம்"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"ஆம்"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"பின்னில் எழுத்துகள் அல்லது குறிகள் உள்ளன"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"கட்டுப்பாடுகளைச் சேர்த்தல்"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"கட்டுப்பாடுகளை மாற்றுதல்"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"ஆப்ஸைச் சேர்"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"ஆப்ஸை அகற்று"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"அவுட்புட்களைச் சேர்த்தல்"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"குழு"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 சாதனம் தேர்ந்தெடுக்கப்பட்டுள்ளது"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index a29df59..4e0e625 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USBని ప్రారంభించండి"</string>
     <string name="learn_more" msgid="4690632085667273811">"మరింత తెలుసుకోండి"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"స్క్రీన్‌షాట్"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock డిజేబుల్ చేయబడింది"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ఇమేజ్‌ను పంపారు"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"స్క్రీన్‌షాట్‌ను సేవ్ చేస్తోంది…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"స్క్రీన్‌షాట్‌ను వర్క్ ప్రొఫైల్‌కు సేవ్ చేస్తోంది…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"మీరు ఒకవేళ తర్వాతి ప్రయత్నంలో తప్పు పిన్‌ను ఎంటర్ చేస్తే, మీ కార్యాలయ ప్రొఫైల్, అలాగే దాని డేటా తొలగించబడతాయి."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"మీరు ఒకవేళ తర్వాతి ప్రయత్నంలో తప్పు పాస్‌వర్డ్‌ను ఎంటర్ చేస్తే, మీ కార్యాలయ ప్రొఫైల్, అలాగే దాని డేటా తొలగించబడతాయి."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"వేలిముద్ర సెన్సార్‌ను తాకండి"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"వేలిముద్ర చిహ్నం"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ముఖం గుర్తించలేము. బదులుగా వేలిముద్ర ఉపయోగించండి."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"నోటిఫికేషన్ షేడ్."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"శీఘ్ర సెట్టింగ్‌లు."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"క్విక్ సెట్టింగ్‌లు, నోటిఫికేషన్ తెర."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"లాక్ స్క్రీన్."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"కార్యాలయ లాక్ స్క్రీన్"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"మూసివేస్తుంది"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ఫుల్ స్క్రీన్‌ను మ్యాగ్నిఫై చేయండి"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"స్క్రీన్‌లో భాగాన్ని మ్యాగ్నిఫై చేయండి"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"స్విచ్ చేయి"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"సైజ్ మార్చడానికి మూలను లాగండి"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"వికర్ణ స్క్రోలింగ్‌ను అనుమతించండి"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"సైజ్ మార్చండి"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"ఎడమవైపు హ్యాండిల్"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"కుడివైపు హ్యాండిల్"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"కింద హ్యాండిల్"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"మాగ్నిఫయర్ సైజ్"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"జూమ్ చేయండి"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"మధ్యస్థం"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# కంట్రోల్ జోడించబడింది.}other{# కంట్రోల్స్ జోడించబడ్డాయి.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"తీసివేయబడింది"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g>ను జోడించాలా?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"మీరు <xliff:g id="APPNAME">%s</xliff:g>ను జోడించినప్పుడు, ఇది ఈ ప్యానెల్‌కు కంట్రోల్స్‌ని, కంటెంట్‌ను జోడించగలదు. కొన్ని యాప్‌లలో, ఇక్కడ ఏయే కంట్రోల్స్ కనిపించాలో మీరు ఎంచుకోవచ్చు."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> కోసం కంట్రోల్స్‌ను తీసివేయాలా?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"ఇష్టమైనదిగా గుర్తు పెట్టబడింది"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"<xliff:g id="NUMBER">%d</xliff:g>వ స్థానంలో ఇష్టమైనదిగా గుర్తు పెట్టబడింది"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ఇష్టమైనదిగా పెట్టిన గుర్తు తీసివేయబడింది"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"ఇతరం"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"పరికరం నియంత్రణలకు జోడించడం"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"జోడించండి"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"తీసివేయండి"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> ద్వారా సూచించబడింది"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"పరికరంలాక్ చేయబడింది"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"లాక్ స్క్రీన్ నుండి పరికరాలను చూపించాలా, కంట్రోల్ చేయాలా?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"మీరు లాక్ స్క్రీన్‌కు మీ బాహ్య పరికరాల కోసం కంట్రోల్స్‌ను జోడించవచ్చు.\n\nమీ ఫోన్ లేదా టాబ్లెట్‌ను అన్‌లాక్ చేయకుండానే కొన్ని పరికరాలను కంట్రోల్ చేయడానికి మీ పరికర యాప్ మిమ్మల్ని అనుమతించవచ్చు.\n\nమీరు సెట్టింగ్‌లలో ఎప్పుడైనా మార్పులు చేయవచ్చు."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"లాక్ స్క్రీన్ నుండి పరికరాలను కంట్రోల్ చేయాలా?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"మీరు మీ ఫోన్ లేదా టాబ్లెట్‌ను అన్‌లాక్ చేయకుండానే కొన్ని పరికరాలను కంట్రోల్ చేయవచ్చు.\n\nమీ పరికర యాప్ \'ఈ విధంగా ఏ పరికరాలను కంట్రోల్ చేయవచ్చు\' అని నిర్ణయిస్తుంది."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"వద్దు, ధన్యవాదాలు"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"అవును"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"పిన్ అక్షరాలను లేదా చిహ్నాలను కలిగి ఉంది"</string>
@@ -935,12 +942,13 @@
     <string name="controls_error_removed" msgid="6675638069846014366">"కనుగొనబడలేదు"</string>
     <string name="controls_error_removed_title" msgid="1207794911208047818">"కంట్రోల్ అందుబాటులో లేదు"</string>
     <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g>ను యాక్సెస్ చేయడం సాధ్యపడలేదు. <xliff:g id="APPLICATION">%2$s</xliff:g> యాప్‌ను చెక్ చేసి, కంట్రోల్ ఇప్పటికీ అందుబాటులో ఉందని, యాప్ సెట్టింగ్‌లు మారలేదని నిర్ధారించుకోండి."</string>
-    <string name="controls_open_app" msgid="483650971094300141">"యాప్‌ను తెరువు"</string>
+    <string name="controls_open_app" msgid="483650971094300141">"యాప్‌‌ను తెరవండి"</string>
     <string name="controls_error_generic" msgid="352500456918362905">"స్టేటస్ లోడ్ చేయడం సాధ్యపడలేదు"</string>
     <string name="controls_error_failed" msgid="960228639198558525">"ఎర్రర్, మళ్లీ ప్రయత్నించండి"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"కంట్రోల్స్‌ను జోడించండి"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"కంట్రోల్స్‌ను ఎడిట్ చేయండి"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"యాప్‌ను జోడించండి"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"యాప్‌ను తీసివేయండి"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"అవుట్‌పుట్‌లను జోడించండి"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"గ్రూప్"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 పరికరం ఎంచుకోబడింది"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index f0a2123..c5de820 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"เปิดใช้ USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"ดูข้อมูลเพิ่มเติม"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ภาพหน้าจอ"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"ปิดใช้ Smart Lock แล้ว"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ส่งรูปภาพ"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"กำลังบันทึกภาพหน้าจอ..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"กำลังบันทึกภาพหน้าจอไปยังโปรไฟล์งาน…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"หากคุณป้อน PIN ไม่ถูกต้องในความพยายามครั้งถัดไป ระบบจะลบโปรไฟล์งานและข้อมูลในโปรไฟล์"</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"หากคุณป้อนรหัสผ่านไม่ถูกต้องในความพยายามครั้งถัดไป ระบบจะลบโปรไฟล์งานและข้อมูลในโปรไฟล์"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"แตะเซ็นเซอร์ลายนิ้วมือ"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"ไอคอนลายนิ้วมือ"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ไม่รู้จักใบหน้า ใช้ลายนิ้วมือแทน"</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -834,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"ขยายเป็นเต็มหน้าจอ"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"ขยายบางส่วนของหน้าจอ"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"เปลี่ยน"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"ลากที่มุมเพื่อปรับขนาด"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"อนุญาตการเลื่อนแบบทแยงมุม"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"ปรับขนาด"</string>
@@ -843,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"แฮนเดิลซ้าย"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"แฮนเดิลขวา"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"แฮนเดิลล่าง"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"ขนาดแว่นขยาย"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"ซูม"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"ปานกลาง"</string>
@@ -869,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{เพิ่มตัวควบคุม # ตัวแล้ว}other{เพิ่มตัวควบคุม # ตัวแล้ว}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"นำออกแล้ว"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"เพิ่ม <xliff:g id="APPNAME">%s</xliff:g> ไหม"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"เมื่อเพิ่ม <xliff:g id="APPNAME">%s</xliff:g> คุณจะเพิ่มการควบคุมและเนื้อหาไปยังแผงนี้ได้ ในบางแอป คุณเลือกได้ว่าต้องการให้การควบคุมใดปรากฏขึ้นที่นี่"</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"นำการควบคุมสำหรับ <xliff:g id="APPNAME">%s</xliff:g> ออกไหม"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"ตั้งเป็นรายการโปรดแล้ว"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"ตั้งเป็นรายการโปรดแล้ว โดยอยู่ลำดับที่ <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"นำออกจากรายการโปรดแล้ว"</string>
@@ -887,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"อื่นๆ"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"เพิ่มไปยังระบบควบคุมอุปกรณ์"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"เพิ่ม"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"นำออก"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"แนะนำโดย <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"อุปกรณ์ถูกล็อก"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"แสดงและควบคุมอุปกรณ์จากหน้าจอล็อกไหม"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"คุณเพิ่มการควบคุมอุปกรณ์ภายนอกลงในหน้าจอล็อกได้\n\nแอปของอุปกรณ์อาจอนุญาตให้คุณควบคุมอุปกรณ์บางอย่างได้โดยไม่ต้องปลดล็อกโทรศัพท์หรือแท็บเล็ต\n\nคุณเปลี่ยนแปลงได้ทุกเมื่อในการตั้งค่า"</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"ควบคุมอุปกรณ์จากหน้าจอล็อกไหม"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"คุณควบคุมอุปกรณ์บางอย่างได้โดยไม่ต้องปลดล็อกโทรศัพท์หรือแท็บเล็ต\n\nแอปของอุปกรณ์จะระบุอุปกรณ์ที่สามารถควบคุมด้วยวิธีนี้ได้"</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"ไม่เป็นไร"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"มี"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN ประกอบด้วยตัวอักษรหรือสัญลักษณ์"</string>
@@ -940,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"เพิ่มตัวควบคุม"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"แก้ไขตัวควบคุม"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"เพิ่มแอป"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"นำแอปออก"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"เพิ่มเอาต์พุต"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"กลุ่ม"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"เลือกอุปกรณ์ไว้ 1 รายการ"</string>
@@ -1110,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"สลับไปใช้โปรไฟล์งาน"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"ปิด"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"การตั้งค่าหน้าจอล็อก"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ไม่พร้อมใช้งาน"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"กล้องถูกบล็อกอยู่"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"กล้องและไมโครโฟนถูกบล็อกอยู่"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"ไมโครโฟนถูกบล็อกอยู่"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"โหมดลำดับความสำคัญเปิดอยู่"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"การเรียกใช้งาน Assistant เปิดอยู่"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 05f4628..d8a9f3e 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"I-enable ang USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Matuto pa"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Naka-disable ang Smart Lock"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"nagpadala ng larawan"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Sine-save ang screenshot…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Sine-save ang screenshot sa profile sa trabaho…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Kung maling PIN ang mailalagay mo sa susunod na pagsubok, made-delete ang iyong profile sa trabaho at ang data nito."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Kung maling password ang mailalagay mo sa susunod na pagsubok, made-delete ang iyong profile sa trabaho at ang data nito."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Pindutin ang fingerprint sensor"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Icon ng fingerprint"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Hindi makilala ang mukha. Gumamit ng fingerprint."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Notification shade."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Mga mabilisang setting."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Mga mabilisang setting at Notification shade."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lock screen."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Lock screen sa trabaho"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Isara"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"I-magnify ang buong screen"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"I-magnify ang isang bahagi ng screen"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Switch"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"I-drag ang sulok para i-resize"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Payagan ang diagonal na pag-scroll"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"I-resize"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Handle sa kaliwa"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Handle sa kanan"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Handle sa ibaba"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Laki ng magnifier"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoom"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Katamtaman"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Nagdagdag ng # kontrol.}one{Nagdagdag ng # kontrol.}other{Nagdagdag ng # na kontrol.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Inalis"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Idagdag ang <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Kapag idinagdag mo ang <xliff:g id="APPNAME">%s</xliff:g>, puwede itong magdagdag ng mga kontrol at content sa panel na ito. Sa ilang app, puwede mong piliin kung aling mga kontrol ang lalabas dito."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Alisin ang mga kontrol para sa <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Ginawang paborito"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Ginawang paborito, posisyon <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Inalis sa paborito"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Iba pa"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Idagdag sa mga kontrol ng device"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Idagdag"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Alisin"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Iminungkahi ng <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Naka-lock ang device"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Ipakita at kontrolin ang mga device mula sa lock screen?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Puwede kang magdagdag ng mga kontrol para sa iyong mga external device sa lock screen.\n\nPosibleng payagan ka ng app ng iyong device na kontrolin ang ilang device nang hindi ina-unlock ang telepono o tablet mo.\n\nPuwede kang magsagawa ng mga pagbabago anumang oras sa Mga Setting."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Kontrolin ang mga device mula sa lock screen?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Puwede mong kontrolin ang ilang device nang hindi ina-unlock ang iyong telepono o tablet.\n\nNakadepende sa app ng iyong device kung aling mga device ang puwedeng kontrolin sa ganitong paraan."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Huwag na lang"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Oo"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"May mga titik o simbolo ang PIN"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Magdagdag ng mga kontrol"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Mag-edit ng mga kontrol"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Magdagdag ng app"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Alisin ang app"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Magdagdag ng mga output"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grupo"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 device ang napili"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 81f8486..baacde08 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USB\'yi etkinleştir"</string>
     <string name="learn_more" msgid="4690632085667273811">"Daha fazla bilgi"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Ekran görüntüsü"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock devre dışı"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"bir resim gönderildi"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Ekran görüntüsü kaydediliyor..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Ekran görüntüsü iş profiline kaydediliyor…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Bir sonraki denemenizde yanlış PIN girerseniz iş profiliniz ve verileri silinir."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Bir sonraki denemenizde yanlış şifre girerseniz iş profiliniz ve verileri silinir."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Parmak izi sensörüne dokunun"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Parmak izi simgesi"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Yüz tanınamadı. Bunun yerine parmak izi kullanın."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bildirim gölgesi."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Hızlı ayarlar."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Hızlı ayarlar ve Bildirim gölgesi."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Kilit ekranı"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"İş profili kilit ekranı"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Kapat"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Tam ekran büyütme"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ekranın bir parçasını büyütün"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Geç"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Yeniden boyutlandırmak için köşeyi sürükleyin"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Çapraz kaydırmaya izin ver"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Yeniden boyutlandır"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Sol tutma yeri"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Sağ tutma yeri"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Alt tutma yeri"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Büyüteç boyutu"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Zoom"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Orta"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# kontrol eklendi.}other{# kontrol eklendi.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Kaldırıldı"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> eklensin mi?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> uygulamasını eklerseniz bu panele kontrol ve içerik ekleyebilir. Bazı uygulamalarda, burada hangi kontrollerin görüneceğini seçebilirsiniz."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> için denetimler kaldırılsın mı?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Favoriler listesine eklendi"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Favorilere eklendi, konum: <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Favorilerden kaldırıldı"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Diğer"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Cihaz denetimlerine ekle"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Ekle"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Kaldır"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> tarafından önerildi"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Cihaz kilitlendi"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Cihazlar kilit ekranında gösterilip buradan kontrol edilsin mi?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Kilit ekranına harici cihazlarınız için kontroller ekleyebilirsiniz.\n\nCihaz uygulamanız, bazı cihazları telefonunuzun veya tabletinizin kilidini açmadan kontrol etmenize izin verebilir.\n\nAyarlar\'da istediğiniz zaman değişiklik yapabilirsiniz."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Cihazlar kilit ekranından kontrol edilsin mi?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Bazı cihazları telefonunuzun veya tabletinizin kilidini açmadan kontrol edebilirsiniz.\n\nHangi cihazların bu şekilde kontrol edilebileceğini cihaz uygulamanız belirler."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Hayır, teşekkürler"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Evet"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN, harf veya simge içerir"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Denetim ekle"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Denetimleri düzenle"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Uygulama ekle"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Uygulamayı kaldır"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Çıkışlar ekleyin"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Grup"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 cihaz seçildi"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 3ba43d5..6c25d7c 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Увімкнути USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Докладніше"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Знімок екрана"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock вимкнено"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"надіслане зображення"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Збереження знімка екрана..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Зберігання знімка екрана в робочому профілі…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Якщо наступного разу ви введете неправильний PIN-код, ваш робочий профіль і його дані буде видалено."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Якщо наступного разу ви введете неправильний пароль, ваш робочий профіль і його дані буде видалено."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Торкніться сканера відбитків пальців"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Значок відбитка пальця"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Обличчя не розпізнано. Скористайтеся відбитком пальця."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Панель сповіщень."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Швидке налаштування."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Швидкі налаштування й панель сповіщень."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Заблокований екран."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Екран блокування завдання"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Закрити"</string>
@@ -236,7 +235,7 @@
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"Джерело сигналу"</string>
     <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="3003338571871392293">"Слухові апарати"</string>
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Увімкнення…"</string>
-    <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Автоматичне обертання"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="2359922767950346112">"Автообертання"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4800050198392260738">"Автоматично обертати екран"</string>
     <string name="quick_settings_location_label" msgid="2621868789013389163">"Геодані"</string>
     <string name="quick_settings_screensaver_label" msgid="1495003469366524120">"Заставка"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Збільшення всього екрана"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Збільшити частину екрана"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Перемкнути"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Потягніть кут, щоб змінити розмір"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Дозволити прокручування по діагоналі"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Змінити розмір"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Лівий маркер"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Правий маркер"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Нижній маркер"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Розмір лупи"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Масштаб"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Звичайна"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Додано # елемент керування.}one{Додано # елемент керування.}few{Додано # елементи керування.}many{Додано # елементів керування.}other{Додано # елемента керування.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Вилучено"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Долучити додаток <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Якщо ви долучите додаток <xliff:g id="APPNAME">%s</xliff:g>, він зможе розміщувати елементи керування й контент на цій панелі. У деяких додатках можна вибрати, які елементи керування тут відображатимуться."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Вилучити елементи керування для додатка <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Додано у вибране"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Додано у вибране, позиція <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Видалено з вибраного"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Інше"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Додати до елементів керування пристроями"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Додати"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Вилучити"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Запропоновано додатком <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Пристрій заблоковано"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Переглядати пристрої та керувати ними на заблокованому екрані?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Елементи керування зовнішніми пристроями можна додавати на заблокований екран.\n\nЗа допомогою спеціального додатка ви можете керувати деякими пристроями, не розблоковуючи телефон або планшет.\n\nВи можете будь-коли вносити зміни в налаштуваннях."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Керувати пристроями на заблокованому екрані?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Ви можете керувати деякими пристроями, не розблоковуючи телефон або планшет.\n\nЯкими пристроями можна керувати в такий спосіб, визначає додаток на пристрої."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Ні, дякую"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Так"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN-код містить літери чи символи"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Додати елементи керування"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Змінити елементи керування"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Долучити додаток"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Вилучити додаток"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Додати пристрої виводу"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Група"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Вибрано 1 пристрій"</string>
@@ -1111,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Перейти в робочий профіль"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Закрити"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Параметри заблокованого екрана"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Мережа Wi-Fi недоступна"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камеру заблоковано"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камеру й мікрофон заблоковано"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Мікрофон заблоковано"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Режим пріоритету ввімкнено"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Асистента активовано"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 5388be5..660fd6d 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"‏USB پورٹ فعال کریں"</string>
     <string name="learn_more" msgid="4690632085667273811">"مزید جانیں"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"اسکرین شاٹ"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"‏Smart Lock کو غیر فعال کیا گیا"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"ایک تصویر بھیجی"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"اسکرین شاٹ محفوظ ہو رہا ہے…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"اسکرین شاٹ دفتری پروفائل میں محفوظ کیا جا رہا ہے…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"‏اگر آپ نے اگلی کوشش میں غلط PIN درج کیا تو آپ کی دفتری پروفائل اور اس کا ڈیٹا حذف کر دیا جائے گا۔"</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"اگر آپ نے اگلی کوشش میں غلط پاس ورڈ درج کیا تو آپ کی دفتری پروفائل اور اس کا ڈیٹا حذف کر دیا جائے گا۔"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"فنگر پرنٹ سینسر پر ٹچ کریں"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"فنگر پرنٹ آئیکن"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"چہرے کی شناخت نہیں ہو سکی۔ اس کے بجائے فنگر پرنٹ استعمال کریں۔"</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"اطلاعاتی شیڈ۔"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"فوری ترتیبات۔"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"فوری ترتیبات اور اطلاعاتی شیڈ۔"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"مقفل اسکرین۔"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"دفتری مقفل اسکرین"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"بند کریں"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"فُل اسکرین کو بڑا کریں"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"اسکرین کا حصہ بڑا کریں"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"سوئچ کریں"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"سائز تبدیل کرنے کے لیے کونے کو گھسیٹیں"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"وتری سکرولنگ کی اجازت دیں"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"سائز تبدیل کریں"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"بایاں ہینڈل"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"دایاں ہینڈل"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"نیچے کا ہینڈل"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"میگنیفائر کا سائز"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"زوم کریں"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"متوسط"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# کنٹرول کو شامل کیا گیا۔}other{# کنٹرولز کو شامل کیا گیا۔}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"ہٹا دیا گیا"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> کو شامل کریں؟"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"جب آپ <xliff:g id="APPNAME">%s</xliff:g> کو شامل کرتے ہیں، تو یہ اس پینل میں کنٹرولز اور مواد کو شامل کر سکتا ہے۔ کچھ ایپس میں، آپ یہ منتخب کر سکتے ہیں کہ کون سے کنٹرولز یہاں ظاہر ہوں۔"</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> کے کنٹرولز کو ہٹا دیں؟"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"پسند کردہ"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"پسند کردہ، پوزیشن <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"ناپسند کردہ"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"دیگر"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"آلہ کے کنٹرولز میں شامل کریں"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"شامل کریں"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"ہٹائیں"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> کی طرف سے تجویز کردہ"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"آلہ مقفل کر دیا گیا"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"لاک اسکرین سے آلات دکھائیں اور کنٹرول کریں؟"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"آپ اپنے بیرونی آلات کے لیے لاک اسکرین پر کنٹرولز شامل کر سکتے ہیں۔\n\nآپ کے آلے کی ایپ آپ کو اپنے فون یا ٹیبلیٹ کو غیر مقفل کیے بغیر کچھ آلات کو کنٹرول کرنے کی اجازت دے سکتی ہے۔\n\nآپ ترتیبات میں کسی بھی وقت تبدیلیاں کر سکتے ہیں۔"</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"لاک اسکرین سے آلات کو کنٹرول کریں؟"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"آپ اپنے فون یا ٹیبلیٹ کو غیر مقفل کیے بغیر کچھ آلات کو کنٹرول کر سکتے ہیں۔\n\nآپ کے آلے کی ایپ اس بات کا تعین کرتی ہے کہ اس طرح کن آلات کو کنٹرول کیا جا سکتا ہے۔"</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"نہیں شکریہ"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"ہاں"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"‏PIN میں حروف یا علامات شامل ہیں"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"کنٹرولز شامل کریں"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"کنٹرولز میں ترمیم کریں"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"ایپ شامل کریں"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"ایپ ہٹائیں"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"آؤٹ پٹس شامل کریں"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"گروپ"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 آلہ منتخب کیا گیا"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 0046e04..31e3ce6 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USB xususiyatini yoqish"</string>
     <string name="learn_more" msgid="4690632085667273811">"Batafsil"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Skrinshot"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock faolsizlantirildi"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"rasm yuborildi"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Skrinshot saqlanmoqda…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Skrinshot ish profiliga saqlanmoqda…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Agar PIN kodni xato kiritsangiz, ish profili va undagi maʼlumotlar oʻchirib tashlanadi."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Agar parolni xato kiritsangiz, ish profili va undagi maʼlumotlar oʻchirib tashlanadi."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Barmoq izi skaneriga tegining"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Barmoq izi belgisi"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Bu yuz notanish. Barmoq izi orqali urining."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -834,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Ekranni toʻliq kattalashtirish"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Ekran qismini kattalashtirish"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Almashtirish"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Oʻlchamini oʻzgartirish uchun burchakni torting"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Diagonal aylantirishga ruxsat berish"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Oʻlchamini oʻzgartirish"</string>
@@ -843,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Chap slayder"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Oʻng slayder"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Quyi slayder"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Lupa oʻlchami"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Masshtab"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Oʻrtacha"</string>
@@ -869,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# ta boshqaruv elementi kiritildi.}other{# ta boshqaruv elementi kiritildi.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Olib tashlandi"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"<xliff:g id="APPNAME">%s</xliff:g> qoʻshilsinmi?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"<xliff:g id="APPNAME">%s</xliff:g> bu panelga boshqaruv elementlari va kontent qoʻshishi mumkin. Ayrim ilovalarda bu yerda qaysi elementlar chiqishini tanlashingiz mumkin."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"<xliff:g id="APPNAME">%s</xliff:g> qurilma boshqaruv panelidan olib tashlansinmi?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Saralanganlarga kiritilgan"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Saralanganlarga kiritilgan, <xliff:g id="NUMBER">%d</xliff:g>-joy"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Saralanganlardan olib tashlangan"</string>
@@ -887,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Boshqa"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Qurilma boshqaruv elementlariga kiritish"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Kiritish"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Olib tashlash"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"<xliff:g id="APP">%s</xliff:g> taklif etgan"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Qurilma qulflandi"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Qurilmalar qulflangan ekranda koʻrsatilsinmi va boshqarilsinmi?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Tashqi qurilmalaringiz uchun ekran qulfiga boshqaruvlarni qoʻshishingiz mumkin.\n\nQurilma ilovasi ayrim qurilmalarni telefon yoki planshet qulfini ochmasdan boshqarish imkonini beradi.\n\nIstalgan vaqtda Sozlamalar orqali oʻzgartirish mumkin."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Qurilmalar ekran qulfidan boshqarilsinmi?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Ayrim qurilmalarni telefon yoki planshet ekran qulfini ochmasdan boshqarish mumkin.\n\nQurilmangiz ilovasi qaysi qurilmalarni shu tarzda boshqarish mumkinligini aniqlaydi."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Yopish"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Ha"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Harflar yoki maxsus belgilardan iborat PIN kod"</string>
@@ -940,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Element kiritish"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Elementlarni tahrirlash"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Ilova kiritish"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Ilovani olib tashlash"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Chiquvchi qurilmani kiritish"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Guruh"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"1 ta qurilma tanlandi"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index d97be06..53adea1 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Bật USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Tìm hiểu thêm"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Chụp ảnh màn hình"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Tính năng Smart Lock đã tắt"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"đã gửi hình ảnh"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Đang lưu ảnh chụp màn hình..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Đang lưu ảnh chụp màn hình vào hồ sơ công việc…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Nếu bạn nhập mã PIN không chính xác vào lần thử tiếp theo, thì hồ sơ công việc của bạn và dữ liệu của hồ sơ công việc sẽ bị xóa."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Nếu bạn nhập mật khẩu không chính xác vào lần thử tiếp theo, thì hồ sơ công việc của bạn và dữ liệu của hồ sơ công việc sẽ bị xóa."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Chạm vào cảm biến vân tay"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Biểu tượng vân tay"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Không thể nhận dạng khuôn mặt. Hãy dùng vân tay."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bóng thông báo."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Cài đặt nhanh."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Cài đặt nhanh và ngăn thông báo."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Màn hình khóa."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Màn hình khóa công việc"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Đóng"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Phóng to toàn màn hình"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Phóng to một phần màn hình"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Chuyển"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Kéo góc để thay đổi kích thước"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Cho phép cuộn chéo"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Đổi kích thước"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Ô điều khiển bên trái"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Ô điều khiển bên phải"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Ô điều khiển dưới cùng"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Kích thước phóng to"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Thu phóng"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Vừa"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Đã thêm # chế độ điều khiển.}other{Đã thêm # chế độ điều khiển.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Đã xóa"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Thêm <xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Khi bạn thêm <xliff:g id="APPNAME">%s</xliff:g>, ứng dụng có thể bổ sung các chế độ điều khiển và nội dung vào bảng điều khiển này. Trong một số ứng dụng, bạn có thể chọn chế độ điều khiển nào sẽ hiển thị tại đây."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Xoá chế độ cài đặt cho <xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Được yêu thích"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Được yêu thích, vị trí số <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Không được yêu thích"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Khác"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Thêm vào mục điều khiển thiết bị"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Thêm"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Xoá"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Do <xliff:g id="APP">%s</xliff:g> đề xuất"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Đã khóa thiết bị"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Bạn muốn hiện và điều khiển các thiết bị từ màn hình khoá?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Bạn có thể thêm các chế độ điều khiển cho những thiết bị bên ngoài vào màn hình khoá.\n\nỨng dụng thiết bị có thể cho phép bạn điều khiển một số thiết bị mà không cần mở khoá điện thoại hoặc máy tính bảng.\n\nBạn có thể thay đổi chế độ cài đặt này bất cứ lúc nào trong phần Cài đặt."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Bạn muốn điều khiển các thiết bị từ màn hình khoá?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Bạn có thể điều khiển một số thiết bị mà không cần mở khoá điện thoại hoặc máy tính bảng.\n\nỨng dụng thiết bị sẽ xác định thiết bị mà bạn có thể điều khiển bằng cách này."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Không, cảm ơn"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Có"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Mã PIN chứa các ký tự hoặc ký hiệu"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Thêm các tùy chọn điều khiển"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Chỉnh sửa tùy chọn điều khiển"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Thêm ứng dụng"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Xoá ứng dụng"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Thêm thiết bị đầu ra"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Nhóm"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"Đã chọn 1 thiết bị"</string>
@@ -1111,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Chuyển sang hồ sơ công việc"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Đóng"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Cài đặt màn hình khoá"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Không có Wi-Fi"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Máy ảnh bị chặn"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Máy ảnh và micrô bị chặn"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Micrô bị chặn"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Chế độ ưu tiên đang bật"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Trợ lý đang bật"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index ea1c94a..e764a74 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"启用 USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"了解详情"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"屏幕截图"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock 已停用"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"发送了一张图片"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"正在保存屏幕截图..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"正在将屏幕截图保存到工作资料…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"如果您下次输入的 PIN 码仍然有误,您的工作资料及其相关数据将会被删除。"</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"如果您下次输入的密码仍然有误,您的工作资料及其相关数据将会被删除。"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"请触摸指纹传感器"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"指纹图标"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"无法识别人脸。请改用指纹。"</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"通知栏。"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"快捷设置。"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"快捷设置和通知栏。"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"锁定屏幕。"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"工作锁定屏幕"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"关闭"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"放大整个屏幕"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"放大部分屏幕"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"切换"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"拖动一角即可调整大小"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"允许沿对角线滚动"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"调整大小"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"左侧手柄"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"右侧手柄"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"底部手柄"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"放大镜大小"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"缩放"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"中"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{已添加 # 个控件。}other{已添加 # 个控件。}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"已移除"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"添加“<xliff:g id="APPNAME">%s</xliff:g>”?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"当您添加“<xliff:g id="APPNAME">%s</xliff:g>”后,它可以将控件和内容添加到此面板。在某些应用中,您可以选择在此处显示哪些控件。"</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"移除<xliff:g id="APPNAME">%s</xliff:g>的控件?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"已收藏"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"已收藏,位置:<xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"已取消收藏"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"其他"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"添加到设备控制器"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"添加"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"移除"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"来自<xliff:g id="APP">%s</xliff:g>的建议"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"设备已锁定"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"要从锁定屏幕上显示和控制设备吗?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"您可以在锁定屏幕上添加用于控制外部设备的控件。\n\n您的设备应用可能会允许您在不解锁手机或平板电脑的情况下控制某些设备。\n\n您可以随时在“设置”中进行更改。"</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"要从锁定屏幕上控制设备吗?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"您可以在不解锁手机或平板电脑的情况下控制某些设备。\n\n您的设备应用将决定哪些设备可以通过这种方式进行控制。"</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"不用了"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"是"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN 码由字母或符号组成"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"添加控制器"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"修改控制器"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"添加应用"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"移除应用"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"添加输出设备"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"群组"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"已选择 1 个设备"</string>
@@ -1019,7 +1027,7 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"移动数据网络"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"已连接"</string>
-    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"暂时已连接"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"已暂时连接"</string>
     <string name="mobile_data_poor_connection" msgid="819617772268371434">"连接状况不佳"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"系统将不会自动连接到移动数据网络"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"无网络连接"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index cfd1cc8..187a4a5 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"啟用 USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"瞭解詳情"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"螢幕截圖"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock 已停用"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"已傳送圖片"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"正在儲存螢幕擷取畫面..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"正在將螢幕截圖儲存至工作設定檔…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"如果您下次輸入錯誤的 PIN,系統將會刪除工作設定檔和相關資料。"</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"如果您下次輸入錯誤的密碼,系統將會刪除工作設定檔和相關資料。"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"請輕觸指紋感應器"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"指紋圖示"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"無法辨識面孔,請改用指紋完成驗證。"</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"通知欄。"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"快速設定。"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"快速設定和通知欄。"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"上鎖畫面。"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"工作螢幕鎖定"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"關閉"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"放大成個畫面"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"放大部分螢幕畫面"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"切換"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"拖曳角落即可調整大小"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"允許斜角捲動"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"調整大小"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"左控點"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"右控點"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"底部控點"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"放大鏡大小"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"縮放"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"中"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{已新增 # 個控制項。}other{已新增 # 個控制項。}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"已移除"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"要新增「<xliff:g id="APPNAME">%s</xliff:g>」嗎?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"如果您新增「<xliff:g id="APPNAME">%s</xliff:g>」,應用程式可將控制項和內容新增至此面板。部份應用程式可讓您選擇要在這裡顯示的控制項。"</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"要移除「<xliff:g id="APPNAME">%s</xliff:g>」的控制項嗎?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"已加入收藏"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"已加入至收藏位置 <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"已取消收藏"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"其他"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"加到裝置控制"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"新增"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"移除"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"由「<xliff:g id="APP">%s</xliff:g>」提供的建議"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"裝置已上鎖"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"要從上鎖畫面查看及控制裝置嗎?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"您可以在上鎖畫面新增外部裝置的控制項。\n\n裝置應用程式可能會讓您在不解鎖手機或平板電腦的情況下控制部分裝置。\n\n您可隨時在「設定」中作出變更。"</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"要在上鎖畫面控制裝置嗎?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"您可以在不解鎖手機或平板電腦的情況下控制部分裝置。\n\n裝置應用程式決定哪些裝置可透過此方式控制。"</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"不用了,謝謝"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"是"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN 含有字母或符號"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"新增控制項"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"編輯控制項"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"新增應用程式"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"移除應用程式"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"新增輸出裝置"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"群組"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"已選取 1 部裝置"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 450a3cc..c2527c6 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"啟用 USB 連接埠"</string>
     <string name="learn_more" msgid="4690632085667273811">"瞭解詳情"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"螢幕截圖"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock 已停用"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"傳送了一張圖片"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"正在儲存螢幕截圖…"</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"正在將螢幕截圖儲存到工作資料夾…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"如果下次輸入的 PIN 碼仍不正確,系統將刪除你的工作資料夾和相關資料。"</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"如果下次輸入的密碼仍不正確,系統將刪除你的工作資料夾和相關資料。"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"請輕觸指紋感應器"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"指紋圖示"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"無法辨識臉孔,請改用指紋完成驗證。"</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"通知欄。"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"快捷設定。"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"快速設定和通知欄。"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"螢幕鎖定。"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Work 螢幕鎖定"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"關閉"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"放大整個螢幕畫面"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"放大局部螢幕畫面"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"切換"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"拖曳角落即可調整大小"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"允許沿對角線捲動"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"調整大小"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"左側控點"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"右側控點"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"底部控點"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"放大鏡大小"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"縮放"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"中"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{已新增 # 個控制項。}other{已新增 # 個控制項。}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"已移除"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"要新增「<xliff:g id="APPNAME">%s</xliff:g>」嗎?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"當你新增「<xliff:g id="APPNAME">%s</xliff:g>」時,應用程式也可將控制選項及內容新增到這個面板。某些應用程式可讓你選擇要顯示在這裡的控制選項。"</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"要移除「<xliff:g id="APPNAME">%s</xliff:g>」的控制嗎?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"已加入收藏"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"已加入收藏,位置 <xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"從收藏中移除"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"其他"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"新增至裝置控制項"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"新增"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"移除"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"來自「<xliff:g id="APP">%s</xliff:g>」的建議"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"裝置已鎖定"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"要在螢幕鎖定畫面上查看及控制裝置嗎?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"你可以在螢幕鎖定畫面上新增外部裝置的控制選項。\n\n你或許可透過裝置應用程式控制某些裝置,而不必解鎖手機或平板電腦。\n\n你隨時可以前往「設定」進行變更。"</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"要在螢幕鎖定畫面上控制裝置嗎?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"你可以直接控制某些裝置,不必解鎖手機或平板電腦。\n\n裝置應用程式會判斷可透過這種方式控制的應用程式。"</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"不用了,謝謝"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"是"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"PIN 碼含有字母或符號"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"新增控制項"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"編輯控制項"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"新增應用程式"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"移除應用程式"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"新增輸出裝置"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"群組"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"已選取 1 部裝置"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 85854c5..0dd4111a5 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -69,7 +69,8 @@
     <string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"Nika amandla i-USB"</string>
     <string name="learn_more" msgid="4690632085667273811">"Funda kabanzi"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Isithombe-skrini"</string>
-    <string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Ukhiye oSmathi ukhutshaziwe"</string>
+    <!-- no translation found for global_action_smart_lock_disabled (6286551337177954859) -->
+    <skip />
     <string name="remote_input_image_insertion_text" msgid="4850791636452521123">"uthumele isithombe"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Ilondoloz umfanekiso weskrini..."</string>
     <string name="screenshot_saving_work_profile_title" msgid="5332829607308450880">"Ilondoloza isithombe-skrini kuphrofayela yomsebenzi…"</string>
@@ -169,7 +170,6 @@
     <string name="biometric_dialog_last_pin_attempt_before_wipe_profile" msgid="545567685899091757">"Uma ufaka iphinikhodi engalungile kumzamo olandelayo, iphrofayela yakho yomsebenzi nedatha yayo izosuswa."</string>
     <string name="biometric_dialog_last_password_attempt_before_wipe_profile" msgid="8538032972389729253">"Uma ufake iphasiwedi engalungile kumzamo olandelayo, iphrofayela yakho yomsebenzi nedatha yayo izosuswa."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Thinta inzwa yesigxivizo zeminwe"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="4465698996175640549">"Isithonjana sezigxivizo zeminwe"</string>
     <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ayibazi ubuso. Sebenzisa izigxivizo zeminwe kunalokho."</string>
     <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
     <skip />
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Umthunzi wesaziso."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Izilingiselelo ezisheshayo."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Amasethingi asheshayo Nomthunzi wezaziso."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Khiya isikrini."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ukukhiya isikrini somsebenzi"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Vala"</string>
@@ -835,6 +834,8 @@
     <string name="magnification_mode_switch_state_full_screen" msgid="5229653514979530561">"Khulisa isikrini esigcwele"</string>
     <string name="magnification_mode_switch_state_window" msgid="8597100249594076965">"Khulisa ingxenye eyesikrini"</string>
     <string name="magnification_mode_switch_click_label" msgid="2786203505805898199">"Iswishi"</string>
+    <!-- no translation found for magnification_open_settings_click_label (6151849212725923363) -->
+    <skip />
     <string name="magnification_drag_corner_to_resize" msgid="1249766311052418130">"Hudula ikhona ukuze usayize kabusha"</string>
     <string name="accessibility_allow_diagonal_scrolling" msgid="3258050349191496398">"Vumela ukuskrola oku-diagonal"</string>
     <string name="accessibility_resize" msgid="5733759136600611551">"Shintsha usayizi"</string>
@@ -844,6 +845,8 @@
     <string name="accessibility_magnification_left_handle" msgid="6694953733271752950">"Isibambi sangakwesokunxele"</string>
     <string name="accessibility_magnification_right_handle" msgid="9055988237319397605">"Isibambi esingakwesokudla"</string>
     <string name="accessibility_magnification_bottom_handle" msgid="6531646968813821258">"Isibambi esingezansi"</string>
+    <!-- no translation found for accessibility_magnification_settings_panel_description (8174187340747846953) -->
+    <skip />
     <string name="accessibility_magnifier_size" msgid="3038755600030422334">"Usayizi wesikhulisi"</string>
     <string name="accessibility_magnification_zoom" msgid="4222088982642063979">"Sondeza"</string>
     <string name="accessibility_magnification_medium" msgid="6994632616884562625">"Kumaphakathi"</string>
@@ -870,7 +873,9 @@
     <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{ulawulo olu-# olwengeziwe.}one{ukulawulwa okungu-# okwengeziwe.}other{ukulawulwa okungu-# okwengeziwe.}}"</string>
     <string name="controls_removed" msgid="3731789252222856959">"Isusiwe"</string>
     <string name="controls_panel_authorization_title" msgid="267429338785864842">"Engeza i-<xliff:g id="APPNAME">%s</xliff:g>?"</string>
-    <string name="controls_panel_authorization" msgid="4540047176861801815">"Uma wengeza i-<xliff:g id="APPNAME">%s</xliff:g>, ingangeza izilawuli nokuqukethwe kuleli phaneli. Kwamanye ama-app, ungakhetha ukuthi yiziphi izilawuli eziboniswa lapha."</string>
+    <!-- no translation found for controls_panel_authorization (4665218066461350247) -->
+    <skip />
+    <string name="controls_panel_remove_app_authorization" msgid="5920442084735364674">"Susa izilawuli ze-<xliff:g id="APPNAME">%s</xliff:g>?"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Kwenziwe intandokazi"</string>
     <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Kwenziwe intandokazi, isimo esiyi-<xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="accessibility_control_not_favorite" msgid="1291760269563092359">"Akwenziwanga intandokazi"</string>
@@ -888,12 +893,14 @@
     <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Okunye"</string>
     <string name="controls_dialog_title" msgid="2343565267424406202">"Engeza kuzilawuli zezinsiza"</string>
     <string name="controls_dialog_ok" msgid="2770230012857881822">"Engeza"</string>
+    <string name="controls_dialog_remove" msgid="3775288002711561936">"Susa"</string>
     <string name="controls_dialog_message" msgid="342066938390663844">"Kuphakanyiswe ngu-<xliff:g id="APP">%s</xliff:g>"</string>
     <string name="controls_tile_locked" msgid="731547768182831938">"Idivayisi ikhiyiwe"</string>
     <string name="controls_settings_show_controls_dialog_title" msgid="3357852503553809554">"Bonisa futhi ulawule amadivayisi ekukhiyeni isikrini?"</string>
     <string name="controls_settings_show_controls_dialog_message" msgid="7666211700524587969">"Ungakwazi ukwengeza izilawuli zamadivayisi wakho angaphandle ekukhiyeni isikrini.\n\nI-app yakho yedivayisi ingakuvumela ukuthi ulawule amanye amadivayisi ngaphandle kokuvula ifoni noma ithebulethi yakho.\n\nUngenza izinguquko nganoma yisiphi isikhathi Kumasethingi."</string>
     <string name="controls_settings_trivial_controls_dialog_title" msgid="7593188157655036677">"Lawula amadivayisi ekukhiyeni isikrini?"</string>
-    <string name="controls_settings_trivial_controls_dialog_message" msgid="237183787721917586">"Ungalawula amanye amadivayisi ngaphandle kokuvula ifoni noma ithebulethi yakho.\n\nI-app yakho yedivayisi inquma ukuthi imaphi amadivayisi angalawulwa ngale ndlela."</string>
+    <!-- no translation found for controls_settings_trivial_controls_dialog_message (397178734990952575) -->
+    <skip />
     <string name="controls_settings_dialog_neutral_button" msgid="4514446354793124140">"Cha ngiyabonga"</string>
     <string name="controls_settings_dialog_positive_button" msgid="436070672551674863">"Yebo"</string>
     <string name="controls_pin_use_alphanumeric" msgid="8478371861023048414">"Iphinikhodi iqukethe amaletha namasimbui"</string>
@@ -941,6 +948,7 @@
     <string name="controls_menu_add" msgid="4447246119229920050">"Engeza Izilawuli"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"Hlela izilawuli"</string>
     <string name="controls_menu_add_another_app" msgid="8661172304650786705">"Engeza i-app"</string>
+    <string name="controls_menu_remove" msgid="3006525275966023468">"Susa i-app"</string>
     <string name="media_output_dialog_add_output" msgid="5642703238877329518">"Engeza okukhiphayo"</string>
     <string name="media_output_dialog_group" msgid="5571251347877452212">"Iqembu"</string>
     <string name="media_output_dialog_single_device" msgid="3102758980643351058">"idivayisi ekhethiwe e-1"</string>
@@ -1111,16 +1119,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Shintshela kuphrofayela yomsebenzi"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Vala"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Amasethingi okukhiya isikrini"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"I-Wi-Fi ayitholakali"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Ikhamera ivinjiwe"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Ikhamera nemakrofoni zivinjiwe"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Imakrofoni ivinjiwe"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Imodi ebalulekile ivuliwe"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Ukunaka kwe-Assistant kuvuliwe"</string>
 </resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index c6cc0bc..62e8c5f 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -153,6 +153,7 @@
 
     <color name="GM2_red_300">#F28B82</color>
     <color name="GM2_red_500">#EA4335</color>
+    <color name="GM2_red_600">#B3261E</color>
     <color name="GM2_red_700">#C5221F</color>
 
     <color name="GM2_blue_300">#8AB4F8</color>
@@ -163,8 +164,8 @@
     <color name="magnification_border_color">#F29900</color>
     <color name="magnification_switch_button_color">#7F000000</color>
     <color name="magnification_drag_corner_background">#E5FFFFFF</color>
-    <color name="magnification_drag_handle_color">#B3000000</color>
-    <color name="magnification_drag_handle_tint">#111111</color>
+    <color name="magnification_drag_handle_stroke">#000000</color>
+    <color name="magnification_drag_handle_background_change">#111111</color>
     <color name="accessibility_magnifier_bg">#FCFCFC</color>
     <color name="accessibility_magnifier_bg_stroke">#E0E0E0</color>
     <color name="accessibility_magnifier_icon_color">#252525</color>
@@ -206,6 +207,11 @@
     <color name="control_thumbnail_shadow_color">@*android:color/black</color>
     <color name="controls_task_view_bg">#CC191C1D</color>
 
+    <!-- Keyboard backlight indicator-->
+    <color name="backlight_indicator_step_filled">#F6E388</color>
+    <color name="backlight_indicator_step_empty">#494740</color>
+    <color name="backlight_indicator_background">#32302A</color>
+
     <!-- Docked misalignment message -->
     <color name="misalignment_text_color">#F28B82</color>
 
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 738cfd7..e5cd0c5 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -453,7 +453,7 @@
          and finally letting user send the screenshot to the calling notes app. This activity
          should not send the screenshot to the calling activity without user consent. -->
     <string name="config_screenshotAppClipsActivityComponent" translatable="false"
-            >com.android.systemui/com.android.systemui.screenshot.AppClipsActivity</string>
+            >com.android.systemui/com.android.systemui.screenshot.appclips.AppClipsActivity</string>
 
     <!-- Remote copy default activity.  Must handle REMOTE_COPY_ACTION intents.
      This name is in the ComponentName flattened format (package/class)  -->
@@ -500,8 +500,8 @@
      space -->
     <bool name="config_showBatteryEstimateQSBH">false</bool>
 
-    <!-- Whether to show a severe low battery dialog. -->
-    <bool name="config_severe_battery_dialog">false</bool>
+    <!-- Whether to show extra battery saver confirmation dialog. -->
+    <bool name="config_extra_battery_saver_confirmation">false</bool>
 
     <!-- A path representing a shield. Will sometimes be displayed with the battery icon when
          needed. This path is a 10px wide and 13px tall. -->
@@ -782,7 +782,7 @@
     <!-- Duration in milliseconds of the dream in complications fade-in animation. -->
     <integer name="config_dreamOverlayInComplicationsDurationMs">250</integer>
     <!-- Duration in milliseconds of the y-translation animation when entering a dream -->
-    <integer name="config_dreamOverlayInTranslationYDurationMs">917</integer>
+    <integer name="config_dreamOverlayInTranslationYDurationMs">1167</integer>
 
     <!-- Delay in milliseconds before switching to the dock user and dreaming if a secondary user is
     active when the device is locked and docked. 0 indicates disabled. Default is 1 minute. -->
@@ -844,4 +844,44 @@
 
     <!-- Configuration to set Learn more in device logs as URL link -->
     <bool name="log_access_confirmation_learn_more_as_link">true</bool>
+
+    <!-- [START] MULTI SHADE -->
+    <!-- Whether the device should use dual shade. If false, the device uses single shade. -->
+    <bool name="dual_shade_enabled">true</bool>
+    <!--
+    When in dual shade, where should the horizontal split be on the screen to help determine whether
+    the user is pulling down the left shade or the right shade. Must be between 0.0 and 1.0,
+    inclusive. In other words: how much of the left-hand side of the screen, when pulled down on,
+    would reveal the left-hand side shade.
+
+    More concretely:
+    A value of 0.67 means that the left two-thirds of the screen are dedicated to the left-hand side
+    shade and the remaining one-third of the screen on the right is dedicated to the right-hand side
+    shade.
+    -->
+    <dimen name="dual_shade_split_fraction">0.67</dimen>
+    <!-- Width of the left-hand side shade. -->
+    <dimen name="left_shade_width">436dp</dimen>
+    <!-- Width of the right-hand side shade. -->
+    <dimen name="right_shade_width">436dp</dimen>
+    <!--
+    Opaque version of the scrim that shows up behind dual shades. The alpha channel is driven
+    programmatically.
+    -->
+    <color name="opaque_scrim">#D9D9D9</color>
+    <!-- Maximum opacity when the scrim that shows up behind the dual shades is fully visible. -->
+    <dimen name="dual_shade_scrim_alpha">0.1</dimen>
+    <!--
+    The amount that the user must swipe down when the shade is fully collapsed to automatically
+    expand once the user lets go of the shade. If the user swipes less than this amount, the shade
+    will automatically revert back to fully collapsed once the user stops swiping.
+    -->
+    <dimen name="shade_swipe_expand_threshold">0.5</dimen>
+    <!--
+    The amount that the user must swipe up when the shade is fully expanded to automatically
+    collapse once the user lets go of the shade. If the user swipes less than this amount, the shade
+    will automatically revert back to fully expanded once the user stops swiping.
+    -->
+    <dimen name="shade_swipe_collapse_threshold">0.5</dimen>
+    <!-- [END] MULTI SHADE -->
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index ac07d564..4d38541 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -196,9 +196,6 @@
     <!-- Increased height of a small notification in the status bar -->
     <dimen name="notification_min_height_increased">146dp</dimen>
 
-    <!-- Increased height of a collapsed media notification in the status bar -->
-    <dimen name="notification_min_height_media">160dp</dimen>
-
     <!-- Height of a small notification in the status bar which was used before android N -->
     <dimen name="notification_min_height_legacy">64dp</dimen>
 
@@ -257,9 +254,6 @@
     <!-- Radius for notifications corners with adjacent notifications -->
     <dimen name="notification_corner_radius_small">4dp</dimen>
 
-    <!-- Vertical padding of the FSI container -->
-    <dimen name="fsi_chrome_vertical_padding">80dp</dimen>
-
     <!-- the padding of the shelf icon container -->
     <dimen name="shelf_icon_container_padding">13dp</dimen>
 
@@ -576,7 +570,7 @@
     <dimen name="qs_tile_margin_horizontal">8dp</dimen>
     <dimen name="qs_tile_margin_vertical">@dimen/qs_tile_margin_horizontal</dimen>
     <dimen name="qs_tile_margin_top_bottom">4dp</dimen>
-    <dimen name="qs_brightness_margin_top">12dp</dimen>
+    <dimen name="qs_brightness_margin_top">8dp</dimen>
     <dimen name="qs_brightness_margin_bottom">16dp</dimen>
     <dimen name="qqs_layout_margin_top">16dp</dimen>
     <dimen name="qqs_layout_padding_bottom">24dp</dimen>
@@ -628,7 +622,7 @@
     <dimen name="qs_header_row_min_height">48dp</dimen>
 
     <dimen name="qs_header_non_clickable_element_height">24dp</dimen>
-    <dimen name="new_qs_header_non_clickable_element_height">20dp</dimen>
+    <dimen name="new_qs_header_non_clickable_element_height">24dp</dimen>
 
     <dimen name="qs_footer_padding">20dp</dimen>
     <dimen name="qs_security_footer_height">88dp</dimen>
@@ -1114,14 +1108,15 @@
     <dimen name="qs_media_rec_album_title_bottom_margin">22dp</dimen>
     <dimen name="qs_media_rec_album_subtitle_height">12dp</dimen>
 
-    <!-- Media tap-to-transfer chip for sender device -->
-    <dimen name="media_ttt_chip_outer_padding">16dp</dimen>
-    <dimen name="media_ttt_text_size">16sp</dimen>
-    <dimen name="media_ttt_app_icon_size">24dp</dimen>
-    <dimen name="media_ttt_status_icon_size">20dp</dimen>
-    <dimen name="media_ttt_undo_button_vertical_padding">8dp</dimen>
-    <dimen name="media_ttt_undo_button_vertical_negative_margin">-8dp</dimen>
-    <dimen name="media_ttt_last_item_start_margin">12dp</dimen>
+    <!-- Chipbar -->
+    <!-- (Used for media tap-to-transfer chip for sender device and active unlock) -->
+    <dimen name="chipbar_outer_padding">16dp</dimen>
+    <dimen name="chipbar_text_size">16sp</dimen>
+    <dimen name="chipbar_start_icon_size">24dp</dimen>
+    <dimen name="chipbar_end_icon_size">20dp</dimen>
+    <dimen name="chipbar_end_button_vertical_padding">8dp</dimen>
+    <dimen name="chipbar_end_button_vertical_negative_margin">-8dp</dimen>
+    <dimen name="chipbar_end_item_start_margin">12dp</dimen>
 
     <!-- Media tap-to-transfer chip for receiver device -->
     <dimen name="media_ttt_icon_size_receiver">112dp</dimen>
@@ -1195,11 +1190,13 @@
 
     <!-- Home Controls -->
     <dimen name="controls_header_menu_size">48dp</dimen>
+    <dimen name="controls_header_menu_button_size">48dp</dimen>
     <dimen name="controls_header_bottom_margin">16dp</dimen>
+    <dimen name="controls_header_horizontal_padding">12dp</dimen>
     <dimen name="controls_header_app_icon_size">24dp</dimen>
     <dimen name="controls_top_margin">48dp</dimen>
-    <dimen name="controls_padding_horizontal">0dp</dimen>
-    <dimen name="control_header_text_size">20sp</dimen>
+    <dimen name="controls_content_margin_horizontal">0dp</dimen>
+    <dimen name="control_header_text_size">24sp</dimen>
     <dimen name="control_item_text_size">16sp</dimen>
     <dimen name="control_menu_item_text_size">16sp</dimen>
     <dimen name="control_menu_item_min_height">56dp</dimen>
@@ -1230,6 +1227,8 @@
     <item name="controls_task_view_width_percentage" translatable="false" format="float" type="dimen">1.0</item>
     <dimen name="controls_task_view_right_margin">0dp</dimen>
 
+    <dimen name="controls_panel_corner_radius">42dp</dimen>
+
     <!-- Home Controls activity view detail panel-->
     <dimen name="controls_activity_view_corner_radius">@*android:dimen/config_bottomDialogCornerRadius</dimen>
 
@@ -1631,6 +1630,10 @@
     <!-- Dream overlay complications related dimensions -->
     <!-- The blur radius applied to the dream overlay when entering and exiting dreams -->
     <dimen name="dream_overlay_anim_blur_radius">50dp</dimen>
+    <dimen name="dream_overlay_bottom_affordance_height">64dp</dimen>
+    <dimen name="dream_overlay_bottom_affordance_width">64dp</dimen>
+    <dimen name="dream_overlay_bottom_affordance_radius">32dp</dimen>
+    <dimen name="dream_overlay_bottom_affordance_padding">14dp</dimen>
     <dimen name="dream_overlay_complication_clock_time_text_size">86dp</dimen>
     <dimen name="dream_overlay_complication_clock_time_translation_y">28dp</dimen>
     <dimen name="dream_overlay_complication_home_controls_padding">28dp</dimen>
@@ -1700,6 +1703,19 @@
     <dimen name="media_output_broadcast_info_summary_height">20dp</dimen>
     <dimen name="media_output_broadcast_info_edit">18dp</dimen>
 
+    <!-- Keyboard backlight indicator-->
+    <dimen name="backlight_indicator_root_corner_radius">48dp</dimen>
+    <dimen name="backlight_indicator_root_vertical_padding">8dp</dimen>
+    <dimen name="backlight_indicator_root_horizontal_padding">4dp</dimen>
+    <dimen name="backlight_indicator_icon_width">22dp</dimen>
+    <dimen name="backlight_indicator_icon_height">11dp</dimen>
+    <dimen name="backlight_indicator_icon_left_margin">2dp</dimen>
+    <dimen name="backlight_indicator_step_width">52dp</dimen>
+    <dimen name="backlight_indicator_step_height">40dp</dimen>
+    <dimen name="backlight_indicator_step_horizontal_margin">4dp</dimen>
+    <dimen name="backlight_indicator_step_small_radius">4dp</dimen>
+    <dimen name="backlight_indicator_step_large_radius">48dp</dimen>
+
     <!-- Broadcast dialog -->
     <dimen name="broadcast_dialog_title_img_margin_top">18dp</dimen>
     <dimen name="broadcast_dialog_title_text_size">24sp</dimen>
@@ -1748,4 +1764,9 @@
     it is long-pressed.
     -->
     <dimen name="keyguard_long_press_settings_popup_vertical_offset">96dp</dimen>
+
+
+    <!-- Bouncer user switcher margins -->
+    <dimen name="bouncer_user_switcher_view_mode_user_switcher_bottom_margin">0dp</dimen>
+    <dimen name="bouncer_user_switcher_view_mode_view_flipper_bottom_margin">0dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 7b3caff..a02c429 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -191,8 +191,8 @@
 
     <!-- Power menu item for taking a screenshot [CHAR LIMIT=20]-->
     <string name="global_action_screenshot">Screenshot</string>
-    <!-- Message shown in power menu when smart lock has been disabled [CHAR_LIMIT=NONE] -->
-    <string name="global_action_smart_lock_disabled">Smart Lock disabled</string>
+    <!-- Message shown in power menu when Extend Unlock has been disabled [CHAR_LIMIT=NONE] -->
+    <string name="global_action_smart_lock_disabled">Extend Unlock disabled</string>
 
     <!-- text to show in place of RemoteInput images when they cannot be shown.
          [CHAR LIMIT=50] -->
@@ -407,8 +407,6 @@
 
     <!-- Message shown when the system-provided fingerprint dialog is shown, asking for authentication -->
     <string name="fingerprint_dialog_touch_sensor">Touch the fingerprint sensor</string>
-    <!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon">Fingerprint icon</string>
     <!-- Message shown to inform the user a face cannot be recognized and fingerprint should instead be used.[CHAR LIMIT=50] -->
     <string name="fingerprint_dialog_use_fingerprint_instead">Can\u2019t recognize face. Use fingerprint instead.</string>
     <!-- Message shown to inform the user a face cannot be recognized and fingerprint should instead be used.[CHAR LIMIT=50] -->
@@ -2339,6 +2337,8 @@
     <string name="magnification_mode_switch_state_window">Magnify part of screen</string>
     <!-- Click action label for magnification switch. [CHAR LIMIT=NONE] -->
     <string name="magnification_mode_switch_click_label">Switch</string>
+    <!-- Click action label for magnification settings panel. [CHAR LIMIT=NONE] -->
+    <string name="magnification_open_settings_click_label">Open magnification settings</string>
     <!-- Label of the corner of a rectangle that you can tap and drag to resize the magnification area. [CHAR LIMIT=NONE] -->
     <string name="magnification_drag_corner_to_resize">Drag corner to resize</string>
 
@@ -2360,6 +2360,8 @@
     <!-- Description of the window magnification Bottom handle [CHAR LIMIT=NONE]-->
     <string name="accessibility_magnification_bottom_handle">Bottom handle</string>
 
+    <!-- Description of the window magnification panel [CHAR LIMIT=NONE]-->
+    <string name="accessibility_magnification_settings_panel_description">Magnification settings</string>
     <!-- Title of the window magnification panel option Magnifier size [CHAR LIMIT=NONE]-->
     <string name="accessibility_magnifier_size">Magnifier size</string>
     <!-- Title of the window magnification panel option Zoom [CHAR LIMIT=NONE]-->
@@ -2429,7 +2431,11 @@
 
     <!-- Shows in a dialog presented to the user to authorize this app to display a Device controls
          panel (embedded activity) instead of controls rendered by SystemUI [CHAR LIMIT=NONE] -->
-    <string name="controls_panel_authorization">When you add <xliff:g id="appName" example="My app">%s</xliff:g>, it can add controls and content to this panel. In some apps, you can choose which controls show up here.</string>
+    <string name="controls_panel_authorization"><xliff:g id="appName" example="My app">%s</xliff:g>can choose which controls and content show here.</string>
+
+    <!-- Shows in a dialog presented to the user to authorize this app removal from a Device
+         controls panel [CHAR LIMIT=NONE] -->
+    <string name="controls_panel_remove_app_authorization">Remove controls for <xliff:g example="My app" id="appName">%s</xliff:g>?</string>
 
     <!-- a11y state description for a control that is currently favorited [CHAR LIMIT=NONE] -->
     <string name="accessibility_control_favorite">Favorited</string>
@@ -2471,6 +2477,8 @@
     <string name="controls_dialog_title">Add to device controls</string>
     <!-- Controls dialog add to favorites [CHAR LIMIT=40] -->
     <string name="controls_dialog_ok">Add</string>
+    <!-- Controls dialog remove app from a panel [CHAR LIMIT=40] -->
+    <string name="controls_dialog_remove">Remove</string>
     <!-- Controls dialog message. Indicates app that suggested this control [CHAR LIMIT=NONE] -->
     <string name="controls_dialog_message">Suggested by <xliff:g id="app" example="System UI">%s</xliff:g></string>
     <!-- Controls tile secondary label when device is locked and user does not want access to controls from lockscreen [CHAR LIMIT=20] -->
@@ -2483,7 +2491,7 @@
     <!-- Title of the dialog to control certain devices from lock screen without auth [CHAR LIMIT=NONE] -->
     <string name="controls_settings_trivial_controls_dialog_title">Control devices from lock screen?</string>
     <!-- Message of the dialog to control certain devices from lock screen without auth [CHAR LIMIT=NONE] -->
-    <string name="controls_settings_trivial_controls_dialog_message">You can control some devices without unlocking your phone or tablet.\n\nYour device app determines which devices can be controlled in this way.</string>
+    <string name="controls_settings_trivial_controls_dialog_message">You can control some devices without unlocking your phone or tablet. Your device app determines which devices can be controlled in this way.</string>
     <!-- Neutral button title of the controls dialog [CHAR LIMIT=NONE] -->
     <string name="controls_settings_dialog_neutral_button">No thanks</string>
     <!-- Positive button title of the controls dialog  [CHAR LIMIT=NONE] -->
@@ -2588,6 +2596,8 @@
     <string name="controls_menu_edit">Edit controls</string>
     <!-- Controls menu, add another app [CHAR LIMIT=30] -->
     <string name="controls_menu_add_another_app">Add app</string>
+    <!-- Controls menu, remove app [CHAR_LIMIT=30] -->
+    <string name="controls_menu_remove">Remove app</string>
 
     <!-- Title for the media output dialog with media related devices [CHAR LIMIT=50] -->
     <string name="media_output_dialog_add_output">Add outputs</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 2cd2173..6596ed2 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -1358,6 +1358,7 @@
         <item name="android:fontFamily">google-sans</item>
         <item name="android:textColor">?androidprv:attr/textColorPrimary</item>
         <item name="android:textSize">@dimen/magnification_setting_text_size</item>
+        <item name="android:singleLine">true</item>
     </style>
 
     <style name="TextAppearance.MagnificationSetting.EditButton">
diff --git a/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewScreenshotTestRule.kt b/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewScreenshotTestRule.kt
index 738b37c..2d47356 100644
--- a/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewScreenshotTestRule.kt
+++ b/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/ViewScreenshotTestRule.kt
@@ -39,14 +39,14 @@
 import platform.test.screenshot.matchers.BitmapMatcher
 
 /** A rule for View screenshot diff unit tests. */
-class ViewScreenshotTestRule(
+open class ViewScreenshotTestRule(
     emulationSpec: DeviceEmulationSpec,
     private val matcher: BitmapMatcher = UnitTestBitmapMatcher,
     assetsPathRelativeToBuildRoot: String
 ) : TestRule {
     private val colorsRule = MaterialYouColorsRule()
     private val deviceEmulationRule = DeviceEmulationRule(emulationSpec)
-    private val screenshotRule =
+    protected val screenshotRule =
         ScreenshotTestRule(
             SystemUIGoldenImagePathManager(
                 getEmulatedDevicePathConfig(emulationSpec),
@@ -64,15 +64,10 @@
         return delegateRule.apply(base, description)
     }
 
-    /**
-     * Compare the content of the view provided by [viewProvider] with the golden image identified
-     * by [goldenIdentifier] in the context of [emulationSpec].
-     */
-    fun screenshotTest(
-        goldenIdentifier: String,
+    protected fun takeScreenshot(
         mode: Mode = Mode.WrapContent,
         viewProvider: (ComponentActivity) -> View,
-    ) {
+    ): Bitmap {
         activityRule.scenario.onActivity { activity ->
             // Make sure that the activity draws full screen and fits the whole display instead of
             // the system bars.
@@ -99,7 +94,19 @@
             contentView = content.getChildAt(0)
         }
 
-        val bitmap = contentView?.toBitmap() ?: error("contentView is null")
+        return contentView?.toBitmap() ?: error("contentView is null")
+    }
+
+    /**
+     * Compare the content of the view provided by [viewProvider] with the golden image identified
+     * by [goldenIdentifier] in the context of [emulationSpec].
+     */
+    fun screenshotTest(
+        goldenIdentifier: String,
+        mode: Mode = Mode.WrapContent,
+        viewProvider: (ComponentActivity) -> View,
+    ) {
+        val bitmap = takeScreenshot(mode, viewProvider)
         screenshotRule.assertBitmapAgainstGolden(
             bitmap,
             goldenIdentifier,
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt
index 12e0b9a..c5979cc 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt
@@ -65,35 +65,40 @@
             } else {
                 1
             }
-        viewsToTranslate.forEach { (view, direction, shouldBeAnimated) ->
-            if (shouldBeAnimated()) {
-                view.get()?.translationX = xTrans * direction.multiplier * rtlMultiplier
-            }
+        viewsToTranslate.forEach { (view, direction) ->
+            view.get()?.translationX = xTrans * direction.multiplier * rtlMultiplier
         }
     }
 
     /** Finds in [parent] all views specified by [ids] and register them for the animation. */
     private fun registerViewsForAnimation(parent: ViewGroup, ids: Set<ViewIdToTranslate>) {
         viewsToTranslate =
-            ids.mapNotNull { (id, dir, pred) ->
-                parent.findViewById<View>(id)?.let { view ->
-                    ViewToTranslate(WeakReference(view), dir, pred)
+            ids.asSequence()
+                .filter { it.shouldBeAnimated() }
+                .mapNotNull {
+                    parent.findViewById<View>(it.viewId)?.let { view ->
+                        ViewToTranslate(WeakReference(view), it.direction)
+                    }
                 }
-            }
+                .toList()
     }
 
-    /** Represents a view to animate. [rootView] should contain a view with [viewId] inside. */
+    /**
+     * Represents a view to animate. [rootView] should contain a view with [viewId] inside.
+     * [shouldBeAnimated] is only evaluated when the viewsToTranslate is registered in
+     * [registerViewsForAnimation].
+     */
     data class ViewIdToTranslate(
         val viewId: Int,
         val direction: Direction,
         val shouldBeAnimated: () -> Boolean = { true }
     )
 
-    private data class ViewToTranslate(
-        val view: WeakReference<View>,
-        val direction: Direction,
-        val shouldBeAnimated: () -> Boolean
-    )
+    /**
+     * Represents a view whose animation process is in-progress. It should be immutable because the
+     * started animation should be completed.
+     */
+    private data class ViewToTranslate(val view: WeakReference<View>, val direction: Direction)
 
     /** Direction of the animation. */
     enum class Direction(val multiplier: Float) {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt
index 23742c5..454294f 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt
@@ -87,7 +87,7 @@
      * Helper for evaluating 3-valued logical AND/OR.
      *
      * @param returnValueIfAnyMatches AND returns false if any value is false. OR returns true if
-     * any value is true.
+     *   any value is true.
      */
     private fun threeValuedAndOrOr(
         conditions: Collection<Condition>,
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java
index 8690b36..0c2341f 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java
@@ -33,8 +33,6 @@
      */
     public static final int STAGE_POSITION_BOTTOM_OR_RIGHT = 1;
 
-    // Contains the portion of the thumbnail that is unclipped when fullscreen progress = 1.
-    private final RectF mClippedInsets = new RectF();
     private final Matrix mMatrix = new Matrix();
     private boolean mIsOrientationChanged;
     private SplitBounds mSplitBounds;
@@ -70,33 +68,6 @@
         int thumbnailRotation = thumbnailData.rotation;
         int deltaRotate = getRotationDelta(currentRotation, thumbnailRotation);
         RectF thumbnailClipHint = new RectF();
-
-        float scaledTaskbarSize;
-        float canvasScreenRatio;
-        if (mSplitBounds != null) {
-            if (mSplitBounds.appsStackedVertically) {
-                if (mDesiredStagePosition == STAGE_POSITION_TOP_OR_LEFT) {
-                    // Top app isn't cropped at all by taskbar
-                    canvasScreenRatio = 0;
-                } else {
-                    // Same as fullscreen ratio
-                    canvasScreenRatio = (float) canvasWidth / screenWidthPx;
-                }
-            } else {
-                // For landscape, scale the width
-                float taskPercent = mDesiredStagePosition == STAGE_POSITION_TOP_OR_LEFT
-                        ? mSplitBounds.leftTaskPercent
-                        : (1 - (mSplitBounds.leftTaskPercent + mSplitBounds.dividerWidthPercent));
-                // Scale landscape width to that of actual screen
-                float fullscreenTaskWidth = screenWidthPx * taskPercent;
-                canvasScreenRatio = canvasWidth / fullscreenTaskWidth;
-            }
-        } else {
-            canvasScreenRatio = (float) canvasWidth / screenWidthPx;
-        }
-        scaledTaskbarSize = taskbarSize * canvasScreenRatio;
-        thumbnailClipHint.bottom = isLargeScreen ? scaledTaskbarSize : 0;
-
         float scale = thumbnailData.scale;
         final float thumbnailScale;
 
@@ -116,10 +87,8 @@
 
             float surfaceWidth = thumbnailBounds.width() / scale;
             float surfaceHeight = thumbnailBounds.height() / scale;
-            float availableWidth = surfaceWidth
-                    - (thumbnailClipHint.left + thumbnailClipHint.right);
-            float availableHeight = surfaceHeight
-                    - (thumbnailClipHint.top + thumbnailClipHint.bottom);
+            float availableWidth = surfaceWidth;
+            float availableHeight = surfaceHeight;
 
             float canvasAspect = canvasWidth / (float) canvasHeight;
             float availableAspect = isRotated
@@ -210,8 +179,6 @@
             setThumbnailRotation(deltaRotate, thumbnailBounds);
         }
 
-        mClippedInsets.set(0, 0, 0, scaledTaskbarSize);
-
         mMatrix.postScale(thumbnailScale, thumbnailScale);
         mIsOrientationChanged = isOrientationDifferent;
     }
@@ -250,8 +217,4 @@
         }
         mMatrix.postTranslate(translateX, translateY);
     }
-
-    public RectF getClippedInsets() {
-        return mClippedInsets;
-    }
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt
index 9a581aa..482158e 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt
@@ -91,6 +91,22 @@
         val sampledRegion = calculateSampledRegion(sampledView)
         val regions = ArrayList<RectF>()
         val sampledRegionWithOffset = convertBounds(sampledRegion)
+
+        if (
+            sampledRegionWithOffset.left < 0.0 ||
+                sampledRegionWithOffset.right > 1.0 ||
+                sampledRegionWithOffset.top < 0.0 ||
+                sampledRegionWithOffset.bottom > 1.0
+        ) {
+            android.util.Log.e(
+                "RegionSampler",
+                "view out of bounds: $sampledRegion | " +
+                    "screen width: ${displaySize.x}, screen height: ${displaySize.y}",
+                Exception()
+            )
+            return
+        }
+
         regions.add(sampledRegionWithOffset)
 
         wallpaperManager?.removeOnColorsChangedListener(this)
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
index 359da13..53fab69 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
@@ -29,8 +29,11 @@
 import android.annotation.DrawableRes;
 import android.annotation.SuppressLint;
 import android.app.StatusBarManager;
+import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
@@ -86,15 +89,16 @@
     private RotationButton mRotationButton;
 
     private boolean mIsRecentsAnimationRunning;
+    private boolean mDocked;
     private boolean mHomeRotationEnabled;
     private int mLastRotationSuggestion;
     private boolean mPendingRotationSuggestion;
     private boolean mHoveringRotationSuggestion;
     private final AccessibilityManager mAccessibilityManager;
     private final TaskStackListenerImpl mTaskStackListener;
-    private Consumer<Integer> mRotWatcherListener;
 
     private boolean mListenersRegistered = false;
+    private boolean mRotationWatcherRegistered = false;
     private boolean mIsNavigationBarShowing;
     @SuppressLint("InlinedApi")
     private @WindowInsetsController.Behavior
@@ -123,6 +127,12 @@
             () -> mPendingRotationSuggestion = false;
     private Animator mRotateHideAnimator;
 
+    private final BroadcastReceiver mDockedReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            updateDockedState(intent);
+        }
+    };
 
     private final IRotationWatcher.Stub mRotationWatcher = new IRotationWatcher.Stub() {
         @Override
@@ -130,21 +140,7 @@
             // We need this to be scheduled as early as possible to beat the redrawing of
             // window in response to the orientation change.
             mMainThreadHandler.postAtFrontOfQueue(() -> {
-                // If the screen rotation changes while locked, potentially update lock to flow with
-                // new screen rotation and hide any showing suggestions.
-                boolean rotationLocked = isRotationLocked();
-                // The isVisible check makes the rotation button disappear when we are not locked
-                // (e.g. for tabletop auto-rotate).
-                if (rotationLocked || mRotationButton.isVisible()) {
-                    if (shouldOverrideUserLockPrefs(rotation) && rotationLocked) {
-                        setRotationLockedAtAngle(rotation);
-                    }
-                    setRotateSuggestionButtonState(false /* visible */, true /* forced */);
-                }
-
-                if (mRotWatcherListener != null) {
-                    mRotWatcherListener.accept(rotation);
-                }
+                onRotationWatcherChanged(rotation);
             });
         }
     };
@@ -195,8 +191,11 @@
         return mContext;
     }
 
+    /**
+     * Called during Taskbar initialization.
+     */
     public void init() {
-        registerListeners();
+        registerListeners(true /* registerRotationWatcher */);
         if (mContext.getDisplay().getDisplayId() != DEFAULT_DISPLAY) {
             // Currently there is no accelerometer sensor on non-default display, disable fixed
             // rotation for non-default display
@@ -204,25 +203,35 @@
         }
     }
 
+    /**
+     * Called during Taskbar uninitialization.
+     */
     public void onDestroy() {
         unregisterListeners();
     }
 
-    public void registerListeners() {
+    public void registerListeners(boolean registerRotationWatcher) {
         if (mListenersRegistered || getContext().getPackageManager().hasSystemFeature(FEATURE_PC)) {
             return;
         }
 
         mListenersRegistered = true;
-        try {
-            WindowManagerGlobal.getWindowManagerService()
-                    .watchRotation(mRotationWatcher, DEFAULT_DISPLAY);
-        } catch (IllegalArgumentException e) {
-            mListenersRegistered = false;
-            Log.w(TAG, "RegisterListeners for the display failed");
-        } catch (RemoteException e) {
-            Log.e(TAG, "RegisterListeners caught a RemoteException", e);
-            return;
+
+        updateDockedState(mContext.registerReceiver(mDockedReceiver,
+                new IntentFilter(Intent.ACTION_DOCK_EVENT)));
+
+        if (registerRotationWatcher) {
+            try {
+                WindowManagerGlobal.getWindowManagerService()
+                        .watchRotation(mRotationWatcher, DEFAULT_DISPLAY);
+                mRotationWatcherRegistered = true;
+            } catch (IllegalArgumentException e) {
+                mListenersRegistered = false;
+                Log.w(TAG, "RegisterListeners for the display failed", e);
+            } catch (RemoteException e) {
+                Log.e(TAG, "RegisterListeners caught a RemoteException", e);
+                return;
+            }
         }
 
         TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener);
@@ -234,20 +243,21 @@
         }
 
         mListenersRegistered = false;
-        try {
-            WindowManagerGlobal.getWindowManagerService().removeRotationWatcher(mRotationWatcher);
-        } catch (RemoteException e) {
-            Log.e(TAG, "UnregisterListeners caught a RemoteException", e);
-            return;
+
+        mContext.unregisterReceiver(mDockedReceiver);
+        if (mRotationWatcherRegistered) {
+            try {
+                WindowManagerGlobal.getWindowManagerService().removeRotationWatcher(
+                        mRotationWatcher);
+            } catch (RemoteException e) {
+                Log.e(TAG, "UnregisterListeners caught a RemoteException", e);
+                return;
+            }
         }
 
         TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
     }
 
-    public void setRotationCallback(Consumer<Integer> watcher) {
-        mRotWatcherListener = watcher;
-    }
-
     public void setRotationLockedAtAngle(int rotationSuggestion) {
         RotationPolicy.setRotationLockAtAngle(mContext, /* enabled= */ isRotationLocked(),
                 /* rotation= */ rotationSuggestion);
@@ -345,6 +355,15 @@
         updateRotationButtonStateInOverview();
     }
 
+    private void updateDockedState(Intent intent) {
+        if (intent == null) {
+            return;
+        }
+
+        mDocked = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_UNDOCKED)
+                != Intent.EXTRA_DOCK_STATE_UNDOCKED;
+    }
+
     private void updateRotationButtonStateInOverview() {
         if (mIsRecentsAnimationRunning && !mHomeRotationEnabled) {
             setRotateSuggestionButtonState(false, true /* hideImmediately */);
@@ -401,6 +420,30 @@
         }
     }
 
+    /**
+     * Called when the rotation watcher rotation changes, either from the watcher registered
+     * internally in this class, or a signal propagated from NavBarHelper.
+     */
+    public void onRotationWatcherChanged(int rotation) {
+        if (!mListenersRegistered) {
+            // Ignore if not registered
+            return;
+        }
+
+        // If the screen rotation changes while locked, potentially update lock to flow with
+        // new screen rotation and hide any showing suggestions.
+        boolean rotationLocked = isRotationLocked();
+        // The isVisible check makes the rotation button disappear when we are not locked
+        // (e.g. for tabletop auto-rotate).
+        if (rotationLocked || mRotationButton.isVisible()) {
+            // Do not allow a change in rotation to set user rotation when docked.
+            if (shouldOverrideUserLockPrefs(rotation) && rotationLocked && !mDocked) {
+                setRotationLockedAtAngle(rotation);
+            }
+            setRotateSuggestionButtonState(false /* visible */, true /* forced */);
+        }
+    }
+
     public void onDisable2FlagChanged(int state2) {
         final boolean rotateSuggestionsDisabled = hasDisable2RotateSuggestionFlag(state2);
         if (rotateSuggestionsDisabled) onRotationSuggestionsDisabled();
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index 6dd359c..45a5ce3 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -18,7 +18,6 @@
 
 import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
 import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
-import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
 import static android.app.ActivityTaskManager.getService;
 
 import android.annotation.NonNull;
@@ -45,6 +44,7 @@
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.util.Log;
+import android.view.Display;
 import android.view.IRecentsAnimationController;
 import android.view.IRecentsAnimationRunner;
 import android.view.RemoteAnimationTarget;
@@ -112,6 +112,13 @@
     }
 
     /**
+     * @see #getRunningTasks(boolean , int)
+     */
+    public ActivityManager.RunningTaskInfo[] getRunningTasks(boolean filterOnlyVisibleRecents) {
+        return getRunningTasks(filterOnlyVisibleRecents, Display.INVALID_DISPLAY);
+    }
+
+    /**
      * We ask for {@link #NUM_RECENT_ACTIVITIES_REQUEST} activities because when in split screen,
      * we'll get back 2 activities for each split app and one for launcher. Launcher might be more
      * "recently" used than one of the split apps so if we only request 2 tasks, then we might miss
@@ -120,10 +127,12 @@
      * @return an array of up to {@link #NUM_RECENT_ACTIVITIES_REQUEST} running tasks
      *         filtering only for tasks that can be visible in the recent tasks list.
      */
-    public ActivityManager.RunningTaskInfo[] getRunningTasks(boolean filterOnlyVisibleRecents) {
+    public ActivityManager.RunningTaskInfo[] getRunningTasks(boolean filterOnlyVisibleRecents,
+            int displayId) {
         // Note: The set of running tasks from the system is ordered by recency
         List<ActivityManager.RunningTaskInfo> tasks =
-                mAtm.getTasks(NUM_RECENT_ACTIVITIES_REQUEST, filterOnlyVisibleRecents);
+                mAtm.getTasks(NUM_RECENT_ACTIVITIES_REQUEST,
+                        filterOnlyVisibleRecents, /* keepInExtras= */ false, displayId);
         return tasks.toArray(new RunningTaskInfo[tasks.size()]);
     }
 
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 7d39c4a..0d36d04 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
@@ -23,6 +23,7 @@
 import android.annotation.IntDef;
 import android.content.Context;
 import android.content.res.Resources;
+import android.os.SystemProperties;
 import android.view.ViewConfiguration;
 import android.view.WindowManagerPolicyConstants;
 
@@ -115,6 +116,30 @@
     public static final int SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE = 1 << 26;
     // Device dreaming state
     public static final int SYSUI_STATE_DEVICE_DREAMING = 1 << 27;
+    // Whether the screen is currently on. Note that the screen is considered on while turning on,
+    // but not while turning off.
+    public static final int SYSUI_STATE_SCREEN_ON = 1 << 28;
+    // Whether the screen is currently transitioning into the state indicated by
+    // SYSUI_STATE_SCREEN_ON.
+    public static final int SYSUI_STATE_SCREEN_TRANSITION = 1 << 29;
+
+    // Mask for SystemUiStateFlags to isolate SYSUI_STATE_SCREEN_ON and
+    // SYSUI_STATE_SCREEN_TRANSITION, to match SCREEN_STATE_*
+    public static final int SYSUI_STATE_SCREEN_STATE_MASK =
+            SYSUI_STATE_SCREEN_ON | SYSUI_STATE_SCREEN_TRANSITION;
+    // Screen is off.
+    public static final int SCREEN_STATE_OFF = 0;
+    // Screen is on.
+    public static final int SCREEN_STATE_ON = SYSUI_STATE_SCREEN_ON;
+    // Screen is still on, but transitioning to turn off.
+    public static final int SCREEN_STATE_TURNING_OFF = SYSUI_STATE_SCREEN_TRANSITION;
+    // Screen was off and is now turning on.
+    public static final int SCREEN_STATE_TURNING_ON =
+            SYSUI_STATE_SCREEN_TRANSITION | SYSUI_STATE_SCREEN_ON;
+
+    // Whether the back gesture is allowed (or ignored) by the Shade
+    public static final boolean ALLOW_BACK_GESTURE_IN_SHADE = SystemProperties.getBoolean(
+            "persist.wm.debug.shade_allow_back_gesture", false);
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({SYSUI_STATE_SCREEN_PINNING,
@@ -144,7 +169,9 @@
             SYSUI_STATE_IMMERSIVE_MODE,
             SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING,
             SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE,
-            SYSUI_STATE_DEVICE_DREAMING
+            SYSUI_STATE_DEVICE_DREAMING,
+            SYSUI_STATE_SCREEN_ON,
+            SYSUI_STATE_SCREEN_TRANSITION,
     })
     public @interface SystemUiStateFlags {}
 
@@ -183,6 +210,9 @@
         str.add((flags & SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE) != 0
                 ? "freeform_active_in_desktop_mode" : "");
         str.add((flags & SYSUI_STATE_DEVICE_DREAMING) != 0 ? "device_dreaming" : "");
+        str.add("screen_"
+                + ((flags & SYSUI_STATE_SCREEN_TRANSITION) != 0 ? "turning_" : "")
+                + ((flags & SYSUI_STATE_SCREEN_ON) != 0 ? "on" : "off"));
 
         return str.toString();
     }
@@ -243,9 +273,14 @@
             sysuiStateFlags &= ~SYSUI_STATE_NAV_BAR_HIDDEN;
         }
         // Disable when in immersive, or the notifications are interactive
-        int disableFlags = SYSUI_STATE_NAV_BAR_HIDDEN
-                | SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED
-                | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
+        int disableFlags = SYSUI_STATE_NAV_BAR_HIDDEN | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
+
+        // EdgeBackGestureHandler ignores Back gesture when SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED.
+        // To allow Shade to respond to Back, we're bypassing this check (behind a flag).
+        if (!ALLOW_BACK_GESTURE_IN_SHADE) {
+            disableFlags |= SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
+        }
+
         return (sysuiStateFlags & disableFlags) != 0;
     }
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
index ae68618..44f9d43 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
@@ -16,30 +16,9 @@
 
 package com.android.systemui.shared.system;
 
-import static android.app.ActivityTaskManager.INVALID_TASK_ID;
-import static android.view.RemoteAnimationTarget.MODE_CHANGING;
-import static android.view.RemoteAnimationTarget.MODE_CLOSING;
-import static android.view.RemoteAnimationTarget.MODE_OPENING;
-import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
-import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
-import static android.view.WindowManager.TRANSIT_OPEN;
-import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY;
-import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
-import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
-
-import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SuppressLint;
-import android.app.ActivityManager;
-import android.app.WindowConfiguration;
-import android.graphics.Rect;
 import android.util.ArrayMap;
-import android.util.SparseBooleanArray;
 import android.view.RemoteAnimationTarget;
 import android.view.SurfaceControl;
-import android.view.WindowManager;
 import android.window.TransitionInfo;
 import android.window.TransitionInfo.Change;
 
@@ -53,156 +32,6 @@
  */
 public class RemoteAnimationTargetCompat {
 
-    private static int newModeToLegacyMode(int newMode) {
-        switch (newMode) {
-            case WindowManager.TRANSIT_OPEN:
-            case WindowManager.TRANSIT_TO_FRONT:
-                return MODE_OPENING;
-            case WindowManager.TRANSIT_CLOSE:
-            case WindowManager.TRANSIT_TO_BACK:
-                return MODE_CLOSING;
-            default:
-                return MODE_CHANGING;
-        }
-    }
-
-    /**
-     * Almost a copy of Transitions#setupStartState.
-     * TODO: remove when there is proper cross-process transaction sync.
-     */
-    @SuppressLint("NewApi")
-    private static void setupLeash(@NonNull SurfaceControl leash,
-            @NonNull TransitionInfo.Change change, int layer,
-            @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t) {
-        final boolean isOpening = TransitionUtil.isOpeningType(info.getType());
-        // Put animating stuff above this line and put static stuff below it.
-        int zSplitLine = info.getChanges().size();
-        // changes should be ordered top-to-bottom in z
-        final int mode = change.getMode();
-
-        t.reparent(leash, info.getRootLeash());
-        final Rect absBounds =
-                (mode == TRANSIT_OPEN) ? change.getEndAbsBounds() : change.getStartAbsBounds();
-        t.setPosition(leash, absBounds.left - info.getRootOffset().x,
-                absBounds.top - info.getRootOffset().y);
-
-        // Put all the OPEN/SHOW on top
-        if (TransitionUtil.isOpeningType(mode)) {
-            if (isOpening) {
-                t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
-                if ((change.getFlags() & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) == 0) {
-                    // if transferred, it should be left visible.
-                    t.setAlpha(leash, 0.f);
-                }
-            } else {
-                // put on bottom and leave it visible
-                t.setLayer(leash, zSplitLine - layer);
-            }
-        } else if (TransitionUtil.isClosingType(mode)) {
-            if (isOpening) {
-                // put on bottom and leave visible
-                t.setLayer(leash, zSplitLine - layer);
-            } else {
-                // put on top
-                t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
-            }
-        } else { // CHANGE
-            t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
-        }
-    }
-
-    @SuppressLint("NewApi")
-    private static SurfaceControl createLeash(TransitionInfo info, TransitionInfo.Change change,
-            int order, SurfaceControl.Transaction t) {
-        // TODO: once we can properly sync transactions across process, then get rid of this leash.
-        if (change.getParent() != null && (change.getFlags() & FLAG_IS_WALLPAPER) != 0) {
-            // Special case for wallpaper atm. Normally these are left alone; but, a quirk of
-            // making leashes means we have to handle them specially.
-            return change.getLeash();
-        }
-        SurfaceControl leashSurface = new SurfaceControl.Builder()
-                .setName(change.getLeash().toString() + "_transition-leash")
-                .setContainerLayer()
-                // Initial the surface visible to respect the visibility of the original surface.
-                .setHidden(false)
-                .setParent(info.getRootLeash())
-                .build();
-        // Copied Transitions setup code (which expects bottom-to-top order, so we swap here)
-        setupLeash(leashSurface, change, info.getChanges().size() - order, info, t);
-        t.reparent(change.getLeash(), leashSurface);
-        t.setAlpha(change.getLeash(), 1.0f);
-        t.show(change.getLeash());
-        t.setPosition(change.getLeash(), 0, 0);
-        t.setLayer(change.getLeash(), 0);
-        return leashSurface;
-    }
-
-    /**
-     * Creates a new RemoteAnimationTarget from the provided change info
-     */
-    public static RemoteAnimationTarget newTarget(TransitionInfo.Change change, int order,
-            TransitionInfo info, SurfaceControl.Transaction t,
-            @Nullable ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
-        final SurfaceControl leash = createLeash(info, change, order, t);
-        if (leashMap != null) {
-            leashMap.put(change.getLeash(), leash);
-        }
-        return newTarget(change, order, leash);
-    }
-
-    /**
-     * Creates a new RemoteAnimationTarget from the provided change and leash
-     */
-    public static RemoteAnimationTarget newTarget(TransitionInfo.Change change, int order,
-            SurfaceControl leash) {
-        int taskId;
-        boolean isNotInRecents;
-        ActivityManager.RunningTaskInfo taskInfo;
-        WindowConfiguration windowConfiguration;
-
-        taskInfo = change.getTaskInfo();
-        if (taskInfo != null) {
-            taskId = taskInfo.taskId;
-            isNotInRecents = !taskInfo.isRunning;
-            windowConfiguration = taskInfo.configuration.windowConfiguration;
-        } else {
-            taskId = INVALID_TASK_ID;
-            isNotInRecents = true;
-            windowConfiguration = new WindowConfiguration();
-        }
-
-        Rect localBounds = new Rect(change.getEndAbsBounds());
-        localBounds.offsetTo(change.getEndRelOffset().x, change.getEndRelOffset().y);
-
-        RemoteAnimationTarget target = new RemoteAnimationTarget(
-                taskId,
-                newModeToLegacyMode(change.getMode()),
-                // TODO: once we can properly sync transactions across process,
-                // then get rid of this leash.
-                leash,
-                (change.getFlags() & TransitionInfo.FLAG_TRANSLUCENT) != 0,
-                null,
-                // TODO(shell-transitions): we need to send content insets? evaluate how its used.
-                new Rect(0, 0, 0, 0),
-                order,
-                null,
-                localBounds,
-                new Rect(change.getEndAbsBounds()),
-                windowConfiguration,
-                isNotInRecents,
-                null,
-                new Rect(change.getStartAbsBounds()),
-                taskInfo,
-                change.getAllowEnterPip(),
-                (change.getFlags() & FLAG_IS_DIVIDER_BAR) != 0
-                        ? TYPE_DOCK_DIVIDER : INVALID_WINDOW_TYPE
-        );
-        target.setWillShowImeOnTarget(
-                (change.getFlags() & TransitionInfo.FLAG_WILL_IME_SHOWN) != 0);
-        target.setRotationChange(change.getEndRotation() - change.getStartRotation());
-        return target;
-    }
-
     /**
      * Represents a TransitionInfo object as an array of old-style app targets
      *
@@ -211,7 +40,7 @@
      */
     public static RemoteAnimationTarget[] wrapApps(TransitionInfo info,
             SurfaceControl.Transaction t, ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
-        return wrap(info, t, leashMap, new LeafTaskFilter());
+        return wrap(info, t, leashMap, new TransitionUtil.LeafTaskFilter());
     }
 
     /**
@@ -224,8 +53,8 @@
      */
     public static RemoteAnimationTarget[] wrapNonApps(TransitionInfo info, boolean wallpapers,
             SurfaceControl.Transaction t, ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
-        return wrap(info, t, leashMap, (change) ->
-                (wallpapers ? isWallpaper(change) : isNonApp(change)));
+        return wrap(info, t, leashMap, (change) -> (wallpapers
+                ? TransitionUtil.isWallpaper(change) : TransitionUtil.isNonApp(change)));
     }
 
     private static RemoteAnimationTarget[] wrap(TransitionInfo info,
@@ -235,45 +64,10 @@
         for (int i = 0; i < info.getChanges().size(); i++) {
             TransitionInfo.Change change = info.getChanges().get(i);
             if (filter.test(change)) {
-                out.add(newTarget(change, info.getChanges().size() - i, info, t, leashMap));
+                out.add(TransitionUtil.newTarget(
+                        change, info.getChanges().size() - i, info, t, leashMap));
             }
         }
         return out.toArray(new RemoteAnimationTarget[out.size()]);
     }
-
-    /** Returns `true` if `change` is a wallpaper. */
-    public static boolean isWallpaper(Change change) {
-        return (change.getTaskInfo() == null)
-                && change.hasFlags(FLAG_IS_WALLPAPER)
-                && !change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY);
-    }
-
-    /** Returns `true` if `change` is not an app window or wallpaper. */
-    public static boolean isNonApp(Change change) {
-        return (change.getTaskInfo() == null)
-                && !change.hasFlags(FLAG_IS_WALLPAPER)
-                && !change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY);
-    }
-
-    /**
-     * Filter that selects leaf-tasks only. THIS IS ORDER-DEPENDENT! For it to work properly, you
-     * MUST call `test` in the same order that the changes appear in the TransitionInfo.
-     */
-    public static class LeafTaskFilter implements Predicate<Change> {
-        private final SparseBooleanArray mChildTaskTargets = new SparseBooleanArray();
-
-        @Override
-        public boolean test(Change change) {
-            final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
-            // Children always come before parent since changes are in top-to-bottom z-order.
-            if ((taskInfo == null) || mChildTaskTargets.get(taskInfo.taskId)) {
-                // has children, so not a leaf. Skip.
-                return false;
-            }
-            if (taskInfo.hasParentTask()) {
-                mChildTaskTargets.put(taskInfo.parentTaskId, true);
-            }
-            return true;
-        }
-    }
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
index 70a36ce..58e7747 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
@@ -20,8 +20,7 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
 import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED;
-
-import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.newTarget;
+import static android.view.WindowManager.TRANSIT_SLEEP;
 
 import android.annotation.SuppressLint;
 import android.app.ActivityManager;
@@ -45,10 +44,10 @@
 import android.window.WindowContainerTransaction;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.shared.recents.model.ThumbnailData;
 import com.android.wm.shell.util.TransitionUtil;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 
 /**
  * Helper class to build {@link RemoteTransition} objects
@@ -58,7 +57,7 @@
 
     /** Constructor specifically for recents animation */
     public static RemoteTransition newRemoteTransition(RecentsAnimationListener recents,
-            RecentsAnimationControllerCompat controller, IApplicationThread appThread) {
+            IApplicationThread appThread) {
         IRemoteTransition remote = new IRemoteTransition.Stub() {
             final RecentsControllerWrap mRecentsSession = new RecentsControllerWrap();
             IBinder mToken = null;
@@ -69,7 +68,7 @@
                     IRemoteTransitionFinishedCallback finishedCallback) {
                 // TODO(b/177438007): Move this set-up logic into launcher's animation impl.
                 mToken = transition;
-                mRecentsSession.start(controller, recents, mToken, info, t, finishedCallback);
+                mRecentsSession.start(recents, mToken, info, t, finishedCallback);
             }
 
             @Override
@@ -98,9 +97,8 @@
      * TODO(b/177438007): Remove this once Launcher handles shell transitions directly.
      */
     @VisibleForTesting
-    static class RecentsControllerWrap extends RecentsAnimationControllerCompat {
+    static class RecentsControllerWrap extends IRecentsAnimationController.Default {
         private RecentsAnimationListener mListener = null;
-        private RecentsAnimationControllerCompat mWrapped = null;
         private IRemoteTransitionFinishedCallback mFinishCB = null;
 
         /**
@@ -137,7 +135,7 @@
         /** The latest state that the recents animation is operating in. */
         private int mState = STATE_NORMAL;
 
-        void start(RecentsAnimationControllerCompat wrapped, RecentsAnimationListener listener,
+        void start(RecentsAnimationListener listener,
                 IBinder transition, TransitionInfo info, SurfaceControl.Transaction t,
                 IRemoteTransitionFinishedCallback finishedCallback) {
             if (mInfo != null) {
@@ -145,7 +143,6 @@
                         + " recents is already active.");
             }
             mListener = listener;
-            mWrapped = wrapped;
             mInfo = info;
             mFinishCB = finishedCallback;
             mPausingTasks = new ArrayList<>();
@@ -160,16 +157,15 @@
 
             final ArrayList<RemoteAnimationTarget> apps = new ArrayList<>();
             final ArrayList<RemoteAnimationTarget> wallpapers = new ArrayList<>();
-            RemoteAnimationTargetCompat.LeafTaskFilter leafTaskFilter =
-                    new RemoteAnimationTargetCompat.LeafTaskFilter();
+            TransitionUtil.LeafTaskFilter leafTaskFilter = new TransitionUtil.LeafTaskFilter();
             // About layering: we divide up the "layer space" into 3 regions (each the size of
             // the change count). This lets us categorize things into above/below/between
             // while maintaining their relative ordering.
             for (int i = 0; i < info.getChanges().size(); ++i) {
                 final TransitionInfo.Change change = info.getChanges().get(i);
                 final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
-                if (RemoteAnimationTargetCompat.isWallpaper(change)) {
-                    final RemoteAnimationTarget target = newTarget(change,
+                if (TransitionUtil.isWallpaper(change)) {
+                    final RemoteAnimationTarget target = TransitionUtil.newTarget(change,
                             // wallpapers go into the "below" layer space
                             info.getChanges().size() - i, info, t, mLeashMap);
                     wallpapers.add(target);
@@ -177,7 +173,7 @@
                     t.setAlpha(target.leash, 1);
                 } else if (leafTaskFilter.test(change)) {
                     // start by putting everything into the "below" layer space.
-                    final RemoteAnimationTarget target = newTarget(change,
+                    final RemoteAnimationTarget target = TransitionUtil.newTarget(change,
                             info.getChanges().size() - i, info, t, mLeashMap);
                     apps.add(target);
                     if (TransitionUtil.isClosingType(change.getMode())) {
@@ -203,13 +199,20 @@
                 }
             }
             t.apply();
-            mListener.onAnimationStart(this, apps.toArray(new RemoteAnimationTarget[apps.size()]),
+            mListener.onAnimationStart(new RecentsAnimationControllerCompat(this),
+                    apps.toArray(new RemoteAnimationTarget[apps.size()]),
                     wallpapers.toArray(new RemoteAnimationTarget[wallpapers.size()]),
                     new Rect(0, 0, 0, 0), new Rect());
         }
 
         @SuppressLint("NewApi")
         boolean merge(TransitionInfo info, SurfaceControl.Transaction t) {
+            if (info.getType() == TRANSIT_SLEEP) {
+                // A sleep event means we need to stop animations immediately, so cancel here.
+                mListener.onAnimationCanceled(new HashMap<>());
+                finish(mWillFinishToHome, false /* userLeaveHint */);
+                return false;
+            }
             ArrayList<TransitionInfo.Change> openingTasks = null;
             ArrayList<TransitionInfo.Change> closingTasks = null;
             mAppearedTargets = null;
@@ -217,8 +220,8 @@
             TransitionInfo.Change recentsOpening = null;
             boolean foundRecentsClosing = false;
             boolean hasChangingApp = false;
-            final RemoteAnimationTargetCompat.LeafTaskFilter leafTaskFilter =
-                    new RemoteAnimationTargetCompat.LeafTaskFilter();
+            final TransitionUtil.LeafTaskFilter leafTaskFilter =
+                    new TransitionUtil.LeafTaskFilter();
             for (int i = 0; i < info.getChanges().size(); ++i) {
                 final TransitionInfo.Change change = info.getChanges().get(i);
                 final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
@@ -246,6 +249,13 @@
                         closingTasks.add(change);
                     }
                 } else if (change.getMode() == TRANSIT_CHANGE) {
+                    // Finish recents animation if the display is changed, so the default
+                    // transition handler can play the animation such as rotation effect.
+                    if (change.hasFlags(TransitionInfo.FLAG_IS_DISPLAY)) {
+                        mListener.onSwitchToScreenshot(() -> finish(false /* toHome */,
+                                false /* userLeaveHint */));
+                        return false;
+                    }
                     hasChangingApp = true;
                 }
             }
@@ -301,7 +311,8 @@
                     int pausingIdx = TaskState.indexOf(mPausingTasks, change);
                     if (pausingIdx >= 0) {
                         // Something is showing/opening a previously-pausing app.
-                        targets[i] = newTarget(change, layer, mPausingTasks.get(pausingIdx).mLeash);
+                        targets[i] = TransitionUtil.newTarget(change, layer,
+                                mPausingTasks.get(pausingIdx).mLeash);
                         mOpeningTasks.add(mPausingTasks.remove(pausingIdx));
                         // Setup hides opening tasks initially, so make it visible again (since we
                         // are already showing it).
@@ -309,8 +320,10 @@
                         t.setAlpha(change.getLeash(), 1.f);
                     } else {
                         // We are receiving new opening tasks, so convert to onTasksAppeared.
-                        targets[i] = newTarget(change, layer, info, t, mLeashMap);
-                        t.reparent(targets[i].leash, mInfo.getRootLeash());
+                        targets[i] = TransitionUtil.newTarget(change, layer, info, t, mLeashMap);
+                        // reparent into the original `mInfo` since that's where we are animating.
+                        final int rootIdx = TransitionUtil.rootIndexFor(change, mInfo);
+                        t.reparent(targets[i].leash, mInfo.getRoot(rootIdx).getLeash());
                         t.setLayer(targets[i].leash, layer);
                         mOpeningTasks.add(new TaskState(change, targets[i].leash));
                     }
@@ -337,13 +350,9 @@
             }
         }
 
-        @Override public ThumbnailData screenshotTask(int taskId) {
+        @Override public TaskSnapshot screenshotTask(int taskId) {
             try {
-                final TaskSnapshot snapshot =
-                        ActivityTaskManager.getService().takeTaskSnapshot(taskId);
-                if (snapshot != null) {
-                    return new ThumbnailData(snapshot);
-                }
+                return ActivityTaskManager.getService().takeTaskSnapshot(taskId);
             } catch (RemoteException e) {
                 Log.e(TAG, "Failed to screenshot task", e);
             }
@@ -351,30 +360,24 @@
         }
 
         @Override public void setInputConsumerEnabled(boolean enabled) {
-            if (enabled) {
-                // transient launches don't receive focus automatically. Since we are taking over
-                // the gesture now, take focus explicitly.
-                // This also moves recents back to top if the user gestured before a switch
-                // animation finished.
-                try {
-                    ActivityTaskManager.getService().setFocusedTask(mRecentsTaskId);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Failed to set focused task", e);
-                }
+            if (!enabled) return;
+            // transient launches don't receive focus automatically. Since we are taking over
+            // the gesture now, take focus explicitly.
+            // This also moves recents back to top if the user gestured before a switch
+            // animation finished.
+            try {
+                ActivityTaskManager.getService().setFocusedTask(mRecentsTaskId);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to set focused task", e);
             }
-            if (mWrapped != null) mWrapped.setInputConsumerEnabled(enabled);
         }
 
         @Override public void setAnimationTargetsBehindSystemBars(boolean behindSystemBars) {
-            if (mWrapped != null) mWrapped.setAnimationTargetsBehindSystemBars(behindSystemBars);
         }
 
         @Override public void setFinishTaskTransaction(int taskId,
                 PictureInPictureSurfaceTransaction finishTransaction, SurfaceControl overlay) {
             mPipTransaction = finishTransaction;
-            if (mWrapped != null) {
-                mWrapped.setFinishTaskTransaction(taskId, finishTransaction, overlay);
-            }
         }
 
         @Override
@@ -384,7 +387,6 @@
                 Log.e(TAG, "Duplicate call to finish", new RuntimeException());
                 return;
             }
-            if (mWrapped != null) mWrapped.finish(toHome, sendUserLeaveHint);
             final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
             final WindowContainerTransaction wct = new WindowContainerTransaction();
 
@@ -457,7 +459,6 @@
             // for releasing the leashes created by local.
             mInfo.releaseAllSurfaces();
             // Reset all members.
-            mWrapped = null;
             mListener = null;
             mFinishCB = null;
             mPausingTasks = null;
@@ -471,23 +472,20 @@
         }
 
         @Override public void setDeferCancelUntilNextTransition(boolean defer, boolean screenshot) {
-            if (mWrapped != null) mWrapped.setDeferCancelUntilNextTransition(defer, screenshot);
         }
 
         @Override public void cleanupScreenshot() {
-            if (mWrapped != null) mWrapped.cleanupScreenshot();
         }
 
         @Override public void setWillFinishToHome(boolean willFinishToHome) {
             mWillFinishToHome = willFinishToHome;
-            if (mWrapped != null) mWrapped.setWillFinishToHome(willFinishToHome);
         }
 
         /**
          * @see IRecentsAnimationController#removeTask
          */
         @Override public boolean removeTask(int taskId) {
-            return mWrapped != null ? mWrapped.removeTask(taskId) : false;
+            return false;
         }
 
         /**
diff --git a/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt b/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
index 8323d09..f005bab 100644
--- a/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
+++ b/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
@@ -23,6 +23,8 @@
 import dagger.Binds
 import dagger.Module
 import dagger.Provides
+import dagger.multibindings.IntoSet
+import javax.inject.Named
 
 @Module(includes = [
     FeatureFlagsDebugStartableModule::class,
@@ -35,7 +37,8 @@
     abstract fun bindsFeatureFlagDebug(impl: FeatureFlagsDebug): FeatureFlags
 
     @Binds
-    abstract fun bindsRestarter(debugRestarter: FeatureFlagsDebugRestarter): Restarter
+    @IntoSet
+    abstract fun bindsScreenIdleCondition(impl: ScreenIdleCondition): ConditionalRestarter.Condition
 
     @Module
     companion object {
@@ -44,5 +47,10 @@
         fun provideFlagManager(context: Context, @Main handler: Handler): FlagManager {
             return FlagManager(context, handler)
         }
+
+        @JvmStatic
+        @Provides
+        @Named(ConditionalRestarter.RESTART_DELAY)
+        fun provideRestartDelaySec(): Long = 1
     }
 }
diff --git a/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt b/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt
index 87beff7..927d4604b 100644
--- a/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt
+++ b/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt
@@ -18,6 +18,9 @@
 
 import dagger.Binds
 import dagger.Module
+import dagger.Provides
+import dagger.multibindings.IntoSet
+import javax.inject.Named
 
 @Module(includes = [
     FeatureFlagsReleaseStartableModule::class,
@@ -29,5 +32,18 @@
     abstract fun bindsFeatureFlagRelease(impl: FeatureFlagsRelease): FeatureFlags
 
     @Binds
-    abstract fun bindsRestarter(debugRestarter: FeatureFlagsReleaseRestarter): Restarter
+    @IntoSet
+    abstract fun bindsScreenIdleCondition(impl: ScreenIdleCondition): ConditionalRestarter.Condition
+
+    @Binds
+    @IntoSet
+    abstract fun bindsPluggedInCondition(impl: PluggedInCondition): ConditionalRestarter.Condition
+
+    @Module
+    companion object {
+        @JvmStatic
+        @Provides
+        @Named(ConditionalRestarter.RESTART_DELAY)
+        fun provideRestartDelaySec(): Long = 30
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
index 92ee373..4aaa566 100644
--- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
@@ -21,6 +21,7 @@
 import android.content.Intent
 import android.content.IntentFilter
 import android.content.res.Resources
+import android.graphics.Rect
 import android.text.format.DateFormat
 import android.util.TypedValue
 import android.view.View
@@ -119,10 +120,6 @@
 
     private val mLayoutChangedListener =
         object : View.OnLayoutChangeListener {
-            private var currentSmallClockView: View? = null
-            private var currentLargeClockView: View? = null
-            private var currentSmallClockLocation = IntArray(2)
-            private var currentLargeClockLocation = IntArray(2)
 
             override fun onLayoutChange(
                 view: View?,
@@ -135,6 +132,8 @@
                 oldRight: Int,
                 oldBottom: Int
             ) {
+                view?.removeOnLayoutChangeListener(this)
+
                 val parent = (view?.parent) as FrameLayout
 
                 // don't pass in negative bounds when clocks are in transition state
@@ -142,31 +141,12 @@
                     return
                 }
 
-                // SMALL CLOCK
-                if (parent.id == R.id.lockscreen_clock_view) {
-                    // view bounds have changed due to clock size changing (i.e. different character
-                    // widths)
-                    // AND/OR the view has been translated when transitioning between small and
-                    // large clock
-                    if (
-                        view != currentSmallClockView ||
-                            !view.locationOnScreen.contentEquals(currentSmallClockLocation)
-                    ) {
-                        currentSmallClockView = view
-                        currentSmallClockLocation = view.locationOnScreen
-                        updateRegionSampler(view)
-                    }
-                }
-                // LARGE CLOCK
-                else if (parent.id == R.id.lockscreen_clock_view_large) {
-                    if (
-                        view != currentLargeClockView ||
-                            !view.locationOnScreen.contentEquals(currentLargeClockLocation)
-                    ) {
-                        currentLargeClockView = view
-                        currentLargeClockLocation = view.locationOnScreen
-                        updateRegionSampler(view)
-                    }
+                val currentViewRect = Rect(left, top, right, bottom)
+                val oldViewRect = Rect(oldLeft, oldTop, oldRight, oldBottom)
+
+                if (currentViewRect.width() != oldViewRect.width() ||
+                    currentViewRect.height() != oldViewRect.height()) {
+                    updateRegionSampler(view)
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt b/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
index e0cf7b6..d8085b9 100644
--- a/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
+++ b/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
@@ -132,6 +132,7 @@
 
 /**
  * UiEvents that are logged to identify why face auth is being triggered.
+ *
  * @param extraInfo is logged as the position. See [UiEventLogger#logWithInstanceIdAndPosition]
  */
 enum class FaceAuthUiEvent
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
index baaef19..f8cb38d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
@@ -44,7 +44,7 @@
 public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKeyInputView>
         extends KeyguardInputViewController<T> {
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
-    private final LockPatternUtils mLockPatternUtils;
+    protected final LockPatternUtils mLockPatternUtils;
     private final LatencyTracker mLatencyTracker;
     private final FalsingCollector mFalsingCollector;
     private final EmergencyButtonController mEmergencyButtonController;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
index fe8b8c9..c98e9b4 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
@@ -40,7 +40,7 @@
     var keyguardGoingAway: Boolean = false,
     var listeningForFaceAssistant: Boolean = false,
     var occludingAppRequestingFaceAuth: Boolean = false,
-    val postureAllowsListening: Boolean = false,
+    var postureAllowsListening: Boolean = false,
     var primaryUser: Boolean = false,
     var secureCameraLaunched: Boolean = false,
     var supportsDetect: Boolean = false,
@@ -70,6 +70,7 @@
             listeningForFaceAssistant.toString(),
             occludingAppRequestingFaceAuth.toString(),
             primaryUser.toString(),
+            postureAllowsListening.toString(),
             secureCameraLaunched.toString(),
             supportsDetect.toString(),
             switchingUser.toString(),
@@ -109,6 +110,7 @@
                 listeningForFaceAssistant = model.listeningForFaceAssistant
                 occludingAppRequestingFaceAuth = model.occludingAppRequestingFaceAuth
                 primaryUser = model.primaryUser
+                postureAllowsListening = model.postureAllowsListening
                 secureCameraLaunched = model.secureCameraLaunched
                 supportsDetect = model.supportsDetect
                 switchingUser = model.switchingUser
@@ -152,6 +154,7 @@
                 "listeningForFaceAssistant",
                 "occludingAppRequestingFaceAuth",
                 "primaryUser",
+                "postureAllowsListening",
                 "secureCameraLaunched",
                 "supportsDetect",
                 "switchingUser",
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
index 67e3400..0394754 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
@@ -217,9 +217,11 @@
     private void animate(float progress) {
         Interpolator standardDecelerate = Interpolators.STANDARD_DECELERATE;
         Interpolator legacyDecelerate = Interpolators.LEGACY_DECELERATE;
+        float standardProgress = standardDecelerate.getInterpolation(progress);
 
         mBouncerMessageView.setTranslationY(
-                mYTrans - mYTrans * standardDecelerate.getInterpolation(progress));
+                mYTrans - mYTrans * standardProgress);
+        mBouncerMessageView.setAlpha(standardProgress);
 
         for (int i = 0; i < mViews.length; i++) {
             View[] row = mViews[i];
@@ -236,7 +238,7 @@
                 view.setAlpha(scaledProgress);
                 int yDistance = mYTrans + mYTransOffset * i;
                 view.setTranslationY(
-                        yDistance - (yDistance * standardDecelerate.getInterpolation(progress)));
+                        yDistance - (yDistance * standardProgress));
                 if (view instanceof NumPadAnimationListener) {
                     ((NumPadAnimationListener) view).setProgress(scaledProgress);
                 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index c1fae9e..33bea02 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -69,6 +69,7 @@
 
     private Interpolator mLinearOutSlowInInterpolator;
     private Interpolator mFastOutLinearInInterpolator;
+    private DisappearAnimationListener mDisappearAnimationListener;
 
     public KeyguardPasswordView(Context context) {
         this(context, null);
@@ -186,9 +187,13 @@
                                 return;
                             }
                             Insets shownInsets = controller.getShownStateInsets();
-                            Insets insets = Insets.add(shownInsets, Insets.of(0, 0, 0,
-                                    (int) (-shownInsets.bottom / 4
-                                            * anim.getAnimatedFraction())));
+                            int dist = (int) (-shownInsets.bottom / 4
+                                    * anim.getAnimatedFraction());
+                            Insets insets = Insets.add(shownInsets, Insets.of(0, 0, 0, dist));
+                            if (mDisappearAnimationListener != null) {
+                                mDisappearAnimationListener.setTranslationY(-dist);
+                            }
+
                             controller.setInsetsAndAlpha(insets,
                                     (float) animation.getAnimatedValue(),
                                     anim.getAnimatedFraction());
@@ -209,6 +214,7 @@
                                     controller.finish(false);
                                     runOnFinishImeAnimationRunnable();
                                     finishRunnable.run();
+                                    mDisappearAnimationListener = null;
                                     Trace.endSection();
                                 });
                             }
@@ -286,4 +292,19 @@
             }
         });
     }
+
+    /**
+     * Listens to the progress of the disappear animation and handles it.
+     */
+    interface DisappearAnimationListener {
+        void setTranslationY(int transY);
+    }
+
+    /**
+     * Set an instance of the disappear animation listener to this class. This will be
+     * removed when the animation completes.
+     */
+    public void setDisappearAnimationListener(DisappearAnimationListener listener) {
+        mDisappearAnimationListener = listener;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
index d221e22..a010c9a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
@@ -26,6 +26,7 @@
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewGroup.MarginLayoutParams;
+import android.view.WindowInsets;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
@@ -156,6 +157,15 @@
         // TODO: Remove this workaround by ensuring such a race condition never happens.
         mMainExecutor.executeDelayed(
                 this::updateSwitchImeButton, DELAY_MILLIS_TO_REEVALUATE_IME_SWITCH_ICON);
+        mView.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
+            @Override
+            public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
+                if (!mKeyguardViewController.isBouncerShowing()) {
+                    mView.hideKeyboard();
+                }
+                return insets;
+            }
+        });
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
index 92e3641..559db76 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
@@ -71,13 +71,17 @@
     protected void onViewAttached() {
         super.onViewAttached();
 
-        for (NumPadKey button: mView.getButtons()) {
+        boolean showAnimations = !mLockPatternUtils
+                .isPinEnhancedPrivacyEnabled(KeyguardUpdateMonitor.getCurrentUser());
+        mPasswordEntry.setShowPassword(showAnimations);
+        for (NumPadKey button : mView.getButtons()) {
             button.setOnTouchListener((v, event) -> {
                 if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
                     mFalsingCollector.avoidGesture();
                 }
                 return false;
             });
+            button.setAnimationEnabled(showAnimations);
         }
         mPasswordEntry.setOnKeyListener(mOnKeyListener);
         mPasswordEntry.setUserActivityListener(this::onUserInput);
@@ -102,12 +106,9 @@
         View okButton = mView.findViewById(R.id.key_enter);
         if (okButton != null) {
             okButton.setOnTouchListener(mActionButtonTouchListener);
-            okButton.setOnClickListener(new View.OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    if (mPasswordEntry.isEnabled()) {
-                        verifyPasswordAndUnlock();
-                    }
+            okButton.setOnClickListener(v -> {
+                if (mPasswordEntry.isEnabled()) {
+                    verifyPasswordAndUnlock();
                 }
             });
             okButton.setOnHoverListener(mLiftToActivateListener);
@@ -118,7 +119,7 @@
     protected void onViewDetached() {
         super.onViewDetached();
 
-        for (NumPadKey button: mView.getButtons()) {
+        for (NumPadKey button : mView.getButtons()) {
             button.setOnTouchListener(null);
         }
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index f164e7d..ba5a8c9 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -174,6 +174,17 @@
     private @Mode int mCurrentMode = MODE_UNINITIALIZED;
     private int mWidth = -1;
 
+    /**
+     * This callback is used to animate KeyguardSecurityContainer and its child views based on
+     * the interaction with the ime. After
+     * {@link WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)},
+     * {@link #onApplyWindowInsets} is called where we
+     * set the bottom padding to be the height of the keyboard. We use this padding to determine
+     * the delta of vertical distance for y-translation animations.
+     * Note that bottom padding is not set when the disappear animation is started because
+     * we are deferring the y translation logic to the animator in
+     * {@link KeyguardPasswordView#startDisappearAnimation(Runnable)}
+     */
     private final WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback =
             new WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) {
 
@@ -214,7 +225,6 @@
                             continue;
                         }
                         interpolatedFraction = animation.getInterpolatedFraction();
-
                         final int paddingBottom = (int) MathUtils.lerp(
                                 start, end,
                                 interpolatedFraction);
@@ -569,13 +579,21 @@
      */
     public void startDisappearAnimation(SecurityMode securitySelection) {
         mDisappearAnimRunning = true;
-        mViewMode.startDisappearAnimation(securitySelection);
+        if (securitySelection == SecurityMode.Password
+                && mSecurityViewFlipper.getSecurityView() instanceof KeyguardPasswordView) {
+            ((KeyguardPasswordView) mSecurityViewFlipper.getSecurityView())
+                    .setDisappearAnimationListener(this::setTranslationY);
+        } else {
+            mViewMode.startDisappearAnimation(securitySelection);
+        }
     }
 
     /**
      * This will run when the bouncer shows in all cases except when the user drags the bouncer up.
      */
     public void startAppearAnimation(SecurityMode securityMode) {
+        setTranslationY(0f);
+        setAlpha(1f);
         updateChildren(0 /* translationY */, 1f /* alpha */);
         mViewMode.startAppearAnimation(securityMode);
     }
@@ -624,7 +642,13 @@
         int inset = max(bottomInset, imeInset);
         int paddingBottom = max(inset, getContext().getResources()
                 .getDimensionPixelSize(R.dimen.keyguard_security_view_bottom_margin));
-        setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), paddingBottom);
+        // If security mode is password, we rely on the animation value of defined in
+        // KeyguardPasswordView to determine the y translation animation.
+        // This means that we will prevent the WindowInsetsAnimationCallback from setting any y
+        // translation values by preventing the setting of the padding here.
+        if (!mDisappearAnimRunning) {
+            setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), paddingBottom);
+        }
         return insets.inset(0, 0, 0, inset);
     }
 
@@ -1046,7 +1070,8 @@
 
             AnimatorSet anims = new AnimatorSet();
             ObjectAnimator yAnim = ObjectAnimator.ofFloat(mView, View.TRANSLATION_Y, yTranslation);
-            ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(mView, View.ALPHA, 0f);
+            ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(mUserSwitcherViewGroup, View.ALPHA,
+                    0f);
 
             anims.setInterpolator(Interpolators.STANDARD_ACCELERATE);
             anims.playTogether(alphaAnim, yAnim);
@@ -1200,8 +1225,7 @@
                 constraintSet.connect(rightElement, LEFT, leftElement, RIGHT);
                 constraintSet.connect(rightElement, RIGHT, PARENT_ID, RIGHT);
                 constraintSet.connect(mUserSwitcherViewGroup.getId(), TOP, PARENT_ID, TOP);
-                constraintSet.connect(mUserSwitcherViewGroup.getId(), BOTTOM, PARENT_ID, BOTTOM,
-                        yTrans);
+                constraintSet.connect(mUserSwitcherViewGroup.getId(), BOTTOM, PARENT_ID, BOTTOM);
                 constraintSet.connect(mViewFlipper.getId(), TOP, PARENT_ID, TOP);
                 constraintSet.connect(mViewFlipper.getId(), BOTTOM, PARENT_ID, BOTTOM);
                 constraintSet.setHorizontalChainStyle(mUserSwitcherViewGroup.getId(), CHAIN_SPREAD);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index f1abdc6..98866c6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -127,6 +127,7 @@
     private View.OnKeyListener mOnKeyListener = (v, keyCode, event) -> interceptMediaKey(event);
     private ActivityStarter.OnDismissAction mDismissAction;
     private Runnable mCancelAction;
+    private boolean mWillRunDismissFromKeyguard;
 
     private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED;
 
@@ -262,8 +263,10 @@
             // If there's a pending runnable because the user interacted with a widget
             // and we're leaving keyguard, then run it.
             boolean deferKeyguardDone = false;
+            mWillRunDismissFromKeyguard = false;
             if (mDismissAction != null) {
                 deferKeyguardDone = mDismissAction.onDismiss();
+                mWillRunDismissFromKeyguard = mDismissAction.willRunAnimationOnKeyguard();
                 mDismissAction = null;
                 mCancelAction = null;
             }
@@ -527,6 +530,13 @@
     }
 
     /**
+     * @return will the dismissal run from the keyguard layout (instead of from bouncer)
+     */
+    public boolean willRunDismissFromKeyguard() {
+        return mWillRunDismissFromKeyguard;
+    }
+
+    /**
      * Remove any dismiss action or cancel action that was set.
      */
     public void cancelDismissAction() {
@@ -637,12 +647,17 @@
 
     public void startAppearAnimation() {
         if (mCurrentSecurityMode != SecurityMode.None) {
-            mView.setAlpha(1f);
+            setAlpha(1f);
             mView.startAppearAnimation(mCurrentSecurityMode);
             getCurrentSecurityController().startAppearAnimation();
         }
     }
 
+    /** Set the alpha of the security container view */
+    public void setAlpha(float alpha) {
+        mView.setAlpha(alpha);
+    }
+
     public boolean startDisappearAnimation(Runnable onFinishRunnable) {
         boolean didRunAnimation = false;
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index bd67115..b3a641c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -29,6 +29,7 @@
 import static android.hardware.biometrics.BiometricSourceType.FACE;
 import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
 import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
+import static android.os.PowerManager.WAKE_REASON_UNKNOWN;
 
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
@@ -73,11 +74,9 @@
 import android.annotation.AnyThread;
 import android.annotation.MainThread;
 import android.annotation.SuppressLint;
-import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.app.ActivityTaskManager.RootTaskInfo;
 import android.app.AlarmManager;
-import android.app.UserSwitchObserver;
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.TrustManager;
 import android.content.BroadcastReceiver;
@@ -108,7 +107,6 @@
 import android.nfc.NfcAdapter;
 import android.os.CancellationSignal;
 import android.os.Handler;
-import android.os.IRemoteCallback;
 import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
@@ -139,9 +137,9 @@
 import com.android.internal.util.LatencyTracker;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.logging.KeyguardUpdateMonitorLogger;
+import com.android.settingslib.Utils;
 import com.android.settingslib.WirelessUtils;
 import com.android.settingslib.fuelgauge.BatteryStatus;
-import com.android.settingslib.Utils;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.biometrics.AuthController;
@@ -152,6 +150,7 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.dump.DumpsysTableLogger;
+import com.android.systemui.keyguard.shared.model.SysUiFaceAuthenticateOptions;
 import com.android.systemui.log.SessionTracker;
 import com.android.systemui.plugins.WeatherData;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -161,6 +160,7 @@
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.policy.DevicePostureController;
+import com.android.systemui.statusbar.policy.DevicePostureController.DevicePostureInt;
 import com.android.systemui.telephony.TelephonyListenerManager;
 import com.android.systemui.util.Assert;
 import com.android.systemui.util.settings.SecureSettings;
@@ -180,6 +180,7 @@
 import java.util.Optional;
 import java.util.Set;
 import java.util.TimeZone;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
 import java.util.stream.Collectors;
 
@@ -368,7 +369,7 @@
     private final FaceManager mFaceManager;
     private final LockPatternUtils mLockPatternUtils;
     @VisibleForTesting
-    @DevicePostureController.DevicePostureInt
+    @DevicePostureInt
     protected int mConfigFaceAuthSupportedPosture;
 
     private KeyguardBypassController mKeyguardBypassController;
@@ -685,7 +686,10 @@
     public void onTrustManagedChanged(boolean managed, int userId) {
         Assert.isMainThread();
         mUserTrustIsManaged.put(userId, managed);
-        mUserTrustIsUsuallyManaged.put(userId, mTrustManager.isTrustUsuallyManaged(userId));
+        boolean trustUsuallyManaged = mTrustManager.isTrustUsuallyManaged(userId);
+        mLogger.logTrustUsuallyManagedUpdated(userId, mUserTrustIsUsuallyManaged.get(userId),
+                trustUsuallyManaged, "onTrustManagedChanged");
+        mUserTrustIsUsuallyManaged.put(userId, trustUsuallyManaged);
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
@@ -713,6 +717,12 @@
         if (mKeyguardGoingAway) {
             updateFaceListeningState(BIOMETRIC_ACTION_STOP,
                     FACE_AUTH_STOPPED_KEYGUARD_GOING_AWAY);
+            for (int i = 0; i < mCallbacks.size(); i++) {
+                KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+                if (cb != null) {
+                    cb.onKeyguardGoingAway();
+                }
+            }
         }
         updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
     }
@@ -823,6 +833,19 @@
         }
     }
 
+    private void onBiometricDetected(int userId, BiometricSourceType biometricSourceType,
+            boolean isStrongBiometric) {
+        Assert.isMainThread();
+        Trace.beginSection("KeyGuardUpdateMonitor#onBiometricDetected");
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+            if (cb != null) {
+                cb.onBiometricDetected(userId, biometricSourceType, isStrongBiometric);
+            }
+        }
+        Trace.endSection();
+    }
+
     @VisibleForTesting
     protected void onFingerprintAuthenticated(int userId, boolean isStrongBiometric) {
         Assert.isMainThread();
@@ -860,7 +883,10 @@
 
     private void reportSuccessfulBiometricUnlock(boolean isStrongBiometric, int userId) {
         mBackgroundExecutor.execute(
-                () -> mLockPatternUtils.reportSuccessfulBiometricUnlock(isStrongBiometric, userId));
+                () -> {
+                    mLogger.logReportSuccessfulBiometricUnlock(isStrongBiometric, userId);
+                    mLockPatternUtils.reportSuccessfulBiometricUnlock(isStrongBiometric, userId);
+                });
     }
 
     private void handleFingerprintAuthFailed() {
@@ -899,6 +925,20 @@
         }
     }
 
+    private void handleBiometricDetected(int authUserId, BiometricSourceType biometricSourceType,
+            boolean isStrongBiometric) {
+        Trace.beginSection("KeyGuardUpdateMonitor#handlerBiometricDetected");
+        onBiometricDetected(authUserId, biometricSourceType, isStrongBiometric);
+        if (biometricSourceType == FINGERPRINT) {
+            mLogger.logFingerprintDetected(authUserId, isStrongBiometric);
+        } else if (biometricSourceType == FACE) {
+            mLogger.logFaceDetected(authUserId, isStrongBiometric);
+            setFaceRunningState(BIOMETRIC_STATE_STOPPED);
+        }
+
+        Trace.endSection();
+    }
+
     private void handleFingerprintAuthenticated(int authUserId, boolean isStrongBiometric) {
         Trace.beginSection("KeyGuardUpdateMonitor#handlerFingerPrintAuthenticated");
         if (mHandler.hasCallbacks(mFpCancelNotReceived)) {
@@ -950,8 +990,14 @@
 
     private void onFingerprintCancelNotReceived() {
         mLogger.e("Fp cancellation not received, transitioning to STOPPED");
+        final boolean wasCancellingRestarting = mFingerprintRunningState
+                == BIOMETRIC_STATE_CANCELLING_RESTARTING;
         mFingerprintRunningState = BIOMETRIC_STATE_STOPPED;
-        KeyguardUpdateMonitor.this.updateFingerprintListeningState(BIOMETRIC_ACTION_STOP);
+        if (wasCancellingRestarting) {
+            KeyguardUpdateMonitor.this.updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
+        } else {
+            KeyguardUpdateMonitor.this.updateFingerprintListeningState(BIOMETRIC_ACTION_STOP);
+        }
     }
 
     private void handleFingerprintError(int msgId, String errString) {
@@ -1038,6 +1084,12 @@
                     () -> updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE),
                     getBiometricLockoutDelay());
         } else {
+            boolean temporaryLockoutReset = wasLockout && !mFingerprintLockedOut;
+            if (temporaryLockoutReset) {
+                mLogger.d("temporaryLockoutReset - stopListeningForFingerprint() to stop"
+                        + " detectFingerprint");
+                stopListeningForFingerprint();
+            }
             updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
         }
 
@@ -1747,10 +1799,16 @@
                 }
             };
 
+    private final FingerprintManager.FingerprintDetectionCallback mFingerprintDetectionCallback =
+            (sensorId, userId, isStrongBiometric) -> {
+                // Trigger the fingerprint detected path so the bouncer can be shown
+                handleBiometricDetected(userId, FINGERPRINT, isStrongBiometric);
+            };
+
     private final FaceManager.FaceDetectionCallback mFaceDetectionCallback
             = (sensorId, userId, isStrongBiometric) -> {
-                // Trigger the face success path so the bouncer can be shown
-                handleFaceAuthenticated(userId, isStrongBiometric);
+                // Trigger the face detected path so the bouncer can be shown
+                handleBiometricDetected(userId, FACE, isStrongBiometric);
             };
 
     @VisibleForTesting
@@ -1814,10 +1872,15 @@
     final DevicePostureController.Callback mPostureCallback =
             new DevicePostureController.Callback() {
                 @Override
-                public void onPostureChanged(int posture) {
+                public void onPostureChanged(@DevicePostureInt int posture) {
+                    boolean currentPostureAllowsFaceAuth = doesPostureAllowFaceAuth(mPostureState);
+                    boolean newPostureAllowsFaceAuth = doesPostureAllowFaceAuth(posture);
                     mPostureState = posture;
-                    updateFaceListeningState(BIOMETRIC_ACTION_UPDATE,
-                            FACE_AUTH_UPDATED_POSTURE_CHANGED);
+                    if (currentPostureAllowsFaceAuth && !newPostureAllowsFaceAuth) {
+                        mLogger.d("New posture does not allow face auth, stopping it");
+                        updateFaceListeningState(BIOMETRIC_ACTION_STOP,
+                                FACE_AUTH_UPDATED_POSTURE_CHANGED);
+                    }
                 }
             };
 
@@ -2175,7 +2238,7 @@
                         handleDevicePolicyManagerStateChanged(msg.arg1);
                         break;
                     case MSG_USER_SWITCHING:
-                        handleUserSwitching(msg.arg1, (IRemoteCallback) msg.obj);
+                        handleUserSwitching(msg.arg1, (CountDownLatch) msg.obj);
                         break;
                     case MSG_USER_SWITCH_COMPLETE:
                         handleUserSwitchComplete(msg.arg1);
@@ -2301,11 +2364,7 @@
                 mHandler, UserHandle.ALL);
 
         mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
-        try {
-            ActivityManager.getService().registerUserSwitchObserver(mUserSwitchObserver, TAG);
-        } catch (RemoteException e) {
-            e.rethrowAsRuntimeException();
-        }
+        mUserTracker.addCallback(mUserChangedCallback, mainExecutor);
 
         mTrustManager.registerTrustListener(this);
 
@@ -2352,8 +2411,12 @@
         updateSecondaryLockscreenRequirement(user);
         List<UserInfo> allUsers = mUserManager.getUsers();
         for (UserInfo userInfo : allUsers) {
+            boolean trustUsuallyManaged = mTrustManager.isTrustUsuallyManaged(userInfo.id);
+            mLogger.logTrustUsuallyManagedUpdated(userInfo.id,
+                    mUserTrustIsUsuallyManaged.get(userInfo.id),
+                    trustUsuallyManaged, "init from constructor");
             mUserTrustIsUsuallyManaged.put(userInfo.id,
-                    mTrustManager.isTrustUsuallyManaged(userInfo.id));
+                    trustUsuallyManaged);
         }
         updateAirplaneModeState();
 
@@ -2393,9 +2456,13 @@
     }
 
     private void updateFaceEnrolled(int userId) {
-        mIsFaceEnrolled = mFaceManager != null && !mFaceSensorProperties.isEmpty()
+        Boolean isFaceEnrolled = mFaceManager != null && !mFaceSensorProperties.isEmpty()
                 && mBiometricEnabledForUser.get(userId)
                 && mAuthController.isFaceAuthEnrolled(userId);
+        if (mIsFaceEnrolled != isFaceEnrolled) {
+            mLogger.logFaceEnrolledUpdated(mIsFaceEnrolled, isFaceEnrolled);
+        }
+        mIsFaceEnrolled = isFaceEnrolled;
     }
 
     public boolean isFaceSupported() {
@@ -2441,17 +2508,17 @@
         return mIsFaceEnrolled;
     }
 
-    private final UserSwitchObserver mUserSwitchObserver = new UserSwitchObserver() {
+    private final UserTracker.Callback mUserChangedCallback = new UserTracker.Callback() {
         @Override
-        public void onUserSwitching(int newUserId, IRemoteCallback reply) {
+        public void onUserChanging(int newUser, Context userContext, CountDownLatch latch) {
             mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING,
-                    newUserId, 0, reply));
+                    newUser, 0, latch));
         }
 
         @Override
-        public void onUserSwitchComplete(int newUserId) {
+        public void onUserChanged(int newUser, Context userContext) {
             mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
-                    newUserId, 0));
+                    newUser, 0));
         }
     };
 
@@ -2474,11 +2541,13 @@
         // If this message exists, we should not authenticate again until this message is
         // consumed by the handler
         if (mHandler.hasMessages(MSG_BIOMETRIC_AUTHENTICATION_CONTINUE)) {
+            mLogger.logHandlerHasAuthContinueMsgs(action);
             return;
         }
 
         // don't start running fingerprint until they're registered
         if (!mAuthController.areAllFingerprintAuthenticatorsRegistered()) {
+            mLogger.d("All FP authenticators not registered, skipping FP listening state update");
             return;
         }
         final boolean shouldListenForFingerprint = shouldListenForFingerprint(isUdfpsSupported());
@@ -2783,8 +2852,7 @@
 
         boolean shouldListen = shouldListenKeyguardState && shouldListenUserState
                 && shouldListenBouncerState && shouldListenUdfpsState
-                && shouldListenSideFpsState
-                && !isFingerprintLockedOut();
+                && shouldListenSideFpsState;
         logListenerModelData(
                 new KeyguardFingerprintListenModel(
                     System.currentTimeMillis(),
@@ -2843,8 +2911,7 @@
         final boolean supportsDetect = !mFaceSensorProperties.isEmpty()
                 && mFaceSensorProperties.get(0).supportsFaceDetection
                 && canBypass && !mPrimaryBouncerIsOrWillBeShowing
-                && !isUserInLockdown(user)
-                && !isFingerprintLockedOut();
+                && !isUserInLockdown(user);
         final boolean faceAuthAllowedOrDetectionIsNeeded = faceAuthAllowed || supportsDetect;
 
         // If the face or fp has recently been authenticated do not attempt to authenticate again.
@@ -2853,9 +2920,7 @@
         final boolean biometricEnabledForUser = mBiometricEnabledForUser.get(user);
         final boolean shouldListenForFaceAssistant = shouldListenForFaceAssistant();
         final boolean isUdfpsFingerDown = mAuthController.isUdfpsFingerDown();
-        final boolean isPostureAllowedForFaceAuth =
-                mConfigFaceAuthSupportedPosture == 0 /* DEVICE_POSTURE_UNKNOWN */ ? true
-                        : (mPostureState == mConfigFaceAuthSupportedPosture);
+        final boolean isPostureAllowedForFaceAuth = doesPostureAllowFaceAuth(mPostureState);
         // Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an
         // instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware.
         final boolean shouldListen =
@@ -2904,6 +2969,11 @@
         return shouldListen;
     }
 
+    private boolean doesPostureAllowFaceAuth(@DevicePostureInt int posture) {
+        return mConfigFaceAuthSupportedPosture == DEVICE_POSTURE_UNKNOWN
+                || (posture == mConfigFaceAuthSupportedPosture);
+    }
+
     private void logListenerModelData(@NonNull KeyguardListenModel model) {
         mLogger.logKeyguardListenerModel(model);
         if (model instanceof KeyguardFingerprintListenModel) {
@@ -2940,11 +3010,7 @@
                 mLogger.v("startListeningForFingerprint - detect");
                 mFpm.detectFingerprint(
                         mFingerprintCancelSignal,
-                        (sensorId, user, isStrongBiometric) -> {
-                            mLogger.d("fingerprint detected");
-                            // Trigger the fingerprint success path so the bouncer can be shown
-                            handleFingerprintAuthenticated(user, isStrongBiometric);
-                        },
+                        mFingerprintDetectionCallback,
                         new FingerprintAuthenticateOptions.Builder()
                                 .setUserId(userId)
                                 .build());
@@ -2984,6 +3050,14 @@
         if (unlockPossible) {
             mFaceCancelSignal = new CancellationSignal();
 
+            final FaceAuthenticateOptions faceAuthenticateOptions =
+                    new SysUiFaceAuthenticateOptions(
+                            userId,
+                            faceAuthUiEvent,
+                            faceAuthUiEvent == FACE_AUTH_UPDATED_STARTED_WAKING_UP
+                                    ? faceAuthUiEvent.getExtraInfo()
+                                    : WAKE_REASON_UNKNOWN
+                    ).toFaceAuthenticateOptions();
             // This would need to be updated for multi-sensor devices
             final boolean supportsFaceDetection = !mFaceSensorProperties.isEmpty()
                     && mFaceSensorProperties.get(0).supportsFaceDetection;
@@ -2994,9 +3068,7 @@
                     // Run face detection. (If a face is detected, show the bouncer.)
                     mLogger.v("startListeningForFace - detect");
                     mFaceManager.detectFace(mFaceCancelSignal, mFaceDetectionCallback,
-                            new FaceAuthenticateOptions.Builder()
-                                    .setUserId(userId)
-                                    .build());
+                            faceAuthenticateOptions);
                 } else {
                     // Don't run face detection. Instead, inform the user
                     // face auth is unavailable and how to proceed.
@@ -3015,7 +3087,8 @@
                 final boolean isBypassEnabled = mKeyguardBypassController != null
                         && mKeyguardBypassController.isBypassEnabled();
                 mFaceManager.authenticate(null /* crypto */, mFaceCancelSignal,
-                        mFaceAuthenticationCallback, null /* handler */, userId);
+                        mFaceAuthenticationCallback, null /* handler */,
+                        faceAuthenticateOptions);
             }
             setFaceRunningState(BIOMETRIC_STATE_RUNNING);
         }
@@ -3061,9 +3134,14 @@
     @VisibleForTesting
     boolean isUnlockWithFingerprintPossible(int userId) {
         // TODO (b/242022358), make this rely on onEnrollmentChanged event and update it only once.
-        mIsUnlockWithFingerprintPossible.put(userId, mFpm != null
+        boolean newFpEnrolled = mFpm != null
                 && !mFingerprintSensorProperties.isEmpty()
-                && !isFingerprintDisabled(userId) && mFpm.hasEnrolledTemplates(userId));
+                && !isFingerprintDisabled(userId) && mFpm.hasEnrolledTemplates(userId);
+        Boolean oldFpEnrolled = mIsUnlockWithFingerprintPossible.getOrDefault(userId, false);
+        if (oldFpEnrolled != newFpEnrolled) {
+            mLogger.logFpEnrolledUpdated(userId, oldFpEnrolled, newFpEnrolled);
+        }
+        mIsUnlockWithFingerprintPossible.put(userId, newFpEnrolled);
         return mIsUnlockWithFingerprintPossible.get(userId);
     }
 
@@ -3176,21 +3254,20 @@
      * Handle {@link #MSG_USER_SWITCHING}
      */
     @VisibleForTesting
-    void handleUserSwitching(int userId, IRemoteCallback reply) {
+    void handleUserSwitching(int userId, CountDownLatch latch) {
         Assert.isMainThread();
         clearBiometricRecognized();
-        mUserTrustIsUsuallyManaged.put(userId, mTrustManager.isTrustUsuallyManaged(userId));
+        boolean trustUsuallyManaged = mTrustManager.isTrustUsuallyManaged(userId);
+        mLogger.logTrustUsuallyManagedUpdated(userId, mUserTrustIsUsuallyManaged.get(userId),
+                trustUsuallyManaged, "userSwitching");
+        mUserTrustIsUsuallyManaged.put(userId, trustUsuallyManaged);
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
                 cb.onUserSwitching(userId);
             }
         }
-        try {
-            reply.sendResult(null);
-        } catch (RemoteException e) {
-            mLogger.logException(e, "Ignored exception while userSwitching");
-        }
+        latch.countDown();
     }
 
     /**
@@ -3331,8 +3408,8 @@
      */
     private void handleBatteryUpdate(BatteryStatus status) {
         Assert.isMainThread();
-        mLogger.d("handleBatteryUpdate");
         final boolean batteryUpdateInteresting = isBatteryUpdateInteresting(mBatteryStatus, status);
+        mLogger.logHandleBatteryUpdate(batteryUpdateInteresting);
         mBatteryStatus = status;
         if (batteryUpdateInteresting) {
             for (int i = 0; i < mCallbacks.size(); i++) {
@@ -3612,7 +3689,9 @@
      * Register to receive notifications about general keyguard information
      * (see {@link KeyguardUpdateMonitorCallback}.
      *
-     * @param callback The callback to register
+     * @param callback The callback to register. Stay away from passing anonymous instances
+     *                 as they will likely be dereferenced. Ensure that the callback is a class
+     *                 field to persist it.
      */
     public void registerCallback(KeyguardUpdateMonitorCallback callback) {
         Assert.isMainThread();
@@ -3963,13 +4042,7 @@
             mContext.getContentResolver().unregisterContentObserver(mTimeFormatChangeObserver);
         }
 
-        try {
-            ActivityManager.getService().unregisterUserSwitchObserver(mUserSwitchObserver);
-        } catch (RemoteException e) {
-            mLogger.logException(
-                    e,
-                    "RemoteException onDestroy. cannot unregister userSwitchObserver");
-        }
+        mUserTracker.removeCallback(mUserChangedCallback);
 
         TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 38f3e50..feff216 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -214,7 +214,7 @@
     public void onBiometricAuthFailed(BiometricSourceType biometricSourceType) { }
 
     /**
-     * Called when a biometric is recognized.
+     * Called when a biometric is authenticated.
      * @param userId the user id for which the biometric sample was authenticated
      * @param biometricSourceType
      */
@@ -222,6 +222,14 @@
             boolean isStrongBiometric) { }
 
     /**
+     * Called when a biometric is detected but not successfully authenticated.
+     * @param userId the user id for which the biometric sample was detected
+     * @param biometricSourceType
+     */
+    public void onBiometricDetected(int userId, BiometricSourceType biometricSourceType,
+            boolean isStrongBiometric) { }
+
+    /**
      * Called when biometric authentication provides help string (e.g. "Try again")
      * @param msgId
      * @param helpString
@@ -309,4 +317,9 @@
      * Called when the non-strong biometric state changed.
      */
     public void onNonStrongBiometricAllowedChanged(int userId) { }
+
+    /**
+     * Called when keyguard is going away or not going away.
+     */
+    public void onKeyguardGoingAway() { }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
index 6c3c246..7661b8d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
@@ -168,7 +168,7 @@
     /**
      * Stop showing the alternate bouncer, if showing.
      */
-    void hideAlternateBouncer(boolean forceUpdateScrim);
+    void hideAlternateBouncer(boolean updateScrim);
 
     // TODO: Deprecate registerStatusBar in KeyguardViewController interface. It is currently
     //  only used for testing purposes in StatusBarKeyguardViewManager, and it prevents us from
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index bfd99d3..1ae380e 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -51,6 +51,7 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
 
+import com.android.settingslib.udfps.UdfpsOverlayParams;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.biometrics.AuthController;
@@ -778,7 +779,7 @@
         }
 
         @Override
-        public void onUdfpsLocationChanged() {
+        public void onUdfpsLocationChanged(UdfpsOverlayParams udfpsOverlayParams) {
             updateUdfpsConfig();
         }
     };
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
index b30a0e0..ad66909 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
@@ -51,7 +51,6 @@
     private float mStartRadius;
     private float mEndRadius;
     private int mHeight;
-    private boolean mInitialized;
 
     private static final int EXPAND_ANIMATION_MS = 100;
     private static final int EXPAND_COLOR_ANIMATION_MS = 50;
@@ -93,15 +92,15 @@
     }
 
     void onLayout(int height) {
+        boolean shouldUpdateHeight = height != mHeight;
         mHeight = height;
         mStartRadius = height / 2f;
         mEndRadius = height / 4f;
         mExpandAnimator.setFloatValues(mStartRadius, mEndRadius);
         mContractAnimator.setFloatValues(mEndRadius, mStartRadius);
         // Set initial corner radius.
-        if (!mInitialized) {
+        if (shouldUpdateHeight) {
             mBackground.setCornerRadius(mStartRadius);
-            mInitialized = true;
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
index 3b0644e..7c7680a 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
@@ -50,6 +50,7 @@
     private int mDigit = -1;
     private int mTextViewResId;
     private PasswordTextView mTextView;
+    private boolean mAnimationsEnabled = true;
 
     @Nullable
     private NumPadAnimator mAnimator;
@@ -164,11 +165,11 @@
         switch(event.getActionMasked()) {
             case MotionEvent.ACTION_DOWN:
                 doHapticKeyClick();
-                if (mAnimator != null) mAnimator.expand();
+                if (mAnimator != null && mAnimationsEnabled) mAnimator.expand();
                 break;
             case MotionEvent.ACTION_UP:
             case MotionEvent.ACTION_CANCEL:
-                if (mAnimator != null) mAnimator.contract();
+                if (mAnimator != null && mAnimationsEnabled) mAnimator.contract();
                 break;
         }
         return super.onTouchEvent(event);
@@ -228,4 +229,11 @@
             mAnimator.setProgress(progress);
         }
     }
+
+    /**
+     * Controls the animation when a key is pressed
+     */
+    public void setAnimationEnabled(boolean enabled) {
+        mAnimationsEnabled = enabled;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
index 8554e11..5400011 100644
--- a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
+++ b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
@@ -30,7 +30,6 @@
 import android.graphics.Typeface;
 import android.os.PowerManager;
 import android.os.SystemClock;
-import android.provider.Settings;
 import android.text.InputType;
 import android.text.TextUtils;
 import android.util.AttributeSet;
@@ -100,7 +99,7 @@
     private Interpolator mAppearInterpolator;
     private Interpolator mDisappearInterpolator;
     private Interpolator mFastOutSlowInInterpolator;
-    private boolean mShowPassword;
+    private boolean mShowPassword = true;
     private UserActivityListener mUserActivityListener;
     private PinShapeInput mPinShapeInput;
     private boolean mUsePinShapes = false;
@@ -158,8 +157,6 @@
         mDrawPaint.setTypeface(Typeface.create(
                 context.getString(com.android.internal.R.string.config_headlineFontFamily),
                 0));
-        mShowPassword = Settings.System.getInt(mContext.getContentResolver(),
-                Settings.System.TEXT_SHOW_PASSWORD, 1) == 1;
         mAppearInterpolator = AnimationUtils.loadInterpolator(mContext,
                 android.R.interpolator.linear_out_slow_in);
         mDisappearInterpolator = AnimationUtils.loadInterpolator(mContext,
@@ -441,6 +438,13 @@
         addView(mPinShapeInput.getView());
     }
 
+    /**
+     * Controls whether the last entered digit is briefly shown after being entered
+     */
+    public void setShowPassword(boolean enabled) {
+        mShowPassword = enabled;
+    }
+
     private class CharState {
         char whichChar;
         ValueAnimator textAnimator;
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/BiometricUnlockLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/BiometricUnlockLogger.kt
index bc0bd8c..20f9007 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/BiometricUnlockLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/BiometricUnlockLogger.kt
@@ -16,6 +16,7 @@
 
 package com.android.keyguard.logging
 
+import android.hardware.biometrics.BiometricSourceType
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.log.dagger.BiometricLog
 import com.android.systemui.plugins.log.LogBuffer
@@ -157,6 +158,36 @@
             }
         )
     }
+
+    fun deferringAuthenticationDueToSleep(
+        userId: Int,
+        biometricSourceType: BiometricSourceType,
+        alreadyPendingAuth: Boolean
+    ) {
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                int1 = userId
+                str1 = biometricSourceType.name
+                bool2 = alreadyPendingAuth
+            },
+            {
+                "onBiometricAuthenticated, deferring auth: userId: $int1, " +
+                    "biometricSourceType: $str1, " +
+                    "goingToSleep: true, " +
+                    "mPendingAuthentication != null: $bool2"
+            }
+        )
+    }
+
+    fun finishedGoingToSleepWithPendingAuth() {
+        logBuffer.log(
+            TAG,
+            LogLevel.DEBUG,
+            "onFinishedGoingToSleep with pendingAuthenticated != null"
+        )
+    }
 }
 
 private fun wakeAndUnlockModeToString(mode: Int): String {
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardLogger.kt
index 379c78a..4d71a89 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardLogger.kt
@@ -16,6 +16,7 @@
 
 package com.android.keyguard.logging
 
+import com.android.systemui.biometrics.AuthRippleController
 import com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController
 import com.android.systemui.log.dagger.KeyguardLog
 import com.android.systemui.plugins.log.LogBuffer
@@ -96,6 +97,21 @@
         )
     }
 
+    fun logUpdateBatteryIndication(
+        powerIndication: String,
+        pluggedIn: Boolean,
+    ) {
+        buffer.log(
+            KeyguardIndicationController.TAG,
+            LogLevel.DEBUG,
+            {
+                str1 = powerIndication
+                bool1 = pluggedIn
+            },
+            { "updateBatteryIndication powerIndication:$str1 pluggedIn:$bool1" }
+        )
+    }
+
     fun logKeyguardSwitchIndication(
         type: Int,
         message: String?,
@@ -111,6 +127,28 @@
         )
     }
 
+    fun logRefreshBatteryInfo(
+        isChargingOrFull: Boolean,
+        powerPluggedIn: Boolean,
+        batteryLevel: Int,
+        batteryOverheated: Boolean
+    ) {
+        buffer.log(
+            KeyguardIndicationController.TAG,
+            LogLevel.DEBUG,
+            {
+                bool1 = isChargingOrFull
+                bool2 = powerPluggedIn
+                bool3 = batteryOverheated
+                int1 = batteryLevel
+            },
+            {
+                "refreshBatteryInfo isChargingOrFull:$bool1 powerPluggedIn:$bool2" +
+                    " batteryOverheated:$bool3 batteryLevel:$int1"
+            }
+        )
+    }
+
     fun getKeyguardSwitchIndicationNonSensitiveLog(type: Int, message: String?): String {
         // only show the battery string. other strings may contain sensitive info
         return if (type == KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BATTERY) {
@@ -120,4 +158,29 @@
             "type=${KeyguardIndicationRotateTextViewController.indicationTypeToString(type)}"
         }
     }
+
+    fun notShowingUnlockRipple(keyguardNotShowing: Boolean, unlockNotAllowed: Boolean) {
+        buffer.log(
+            AuthRippleController.TAG,
+            LogLevel.DEBUG,
+            {
+                bool1 = keyguardNotShowing
+                bool2 = unlockNotAllowed
+            },
+            { "Not showing unlock ripple: keyguardNotShowing: $bool1, unlockNotAllowed: $bool2" }
+        )
+    }
+
+    fun showingUnlockRippleAt(x: Int, y: Int, context: String) {
+        buffer.log(
+            AuthRippleController.TAG,
+            LogLevel.DEBUG,
+            {
+                int1 = x
+                int2 = y
+                str1 = context
+            },
+            { "Showing unlock ripple with center (x, y): ($int1, $int2), context: $str1" }
+        )
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
index c414c08..5162807 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
@@ -26,6 +26,7 @@
 import com.android.keyguard.KeyguardListenModel
 import com.android.keyguard.KeyguardUpdateMonitorCallback
 import com.android.keyguard.TrustGrantFlags
+import com.android.systemui.log.dagger.KeyguardUpdateMonitorLog
 import com.android.systemui.plugins.log.LogBuffer
 import com.android.systemui.plugins.log.LogLevel
 import com.android.systemui.plugins.log.LogLevel.DEBUG
@@ -33,18 +34,15 @@
 import com.android.systemui.plugins.log.LogLevel.INFO
 import com.android.systemui.plugins.log.LogLevel.VERBOSE
 import com.android.systemui.plugins.log.LogLevel.WARNING
-import com.android.systemui.log.dagger.KeyguardUpdateMonitorLog
 import com.google.errorprone.annotations.CompileTimeConstant
 import javax.inject.Inject
 
 private const val TAG = "KeyguardUpdateMonitorLog"
 
-/**
- * Helper class for logging for [com.android.keyguard.KeyguardUpdateMonitor]
- */
-class KeyguardUpdateMonitorLogger @Inject constructor(
-        @KeyguardUpdateMonitorLog private val logBuffer: LogBuffer
-) {
+/** Helper class for logging for [com.android.keyguard.KeyguardUpdateMonitor] */
+class KeyguardUpdateMonitorLogger
+@Inject
+constructor(@KeyguardUpdateMonitorLog private val logBuffer: LogBuffer) {
     fun d(@CompileTimeConstant msg: String) = log(msg, DEBUG)
 
     fun e(@CompileTimeConstant msg: String) = log(msg, ERROR)
@@ -56,15 +54,16 @@
     fun log(@CompileTimeConstant msg: String, level: LogLevel) = logBuffer.log(TAG, level, msg)
 
     fun logActiveUnlockTriggered(reason: String?) {
-        logBuffer.log("ActiveUnlock", DEBUG,
-                { str1 = reason },
-                { "initiate active unlock triggerReason=$str1" })
+        logBuffer.log(
+            "ActiveUnlock",
+            DEBUG,
+            { str1 = reason },
+            { "initiate active unlock triggerReason=$str1" }
+        )
     }
 
     fun logAuthInterruptDetected(active: Boolean) {
-        logBuffer.log(TAG, DEBUG,
-                { bool1 = active },
-                { "onAuthInterruptDetected($bool1)" })
+        logBuffer.log(TAG, DEBUG, { bool1 = active }, { "onAuthInterruptDetected($bool1)" })
     }
 
     fun logBroadcastReceived(action: String?) {
@@ -72,9 +71,12 @@
     }
 
     fun logDeviceProvisionedState(deviceProvisioned: Boolean) {
-        logBuffer.log(TAG, DEBUG,
-                { bool1 = deviceProvisioned },
-                { "DEVICE_PROVISIONED state = $bool1" })
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            { bool1 = deviceProvisioned },
+            { "DEVICE_PROVISIONED state = $bool1" }
+        )
     }
 
     fun logException(ex: Exception, @CompileTimeConstant logMsg: String) {
@@ -82,46 +84,56 @@
     }
 
     fun logFaceAcquired(acquireInfo: Int) {
-        logBuffer.log(TAG, DEBUG,
-                { int1 = acquireInfo },
-                { "Face acquired acquireInfo=$int1" })
+        logBuffer.log(TAG, DEBUG, { int1 = acquireInfo }, { "Face acquired acquireInfo=$int1" })
     }
 
     fun logFaceAuthDisabledForUser(userId: Int) {
-        logBuffer.log(TAG, DEBUG,
-                { int1 = userId },
-                { "Face authentication disabled by DPM for userId: $int1" })
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            { int1 = userId },
+            { "Face authentication disabled by DPM for userId: $int1" }
+        )
     }
     fun logFaceAuthError(msgId: Int, originalErrMsg: String) {
-        logBuffer.log(TAG, DEBUG, {
-                    str1 = originalErrMsg
-                    int1 = msgId
-                }, { "Face error received: $str1 msgId= $int1" })
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                str1 = originalErrMsg
+                int1 = msgId
+            },
+            { "Face error received: $str1 msgId= $int1" }
+        )
     }
 
     fun logFaceAuthForWrongUser(authUserId: Int) {
-        logBuffer.log(TAG, DEBUG,
-                { int1 = authUserId },
-                { "Face authenticated for wrong user: $int1" })
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            { int1 = authUserId },
+            { "Face authenticated for wrong user: $int1" }
+        )
     }
 
     fun logFaceAuthHelpMsg(msgId: Int, helpMsg: String?) {
-        logBuffer.log(TAG, DEBUG, {
-                    int1 = msgId
-                    str1 = helpMsg
-                }, { "Face help received, msgId: $int1 msg: $str1" })
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                int1 = msgId
+                str1 = helpMsg
+            },
+            { "Face help received, msgId: $int1 msg: $str1" }
+        )
     }
 
     fun logFaceAuthRequested(reason: String?) {
-        logBuffer.log(TAG, DEBUG, {
-            str1 = reason
-        }, { "requestFaceAuth() reason=$str1" })
+        logBuffer.log(TAG, DEBUG, { str1 = reason }, { "requestFaceAuth() reason=$str1" })
     }
 
     fun logFaceAuthSuccess(userId: Int) {
-        logBuffer.log(TAG, DEBUG,
-                { int1 = userId },
-                { "Face auth succeeded for user $int1" })
+        logBuffer.log(TAG, DEBUG, { int1 = userId }, { "Face auth succeeded for user $int1" })
     }
 
     fun logFaceLockoutReset(@LockoutMode mode: Int) {
@@ -133,21 +145,30 @@
     }
 
     fun logFaceUnlockPossible(isFaceUnlockPossible: Boolean) {
-        logBuffer.log(TAG, DEBUG,
-                { bool1 = isFaceUnlockPossible },
-                {"isUnlockWithFacePossible: $bool1"})
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            { bool1 = isFaceUnlockPossible },
+            { "isUnlockWithFacePossible: $bool1" }
+        )
     }
 
     fun logFingerprintAuthForWrongUser(authUserId: Int) {
-        logBuffer.log(TAG, DEBUG,
-                { int1 = authUserId },
-                { "Fingerprint authenticated for wrong user: $int1" })
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            { int1 = authUserId },
+            { "Fingerprint authenticated for wrong user: $int1" }
+        )
     }
 
     fun logFingerprintDisabledForUser(userId: Int) {
-        logBuffer.log(TAG, DEBUG,
-                { int1 = userId },
-                { "Fingerprint disabled by DPM for userId: $int1" })
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            { int1 = userId },
+            { "Fingerprint disabled by DPM for userId: $int1" }
+        )
     }
 
     fun logFingerprintLockoutReset(@LockoutMode mode: Int) {
@@ -155,42 +176,77 @@
     }
 
     fun logFingerprintRunningState(fingerprintRunningState: Int) {
-        logBuffer.log(TAG, DEBUG,
-                { int1 = fingerprintRunningState },
-                { "fingerprintRunningState: $int1" })
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            { int1 = fingerprintRunningState },
+            { "fingerprintRunningState: $int1" }
+        )
     }
 
     fun logFingerprintSuccess(userId: Int, isStrongBiometric: Boolean) {
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                int1 = userId
+                bool1 = isStrongBiometric
+            },
+            { "Fingerprint auth successful: userId: $int1, isStrongBiometric: $bool1" }
+        )
+    }
+
+    fun logFaceDetected(userId: Int, isStrongBiometric: Boolean) {
         logBuffer.log(TAG, DEBUG, {
             int1 = userId
             bool1 = isStrongBiometric
-        }, {"Fingerprint auth successful: userId: $int1, isStrongBiometric: $bool1"})
+        }, {"Face detected: userId: $int1, isStrongBiometric: $bool1"})
+    }
+
+    fun logFingerprintDetected(userId: Int, isStrongBiometric: Boolean) {
+        logBuffer.log(TAG, DEBUG, {
+            int1 = userId
+            bool1 = isStrongBiometric
+        }, {"Fingerprint detected: userId: $int1, isStrongBiometric: $bool1"})
     }
 
     fun logFingerprintError(msgId: Int, originalErrMsg: String) {
-        logBuffer.log(TAG, DEBUG, {
-            str1 = originalErrMsg
-            int1 = msgId
-        }, { "Fingerprint error received: $str1 msgId= $int1" })
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                str1 = originalErrMsg
+                int1 = msgId
+            },
+            { "Fingerprint error received: $str1 msgId= $int1" }
+        )
     }
 
     fun logInvalidSubId(subId: Int) {
-        logBuffer.log(TAG, INFO,
-                { int1 = subId },
-                { "Previously active sub id $int1 is now invalid, will remove" })
+        logBuffer.log(
+            TAG,
+            INFO,
+            { int1 = subId },
+            { "Previously active sub id $int1 is now invalid, will remove" }
+        )
     }
 
     fun logPrimaryKeyguardBouncerChanged(
-            primaryBouncerIsOrWillBeShowing: Boolean,
-            primaryBouncerFullyShown: Boolean
+        primaryBouncerIsOrWillBeShowing: Boolean,
+        primaryBouncerFullyShown: Boolean
     ) {
-        logBuffer.log(TAG, DEBUG, {
-            bool1 = primaryBouncerIsOrWillBeShowing
-            bool2 = primaryBouncerFullyShown
-        }, {
-            "handlePrimaryBouncerChanged " +
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                bool1 = primaryBouncerIsOrWillBeShowing
+                bool2 = primaryBouncerFullyShown
+            },
+            {
+                "handlePrimaryBouncerChanged " +
                     "primaryBouncerIsOrWillBeShowing=$bool1 primaryBouncerFullyShown=$bool2"
-        })
+            }
+        )
     }
 
     fun logKeyguardListenerModel(model: KeyguardListenModel) {
@@ -198,98 +254,134 @@
     }
 
     fun logKeyguardShowingChanged(showing: Boolean, occluded: Boolean, visible: Boolean) {
-        logBuffer.log(TAG, DEBUG, {
-            bool1 = showing
-            bool2 = occluded
-            bool3 = visible
-        }, {
-            "keyguardShowingChanged(showing=$bool1 occluded=$bool2 visible=$bool3)"
-        })
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                bool1 = showing
+                bool2 = occluded
+                bool3 = visible
+            },
+            { "keyguardShowingChanged(showing=$bool1 occluded=$bool2 visible=$bool3)" }
+        )
     }
 
     fun logMissingSupervisorAppError(userId: Int) {
-        logBuffer.log(TAG, ERROR,
-                { int1 = userId },
-                { "No Profile Owner or Device Owner supervision app found for User $int1" })
+        logBuffer.log(
+            TAG,
+            ERROR,
+            { int1 = userId },
+            { "No Profile Owner or Device Owner supervision app found for User $int1" }
+        )
     }
 
     fun logPhoneStateChanged(newState: String?) {
-        logBuffer.log(TAG, DEBUG,
-                { str1 = newState },
-                { "handlePhoneStateChanged($str1)" })
+        logBuffer.log(TAG, DEBUG, { str1 = newState }, { "handlePhoneStateChanged($str1)" })
     }
 
     fun logRegisterCallback(callback: KeyguardUpdateMonitorCallback?) {
-        logBuffer.log(TAG, VERBOSE,
-                { str1 = "$callback" },
-                { "*** register callback for $str1" })
+        logBuffer.log(TAG, VERBOSE, { str1 = "$callback" }, { "*** register callback for $str1" })
     }
 
     fun logRetryingAfterFaceHwUnavailable(retryCount: Int) {
-        logBuffer.log(TAG, WARNING,
-                { int1 = retryCount },
-                { "Retrying face after HW unavailable, attempt $int1" })
+        logBuffer.log(
+            TAG,
+            WARNING,
+            { int1 = retryCount },
+            { "Retrying face after HW unavailable, attempt $int1" }
+        )
     }
 
     fun logRetryAfterFpErrorWithDelay(msgId: Int, errString: String?, delay: Int) {
-        logBuffer.log(TAG, DEBUG, {
-            int1 = msgId
-            int2 = delay
-            str1 = "$errString"
-        }, {
-            "Fingerprint scheduling retry auth after $int2 ms due to($int1) -> $str1"
-        })
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                int1 = msgId
+                int2 = delay
+                str1 = "$errString"
+            },
+            { "Fingerprint scheduling retry auth after $int2 ms due to($int1) -> $str1" }
+        )
     }
 
     fun logRetryAfterFpHwUnavailable(retryCount: Int) {
-        logBuffer.log(TAG, WARNING,
-                { int1 = retryCount },
-                { "Retrying fingerprint attempt: $int1" })
+        logBuffer.log(
+            TAG,
+            WARNING,
+            { int1 = retryCount },
+            { "Retrying fingerprint attempt: $int1" }
+        )
     }
 
     fun logSendPrimaryBouncerChanged(
         primaryBouncerIsOrWillBeShowing: Boolean,
         primaryBouncerFullyShown: Boolean,
     ) {
-        logBuffer.log(TAG, DEBUG, {
-            bool1 = primaryBouncerIsOrWillBeShowing
-            bool2 = primaryBouncerFullyShown
-        }, {
-            "sendPrimaryBouncerChanged primaryBouncerIsOrWillBeShowing=$bool1 " +
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                bool1 = primaryBouncerIsOrWillBeShowing
+                bool2 = primaryBouncerFullyShown
+            },
+            {
+                "sendPrimaryBouncerChanged primaryBouncerIsOrWillBeShowing=$bool1 " +
                     "primaryBouncerFullyShown=$bool2"
-        })
+            }
+        )
     }
 
     fun logServiceStateChange(subId: Int, serviceState: ServiceState?) {
-        logBuffer.log(TAG, DEBUG, {
-            int1 = subId
-            str1 = "$serviceState"
-        }, { "handleServiceStateChange(subId=$int1, serviceState=$str1)" })
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                int1 = subId
+                str1 = "$serviceState"
+            },
+            { "handleServiceStateChange(subId=$int1, serviceState=$str1)" }
+        )
     }
 
     fun logServiceStateIntent(action: String?, serviceState: ServiceState?, subId: Int) {
-        logBuffer.log(TAG, VERBOSE, {
-            str1 = action
-            str2 = "$serviceState"
-            int1 = subId
-        }, { "action $str1 serviceState=$str2 subId=$int1" })
+        logBuffer.log(
+            TAG,
+            VERBOSE,
+            {
+                str1 = action
+                str2 = "$serviceState"
+                int1 = subId
+            },
+            { "action $str1 serviceState=$str2 subId=$int1" }
+        )
     }
 
     fun logSimState(subId: Int, slotId: Int, state: Int) {
-        logBuffer.log(TAG, DEBUG, {
-            int1 = subId
-            int2 = slotId
-            long1 = state.toLong()
-        }, { "handleSimStateChange(subId=$int1, slotId=$int2, state=$long1)" })
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                int1 = subId
+                int2 = slotId
+                long1 = state.toLong()
+            },
+            { "handleSimStateChange(subId=$int1, slotId=$int2, state=$long1)" }
+        )
     }
 
     fun logSimStateFromIntent(action: String?, extraSimState: String?, slotId: Int, subId: Int) {
-        logBuffer.log(TAG, VERBOSE, {
-            str1 = action
-            str2 = extraSimState
-            int1 = slotId
-            int2 = subId
-        }, { "action $str1 state: $str2 slotId: $int1 subid: $int2" })
+        logBuffer.log(
+            TAG,
+            VERBOSE,
+            {
+                str1 = action
+                str2 = extraSimState
+                int1 = slotId
+                int2 = subId
+            },
+            { "action $str1 state: $str2 slotId: $int1 subid: $int2" }
+        )
     }
 
     fun logSimUnlocked(subId: Int) {
@@ -297,78 +389,98 @@
     }
 
     fun logStartedListeningForFace(faceRunningState: Int, faceAuthUiEvent: FaceAuthUiEvent) {
-        logBuffer.log(TAG, VERBOSE, {
-            int1 = faceRunningState
-            str1 = faceAuthUiEvent.reason
-            str2 = faceAuthUiEvent.extraInfoToString()
-        }, { "startListeningForFace(): $int1, reason: $str1 $str2" })
+        logBuffer.log(
+            TAG,
+            VERBOSE,
+            {
+                int1 = faceRunningState
+                str1 = faceAuthUiEvent.reason
+                str2 = faceAuthUiEvent.extraInfoToString()
+            },
+            { "startListeningForFace(): $int1, reason: $str1 $str2" }
+        )
     }
 
     fun logStartedListeningForFaceFromWakeUp(faceRunningState: Int, @WakeReason pmWakeReason: Int) {
-        logBuffer.log(TAG, VERBOSE, {
-            int1 = faceRunningState
-            str1 = PowerManager.wakeReasonToString(pmWakeReason)
-        }, { "startListeningForFace(): $int1, reason: wakeUp-$str1" })
+        logBuffer.log(
+            TAG,
+            VERBOSE,
+            {
+                int1 = faceRunningState
+                str1 = PowerManager.wakeReasonToString(pmWakeReason)
+            },
+            { "startListeningForFace(): $int1, reason: wakeUp-$str1" }
+        )
     }
 
     fun logStoppedListeningForFace(faceRunningState: Int, faceAuthReason: String) {
-        logBuffer.log(TAG, VERBOSE, {
-            int1 = faceRunningState
-            str1 = faceAuthReason
-        }, { "stopListeningForFace(): currentFaceRunningState: $int1, reason: $str1" })
+        logBuffer.log(
+            TAG,
+            VERBOSE,
+            {
+                int1 = faceRunningState
+                str1 = faceAuthReason
+            },
+            { "stopListeningForFace(): currentFaceRunningState: $int1, reason: $str1" }
+        )
     }
 
     fun logSubInfo(subInfo: SubscriptionInfo?) {
-        logBuffer.log(TAG, VERBOSE,
-                { str1 = "$subInfo" },
-                { "SubInfo:$str1" })
+        logBuffer.log(TAG, VERBOSE, { str1 = "$subInfo" }, { "SubInfo:$str1" })
     }
 
     fun logTimeFormatChanged(newTimeFormat: String?) {
-        logBuffer.log(TAG, DEBUG,
-                { str1 = newTimeFormat },
-                { "handleTimeFormatUpdate timeFormat=$str1" })
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            { str1 = newTimeFormat },
+            { "handleTimeFormatUpdate timeFormat=$str1" }
+        )
     }
     fun logUdfpsPointerDown(sensorId: Int) {
-        logBuffer.log(TAG, DEBUG,
-                { int1 = sensorId },
-                { "onUdfpsPointerDown, sensorId: $int1" })
+        logBuffer.log(TAG, DEBUG, { int1 = sensorId }, { "onUdfpsPointerDown, sensorId: $int1" })
     }
 
     fun logUdfpsPointerUp(sensorId: Int) {
-        logBuffer.log(TAG, DEBUG,
-                { int1 = sensorId },
-                { "onUdfpsPointerUp, sensorId: $int1" })
+        logBuffer.log(TAG, DEBUG, { int1 = sensorId }, { "onUdfpsPointerUp, sensorId: $int1" })
     }
 
     fun logUnexpectedFaceCancellationSignalState(faceRunningState: Int, unlockPossible: Boolean) {
-        logBuffer.log(TAG, ERROR, {
-                    int1 = faceRunningState
-                    bool1 = unlockPossible
-                }, {
-                    "Cancellation signal is not null, high chance of bug in " +
-                            "face auth lifecycle management. " +
-                            "Face state: $int1, unlockPossible: $bool1"
-                })
+        logBuffer.log(
+            TAG,
+            ERROR,
+            {
+                int1 = faceRunningState
+                bool1 = unlockPossible
+            },
+            {
+                "Cancellation signal is not null, high chance of bug in " +
+                    "face auth lifecycle management. " +
+                    "Face state: $int1, unlockPossible: $bool1"
+            }
+        )
     }
 
     fun logUnexpectedFpCancellationSignalState(
         fingerprintRunningState: Int,
         unlockPossible: Boolean
     ) {
-        logBuffer.log(TAG, ERROR, {
-                    int1 = fingerprintRunningState
-                    bool1 = unlockPossible
-                }, {
-                    "Cancellation signal is not null, high chance of bug in " +
-                            "fp auth lifecycle management. FP state: $int1, unlockPossible: $bool1"
-                })
+        logBuffer.log(
+            TAG,
+            ERROR,
+            {
+                int1 = fingerprintRunningState
+                bool1 = unlockPossible
+            },
+            {
+                "Cancellation signal is not null, high chance of bug in " +
+                    "fp auth lifecycle management. FP state: $int1, unlockPossible: $bool1"
+            }
+        )
     }
 
     fun logUnregisterCallback(callback: KeyguardUpdateMonitorCallback?) {
-        logBuffer.log(TAG, VERBOSE,
-                { str1 = "$callback" },
-                { "*** unregister callback for $str1" })
+        logBuffer.log(TAG, VERBOSE, { str1 = "$callback" }, { "*** unregister callback for $str1" })
     }
 
     fun logUserRequestedUnlock(
@@ -376,75 +488,184 @@
         reason: String?,
         dismissKeyguard: Boolean
     ) {
-        logBuffer.log("ActiveUnlock", DEBUG, {
-                    str1 = requestOrigin?.name
-                    str2 = reason
-                    bool1 = dismissKeyguard
-                }, { "reportUserRequestedUnlock origin=$str1 reason=$str2 dismissKeyguard=$bool1" })
+        logBuffer.log(
+            "ActiveUnlock",
+            DEBUG,
+            {
+                str1 = requestOrigin?.name
+                str2 = reason
+                bool1 = dismissKeyguard
+            },
+            { "reportUserRequestedUnlock origin=$str1 reason=$str2 dismissKeyguard=$bool1" }
+        )
     }
 
     fun logTrustGrantedWithFlags(
-            flags: Int,
-            newlyUnlocked: Boolean,
-            userId: Int,
-            message: String?
+        flags: Int,
+        newlyUnlocked: Boolean,
+        userId: Int,
+        message: String?
     ) {
-        logBuffer.log(TAG, DEBUG, {
-            int1 = flags
-            bool1 = newlyUnlocked
-            int2 = userId
-            str1 = message
-        }, { "trustGrantedWithFlags[user=$int2] newlyUnlocked=$bool1 " +
-                "flags=${TrustGrantFlags(int1)} message=$str1" })
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                int1 = flags
+                bool1 = newlyUnlocked
+                int2 = userId
+                str1 = message
+            },
+            {
+                "trustGrantedWithFlags[user=$int2] newlyUnlocked=$bool1 " +
+                    "flags=${TrustGrantFlags(int1)} message=$str1"
+            }
+        )
     }
 
-    fun logTrustChanged(
-            wasTrusted: Boolean,
-            isNowTrusted: Boolean,
-            userId: Int
-    ) {
-        logBuffer.log(TAG, DEBUG, {
-            bool1 = wasTrusted
-            bool2 = isNowTrusted
-            int1 = userId
-        }, { "onTrustChanged[user=$int1] wasTrusted=$bool1 isNowTrusted=$bool2" })
+    fun logTrustChanged(wasTrusted: Boolean, isNowTrusted: Boolean, userId: Int) {
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                bool1 = wasTrusted
+                bool2 = isNowTrusted
+                int1 = userId
+            },
+            { "onTrustChanged[user=$int1] wasTrusted=$bool1 isNowTrusted=$bool2" }
+        )
     }
 
     fun logKeyguardStateUpdate(
-            secure: Boolean,
-            canDismissLockScreen: Boolean,
-            trusted: Boolean,
-            trustManaged: Boolean
-
+        secure: Boolean,
+        canDismissLockScreen: Boolean,
+        trusted: Boolean,
+        trustManaged: Boolean
     ) {
-        logBuffer.log("KeyguardState", DEBUG, {
-            bool1 = secure
-            bool2 = canDismissLockScreen
-            bool3 = trusted
-            bool4 = trustManaged
-        }, { "#update secure=$bool1 canDismissKeyguard=$bool2" +
-                " trusted=$bool3 trustManaged=$bool4" })
+        logBuffer.log(
+            "KeyguardState",
+            DEBUG,
+            {
+                bool1 = secure
+                bool2 = canDismissLockScreen
+                bool3 = trusted
+                bool4 = trustManaged
+            },
+            {
+                "#update secure=$bool1 canDismissKeyguard=$bool2" +
+                    " trusted=$bool3 trustManaged=$bool4"
+            }
+        )
     }
 
     fun logSkipUpdateFaceListeningOnWakeup(@WakeReason pmWakeReason: Int) {
-        logBuffer.log(TAG, VERBOSE, {
-            str1 = PowerManager.wakeReasonToString(pmWakeReason)
-        }, { "Skip updating face listening state on wakeup from $str1"})
+        logBuffer.log(
+            TAG,
+            VERBOSE,
+            { str1 = PowerManager.wakeReasonToString(pmWakeReason) },
+            { "Skip updating face listening state on wakeup from $str1" }
+        )
     }
 
     fun logTaskStackChangedForAssistant(assistantVisible: Boolean) {
-        logBuffer.log(TAG, VERBOSE, {
-            bool1 = assistantVisible
-        }, {
-            "TaskStackChanged for ACTIVITY_TYPE_ASSISTANT, assistant visible: $bool1"
-        })
+        logBuffer.log(
+            TAG,
+            VERBOSE,
+            { bool1 = assistantVisible },
+            { "TaskStackChanged for ACTIVITY_TYPE_ASSISTANT, assistant visible: $bool1" }
+        )
     }
 
     fun logAssistantVisible(assistantVisible: Boolean) {
-        logBuffer.log(TAG, VERBOSE, {
-            bool1 = assistantVisible
-        }, {
-            "Updating mAssistantVisible to new value: $bool1"
-        })
+        logBuffer.log(
+            TAG,
+            VERBOSE,
+            { bool1 = assistantVisible },
+            { "Updating mAssistantVisible to new value: $bool1" }
+        )
+    }
+
+    fun logReportSuccessfulBiometricUnlock(isStrongBiometric: Boolean, userId: Int) {
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                bool1 = isStrongBiometric
+                int1 = userId
+            },
+            { "reporting successful biometric unlock: isStrongBiometric: $bool1, userId: $int1" }
+        )
+    }
+
+    fun logHandlerHasAuthContinueMsgs(action: Int) {
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            { int1 = action },
+            {
+                "MSG_BIOMETRIC_AUTHENTICATION_CONTINUE already queued up, " +
+                    "ignoring updating FP listening state to $int1"
+            }
+        )
+    }
+
+    fun logFaceEnrolledUpdated(oldValue: Boolean, newValue: Boolean) {
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                bool1 = oldValue
+                bool2 = newValue
+            },
+            { "Face enrolled state changed: old: $bool1, new: $bool2" }
+        )
+    }
+
+    fun logFpEnrolledUpdated(userId: Int, oldValue: Boolean, newValue: Boolean) {
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                int1 = userId
+                bool1 = oldValue
+                bool2 = newValue
+            },
+            { "Fp enrolled state changed for userId: $int1 old: $bool1, new: $bool2" }
+        )
+    }
+
+    fun logTrustUsuallyManagedUpdated(
+        userId: Int,
+        oldValue: Boolean,
+        newValue: Boolean,
+        context: String
+    ) {
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                int1 = userId
+                bool1 = oldValue
+                bool2 = newValue
+                str1 = context
+            },
+            {
+                "trustUsuallyManaged changed for " +
+                    "userId: $int1 " +
+                    "old: $bool1, " +
+                    "new: $bool2 " +
+                    "context: $context"
+            }
+        )
+    }
+
+    fun logHandleBatteryUpdate(isInteresting: Boolean) {
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                bool1 = isInteresting
+            },
+            { "handleBatteryUpdate: $bool1" }
+        )
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
index b111e1f..57c9918 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
@@ -37,6 +37,8 @@
 import android.graphics.Insets;
 import android.graphics.Matrix;
 import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.Region;
@@ -401,15 +403,21 @@
         mAnimationController.deleteWindowMagnification(animationCallback);
     }
 
+    void deleteWindowMagnification() {
+        deleteWindowMagnification(/* closeSettingPanel= */ true);
+    }
+
     /**
      * Deletes the magnification window.
      */
-    void deleteWindowMagnification() {
+    void deleteWindowMagnification(boolean closeSettingPanel) {
         if (!isWindowVisible()) {
             return;
         }
 
-        closeMagnificationSettings();
+        if (closeSettingPanel) {
+            closeMagnificationSettings();
+        }
 
         if (mMirrorSurface != null) {
             mTransaction.remove(mMirrorSurface).apply();
@@ -487,7 +495,7 @@
         // Recreate the window again to correct the window appearance due to density or
         // window size changed not caused by rotation.
         if (isWindowVisible() && reCreateWindow) {
-            deleteWindowMagnification();
+            deleteWindowMagnification(/* closeSettingPanel= */ false);
             enableWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN);
         }
     }
@@ -1398,6 +1406,11 @@
             mWindowMagnifierCallback.onPerformScaleAction(mDisplayId,
                     A11Y_ACTION_SCALE_RANGE.clamp(scale));
         }
+
+        @Override
+        public void onSettingsPanelVisibilityChanged(boolean shown) {
+            updateDragHandleResourcesIfNeeded(/* settingsPanelIsShown= */ shown);
+        }
     };
 
     @Override
@@ -1436,6 +1449,20 @@
         }
     }
 
+    private void updateDragHandleResourcesIfNeeded(boolean settingsPanelIsShown) {
+        mDragView.setBackground(mContext.getResources().getDrawable(settingsPanelIsShown
+                ? R.drawable.accessibility_window_magnification_drag_handle_background_change
+                : R.drawable.accessibility_window_magnification_drag_handle_background));
+
+        PorterDuffColorFilter filter = new PorterDuffColorFilter(
+                mContext.getColor(settingsPanelIsShown
+                        ? R.color.magnification_border_color
+                        : R.color.magnification_drag_handle_stroke),
+                PorterDuff.Mode.SRC_ATOP);
+
+        mDragView.setColorFilter(filter);
+    }
+
     private void animateBounceEffect() {
         final ObjectAnimator scaleAnimator = ObjectAnimator.ofPropertyValuesHolder(mMirrorView,
                 PropertyValuesHolder.ofFloat(View.SCALE_X, 1, mBounceEffectAnimationScale, 1),
@@ -1468,7 +1495,7 @@
             super.onInitializeAccessibilityNodeInfo(host, info);
             final AccessibilityAction clickAction = new AccessibilityAction(
                     AccessibilityAction.ACTION_CLICK.getId(), mContext.getResources().getString(
-                    R.string.magnification_mode_switch_click_label));
+                    R.string.magnification_open_settings_click_label));
             info.addAction(clickAction);
             info.setClickable(true);
             info.addAction(
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
index 15264e64..d9f5544 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
@@ -215,9 +215,7 @@
 
         private boolean performA11yAction(View view, int action) {
             final Rect windowBounds = mWindowManager.getCurrentWindowMetrics().getBounds();
-            if (action == AccessibilityAction.ACTION_CLICK.getId()) {
-                handleSingleTap(view);
-            } else if (action == R.id.accessibility_action_move_up) {
+            if (action == R.id.accessibility_action_move_up) {
                 moveButton(0, -windowBounds.height());
             } else if (action == R.id.accessibility_action_move_down) {
                 moveButton(0, windowBounds.height());
@@ -232,14 +230,6 @@
         }
     };
 
-    private void applyResourcesValuesWithDensityChanged() {
-        if (mIsVisible) {
-            // Reset button to make its window layer always above the mirror window.
-            hideSettingPanel();
-            showSettingPanel(false);
-        }
-    }
-
     private boolean onTouch(View v, MotionEvent event) {
         if (!mIsVisible) {
             return false;
@@ -264,8 +254,6 @@
             } else if (id == R.id.magnifier_full_button) {
                 hideSettingPanel();
                 toggleMagnificationMode();
-            } else {
-                hideSettingPanel();
             }
         }
     };
@@ -273,7 +261,6 @@
     @Override
     public boolean onSingleTap(View view) {
         mSingleTapDetected = true;
-        handleSingleTap(view);
         return true;
     }
 
@@ -328,6 +315,7 @@
         }
 
         mContext.unregisterReceiver(mScreenOffReceiver);
+        mCallback.onSettingsPanelVisibilityChanged(/* shown= */ false);
     }
 
     public void showSettingPanel() {
@@ -362,6 +350,7 @@
             // Exclude magnification switch button from system gesture area.
             setSystemGestureExclusion();
             mIsVisible = true;
+            mCallback.onSettingsPanelVisibilityChanged(/* shown= */ true);
         }
         mContext.registerReceiver(mScreenOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
     }
@@ -385,8 +374,8 @@
         mSettingView = (LinearLayout) View.inflate(mContext,
                 R.layout.window_magnification_settings_view, null);
 
-        mSettingView.setClickable(true);
         mSettingView.setFocusable(true);
+        mSettingView.setFocusableInTouchMode(true);
         mSettingView.setOnTouchListener(this::onTouch);
 
         mPanelView = mSettingView.findViewById(R.id.magnifier_panel_view);
@@ -444,7 +433,15 @@
 
     void onConfigurationChanged(int configDiff) {
         if ((configDiff & ActivityInfo.CONFIG_UI_MODE) != 0
-                || (configDiff & ActivityInfo.CONFIG_ASSETS_PATHS) != 0) {
+                || (configDiff & ActivityInfo.CONFIG_ASSETS_PATHS) != 0
+                || (configDiff & ActivityInfo.CONFIG_FONT_SCALE) != 0
+                || (configDiff & ActivityInfo.CONFIG_DENSITY) != 0) {
+            // We listen to following config changes to trigger layout inflation:
+            // CONFIG_UI_MODE: theme change
+            // CONFIG_ASSETS_PATHS: wallpaper change
+            // CONFIG_FONT_SCALE: font size change
+            // CONFIG_DENSITY: display size change
+
             boolean showSettingPanelAfterThemeChange = mIsVisible;
             hideSettingPanel(/* resetPosition= */ false);
             inflateView();
@@ -453,6 +450,7 @@
             }
             return;
         }
+
         if ((configDiff & ActivityInfo.CONFIG_ORIENTATION) != 0) {
             final Rect previousDraggableBounds = new Rect(mDraggableWindowBounds);
             mDraggableWindowBounds.set(getDraggableWindowBounds());
@@ -464,10 +462,7 @@
                     + mDraggableWindowBounds.top;
             return;
         }
-        if ((configDiff & ActivityInfo.CONFIG_DENSITY) != 0) {
-            applyResourcesValuesWithDensityChanged();
-            return;
-        }
+
         if ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0) {
             updateAccessibilityWindowTitle();
             return;
@@ -499,22 +494,6 @@
         }
     }
 
-    private void handleSingleTap(View view) {
-        int id = view.getId();
-        if (id == R.id.magnifier_small_button) {
-            setMagnifierSize(MagnificationSize.SMALL);
-        } else if (id == R.id.magnifier_medium_button) {
-            setMagnifierSize(MagnificationSize.MEDIUM);
-        } else if (id == R.id.magnifier_large_button) {
-            setMagnifierSize(MagnificationSize.LARGE);
-        } else if (id == R.id.magnifier_full_button) {
-            hideSettingPanel();
-            toggleMagnificationMode();
-        } else {
-            hideSettingPanel();
-        }
-    }
-
     public void editMagnifierSizeMode(boolean enable) {
         setEditMagnifierSizeMode(enable);
         updateSelectedButton(MagnificationSize.NONE);
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettingsCallback.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettingsCallback.java
index 22ec650..1d83340 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettingsCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettingsCallback.java
@@ -61,4 +61,11 @@
      * 1 : ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN, 2 : ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW
      */
     void onModeSwitch(int newMode);
+
+    /**
+     * Called when the visibility of the magnification settings panel changed.
+     *
+     * @param shown The visibility of the magnification settings panel.
+     */
+    void onSettingsPanelVisibilityChanged(boolean shown);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/fontscaling/FontScalingDialog.kt b/packages/SystemUI/src/com/android/systemui/accessibility/fontscaling/FontScalingDialog.kt
index 54f933a..53a421d 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/fontscaling/FontScalingDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/fontscaling/FontScalingDialog.kt
@@ -29,6 +29,7 @@
 import com.android.systemui.common.ui.view.SeekBarWithIconButtonsView
 import com.android.systemui.statusbar.phone.SystemUIDialog
 import com.android.systemui.util.settings.SystemSettings
+import kotlin.math.roundToInt
 
 /** The Dialog that contains a seekbar for changing the font size. */
 class FontScalingDialog(context: Context, private val systemSettings: SystemSettings) :
@@ -56,6 +57,16 @@
         doneButton = requireViewById(com.android.internal.R.id.button1)
         seekBarWithIconButtonsView = requireViewById(R.id.font_scaling_slider)
 
+        val labelArray = arrayOfNulls<String>(strEntryValues.size)
+        for (i in strEntryValues.indices) {
+            labelArray[i] =
+                context.resources.getString(
+                    com.android.settingslib.R.string.font_scale_percentage,
+                    (strEntryValues[i].toFloat() * 100).roundToInt()
+                )
+        }
+        seekBarWithIconButtonsView.setProgressStateLabels(labelArray)
+
         seekBarWithIconButtonsView.setMax((strEntryValues).size - 1)
 
         val currentScale = systemSettings.getFloat(Settings.System.FONT_SCALE, 1.0f)
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
index ce42534..0002ae9 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
@@ -38,7 +38,6 @@
 import android.util.TypedValue;
 import android.view.Gravity;
 import android.view.LayoutInflater;
-import android.view.ViewGroup;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -347,10 +346,9 @@
                 }
                 if (mTextColor != 0) mBatteryPercentView.setTextColor(mTextColor);
                 updatePercentText();
-                addView(mBatteryPercentView,
-                        new ViewGroup.LayoutParams(
-                                LayoutParams.WRAP_CONTENT,
-                                LayoutParams.MATCH_PARENT));
+                addView(mBatteryPercentView, new LayoutParams(
+                        LayoutParams.WRAP_CONTENT,
+                        LayoutParams.MATCH_PARENT));
             }
         } else {
             if (showing) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
index 709ddf5..52312b8 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
@@ -97,7 +97,6 @@
         val iconContentDescription = getIconContentDescription(newState)
         if (iconContentDescription != null) {
             iconView.contentDescription = iconContentDescription
-            iconViewOverlay.contentDescription = iconContentDescription
         }
 
         iconView.frame = 0
@@ -152,7 +151,7 @@
             STATE_AUTHENTICATING_ANIMATING_IN,
             STATE_AUTHENTICATING,
             STATE_PENDING_CONFIRMATION,
-            STATE_AUTHENTICATED -> R.string.accessibility_fingerprint_dialog_fingerprint_icon
+            STATE_AUTHENTICATED -> R.string.security_settings_sfps_enroll_find_sensor_message
             STATE_ERROR,
             STATE_HELP -> R.string.biometric_dialog_try_again
             else -> null
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index e698faf..4aa985b 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -85,6 +85,8 @@
 import com.android.systemui.util.concurrency.DelayableExecutor;
 import com.android.systemui.util.concurrency.Execution;
 
+import kotlin.Unit;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -98,8 +100,6 @@
 import javax.inject.Inject;
 import javax.inject.Provider;
 
-import kotlin.Unit;
-
 /**
  * Receives messages sent from {@link com.android.server.biometrics.BiometricService} and shows the
  * appropriate biometric UI (e.g. BiometricDialogView).
@@ -148,6 +148,7 @@
     @NonNull private final WindowManager mWindowManager;
     @NonNull private final DisplayManager mDisplayManager;
     @Nullable private UdfpsController mUdfpsController;
+    @Nullable private UdfpsOverlayParams mUdfpsOverlayParams;
     @Nullable private IUdfpsRefreshRateRequestCallback mUdfpsRefreshRateRequestCallback;
     @Nullable private SideFpsController mSideFpsController;
     @Nullable private UdfpsLogger mUdfpsLogger;
@@ -197,32 +198,36 @@
     final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            if (mCurrentDialog != null
-                    && Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
+            if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
                 String reason = intent.getStringExtra("reason");
                 reason = (reason != null) ? reason : "unknown";
-                Log.d(TAG, "ACTION_CLOSE_SYSTEM_DIALOGS received, reason: " + reason);
-
-                mCurrentDialog.dismissWithoutCallback(true /* animate */);
-                mCurrentDialog = null;
-
-                for (Callback cb : mCallbacks) {
-                    cb.onBiometricPromptDismissed();
-                }
-
-                try {
-                    if (mReceiver != null) {
-                        mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_USER_CANCEL,
-                                null /* credentialAttestation */);
-                        mReceiver = null;
-                    }
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Remote exception", e);
-                }
+                closeDioalog(reason);
             }
         }
     };
 
+    private void closeDioalog(String reason) {
+        if (isShowing()) {
+            Log.i(TAG, "Close BP, reason :" + reason);
+            mCurrentDialog.dismissWithoutCallback(true /* animate */);
+            mCurrentDialog = null;
+
+            for (Callback cb : mCallbacks) {
+                cb.onBiometricPromptDismissed();
+            }
+
+            try {
+                if (mReceiver != null) {
+                    mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_USER_CANCEL,
+                            null /* credentialAttestation */);
+                    mReceiver = null;
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "Remote exception", e);
+            }
+        }
+    }
+
     private void cancelIfOwnerIsNotInForeground() {
         mExecution.assertIsMainThread();
         if (mCurrentDialog != null) {
@@ -545,6 +550,11 @@
         }
     }
 
+    @Override
+    public void handleShowGlobalActionsMenu() {
+        closeDioalog("PowerMenu shown");
+    }
+
     /**
      * @return where the UDFPS exists on the screen in pixels in portrait mode.
      */
@@ -806,6 +816,8 @@
             final FingerprintSensorPropertiesInternal udfpsProp = mUdfpsProps.get(0);
 
             final Rect previousUdfpsBounds = mUdfpsBounds;
+            final UdfpsOverlayParams previousUdfpsOverlayParams = mUdfpsOverlayParams;
+
             mUdfpsBounds = udfpsProp.getLocation().getRect();
             mUdfpsBounds.scale(mScaleFactor);
 
@@ -815,7 +827,7 @@
                     mCachedDisplayInfo.getNaturalWidth(), /* right */
                     mCachedDisplayInfo.getNaturalHeight() /* botom */);
 
-            final UdfpsOverlayParams overlayParams = new UdfpsOverlayParams(
+            mUdfpsOverlayParams = new UdfpsOverlayParams(
                     mUdfpsBounds,
                     overlayBounds,
                     mCachedDisplayInfo.getNaturalWidth(),
@@ -823,10 +835,11 @@
                     mScaleFactor,
                     mCachedDisplayInfo.rotation);
 
-            mUdfpsController.updateOverlayParams(udfpsProp, overlayParams);
-            if (!Objects.equals(previousUdfpsBounds, mUdfpsBounds)) {
+            mUdfpsController.updateOverlayParams(udfpsProp, mUdfpsOverlayParams);
+            if (!Objects.equals(previousUdfpsBounds, mUdfpsBounds) || !Objects.equals(
+                    previousUdfpsOverlayParams, mUdfpsOverlayParams)) {
                 for (Callback cb : mCallbacks) {
-                    cb.onUdfpsLocationChanged();
+                    cb.onUdfpsLocationChanged(mUdfpsOverlayParams);
                 }
             }
         }
@@ -872,7 +885,8 @@
     }
 
     /**
-     * Stores the callback received from {@link com.android.server.display.DisplayModeDirector}.
+     * Stores the callback received from
+     * {@link com.android.server.display.mode.DisplayModeDirector}.
      *
      * DisplayModeDirector implements {@link IUdfpsRefreshRateRequestCallback}
      * and registers it with this class by calling
@@ -1335,7 +1349,7 @@
          * On devices with UDFPS, this is always called alongside
          * {@link #onFingerprintLocationChanged}.
          */
-        default void onUdfpsLocationChanged() {}
+        default void onUdfpsLocationChanged(UdfpsOverlayParams udfpsOverlayParams) {}
 
         /**
          * Called when the location of the face unlock sensor (typically the front facing camera)
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
index d561cd7..46e945b 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
@@ -26,7 +26,9 @@
 import androidx.annotation.VisibleForTesting
 import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.keyguard.KeyguardUpdateMonitorCallback
+import com.android.keyguard.logging.KeyguardLogger
 import com.android.settingslib.Utils
+import com.android.settingslib.udfps.UdfpsOverlayParams
 import com.android.systemui.R
 import com.android.systemui.animation.Interpolators
 import com.android.systemui.flags.FeatureFlags
@@ -40,8 +42,8 @@
 import com.android.systemui.statusbar.commandline.Command
 import com.android.systemui.statusbar.commandline.CommandRegistry
 import com.android.systemui.statusbar.phone.BiometricUnlockController
+import com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_DISMISS_BOUNCER
 import com.android.systemui.statusbar.phone.CentralSurfaces
-import com.android.systemui.statusbar.phone.KeyguardBypassController
 import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent.CentralSurfacesScope
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -59,7 +61,9 @@
  * The ripple uses the accent color of the current theme.
  */
 @CentralSurfacesScope
-class AuthRippleController @Inject constructor(
+class AuthRippleController
+@Inject
+constructor(
     private val centralSurfaces: CentralSurfaces,
     private val sysuiContext: Context,
     private val authController: AuthController,
@@ -69,17 +73,18 @@
     private val wakefulnessLifecycle: WakefulnessLifecycle,
     private val commandRegistry: CommandRegistry,
     private val notificationShadeWindowController: NotificationShadeWindowController,
-    private val bypassController: KeyguardBypassController,
     private val biometricUnlockController: BiometricUnlockController,
     private val udfpsControllerProvider: Provider<UdfpsController>,
     private val statusBarStateController: StatusBarStateController,
     private val featureFlags: FeatureFlags,
-        rippleView: AuthRippleView?
-) : ViewController<AuthRippleView>(rippleView), KeyguardStateController.Callback,
+    private val logger: KeyguardLogger,
+    rippleView: AuthRippleView?
+) :
+    ViewController<AuthRippleView>(rippleView),
+    KeyguardStateController.Callback,
     WakefulnessLifecycle.Observer {
 
-    @VisibleForTesting
-    internal var startLightRevealScrimOnKeyguardFadingAway = false
+    @VisibleForTesting internal var startLightRevealScrimOnKeyguardFadingAway = false
     var lightRevealScrimAnimator: ValueAnimator? = null
     var fingerprintSensorLocation: Point? = null
     private var faceSensorLocation: Point? = null
@@ -88,6 +93,16 @@
     private var udfpsController: UdfpsController? = null
     private var udfpsRadius: Float = -1f
 
+    private val biometricModeListener = object : BiometricUnlockController.BiometricModeListener {
+        override fun onModeChanged(mode: Int) {
+            // isBiometricUnlock does not cover the scenario when biometrics unlocks
+            // the device while the bouncer is showing.
+            if (biometricUnlockController.isBiometricUnlock || mode == MODE_DISMISS_BOUNCER) {
+                showUnlockRipple(biometricUnlockController.biometricType)
+            }
+        }
+    }
+
     override fun onInit() {
         mView.setAlphaInDuration(sysuiContext.resources.getInteger(
                 R.integer.auth_ripple_alpha_in_duration).toLong())
@@ -104,6 +119,7 @@
         keyguardStateController.addCallback(this)
         wakefulnessLifecycle.addObserver(this)
         commandRegistry.registerCommand("auth-ripple") { AuthRippleCommand() }
+        biometricUnlockController.addBiometricModeListener(biometricModeListener)
     }
 
     @VisibleForTesting
@@ -115,13 +131,17 @@
         keyguardStateController.removeCallback(this)
         wakefulnessLifecycle.removeObserver(this)
         commandRegistry.unregisterCommand("auth-ripple")
+        biometricUnlockController.removeBiometricModeListener(biometricModeListener)
 
         notificationShadeWindowController.setForcePluginOpen(false, this)
     }
 
     fun showUnlockRipple(biometricSourceType: BiometricSourceType) {
-        if (!keyguardStateController.isShowing ||
-                !keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(biometricSourceType)) {
+        val keyguardNotShowing = !keyguardStateController.isShowing
+        val unlockNotAllowed = !keyguardUpdateMonitor
+                .isUnlockingWithBiometricAllowed(biometricSourceType)
+        if (keyguardNotShowing || unlockNotAllowed) {
+            logger.notShowingUnlockRipple(keyguardNotShowing, unlockNotAllowed)
             return
         }
 
@@ -138,13 +158,11 @@
                                 Math.max(it.y, centralSurfaces.displayHeight.toInt() - it.y)
                         )
                 )
+                logger.showingUnlockRippleAt(it.x, it.y, "FP sensor radius: $udfpsRadius")
                 showUnlockedRipple()
             }
         } else if (biometricSourceType == BiometricSourceType.FACE) {
-            if (!bypassController.canBypass() && !authController.isUdfpsFingerDown) {
-                return
-            }
-            faceSensorLocation?.let {
+             faceSensorLocation?.let {
                 mView.setSensorLocation(it)
                 circleReveal = CircleReveal(
                         it.x,
@@ -155,6 +173,7 @@
                                 Math.max(it.y, centralSurfaces.displayHeight.toInt() - it.y)
                         )
                 )
+                logger.showingUnlockRippleAt(it.x, it.y, "Face unlock ripple")
                 showUnlockedRipple()
             }
         }
@@ -264,7 +283,6 @@
                 if (biometricSourceType == BiometricSourceType.FINGERPRINT) {
                     mView.fadeDwellRipple()
                 }
-                showUnlockRipple(biometricSourceType)
             }
 
         override fun onBiometricAuthFailed(biometricSourceType: BiometricSourceType) {
@@ -319,7 +337,7 @@
                 updateUdfpsDependentParams()
             }
 
-            override fun onUdfpsLocationChanged() {
+            override fun onUdfpsLocationChanged(udfpsOverlayParams: UdfpsOverlayParams) {
                 updateUdfpsDependentParams()
             }
         }
@@ -390,6 +408,7 @@
     }
 
     companion object {
-        const val RIPPLE_ANIMATION_DURATION: Long = 1533
+        const val RIPPLE_ANIMATION_DURATION: Long = 800
+        const val TAG = "AuthRippleController"
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
index 4b32759..8409462 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
@@ -31,7 +31,7 @@
 import com.android.systemui.animation.Interpolators
 import com.android.systemui.surfaceeffects.ripple.RippleShader
 
-private const val RIPPLE_SPARKLE_STRENGTH: Float = 0.4f
+private const val RIPPLE_SPARKLE_STRENGTH: Float = 0.3f
 
 /**
  * Handles two ripple effects: dwell ripple and unlocked ripple
@@ -75,8 +75,8 @@
         }
     private var radius: Float = 0f
         set(value) {
-            rippleShader.rippleSize.setMaxSize(value * 2f, value * 2f)
-            field = value
+            field = value * .9f
+            rippleShader.rippleSize.setMaxSize(field * 2f, field * 2f)
         }
     private var origin: Point = Point()
         set(value) {
@@ -87,8 +87,9 @@
     init {
         rippleShader.color = 0xffffffff.toInt() // default color
         rippleShader.rawProgress = 0f
+        rippleShader.pixelDensity = resources.displayMetrics.density
         rippleShader.sparkleStrength = RIPPLE_SPARKLE_STRENGTH
-        setupRippleFadeParams()
+        updateRippleFadeParams()
         ripplePaint.shader = rippleShader
 
         dwellShader.color = 0xffffffff.toInt() // default color
@@ -266,7 +267,6 @@
         unlockedRippleAnimator?.cancel()
 
         val rippleAnimator = ValueAnimator.ofFloat(0f, 1f).apply {
-            interpolator = Interpolators.LINEAR_OUT_SLOW_IN
             duration = AuthRippleController.RIPPLE_ANIMATION_DURATION
             addUpdateListener { animator ->
                 val now = animator.currentPlayTime
@@ -277,7 +277,7 @@
             }
         }
 
-        val alphaInAnimator = ValueAnimator.ofInt(0, 255).apply {
+        val alphaInAnimator = ValueAnimator.ofInt(0, 62).apply {
             duration = alphaInDuration
             addUpdateListener { animator ->
                 rippleShader.color = ColorUtils.setAlphaComponent(
@@ -339,15 +339,17 @@
         )
     }
 
-    private fun setupRippleFadeParams() {
+    private fun updateRippleFadeParams() {
         with(rippleShader) {
-            baseRingFadeParams.fadeOutStart = RippleShader.DEFAULT_BASE_RING_FADE_OUT_START
-            baseRingFadeParams.fadeOutEnd = RippleShader.DEFAULT_FADE_OUT_END
+            baseRingFadeParams.fadeInStart = 0f
+            baseRingFadeParams.fadeInEnd = .2f
+            baseRingFadeParams.fadeOutStart = .2f
+            baseRingFadeParams.fadeOutEnd = 1f
 
-            centerFillFadeParams.fadeInStart = RippleShader.DEFAULT_FADE_IN_START
-            centerFillFadeParams.fadeInEnd = RippleShader.DEFAULT_CENTER_FILL_FADE_IN_END
-            centerFillFadeParams.fadeOutStart = RippleShader.DEFAULT_CENTER_FILL_FADE_OUT_START
-            centerFillFadeParams.fadeOutEnd = RippleShader.DEFAULT_CENTER_FILL_FADE_OUT_END
+            centerFillFadeParams.fadeInStart = 0f
+            centerFillFadeParams.fadeInEnd = .15f
+            centerFillFadeParams.fadeOutStart = .15f
+            centerFillFadeParams.fadeOutEnd = .56f
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt b/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt
index fabc1c1..e16121d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt
@@ -49,8 +49,8 @@
 
 /**
  * @property messagesToDefer messages that shouldn't show immediately when received, but may be
- * shown later if the message is the most frequent acquiredInfo processed and meets [threshold]
- * percentage of all passed acquired frames.
+ *   shown later if the message is the most frequent acquiredInfo processed and meets [threshold]
+ *   percentage of all passed acquired frames.
  */
 open class BiometricMessageDeferral(
     private val messagesToDefer: Set<Int>,
@@ -127,8 +127,9 @@
     /**
      * Get the most frequent deferred message that meets the [threshold] percentage of processed
      * frames.
+     *
      * @return null if no acquiredInfo have been deferred OR deferred messages didn't meet the
-     * [threshold] percentage.
+     *   [threshold] percentage.
      */
     fun getDeferredMessage(): CharSequence? {
         mostFrequentAcquiredInfoToDefer?.let {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
index ac6a22c..b62c729 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
@@ -64,6 +64,7 @@
 import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
 import com.android.systemui.recents.OverviewProxyService
 import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.traceSection
 import java.io.PrintWriter
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
@@ -215,7 +216,9 @@
         requests.add(request)
         mainExecutor.execute {
             if (overlayView == null) {
-                createOverlayForDisplay(reason)
+                traceSection("SideFpsController#show(request=${request.name}, reason=$reason") {
+                    createOverlayForDisplay(reason)
+                }
             } else {
                 Log.v(TAG, "overlay already shown")
             }
@@ -227,7 +230,7 @@
         requests.remove(request)
         mainExecutor.execute {
             if (requests.isEmpty()) {
-                overlayView = null
+                traceSection("SideFpsController#hide(${request.name}") { overlayView = null }
             }
         }
     }
@@ -492,7 +495,9 @@
             displayManager,
             handler,
             BiometricDisplayListener.SensorType.SideFingerprint(sensorProps)
-        ) { onOrientationChanged(reason) }
+        ) {
+            onOrientationChanged(reason)
+        }
 }
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 9e83264..bb35355 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -100,6 +100,8 @@
 import com.android.systemui.util.settings.SecureSettings;
 import com.android.systemui.util.time.SystemClock;
 
+import kotlin.Unit;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -110,8 +112,6 @@
 import javax.inject.Inject;
 import javax.inject.Provider;
 
-import kotlin.Unit;
-
 /**
  * Shows and hides the under-display fingerprint sensor (UDFPS) overlay, handles UDFPS touch events,
  * and toggles the UDFPS display mode.
@@ -598,14 +598,20 @@
                 mFalsingManager.isFalseTouch(UDFPS_AUTHENTICATION);
                 break;
 
+            case UNCHANGED:
+                if (!isWithinSensorArea(mOverlay.getOverlayView(), event.getX(), event.getY(),
+                        true) && mActivePointerId == MotionEvent.INVALID_POINTER_ID
+                        && event.getActionMasked() == MotionEvent.ACTION_DOWN
+                        && mAlternateBouncerInteractor.isVisibleState()) {
+                    // No pointer on sensor, forward to keyguard if alternateBouncer is visible
+                    mKeyguardViewManager.onTouch(event);
+                }
+
             default:
                 break;
         }
         logBiometricTouch(processedTouch.getEvent(), data);
 
-        // We should only consume touches that are within the sensor. By returning "false" for
-        // touches outside of the sensor, we let other UI components consume these events and act on
-        // them appropriately.
         return processedTouch.getTouchData().isWithinSensor(mOverlayParams.getNativeSensorBounds());
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
index 2d0d52e..231e7a4 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
@@ -348,6 +348,7 @@
 
     /**
      * Overrides non-bouncer show logic in shouldPauseAuth to still show icon.
+     *
      * @return whether the udfpsBouncer has been newly shown or hidden
      */
     private fun showUdfpsBouncer(show: Boolean): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractor.kt
new file mode 100644
index 0000000..92a7094
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractor.kt
@@ -0,0 +1,71 @@
+/*
+ * 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.view.MotionEvent
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.settingslib.udfps.UdfpsOverlayParams
+import com.android.systemui.biometrics.AuthController
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.stateIn
+
+/** Encapsulates business logic for interacting with the UDFPS overlay. */
+@SysUISingleton
+class UdfpsOverlayInteractor
+@Inject
+constructor(private val authController: AuthController, @Application scope: CoroutineScope) {
+
+    /** Whether a touch should be intercepted or allowed to pass to the UdfpsOverlay */
+    fun canInterceptTouchInUdfpsBounds(ev: MotionEvent): Boolean {
+        val isUdfpsEnrolled = authController.isUdfpsEnrolled(KeyguardUpdateMonitor.getCurrentUser())
+        val isWithinUdfpsOverlayBounds =
+            udfpsOverlayParams.value.overlayBounds.contains(ev.rawX.toInt(), ev.rawY.toInt())
+        return !isUdfpsEnrolled || !isWithinUdfpsOverlayBounds
+    }
+
+    /** Returns the current udfpsOverlayParams */
+    val udfpsOverlayParams: StateFlow<UdfpsOverlayParams> =
+        ConflatedCallbackFlow.conflatedCallbackFlow {
+                val callback =
+                    object : AuthController.Callback {
+                        override fun onUdfpsLocationChanged(
+                            udfpsOverlayParams: UdfpsOverlayParams
+                        ) {
+                            trySendWithFailureLogging(
+                                udfpsOverlayParams,
+                                TAG,
+                                "update udfpsOverlayParams"
+                            )
+                        }
+                    }
+                authController.addCallback(callback)
+                awaitClose { authController.removeCallback(callback) }
+            }
+            .stateIn(scope, started = SharingStarted.Eagerly, initialValue = UdfpsOverlayParams())
+
+    companion object {
+        private const val TAG = "UdfpsOverlayInteractor"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt
index 28bc2b7..6854b50 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt
@@ -76,5 +76,6 @@
         |          time: $time
         |  gestureStart: $gestureStart
         |}
-        """.trimMargin()
+        """
+            .trimMargin()
 }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
index bc0f995..f83885b 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
@@ -38,6 +38,7 @@
 public class FalsingDataProvider {
 
     private static final long MOTION_EVENT_AGE_MS = 1000;
+    private static final long DROP_EVENT_THRESHOLD_MS = 50;
     private static final float THREE_HUNDRED_SIXTY_DEG = (float) (2 * Math.PI);
 
     private final int mWidthPixels;
@@ -60,6 +61,7 @@
     private float mAngle = 0;
     private MotionEvent mFirstRecentMotionEvent;
     private MotionEvent mLastMotionEvent;
+    private boolean mDropLastEvent;
     private boolean mJustUnlockedWithFace;
     private boolean mA11YAction;
 
@@ -95,6 +97,12 @@
             // Ensure prior gesture was completed. May be a no-op.
             completePriorGesture();
         }
+
+        // Drop the gesture closing event if it is close in time to a previous ACTION_MOVE event.
+        // The reason is that the closing ACTION_UP event of  a swipe can be a bit offseted from the
+        // previous ACTION_MOVE event and when it happens, it makes some classifiers fail.
+        mDropLastEvent = shouldDropEvent(motionEvent);
+
         mRecentMotionEvents.addAll(motionEvents);
 
         FalsingClassifier.logVerbose("Size: " + mRecentMotionEvents.size());
@@ -129,6 +137,7 @@
             mPriorMotionEvents = mRecentMotionEvents;
             mRecentMotionEvents = new TimeLimitedMotionEventBuffer(MOTION_EVENT_AGE_MS);
         }
+        mDropLastEvent = false;
         mA11YAction = false;
     }
 
@@ -150,8 +159,18 @@
         return mYdpi;
     }
 
+    /**
+     * Get the {@link MotionEvent}s of the most recent gesture.
+     *
+     * Note that this list may not include the last recorded event.
+     * @see #mDropLastEvent
+     */
     public List<MotionEvent> getRecentMotionEvents() {
-        return mRecentMotionEvents;
+        if (!mDropLastEvent || mRecentMotionEvents.isEmpty()) {
+            return mRecentMotionEvents;
+        } else {
+            return mRecentMotionEvents.subList(0, mRecentMotionEvents.size() - 1);
+        }
     }
 
     public List<MotionEvent> getPriorMotionEvents() {
@@ -169,7 +188,12 @@
         return mFirstRecentMotionEvent;
     }
 
-    /** Get the last recorded {@link MotionEvent}. */
+    /**
+     * Get the last {@link MotionEvent} of the most recent gesture.
+     *
+     * Note that this may be the event prior to the last recorded event.
+     * @see #mDropLastEvent
+     */
     public MotionEvent getLastMotionEvent() {
         recalculateData();
         return mLastMotionEvent;
@@ -236,12 +260,13 @@
             return;
         }
 
-        if (mRecentMotionEvents.isEmpty()) {
+        List<MotionEvent> recentMotionEvents = getRecentMotionEvents();
+        if (recentMotionEvents.isEmpty()) {
             mFirstRecentMotionEvent = null;
             mLastMotionEvent = null;
         } else {
-            mFirstRecentMotionEvent = mRecentMotionEvents.get(0);
-            mLastMotionEvent = mRecentMotionEvents.get(mRecentMotionEvents.size() - 1);
+            mFirstRecentMotionEvent = recentMotionEvents.get(0);
+            mLastMotionEvent = recentMotionEvents.get(recentMotionEvents.size() - 1);
         }
 
         calculateAngleInternal();
@@ -249,6 +274,17 @@
         mDirty = false;
     }
 
+    private boolean shouldDropEvent(MotionEvent event) {
+        if (mRecentMotionEvents.size() < 3) return false;
+
+        MotionEvent lastEvent = mRecentMotionEvents.get(mRecentMotionEvents.size() - 1);
+        boolean isCompletingGesture = event.getActionMasked() == MotionEvent.ACTION_UP
+                && lastEvent.getActionMasked() == MotionEvent.ACTION_MOVE;
+        boolean isRecentEvent =
+                event.getEventTime() - lastEvent.getEventTime() < DROP_EVENT_THRESHOLD_MS;
+        return isCompletingGesture && isRecentEvent;
+    }
+
     private void calculateAngleInternal() {
         if (mRecentMotionEvents.size() < 2) {
             mAngle = Float.MAX_VALUE;
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedMotionEventBuffer.java b/packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedMotionEventBuffer.java
index 4773f2a..51aede7 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedMotionEventBuffer.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedMotionEventBuffer.java
@@ -183,7 +183,7 @@
 
     @Override
     public List<MotionEvent> subList(int fromIndex, int toIndex) {
-        throw new UnsupportedOperationException();
+        return mMotionEvents.subList(fromIndex, toIndex);
     }
 
     class Iter implements ListIterator<MotionEvent> {
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
index c214f53..e049ae0 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
@@ -263,10 +263,11 @@
     @Override // ClipboardListener.ClipboardOverlay
     public void setClipData(ClipData data, String source) {
         ClipboardModel model = ClipboardModel.fromClipData(mContext, mClipboardUtils, data, source);
-        if (mExitAnimator != null && mExitAnimator.isRunning()) {
+        boolean wasExiting = (mExitAnimator != null && mExitAnimator.isRunning());
+        if (wasExiting) {
             mExitAnimator.cancel();
         }
-        boolean shouldAnimate = !model.dataMatches(mClipboardModel);
+        boolean shouldAnimate = !model.dataMatches(mClipboardModel) || wasExiting;
         mClipboardModel = model;
         mClipboardLogger.setClipSource(mClipboardModel.getSource());
         if (shouldAnimate) {
@@ -313,15 +314,19 @@
                 mOnPreviewTapped = this::editText;
                 break;
             case IMAGE:
-                if (model.isSensitive() || model.loadThumbnail(mContext) != null) {
-                    mView.showImagePreview(
-                            model.isSensitive() ? null : model.loadThumbnail(mContext));
-                    mView.setEditAccessibilityAction(true);
-                    mOnPreviewTapped = () -> editImage(model.getUri());
-                } else {
-                    // image loading failed
-                    mView.showDefaultTextPreview();
-                }
+                mBgExecutor.execute(() -> {
+                    if (model.isSensitive() || model.loadThumbnail(mContext) != null) {
+                        mView.post(() -> {
+                            mView.showImagePreview(
+                                    model.isSensitive() ? null : model.loadThumbnail(mContext));
+                            mView.setEditAccessibilityAction(true);
+                        });
+                        mOnPreviewTapped = () -> editImage(model.getUri());
+                    } else {
+                        // image loading failed
+                        mView.post(mView::showDefaultTextPreview);
+                    }
+                });
                 break;
             case URI:
             case OTHER:
@@ -346,9 +351,20 @@
     }
 
     private void animateFromMinimized() {
-        mIsMinimized = false;
-        setExpandedView();
-        animateIn();
+        if (mEnterAnimator != null && mEnterAnimator.isRunning()) {
+            mEnterAnimator.cancel();
+        }
+        mEnterAnimator = mView.getMinimizedFadeoutAnimation();
+        mEnterAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                super.onAnimationEnd(animation);
+                mIsMinimized = false;
+                setExpandedView();
+                animateIn();
+            }
+        });
+        mEnterAnimator.start();
     }
 
     private String getAccessibilityAnnouncement(ClipboardModel.Type type) {
@@ -363,15 +379,15 @@
 
     private void classifyText(ClipboardModel model) {
         mBgExecutor.execute(() -> {
-            Optional<RemoteAction> remoteAction = mClipboardUtils.getAction(
-                            model.getText(), model.getTextLinks(), model.getSource());
+            Optional<RemoteAction> remoteAction =
+                    mClipboardUtils.getAction(model.getTextLinks(), model.getSource());
             if (model.equals(mClipboardModel)) {
                 remoteAction.ifPresent(action -> {
                     mClipboardLogger.logUnguarded(CLIPBOARD_OVERLAY_ACTION_SHOWN);
-                    mView.setActionChip(action, () -> {
+                    mView.post(() -> mView.setActionChip(action, () -> {
                         mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_ACTION_TAPPED);
                         animateOut();
-                    });
+                    }));
                 });
             }
         });
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtils.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtils.java
index a85f8b9..25caaea 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtils.java
@@ -39,6 +39,9 @@
 
 class ClipboardOverlayUtils {
 
+    // minimum proportion of entire text an entity must take up, to be considered for smart actions
+    private static final float MINIMUM_ENTITY_PROPORTION = .8f;
+
     private final TextClassifier mTextClassifier;
 
     @Inject
@@ -65,19 +68,23 @@
         return false;
     }
 
-    public Optional<RemoteAction> getAction(CharSequence text, TextLinks textLinks, String source) {
-        return getActions(text, textLinks).stream().filter(remoteAction -> {
+    public Optional<RemoteAction> getAction(TextLinks textLinks, String source) {
+        return getActions(textLinks).stream().filter(remoteAction -> {
             ComponentName component = remoteAction.getActionIntent().getIntent().getComponent();
             return component != null && !TextUtils.equals(source, component.getPackageName());
         }).findFirst();
     }
 
-    private ArrayList<RemoteAction> getActions(CharSequence text, TextLinks textLinks) {
+    private ArrayList<RemoteAction> getActions(TextLinks textLinks) {
         ArrayList<RemoteAction> actions = new ArrayList<>();
         for (TextLinks.TextLink link : textLinks.getLinks()) {
-            TextClassification classification = mTextClassifier.classifyText(
-                    text, link.getStart(), link.getEnd(), null);
-            actions.addAll(classification.getActions());
+            // skip classification for incidental entities
+            if (link.getEnd() - link.getStart()
+                    >= textLinks.getText().length() * MINIMUM_ENTITY_PROPORTION) {
+                TextClassification classification = mTextClassifier.classifyText(
+                        textLinks.getText(), link.getStart(), link.getEnd(), null);
+                actions.addAll(classification.getActions());
+            }
         }
         return actions;
     }
@@ -92,9 +99,13 @@
     private ArrayList<RemoteAction> getActions(ClipData.Item item) {
         ArrayList<RemoteAction> actions = new ArrayList<>();
         for (TextLinks.TextLink link : item.getTextLinks().getLinks()) {
-            TextClassification classification = mTextClassifier.classifyText(
-                    item.getText(), link.getStart(), link.getEnd(), null);
-            actions.addAll(classification.getActions());
+            // skip classification for incidental entities
+            if (link.getEnd() - link.getStart()
+                    >= item.getText().length() * MINIMUM_ENTITY_PROPORTION) {
+                TextClassification classification = mTextClassifier.classifyText(
+                        item.getText(), link.getStart(), link.getEnd(), null);
+                actions.addAll(classification.getActions());
+            }
         }
         return actions;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java
index f372bb4..28c57d3 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayView.java
@@ -21,6 +21,7 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
 import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
 import android.annotation.Nullable;
@@ -286,6 +287,20 @@
         mActionChips.clear();
     }
 
+    Animator getMinimizedFadeoutAnimation() {
+        ObjectAnimator anim = ObjectAnimator.ofFloat(mMinimizedPreview, "alpha", 1, 0);
+        anim.setDuration(66);
+        anim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                super.onAnimationEnd(animation);
+                mMinimizedPreview.setVisibility(View.GONE);
+                mMinimizedPreview.setAlpha(1);
+            }
+        });
+        return anim;
+    }
+
     Animator getEnterAnimation() {
         if (mAccessibilityManager.isEnabled()) {
             mDismissButton.setVisibility(View.VISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/common/coroutine/ChannelExt.kt b/packages/SystemUI/src/com/android/systemui/common/coroutine/ChannelExt.kt
index a0b19dc..c0e1717 100644
--- a/packages/SystemUI/src/com/android/systemui/common/coroutine/ChannelExt.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/coroutine/ChannelExt.kt
@@ -26,7 +26,6 @@
     /**
      * Convenience wrapper around [SendChannel.trySend] that also logs on failure. This is the
      * equivalent of calling:
-     *
      * ```
      * sendChannel.trySend(element).onFailure {
      *     Log.e(
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java b/packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java
index 24f6296..de3a990 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java
@@ -45,6 +45,7 @@
     private SeekBar mSeekbar;
 
     private SeekBarChangeListener mSeekBarListener = new SeekBarChangeListener();
+    private String[] mStateLabels = null;
 
     public SeekBarWithIconButtonsView(Context context) {
         this(context, null);
@@ -132,6 +133,30 @@
     }
 
     /**
+     * Stores the String array we would like to use for describing the state of seekbar progress
+     * and updates the state description with current progress.
+     *
+     * @param labels The state descriptions to be announced for each progress.
+     */
+    public void setProgressStateLabels(String[] labels) {
+        mStateLabels = labels;
+        if (mStateLabels != null) {
+            setSeekbarStateDescription();
+        }
+    }
+
+    /**
+     * Sets the state of seekbar based on current progress. The progress of seekbar is
+     * corresponding to the index of the string array. If the progress is larger than or equals
+     * to the length of the array, the state description is set to an empty string.
+     */
+    private void setSeekbarStateDescription() {
+        mSeekbar.setStateDescription(
+                (mSeekbar.getProgress() < mStateLabels.length)
+                        ? mStateLabels[mSeekbar.getProgress()] : "");
+    }
+
+    /**
      * Sets a onSeekbarChangeListener to the seekbar in the layout.
      * We update the Start Icon and End Icon if needed when the seekbar progress is changed.
      */
@@ -173,6 +198,9 @@
 
         @Override
         public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+            if (mStateLabels != null) {
+                setSeekbarStateDescription();
+            }
             if (mOnSeekBarChangeListener != null) {
                 mOnSeekBarChangeListener.onProgressChanged(seekBar, progress, fromUser);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt b/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt
index c0f8549..4173bdc 100644
--- a/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt
+++ b/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt
@@ -21,8 +21,10 @@
 import android.view.View
 import androidx.activity.ComponentActivity
 import androidx.lifecycle.LifecycleOwner
+import com.android.systemui.multishade.ui.viewmodel.MultiShadeViewModel
 import com.android.systemui.people.ui.viewmodel.PeopleViewModel
 import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
+import com.android.systemui.util.time.SystemClock
 
 /**
  * A facade to interact with Compose, when it is available.
@@ -57,4 +59,11 @@
         viewModel: FooterActionsViewModel,
         qsVisibilityLifecycleOwner: LifecycleOwner,
     ): View
+
+    /** Create a [View] to represent [viewModel] on screen. */
+    fun createMultiShadeView(
+        context: Context,
+        viewModel: MultiShadeViewModel,
+        clock: SystemClock,
+    ): View
 }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
index b3c18fb..3744344 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
@@ -86,6 +86,7 @@
      *
      * When the favorites for that application are returned, they will be removed from the auxiliary
      * file immediately, so they won't be retrieved again.
+     *
      * @param componentName the name of the service that provided the controls
      * @return a list of structures with favorites
      */
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
index 822190f..2d37c29 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
@@ -166,6 +166,13 @@
     )
 
     /**
+     * Removes favorites for a given component
+     * @param componentName the name of the service that provides the [Control]
+     * @return true when favorites is scheduled for deletion
+     */
+    fun removeFavorites(componentName: ComponentName): Boolean
+
+    /**
      * Replaces the favorites for the given structure.
      *
      * Calling this method will eliminate the previous selection of favorites and replace it with a
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
index 700f4f6..ac1150e 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
@@ -38,6 +38,7 @@
 import com.android.systemui.controls.ControlsServiceInfo
 import com.android.systemui.controls.management.ControlsListingController
 import com.android.systemui.controls.panels.AuthorizedPanelsRepository
+import com.android.systemui.controls.panels.SelectedComponentRepository
 import com.android.systemui.controls.ui.ControlsUiController
 import com.android.systemui.controls.ui.SelectedItem
 import com.android.systemui.dagger.SysUISingleton
@@ -57,16 +58,17 @@
 
 @SysUISingleton
 class ControlsControllerImpl @Inject constructor (
-    private val context: Context,
-    @Background private val executor: DelayableExecutor,
-    private val uiController: ControlsUiController,
-    private val bindingController: ControlsBindingController,
-    private val listingController: ControlsListingController,
-    private val userFileManager: UserFileManager,
-    private val userTracker: UserTracker,
-    private val authorizedPanelsRepository: AuthorizedPanelsRepository,
-    optionalWrapper: Optional<ControlsFavoritePersistenceWrapper>,
-    dumpManager: DumpManager,
+        private val context: Context,
+        @Background private val executor: DelayableExecutor,
+        private val uiController: ControlsUiController,
+        private val selectedComponentRepository: SelectedComponentRepository,
+        private val bindingController: ControlsBindingController,
+        private val listingController: ControlsListingController,
+        private val userFileManager: UserFileManager,
+        private val userTracker: UserTracker,
+        private val authorizedPanelsRepository: AuthorizedPanelsRepository,
+        optionalWrapper: Optional<ControlsFavoritePersistenceWrapper>,
+        dumpManager: DumpManager,
 ) : Dumpable, ControlsController {
 
     companion object {
@@ -499,6 +501,18 @@
         }
     }
 
+    override fun removeFavorites(componentName: ComponentName): Boolean {
+        if (!confirmAvailability()) return false
+
+        executor.execute {
+            if (Favorites.removeStructures(componentName)) {
+                persistenceWrapper.storeFavorites(Favorites.getAllStructures())
+            }
+            authorizedPanelsRepository.removeAuthorizedPanels(setOf(componentName.packageName))
+        }
+        return true
+    }
+
     override fun replaceFavoritesForStructure(structureInfo: StructureInfo) {
         if (!confirmAvailability()) return
         executor.execute {
@@ -561,7 +575,9 @@
     }
 
     override fun setPreferredSelection(selectedItem: SelectedItem) {
-        uiController.updatePreferences(selectedItem)
+        selectedComponentRepository.setSelectedComponent(
+                SelectedComponentRepository.SelectedComponent(selectedItem)
+        )
     }
 
     override fun dump(pw: PrintWriter, args: Array<out String>) {
@@ -657,10 +673,11 @@
         return true
     }
 
-    fun removeStructures(componentName: ComponentName) {
+    fun removeStructures(componentName: ComponentName): Boolean {
         val newFavMap = favMap.toMutableMap()
-        newFavMap.remove(componentName)
+        val removed = newFavMap.remove(componentName) != null
         favMap = newFavMap
+        return removed
     }
 
     fun addFavorite(
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
index 72c3a94..217f4d8 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
@@ -84,7 +84,7 @@
         private val BIND_FLAGS_PANEL = Context.BIND_AUTO_CREATE or Context.BIND_NOT_PERCEPTIBLE
     }
 
-    private val intent = Intent().apply {
+    private val intent = Intent(ControlsProviderService.SERVICE_CONTROLS).apply {
         component = componentName
         putExtra(CALLBACK_BUNDLE, Bundle().apply {
             putBinder(CALLBACK_TOKEN, token)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt
index d949d11..2af49aa 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt
@@ -36,6 +36,8 @@
 import com.android.systemui.controls.management.ControlsRequestDialog
 import com.android.systemui.controls.panels.AuthorizedPanelsRepository
 import com.android.systemui.controls.panels.AuthorizedPanelsRepositoryImpl
+import com.android.systemui.controls.panels.SelectedComponentRepository
+import com.android.systemui.controls.panels.SelectedComponentRepositoryImpl
 import com.android.systemui.controls.settings.ControlsSettingsDialogManager
 import com.android.systemui.controls.settings.ControlsSettingsDialogManagerImpl
 import com.android.systemui.controls.ui.ControlActionCoordinator
@@ -114,6 +116,11 @@
         repository: AuthorizedPanelsRepositoryImpl
     ): AuthorizedPanelsRepository
 
+    @Binds
+    abstract fun providePreferredPanelRepository(
+        repository: SelectedComponentRepositoryImpl
+    ): SelectedComponentRepository
+
     @BindsOptionalOf
     abstract fun optionalPersistenceWrapper(): ControlsFavoritePersistenceWrapper
 
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt
index b9f1666..cf5ccc5 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.controls.management
 
+import android.annotation.WorkerThread
 import android.content.ComponentName
 import com.android.systemui.controls.ControlsServiceInfo
 import com.android.systemui.util.UserAwareController
@@ -33,6 +34,9 @@
      */
     fun getCurrentServices(): List<ControlsServiceInfo>
 
+    @WorkerThread
+    fun forceReload()
+
     /**
      * Get the app label for a given component.
      *
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt
index c81a2c7..8ba060e 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt
@@ -16,8 +16,11 @@
 
 package com.android.systemui.controls.management
 
+import android.annotation.WorkerThread
 import android.content.ComponentName
 import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
 import android.os.UserHandle
 import android.service.controls.ControlsProviderService
 import android.util.Log
@@ -65,7 +68,7 @@
     private val serviceListingBuilder: (Context) -> ServiceListing,
     private val userTracker: UserTracker,
     dumpManager: DumpManager,
-    featureFlags: FeatureFlags
+    private val featureFlags: FeatureFlags
 ) : ControlsListingController, Dumpable {
 
     @Inject
@@ -97,18 +100,7 @@
         // After here, `list` is not captured, so we don't risk modifying it outside of the callback
         backgroundExecutor.execute {
             if (userChangeInProgress.get() > 0) return@execute
-            if (featureFlags.isEnabled(Flags.USE_APP_PANELS)) {
-                val allowAllApps = featureFlags.isEnabled(Flags.APP_PANELS_ALL_APPS_ALLOWED)
-                newServices.forEach {
-                    it.resolvePanelActivity(allowAllApps) }
-            }
-
-            if (newServices != availableServices) {
-                availableServices = newServices
-                callbacks.forEach {
-                    it.onServicesUpdated(getCurrentServices())
-                }
-            }
+            updateServices(newServices)
         }
     }
 
@@ -120,6 +112,21 @@
         serviceListing.reload()
     }
 
+    private fun updateServices(newServices: List<ControlsServiceInfo>) {
+        if (featureFlags.isEnabled(Flags.USE_APP_PANELS)) {
+            val allowAllApps = featureFlags.isEnabled(Flags.APP_PANELS_ALL_APPS_ALLOWED)
+            newServices.forEach {
+                it.resolvePanelActivity(allowAllApps) }
+        }
+
+        if (newServices != availableServices) {
+            availableServices = newServices
+            callbacks.forEach {
+                it.onServicesUpdated(getCurrentServices())
+            }
+        }
+    }
+
     override fun changeUser(newUser: UserHandle) {
         userChangeInProgress.incrementAndGet()
         serviceListing.setListening(false)
@@ -178,6 +185,23 @@
     override fun getCurrentServices(): List<ControlsServiceInfo> =
             availableServices.map(ControlsServiceInfo::copy)
 
+    @WorkerThread
+    override fun forceReload() {
+        val packageManager = context.packageManager
+        val intent = Intent(ControlsProviderService.SERVICE_CONTROLS)
+        val user = userTracker.userHandle
+        val flags = PackageManager.GET_SERVICES or
+                PackageManager.GET_META_DATA or
+                PackageManager.MATCH_DIRECT_BOOT_UNAWARE or
+                PackageManager.MATCH_DIRECT_BOOT_AWARE
+        val services = packageManager.queryIntentServicesAsUser(
+                intent,
+                PackageManager.ResolveInfoFlags.of(flags.toLong()),
+                user
+        ).map { ControlsServiceInfo(userTracker.userContext, it.serviceInfo) }
+        updateServices(services)
+    }
+
     /**
      * Get the localized label for the component.
      *
diff --git a/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt b/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt
index 3e672f3..ae9c37a 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt
@@ -26,6 +26,14 @@
     /** A set of package names that the user has previously authorized to show panels. */
     fun getAuthorizedPanels(): Set<String>
 
+    /** Preferred applications to query controls suggestions from */
+    fun getPreferredPackages(): Set<String>
+
     /** Adds [packageNames] to the set of packages that the user has authorized to show panels. */
     fun addAuthorizedPanels(packageNames: Set<String>)
+
+    /**
+     * Removes [packageNames] from the set of packages that the user has authorized to show panels.
+     */
+    fun removeAuthorizedPanels(packageNames: Set<String>)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImpl.kt
index f7e43a7..5c2402b 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImpl.kt
@@ -20,6 +20,8 @@
 import android.content.Context
 import android.content.SharedPreferences
 import com.android.systemui.R
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
 import com.android.systemui.settings.UserFileManager
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl
@@ -30,17 +32,28 @@
 constructor(
     private val context: Context,
     private val userFileManager: UserFileManager,
-    private val userTracker: UserTracker
+    private val userTracker: UserTracker,
+    private val featureFlags: FeatureFlags,
 ) : AuthorizedPanelsRepository {
 
     override fun getAuthorizedPanels(): Set<String> {
         return getAuthorizedPanelsInternal(instantiateSharedPrefs())
     }
 
+    override fun getPreferredPackages(): Set<String> =
+        context.resources.getStringArray(R.array.config_controlsPreferredPackages).toSet()
+
     override fun addAuthorizedPanels(packageNames: Set<String>) {
         addAuthorizedPanelsInternal(instantiateSharedPrefs(), packageNames)
     }
 
+    override fun removeAuthorizedPanels(packageNames: Set<String>) {
+        with(instantiateSharedPrefs()) {
+            val currentSet = getAuthorizedPanelsInternal(this)
+            edit().putStringSet(KEY, currentSet - packageNames).apply()
+        }
+    }
+
     private fun getAuthorizedPanelsInternal(sharedPreferences: SharedPreferences): Set<String> {
         return sharedPreferences.getStringSet(KEY, emptySet())!!
     }
@@ -61,17 +74,19 @@
                 userTracker.userId,
             )
 
-        // If we've never run this (i.e., the key doesn't exist), add the default packages
-        if (sharedPref.getStringSet(KEY, null) == null) {
-            sharedPref
-                .edit()
-                .putStringSet(
-                    KEY,
-                    context.resources
-                        .getStringArray(R.array.config_controlsPreferredPackages)
-                        .toSet()
-                )
-                .apply()
+        // We should add default packages in two cases:
+        // 1) We've never run this
+        // 2) APP_PANELS_REMOVE_APPS_ALLOWED got disabled after user removed all apps
+        val needToSetup =
+            if (featureFlags.isEnabled(Flags.APP_PANELS_REMOVE_APPS_ALLOWED)) {
+                sharedPref.getStringSet(KEY, null) == null
+            } else {
+                // There might be an empty set that need to be overridden after the feature has been
+                // turned off after being turned on
+                sharedPref.getStringSet(KEY, null).isNullOrEmpty()
+            }
+        if (needToSetup) {
+            sharedPref.edit().putStringSet(KEY, getPreferredPackages()).apply()
         }
         return sharedPref
     }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/panels/SelectedComponentRepository.kt b/packages/SystemUI/src/com/android/systemui/controls/panels/SelectedComponentRepository.kt
new file mode 100644
index 0000000..5bb6eec
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/panels/SelectedComponentRepository.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.controls.panels
+
+import android.content.ComponentName
+import com.android.systemui.controls.ui.ControlsUiController
+import com.android.systemui.controls.ui.SelectedItem
+import com.android.systemui.flags.Flags
+
+/** Stores user-selected preferred component. */
+interface SelectedComponentRepository {
+
+    /**
+     * Returns currently set preferred component, or null when nothing is set. Consider using
+     * [ControlsUiController.getPreferredSelectedItem] to get domain specific data
+     */
+    fun getSelectedComponent(): SelectedComponent?
+
+    /** Sets preferred component. Use [getSelectedComponent] to get current one */
+    fun setSelectedComponent(selectedComponent: SelectedComponent)
+
+    /** Clears current preferred component. [getSelectedComponent] will return null afterwards */
+    fun removeSelectedComponent()
+
+    /**
+     * Return true when default preferred component should be set up and false the otherwise. This
+     * is always true when [Flags.APP_PANELS_REMOVE_APPS_ALLOWED] is disabled
+     */
+    fun shouldAddDefaultComponent(): Boolean
+
+    /**
+     * Sets if default component should be added. This is ignored when
+     * [Flags.APP_PANELS_REMOVE_APPS_ALLOWED] is disabled
+     */
+    fun setShouldAddDefaultComponent(shouldAdd: Boolean)
+
+    data class SelectedComponent(
+        val name: String,
+        val componentName: ComponentName?,
+        val isPanel: Boolean,
+    ) {
+        constructor(
+            selectedItem: SelectedItem
+        ) : this(
+            name = selectedItem.name.toString(),
+            componentName = selectedItem.componentName,
+            isPanel = selectedItem is SelectedItem.PanelItem,
+        )
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/panels/SelectedComponentRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/panels/SelectedComponentRepositoryImpl.kt
new file mode 100644
index 0000000..0fb5b66
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/panels/SelectedComponentRepositoryImpl.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.controls.panels
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.SharedPreferences
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.settings.UserFileManager
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl
+import javax.inject.Inject
+
+@SysUISingleton
+class SelectedComponentRepositoryImpl
+@Inject
+constructor(
+    private val userFileManager: UserFileManager,
+    private val userTracker: UserTracker,
+    private val featureFlags: FeatureFlags,
+) : SelectedComponentRepository {
+
+    private companion object {
+        const val PREF_COMPONENT = "controls_component"
+        const val PREF_STRUCTURE_OR_APP_NAME = "controls_structure"
+        const val PREF_IS_PANEL = "controls_is_panel"
+        const val SHOULD_ADD_DEFAULT_PANEL = "should_add_default_panel"
+    }
+
+    private val sharedPreferences: SharedPreferences
+        get() =
+            userFileManager.getSharedPreferences(
+                fileName = DeviceControlsControllerImpl.PREFS_CONTROLS_FILE,
+                mode = Context.MODE_PRIVATE,
+                userId = userTracker.userId
+            )
+
+    override fun getSelectedComponent(): SelectedComponentRepository.SelectedComponent? {
+        with(sharedPreferences) {
+            val componentString = getString(PREF_COMPONENT, null) ?: return null
+            return SelectedComponentRepository.SelectedComponent(
+                name = getString(PREF_STRUCTURE_OR_APP_NAME, "")!!,
+                componentName = ComponentName.unflattenFromString(componentString),
+                isPanel = getBoolean(PREF_IS_PANEL, false)
+            )
+        }
+    }
+
+    override fun setSelectedComponent(
+        selectedComponent: SelectedComponentRepository.SelectedComponent
+    ) {
+        sharedPreferences
+            .edit()
+            .putString(PREF_COMPONENT, selectedComponent.componentName?.flattenToString())
+            .putString(PREF_STRUCTURE_OR_APP_NAME, selectedComponent.name)
+            .putBoolean(PREF_IS_PANEL, selectedComponent.isPanel)
+            .apply()
+    }
+
+    override fun removeSelectedComponent() {
+        sharedPreferences
+            .edit()
+            .remove(PREF_COMPONENT)
+            .remove(PREF_STRUCTURE_OR_APP_NAME)
+            .remove(PREF_IS_PANEL)
+            .apply()
+    }
+
+    override fun shouldAddDefaultComponent(): Boolean =
+        if (featureFlags.isEnabled(Flags.APP_PANELS_REMOVE_APPS_ALLOWED)) {
+            sharedPreferences.getBoolean(SHOULD_ADD_DEFAULT_PANEL, true)
+        } else {
+            true
+        }
+
+    override fun setShouldAddDefaultComponent(shouldAdd: Boolean) {
+        sharedPreferences.edit().putBoolean(SHOULD_ADD_DEFAULT_PANEL, shouldAdd).apply()
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt b/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt
index bb2e2d7..ce0f2e9 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt
@@ -38,7 +38,6 @@
 
 /**
  * Manager to display a dialog to prompt user to enable controls related Settings:
- *
  * * [Settings.Secure.LOCKSCREEN_SHOW_CONTROLS]
  * * [Settings.Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS]
  */
@@ -46,20 +45,19 @@
 
     /**
      * Shows the corresponding dialog. In order for a dialog to appear, the following must be true
-     *
      * * At least one of the Settings in [ControlsSettingsRepository] are `false`.
      * * The dialog has not been seen by the user too many times (as defined by
-     * [MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG]).
+     *   [MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG]).
      *
      * When the dialogs are shown, the following outcomes are possible:
      * * User cancels the dialog by clicking outside or going back: we register that the dialog was
-     * seen but the settings don't change.
+     *   seen but the settings don't change.
      * * User responds negatively to the dialog: we register that the user doesn't want to change
-     * the settings (dialog will not appear again) and the settings don't change.
+     *   the settings (dialog will not appear again) and the settings don't change.
      * * User responds positively to the dialog: the settings are set to `true` and the dialog will
-     * not appear again.
+     *   not appear again.
      * * SystemUI closes the dialogs (for example, the activity showing it is closed). In this case,
-     * we don't modify anything.
+     *   we don't modify anything.
      *
      * Of those four scenarios, only the first three will cause [onAttemptCompleted] to be called.
      * It will also be called if the dialogs are not shown.
@@ -157,17 +155,18 @@
         d.show()
     }
 
-    private fun turnOnSettingSecurely(settings: List<String>) {
+    private fun turnOnSettingSecurely(settings: List<String>, onComplete: () -> Unit) {
         val action =
             ActivityStarter.OnDismissAction {
                 settings.forEach { setting ->
                     secureSettings.putIntForUser(setting, 1, userTracker.userId)
                 }
+                onComplete()
                 true
             }
         activityStarter.dismissKeyguardThenExecute(
             action,
-            /* cancel */ null,
+            /* cancel */ onComplete,
             /* afterKeyguardGone */ true
         )
     }
@@ -188,7 +187,11 @@
                 if (!showDeviceControlsInLockscreen) {
                     settings.add(Settings.Secure.LOCKSCREEN_SHOW_CONTROLS)
                 }
-                turnOnSettingSecurely(settings)
+                // If we are toggling the flag, we want to call onComplete after the keyguard is
+                // dismissed (and the setting is turned on), to pass the correct value.
+                turnOnSettingSecurely(settings, onComplete)
+            } else {
+                onComplete()
             }
             if (attempts != MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG) {
                 prefs
@@ -196,7 +199,6 @@
                     .putInt(PREFS_SETTINGS_DIALOG_ATTEMPTS, MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG)
                     .apply()
             }
-            onComplete()
         }
 
         override fun onCancel(dialog: DialogInterface?) {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/start/ControlsStartable.kt b/packages/SystemUI/src/com/android/systemui/controls/start/ControlsStartable.kt
index 9d99253..461cacc 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/start/ControlsStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/start/ControlsStartable.kt
@@ -18,17 +18,17 @@
 package com.android.systemui.controls.start
 
 import android.content.Context
-import android.content.res.Resources
 import android.os.UserHandle
+import androidx.annotation.WorkerThread
 import com.android.systemui.CoreStartable
-import com.android.systemui.R
 import com.android.systemui.controls.controller.ControlsController
 import com.android.systemui.controls.dagger.ControlsComponent
 import com.android.systemui.controls.management.ControlsListingController
+import com.android.systemui.controls.panels.AuthorizedPanelsRepository
+import com.android.systemui.controls.panels.SelectedComponentRepository
 import com.android.systemui.controls.ui.SelectedItem
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.settings.UserTracker
 import java.util.concurrent.Executor
 import javax.inject.Inject
@@ -37,7 +37,7 @@
  * Started with SystemUI to perform early operations for device controls subsystem (only if enabled)
  *
  * In particular, it will perform the following:
- * * If there is no preferred selection for provider and at least one of the preferred packages 
+ * * If there is no preferred selection for provider and at least one of the preferred packages
  * provides a panel, it will select the first one that does.
  * * If the preferred selection provides a panel, it will bind to that service (to reduce latency on
  * displaying the panel).
@@ -48,10 +48,11 @@
 class ControlsStartable
 @Inject
 constructor(
-    @Main private val resources: Resources,
-    @Background private val executor: Executor,
-    private val controlsComponent: ControlsComponent,
-    private val userTracker: UserTracker
+        @Background private val executor: Executor,
+        private val controlsComponent: ControlsComponent,
+        private val userTracker: UserTracker,
+        private val authorizedPanelsRepository: AuthorizedPanelsRepository,
+        private val selectedComponentRepository: SelectedComponentRepository,
 ) : CoreStartable {
 
     // These two controllers can only be accessed after `start` method once we've checked if the
@@ -75,22 +76,27 @@
             // Controls is disabled, we don't need this anymore
             return
         }
-        startForUser()
+        executor.execute(this::startForUser)
         userTracker.addCallback(userTrackerCallback, executor)
     }
 
+    @WorkerThread
     private fun startForUser() {
+        controlsListingController.forceReload()
         selectDefaultPanelIfNecessary()
         bindToPanel()
     }
 
     private fun selectDefaultPanelIfNecessary() {
+        if (!selectedComponentRepository.shouldAddDefaultComponent()) {
+            return
+        }
         val currentSelection = controlsController.getPreferredSelection()
         if (currentSelection == SelectedItem.EMPTY_SELECTION) {
             val availableServices = controlsListingController.getCurrentServices()
             val panels = availableServices.filter { it.panelActivity != null }
-            resources
-                .getStringArray(R.array.config_controlsPreferredPackages)
+            authorizedPanelsRepository
+                .getPreferredPackages()
                 // Looking for the first element in the string array such that there is one package
                 // that has a panel. It will return null if there are no packages in the array,
                 // or if no packages in the array have a panel associated with it.
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
index 3a3f9b4..bf0a692 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
@@ -68,7 +68,7 @@
 
         getLifecycle().addObserver(
             ControlsAnimations.observerForAnimations(
-                requireViewById<ViewGroup>(R.id.control_detail_root),
+                requireViewById(R.id.control_detail_root),
                 window,
                 intent,
                 !featureFlags.isEnabled(Flags.USE_APP_PANELS)
@@ -95,7 +95,7 @@
     override fun onStart() {
         super.onStart()
 
-        parent = requireViewById<ViewGroup>(R.id.global_actions_controls)
+        parent = requireViewById(R.id.control_detail_root)
         parent.alpha = 0f
         if (featureFlags.isEnabled(Flags.USE_APP_PANELS) && !keyguardStateController.isUnlocked) {
             controlsSettingsDialogManager.maybeShowDialog(this) {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialogsFactory.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialogsFactory.kt
new file mode 100644
index 0000000..d6cfb79
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialogsFactory.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.controls.ui
+
+import android.app.Dialog
+import android.content.Context
+import android.content.DialogInterface
+import com.android.systemui.R
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import java.util.function.Consumer
+import javax.inject.Inject
+
+class ControlsDialogsFactory(private val internalDialogFactory: (Context) -> SystemUIDialog) {
+
+    @Inject constructor() : this({ SystemUIDialog(it) })
+
+    fun createRemoveAppDialog(
+        context: Context,
+        appName: CharSequence,
+        response: Consumer<Boolean>
+    ): Dialog {
+        val listener =
+            DialogInterface.OnClickListener { _, which ->
+                response.accept(which == DialogInterface.BUTTON_POSITIVE)
+            }
+        return internalDialogFactory(context).apply {
+            setTitle(context.getString(R.string.controls_panel_remove_app_authorization, appName))
+            setCanceledOnTouchOutside(true)
+            setOnCancelListener { response.accept(false) }
+            setPositiveButton(R.string.controls_dialog_remove, listener)
+            setNeutralButton(R.string.cancel, listener)
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
index 58673bb..0d53117 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
@@ -64,8 +64,6 @@
      * This element will be the one that appears when the user first opens the controls activity.
      */
     fun getPreferredSelectedItem(structures: List<StructureInfo>): SelectedItem
-
-    fun updatePreferences(selectedItem: SelectedItem)
 }
 
 sealed class SelectedItem {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index 9405c60..5da86de9 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -21,6 +21,7 @@
 import android.animation.ObjectAnimator
 import android.app.Activity
 import android.app.ActivityOptions
+import android.app.Dialog
 import android.app.PendingIntent
 import android.content.ComponentName
 import android.content.Context
@@ -52,7 +53,6 @@
 import com.android.systemui.R
 import com.android.systemui.controls.ControlsMetricsLogger
 import com.android.systemui.controls.ControlsServiceInfo
-import com.android.systemui.controls.settings.ControlsSettingsRepository
 import com.android.systemui.controls.CustomIconCache
 import com.android.systemui.controls.controller.ControlsController
 import com.android.systemui.controls.controller.StructureInfo
@@ -64,6 +64,8 @@
 import com.android.systemui.controls.management.ControlsListingController
 import com.android.systemui.controls.management.ControlsProviderSelectorActivity
 import com.android.systemui.controls.panels.AuthorizedPanelsRepository
+import com.android.systemui.controls.panels.SelectedComponentRepository
+import com.android.systemui.controls.settings.ControlsSettingsRepository
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
@@ -72,9 +74,7 @@
 import com.android.systemui.flags.Flags
 import com.android.systemui.globalactions.GlobalActionsPopupMenu
 import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.settings.UserFileManager
 import com.android.systemui.settings.UserTracker
-import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.util.asIndenting
 import com.android.systemui.util.concurrency.DelayableExecutor
@@ -97,24 +97,22 @@
         @Main val uiExecutor: DelayableExecutor,
         @Background val bgExecutor: DelayableExecutor,
         val controlsListingController: Lazy<ControlsListingController>,
-        val controlActionCoordinator: ControlActionCoordinator,
+        private val controlActionCoordinator: ControlActionCoordinator,
         private val activityStarter: ActivityStarter,
         private val iconCache: CustomIconCache,
         private val controlsMetricsLogger: ControlsMetricsLogger,
         private val keyguardStateController: KeyguardStateController,
-        private val userFileManager: UserFileManager,
         private val userTracker: UserTracker,
         private val taskViewFactory: Optional<TaskViewFactory>,
         private val controlsSettingsRepository: ControlsSettingsRepository,
         private val authorizedPanelsRepository: AuthorizedPanelsRepository,
+        private val selectedComponentRepository: SelectedComponentRepository,
         private val featureFlags: FeatureFlags,
+        private val dialogsFactory: ControlsDialogsFactory,
         dumpManager: DumpManager
 ) : ControlsUiController, Dumpable {
 
     companion object {
-        private const val PREF_COMPONENT = "controls_component"
-        private const val PREF_STRUCTURE_OR_APP_NAME = "controls_structure"
-        private const val PREF_IS_PANEL = "controls_is_panel"
 
         private const val FADE_IN_MILLIS = 200L
 
@@ -122,6 +120,7 @@
         private const val ADD_CONTROLS_ID = 1L
         private const val ADD_APP_ID = 2L
         private const val EDIT_CONTROLS_ID = 3L
+        private const val REMOVE_APP_ID = 4L
     }
 
     private var selectedItem: SelectedItem = SelectedItem.EMPTY_SELECTION
@@ -135,12 +134,6 @@
     private val popupThemedContext = ContextThemeWrapper(context, R.style.Control_ListPopupWindow)
     private var retainCache = false
     private var lastSelections = emptyList<SelectionItem>()
-    private val sharedPreferences
-        get() = userFileManager.getSharedPreferences(
-            fileName = DeviceControlsControllerImpl.PREFS_CONTROLS_FILE,
-            mode = 0,
-            userId = userTracker.userId
-        )
 
     private var taskViewController: PanelTaskViewController? = null
 
@@ -151,6 +144,7 @@
 
     private var openAppIntent: Intent? = null
     private var overflowMenuAdapter: BaseAdapter? = null
+    private var removeAppDialog: Dialog? = null
 
     private val onSeedingComplete = Consumer<Boolean> {
         accepted ->
@@ -330,6 +324,29 @@
         }
     }
 
+    @VisibleForTesting
+    internal fun startRemovingApp(componentName: ComponentName, appName: CharSequence) {
+        removeAppDialog?.cancel()
+        removeAppDialog = dialogsFactory.createRemoveAppDialog(context, appName) {
+            if (!controlsController.get().removeFavorites(componentName)) {
+                return@createRemoveAppDialog
+            }
+
+            if (selectedComponentRepository.getSelectedComponent()?.componentName ==
+                    componentName) {
+                selectedComponentRepository.removeSelectedComponent()
+            }
+
+            val selectedItem = getPreferredSelectedItem(controlsController.get().getFavorites())
+            if (selectedItem == SelectedItem.EMPTY_SELECTION) {
+                // User removed the last panel. In this case we start app selection flow and don't
+                // want to auto-add it again
+                selectedComponentRepository.setShouldAddDefaultComponent(false)
+            }
+            reload(parent)
+        }.apply { show() }
+    }
+
     private fun startTargetedActivity(si: StructureInfo, klazz: Class<*>) {
         val i = Intent(activityContext, klazz)
         putIntentExtras(i, si)
@@ -433,7 +450,10 @@
         val currentApps = panelsAndStructures.map { it.componentName }.toSet()
         val allApps = controlsListingController.get()
                 .getCurrentServices().map { it.componentName }.toSet()
-        createMenu(extraApps = (allApps - currentApps).isNotEmpty())
+        createMenu(
+                selectionItem = selectionItem,
+                extraApps = (allApps - currentApps).isNotEmpty(),
+        )
     }
 
     private fun createPanelView(componentName: ComponentName) {
@@ -472,7 +492,7 @@
         }
     }
 
-    private fun createMenu(extraApps: Boolean) {
+    private fun createMenu(selectionItem: SelectionItem, extraApps: Boolean) {
         val isPanel = selectedItem is SelectedItem.PanelItem
         val selectedStructure = (selectedItem as? SelectedItem.StructureItem)?.structure
                 ?: EMPTY_STRUCTURE
@@ -490,6 +510,12 @@
                             ADD_APP_ID
                     ))
                 }
+                if (featureFlags.isEnabled(Flags.APP_PANELS_REMOVE_APPS_ALLOWED)) {
+                    add(OverflowMenuAdapter.MenuItem(
+                            context.getText(R.string.controls_menu_remove),
+                            REMOVE_APP_ID,
+                    ))
+                }
             } else {
                 add(OverflowMenuAdapter.MenuItem(
                         context.getText(R.string.controls_menu_add),
@@ -529,6 +555,9 @@
                                 ADD_APP_ID -> startProviderSelectorActivity()
                                 ADD_CONTROLS_ID -> startFavoritingActivity(selectedStructure)
                                 EDIT_CONTROLS_ID -> startEditingActivity(selectedStructure)
+                                REMOVE_APP_ID -> startRemovingApp(
+                                        selectionItem.componentName, selectionItem.appName
+                                )
                             }
                             dismiss()
                         }
@@ -546,8 +575,12 @@
             RenderInfo.registerComponentIcon(it.componentName, it.icon)
         }
 
-        var adapter = ItemAdapter(context, R.layout.controls_spinner_item).apply {
-            addAll(items)
+        val adapter = ItemAdapter(context, R.layout.controls_spinner_item).apply {
+            add(selected)
+            addAll(items
+                    .filter { it !== selected }
+                    .sortedBy { it.appName.toString() }
+            )
         }
 
         val iconSize = context.resources
@@ -668,29 +701,22 @@
     }
 
     override fun getPreferredSelectedItem(structures: List<StructureInfo>): SelectedItem {
-        val sp = sharedPreferences
-
-        val component = sp.getString(PREF_COMPONENT, null)?.let {
-            ComponentName.unflattenFromString(it)
-        } ?: EMPTY_COMPONENT
-        val name = sp.getString(PREF_STRUCTURE_OR_APP_NAME, "")!!
-        val isPanel = sp.getBoolean(PREF_IS_PANEL, false)
-        return if (isPanel) {
-            SelectedItem.PanelItem(name, component)
+        val preferredPanel = selectedComponentRepository.getSelectedComponent()
+        val component = preferredPanel?.componentName ?: EMPTY_COMPONENT
+        return if (preferredPanel?.isPanel == true) {
+            SelectedItem.PanelItem(preferredPanel.name, component)
         } else {
             if (structures.isEmpty()) return SelectedItem.EMPTY_SELECTION
             SelectedItem.StructureItem(structures.firstOrNull {
-                component == it.componentName && name == it.structure
-            } ?: structures.get(0))
+                component == it.componentName && preferredPanel?.name == it.structure
+            } ?: structures[0])
         }
     }
 
-    override fun updatePreferences(selectedItem: SelectedItem) {
-        sharedPreferences.edit()
-                .putString(PREF_COMPONENT, selectedItem.componentName.flattenToString())
-                .putString(PREF_STRUCTURE_OR_APP_NAME, selectedItem.name.toString())
-                .putBoolean(PREF_IS_PANEL, selectedItem is SelectedItem.PanelItem)
-                .apply()
+    private fun updatePreferences(selectedItem: SelectedItem) {
+        selectedComponentRepository.setSelectedComponent(
+                SelectedComponentRepository.SelectedComponent(selectedItem)
+        )
     }
 
     private fun maybeUpdateSelectedItem(item: SelectionItem): Boolean {
@@ -728,6 +754,7 @@
             it.value.dismiss()
         }
         controlActionCoordinator.closeDialogs()
+        removeAppDialog?.cancel()
     }
 
     override fun hide(parent: ViewGroup) {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt
index 3b6ab20..78e87ca 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt
@@ -71,7 +71,7 @@
                 taskView.post {
                     val roundedCorner =
                         activityContext.resources.getDimensionPixelSize(
-                            R.dimen.notification_corner_radius
+                            R.dimen.controls_panel_corner_radius
                         )
                     val radii = FloatArray(8) { roundedCorner.toFloat() }
                     taskView.background =
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
index a5beb4e..3cf26b3 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
@@ -23,15 +23,16 @@
 import com.android.systemui.keyguard.WorkLockActivity;
 import com.android.systemui.people.PeopleSpaceActivity;
 import com.android.systemui.people.widget.LaunchConversationActivity;
-import com.android.systemui.screenshot.AppClipsActivity;
-import com.android.systemui.screenshot.AppClipsTrampolineActivity;
 import com.android.systemui.screenshot.LongScreenshotActivity;
+import com.android.systemui.screenshot.appclips.AppClipsActivity;
+import com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity;
 import com.android.systemui.sensorprivacy.SensorUseStartedActivity;
 import com.android.systemui.sensorprivacy.television.TvSensorPrivacyChangedActivity;
 import com.android.systemui.sensorprivacy.television.TvUnblockSensorActivity;
 import com.android.systemui.settings.brightness.BrightnessDialog;
 import com.android.systemui.statusbar.tv.notifications.TvNotificationPanelActivity;
 import com.android.systemui.tuner.TunerActivity;
+import com.android.systemui.usb.UsbAccessoryUriActivity;
 import com.android.systemui.usb.UsbConfirmActivity;
 import com.android.systemui.usb.UsbDebuggingActivity;
 import com.android.systemui.usb.UsbDebuggingSecondaryUserActivity;
@@ -97,6 +98,12 @@
     @ClassKey(UsbConfirmActivity.class)
     public abstract Activity bindUsbConfirmActivity(UsbConfirmActivity activity);
 
+    /** Inject into UsbAccessoryUriActivity. */
+    @Binds
+    @IntoMap
+    @ClassKey(UsbAccessoryUriActivity.class)
+    public abstract Activity bindUsbAccessoryUriActivity(UsbAccessoryUriActivity activity);
+
     /** Inject into CreateUserActivity. */
     @Binds
     @IntoMap
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
index 9921b1f..b86d419 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
@@ -47,10 +47,7 @@
 import com.android.systemui.recents.Recents
 import com.android.systemui.settings.dagger.MultiUserUtilsModule
 import com.android.systemui.shortcut.ShortcutKeyDispatcher
-import com.android.systemui.statusbar.notification.fsi.FsiChromeRepo
 import com.android.systemui.statusbar.notification.InstantAppNotifier
-import com.android.systemui.statusbar.notification.fsi.FsiChromeViewModelFactory
-import com.android.systemui.statusbar.notification.fsi.FsiChromeViewBinder
 import com.android.systemui.statusbar.phone.KeyguardLiftController
 import com.android.systemui.stylus.StylusUsiPowerStartable
 import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
@@ -91,24 +88,6 @@
     @ClassKey(ClipboardListener::class)
     abstract fun bindClipboardListener(sysui: ClipboardListener): CoreStartable
 
-    /** Inject into FsiChromeRepo.  */
-    @Binds
-    @IntoMap
-    @ClassKey(FsiChromeRepo::class)
-    abstract fun bindFSIChromeRepo(sysui: FsiChromeRepo): CoreStartable
-
-    /** Inject into FsiChromeWindowViewModel.  */
-    @Binds
-    @IntoMap
-    @ClassKey(FsiChromeViewModelFactory::class)
-    abstract fun bindFSIChromeWindowViewModel(sysui: FsiChromeViewModelFactory): CoreStartable
-
-    /** Inject into FsiChromeWindowBinder.  */
-    @Binds
-    @IntoMap
-    @ClassKey(FsiChromeViewBinder::class)
-    abstract fun bindFsiChromeWindowBinder(sysui: FsiChromeViewBinder): CoreStartable
-
     /** Inject into GlobalActionsComponent.  */
     @Binds
     @IntoMap
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index c96946b..63a4fd2 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -70,11 +70,14 @@
 import com.android.systemui.security.data.repository.SecurityRepositoryModule;
 import com.android.systemui.settings.DisplayTracker;
 import com.android.systemui.shade.ShadeController;
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolatorImpl;
 import com.android.systemui.smartspace.dagger.SmartspaceModule;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
 import com.android.systemui.statusbar.connectivity.ConnectivityModule;
+import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
 import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
 import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
@@ -257,9 +260,7 @@
     abstract FingerprintInteractiveToAuthProvider optionalFingerprintInteractiveToAuthProvider();
 
     @BindsOptionalOf
-    //TODO(b/269430792 remove full qualifier. Full qualifier is used to avoid merge conflict.)
-    abstract com.android.systemui.statusbar.events.SystemStatusAnimationScheduler
-    optionalSystemStatusAnimationScheduler();
+    abstract SystemStatusAnimationScheduler optionalSystemStatusAnimationScheduler();
 
     @SysUISingleton
     @Binds
@@ -310,4 +311,8 @@
 
     @Binds
     abstract FgsManagerController bindFgsManagerController(FgsManagerControllerImpl impl);
+
+    @Binds
+    abstract LargeScreenShadeInterpolator largeScreensShadeInterpolator(
+            LargeScreenShadeInterpolatorImpl impl);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt b/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
index 84f83f1..45ff963 100644
--- a/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
+++ b/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
@@ -128,7 +128,6 @@
      *
      * This is equivalent of creating a listener manually and adding an event handler for the given
      * command, like so:
-     *
      * ```
      * class Demoable {
      *   private val demoHandler = object : DemoMode {
diff --git a/packages/SystemUI/src/com/android/systemui/devicepolicy/DevicePolicyManagerExt.kt b/packages/SystemUI/src/com/android/systemui/devicepolicy/DevicePolicyManagerExt.kt
new file mode 100644
index 0000000..1390b4d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/devicepolicy/DevicePolicyManagerExt.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.devicepolicy
+
+import android.app.admin.DevicePolicyManager
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL
+import android.content.ComponentName
+
+/** Returns true if the admin of [userId] disallows keyguard shortcuts. */
+fun DevicePolicyManager.areKeyguardShortcutsDisabled(
+    admin: ComponentName? = null,
+    userId: Int
+): Boolean {
+    val flags = getKeyguardDisabledFeatures(admin, userId)
+    return flags and KEYGUARD_DISABLE_SHORTCUTS_ALL == KEYGUARD_DISABLE_SHORTCUTS_ALL ||
+        flags and KEYGUARD_DISABLE_FEATURES_ALL == KEYGUARD_DISABLE_FEATURES_ALL
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
index c3bd5d9..d0a92f0 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
@@ -43,7 +43,6 @@
 import javax.inject.Inject
 import javax.inject.Named
 import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.launch
 
@@ -131,9 +130,17 @@
         }
     }
 
-    /** Starts the dream content and dream overlay entry animations. */
+    /**
+     * Starts the dream content and dream overlay entry animations.
+     *
+     * @param downwards if true, the entry animation translations downwards into position rather
+     *   than upwards.
+     */
     @JvmOverloads
-    fun startEntryAnimations(animatorBuilder: () -> AnimatorSet = { AnimatorSet() }) {
+    fun startEntryAnimations(
+        downwards: Boolean,
+        animatorBuilder: () -> AnimatorSet = { AnimatorSet() }
+    ) {
         cancelAnimations()
 
         mAnimator =
@@ -153,7 +160,7 @@
                         interpolator = Interpolators.LINEAR
                     ),
                     translationYAnimator(
-                        from = mDreamInTranslationYDistance.toFloat(),
+                        from = mDreamInTranslationYDistance.toFloat() * (if (downwards) -1 else 1),
                         to = 0f,
                         durationMs = mDreamInTranslationYDurationMs,
                         interpolator = Interpolators.EMPHASIZED_DECELERATE
@@ -167,6 +174,71 @@
             }
     }
 
+    /**
+     * Starts the dream content and dream overlay exit animations.
+     *
+     * This should only be used when the low light dream is entering, animations to/from other SysUI
+     * views is controlled by `transitionViewModel`.
+     */
+    // TODO(b/256916668): integrate with the keyguard transition model once dream surfaces work is
+    // done.
+    @JvmOverloads
+    fun startExitAnimations(animatorBuilder: () -> AnimatorSet = { AnimatorSet() }): Animator {
+        cancelAnimations()
+
+        mAnimator =
+            animatorBuilder().apply {
+                playTogether(
+                    translationYAnimator(
+                        from = 0f,
+                        to = -mDreamInTranslationYDistance.toFloat(),
+                        durationMs = mDreamInTranslationYDurationMs,
+                        delayMs = 0,
+                        interpolator = Interpolators.EMPHASIZED
+                    ),
+                    alphaAnimator(
+                            from =
+                                mCurrentAlphaAtPosition.getOrDefault(
+                                    key = POSITION_BOTTOM,
+                                    defaultValue = 1f
+                                ),
+                            to = 0f,
+                            durationMs = mDreamInComplicationsAnimDurationMs,
+                            delayMs = 0,
+                            positions = POSITION_BOTTOM
+                        )
+                        .apply {
+                            doOnEnd {
+                                // The logical end of the animation is once the alpha and blur
+                                // animations finish, end the animation so that any listeners are
+                                // notified. The Y translation animation is much longer than all of
+                                // the other animations due to how the spec is defined, but is not
+                                // expected to run to completion.
+                                mAnimator?.end()
+                            }
+                        },
+                    alphaAnimator(
+                        from =
+                            mCurrentAlphaAtPosition.getOrDefault(
+                                key = POSITION_TOP,
+                                defaultValue = 1f
+                            ),
+                        to = 0f,
+                        durationMs = mDreamInComplicationsAnimDurationMs,
+                        delayMs = 0,
+                        positions = POSITION_TOP
+                    )
+                )
+                doOnEnd {
+                    mAnimator = null
+                    mOverlayStateController.setExitAnimationsRunning(false)
+                }
+                start()
+            }
+        mOverlayStateController.setExitAnimationsRunning(true)
+        return mAnimator as AnimatorSet
+    }
+
     /** Starts the dream content and dream overlay exit animations. */
     fun wakeUp(doneCallback: Runnable, executor: DelayableExecutor) {
         cancelAnimations()
@@ -182,18 +254,6 @@
             }
     }
 
-    /**
-     * Ends the dream content and dream overlay animations, if they're currently running.
-     * @see [AnimatorSet.end]
-     */
-    fun endAnimations() {
-        mAnimator =
-            mAnimator?.let {
-                it.end()
-                null
-            }
-    }
-
     private fun blurAnimator(
         view: View,
         fromBlurRadius: Float,
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
index 50cfb6a..4b478cd 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
@@ -23,6 +23,7 @@
 import static com.android.systemui.dreams.complication.ComplicationLayoutParams.POSITION_BOTTOM;
 import static com.android.systemui.dreams.complication.ComplicationLayoutParams.POSITION_TOP;
 
+import android.animation.Animator;
 import android.content.res.Resources;
 import android.os.Handler;
 import android.util.MathUtils;
@@ -31,6 +32,7 @@
 
 import androidx.annotation.NonNull;
 
+import com.android.dream.lowlight.LowLightTransitionCoordinator;
 import com.android.systemui.R;
 import com.android.systemui.animation.Interpolators;
 import com.android.systemui.dagger.qualifiers.Main;
@@ -54,11 +56,14 @@
  * View controller for {@link DreamOverlayContainerView}.
  */
 @DreamOverlayComponent.DreamOverlayScope
-public class DreamOverlayContainerViewController extends ViewController<DreamOverlayContainerView> {
+public class DreamOverlayContainerViewController extends
+        ViewController<DreamOverlayContainerView> implements
+        LowLightTransitionCoordinator.LowLightEnterListener {
     private final DreamOverlayStatusBarViewController mStatusBarViewController;
     private final BlurUtils mBlurUtils;
     private final DreamOverlayAnimationsController mDreamOverlayAnimationsController;
     private final DreamOverlayStateController mStateController;
+    private final LowLightTransitionCoordinator mLowLightTransitionCoordinator;
 
     private final ComplicationHostViewController mComplicationHostViewController;
 
@@ -143,19 +148,18 @@
             };
 
     /**
-     * If true, overlay entry animations should be skipped once.
-     *
-     * This is turned on when exiting low light and should be turned off once the entry animations
-     * are skipped once.
+     * If {@code true}, the dream has just transitioned from the low light dream back to the user
+     * dream and we should play an entry animation where the overlay slides in downwards from the
+     * top instead of the typicla slide in upwards from the bottom.
      */
-    private boolean mSkipEntryAnimations;
+    private boolean mExitingLowLight;
 
     private final DreamOverlayStateController.Callback
             mDreamOverlayStateCallback =
             new DreamOverlayStateController.Callback() {
                 @Override
                 public void onExitLowLight() {
-                    mSkipEntryAnimations = true;
+                    mExitingLowLight = true;
                 }
             };
 
@@ -165,6 +169,7 @@
             ComplicationHostViewController complicationHostViewController,
             @Named(DreamOverlayModule.DREAM_OVERLAY_CONTENT_VIEW) ViewGroup contentView,
             DreamOverlayStatusBarViewController statusBarViewController,
+            LowLightTransitionCoordinator lowLightTransitionCoordinator,
             BlurUtils blurUtils,
             @Main Handler handler,
             @Main Resources resources,
@@ -182,6 +187,7 @@
         mBlurUtils = blurUtils;
         mDreamOverlayAnimationsController = animationsController;
         mStateController = stateController;
+        mLowLightTransitionCoordinator = lowLightTransitionCoordinator;
 
         mBouncerlessScrimController = bouncerlessScrimController;
         mBouncerlessScrimController.addCallback(mBouncerlessExpansionCallback);
@@ -208,6 +214,7 @@
         mStatusBarViewController.init();
         mComplicationHostViewController.init();
         mDreamOverlayAnimationsController.init(mView);
+        mLowLightTransitionCoordinator.setLowLightEnterListener(this);
     }
 
     @Override
@@ -219,14 +226,10 @@
 
         // Start dream entry animations. Skip animations for low light clock.
         if (!mStateController.isLowLightActive()) {
-            mDreamOverlayAnimationsController.startEntryAnimations();
-
-            if (mSkipEntryAnimations) {
-                // If we're transitioning from the low light dream back to the user dream, skip the
-                // overlay animations and show immediately.
-                mDreamOverlayAnimationsController.endAnimations();
-                mSkipEntryAnimations = false;
-            }
+            // If this is transitioning from the low light dream to the user dream, the overlay
+            // should translate in downwards instead of upwards.
+            mDreamOverlayAnimationsController.startEntryAnimations(mExitingLowLight);
+            mExitingLowLight = false;
         }
     }
 
@@ -310,4 +313,12 @@
 
         mDreamOverlayAnimationsController.wakeUp(onAnimationEnd, callbackExecutor);
     }
+
+    @Override
+    public Animator onBeforeEnterLowLight() {
+        // Return the animator so that the transition coordinator waits for the overlay exit
+        // animations to finish before entering low light, as otherwise the default DreamActivity
+        // animation plays immediately and there's no time for this animation to play.
+        return mDreamOverlayAnimationsController.startExitAnimations();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
index f282aae..471c445 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.dreams;
 
+import static com.android.systemui.dreams.dagger.DreamModule.DREAM_OVERLAY_WINDOW_TITLE;
+
 import android.content.ComponentName;
 import android.content.Context;
 import android.graphics.drawable.ColorDrawable;
@@ -76,6 +78,7 @@
     private final ComponentName mLowLightDreamComponent;
     private final UiEventLogger mUiEventLogger;
     private final WindowManager mWindowManager;
+    private final String mWindowTitle;
 
     // A reference to the {@link Window} used to hold the dream overlay.
     private Window mWindow;
@@ -151,7 +154,9 @@
             TouchInsetManager touchInsetManager,
             @Nullable @Named(LowLightDreamModule.LOW_LIGHT_DREAM_COMPONENT)
                     ComponentName lowLightDreamComponent,
-            DreamOverlayCallbackController dreamOverlayCallbackController) {
+            DreamOverlayCallbackController dreamOverlayCallbackController,
+            @Named(DREAM_OVERLAY_WINDOW_TITLE) String windowTitle) {
+        super(executor);
         mContext = context;
         mExecutor = executor;
         mWindowManager = windowManager;
@@ -161,6 +166,7 @@
         mStateController = stateController;
         mUiEventLogger = uiEventLogger;
         mDreamOverlayCallbackController = dreamOverlayCallbackController;
+        mWindowTitle = windowTitle;
 
         final ViewModelStore viewModelStore = new ViewModelStore();
         final Complication.Host host =
@@ -197,55 +203,50 @@
 
     @Override
     public void onStartDream(@NonNull WindowManager.LayoutParams layoutParams) {
-        mExecutor.execute(() -> {
-            setCurrentStateLocked(Lifecycle.State.STARTED);
+        setCurrentStateLocked(Lifecycle.State.STARTED);
 
-            mUiEventLogger.log(DreamOverlayEvent.DREAM_OVERLAY_ENTER_START);
+        mUiEventLogger.log(DreamOverlayEvent.DREAM_OVERLAY_ENTER_START);
 
-            if (mDestroyed) {
-                // The task could still be executed after the service has been destroyed. Bail if
-                // that is the case.
-                return;
-            }
+        if (mDestroyed) {
+            // The task could still be executed after the service has been destroyed. Bail if
+            // that is the case.
+            return;
+        }
 
-            if (mStarted) {
-                // Reset the current dream overlay before starting a new one. This can happen
-                // when two dreams overlap (briefly, for a smoother dream transition) and both
-                // dreams are bound to the dream overlay service.
-                resetCurrentDreamOverlayLocked();
-            }
+        if (mStarted) {
+            // Reset the current dream overlay before starting a new one. This can happen
+            // when two dreams overlap (briefly, for a smoother dream transition) and both
+            // dreams are bound to the dream overlay service.
+            resetCurrentDreamOverlayLocked();
+        }
 
-            mDreamOverlayContainerViewController =
-                    mDreamOverlayComponent.getDreamOverlayContainerViewController();
-            mDreamOverlayTouchMonitor = mDreamOverlayComponent.getDreamOverlayTouchMonitor();
-            mDreamOverlayTouchMonitor.init();
+        mDreamOverlayContainerViewController =
+                mDreamOverlayComponent.getDreamOverlayContainerViewController();
+        mDreamOverlayTouchMonitor = mDreamOverlayComponent.getDreamOverlayTouchMonitor();
+        mDreamOverlayTouchMonitor.init();
 
-            mStateController.setShouldShowComplications(shouldShowComplications());
+        mStateController.setShouldShowComplications(shouldShowComplications());
 
-            // If we are not able to add the overlay window, reset the overlay.
-            if (!addOverlayWindowLocked(layoutParams)) {
-                resetCurrentDreamOverlayLocked();
-                return;
-            }
+        // If we are not able to add the overlay window, reset the overlay.
+        if (!addOverlayWindowLocked(layoutParams)) {
+            resetCurrentDreamOverlayLocked();
+            return;
+        }
 
+        setCurrentStateLocked(Lifecycle.State.RESUMED);
+        mStateController.setOverlayActive(true);
+        final ComponentName dreamComponent = getDreamComponent();
+        mStateController.setLowLightActive(
+                dreamComponent != null && dreamComponent.equals(mLowLightDreamComponent));
+        mUiEventLogger.log(DreamOverlayEvent.DREAM_OVERLAY_COMPLETE_START);
 
-            setCurrentStateLocked(Lifecycle.State.RESUMED);
-            mStateController.setOverlayActive(true);
-            final ComponentName dreamComponent = getDreamComponent();
-            mStateController.setLowLightActive(
-                    dreamComponent != null && dreamComponent.equals(mLowLightDreamComponent));
-            mUiEventLogger.log(DreamOverlayEvent.DREAM_OVERLAY_COMPLETE_START);
-
-            mDreamOverlayCallbackController.onStartDream();
-            mStarted = true;
-        });
+        mDreamOverlayCallbackController.onStartDream();
+        mStarted = true;
     }
 
     @Override
     public void onEndDream() {
-        mExecutor.execute(() -> {
-            resetCurrentDreamOverlayLocked();
-        });
+        resetCurrentDreamOverlayLocked();
     }
 
     private Lifecycle.State getCurrentStateLocked() {
@@ -258,12 +259,10 @@
 
     @Override
     public void onWakeUp(@NonNull Runnable onCompletedCallback) {
-        mExecutor.execute(() -> {
-            if (mDreamOverlayContainerViewController != null) {
-                mDreamOverlayCallbackController.onWakeUp();
-                mDreamOverlayContainerViewController.wakeUp(onCompletedCallback, mExecutor);
-            }
-        });
+        if (mDreamOverlayContainerViewController != null) {
+            mDreamOverlayCallbackController.onWakeUp();
+            mDreamOverlayContainerViewController.wakeUp(onCompletedCallback, mExecutor);
+        }
     }
 
     /**
@@ -277,7 +276,7 @@
     private boolean addOverlayWindowLocked(WindowManager.LayoutParams layoutParams) {
         mWindow = new PhoneWindow(mContext);
         // Default to SystemUI name for TalkBack.
-        mWindow.setTitle("");
+        mWindow.setTitle(mWindowTitle);
         mWindow.setAttributes(layoutParams);
         mWindow.setWindowManager(null, layoutParams.token, "DreamOverlay", true);
 
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationHostViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationHostViewController.java
index a2e11b2..aad2090 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationHostViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationHostViewController.java
@@ -22,14 +22,18 @@
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.os.Debug;
+import android.os.UserHandle;
+import android.provider.Settings;
 import android.util.Log;
 import android.view.View;
 
 import androidx.constraintlayout.widget.ConstraintLayout;
 import androidx.lifecycle.LifecycleOwner;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.dreams.DreamOverlayStateController;
 import com.android.systemui.util.ViewController;
+import com.android.systemui.util.settings.SecureSettings;
 
 import java.util.Collection;
 import java.util.HashMap;
@@ -54,9 +58,8 @@
     private final LifecycleOwner mLifecycleOwner;
     private final ComplicationCollectionViewModel mComplicationCollectionViewModel;
     private final HashMap<ComplicationId, Complication.ViewHolder> mComplications = new HashMap<>();
-
-    // Whether dream entry animations are finished.
-    private boolean mEntryAnimationsFinished = false;
+    @VisibleForTesting
+    boolean mIsAnimationEnabled;
 
     @Inject
     protected ComplicationHostViewController(
@@ -64,20 +67,17 @@
             ComplicationLayoutEngine layoutEngine,
             DreamOverlayStateController dreamOverlayStateController,
             LifecycleOwner lifecycleOwner,
-            @Named(SCOPED_COMPLICATIONS_MODEL) ComplicationCollectionViewModel viewModel) {
+            @Named(SCOPED_COMPLICATIONS_MODEL) ComplicationCollectionViewModel viewModel,
+            SecureSettings secureSettings) {
         super(view);
         mLayoutEngine = layoutEngine;
         mLifecycleOwner = lifecycleOwner;
         mComplicationCollectionViewModel = viewModel;
         mDreamOverlayStateController = dreamOverlayStateController;
 
-        mDreamOverlayStateController.addCallback(new DreamOverlayStateController.Callback() {
-            @Override
-            public void onStateChanged() {
-                mEntryAnimationsFinished =
-                        mDreamOverlayStateController.areEntryAnimationsFinished();
-            }
-        });
+        // Whether animations are enabled.
+        mIsAnimationEnabled = secureSettings.getFloatForUser(
+                Settings.Global.ANIMATOR_DURATION_SCALE, 1.0f, UserHandle.USER_CURRENT) != 0.0f;
     }
 
     @Override
@@ -148,7 +148,8 @@
 
                     // Complications to be added before dream entry animations are finished are set
                     // to invisible and are animated in.
-                    if (!mEntryAnimationsFinished) {
+                    if (!mDreamOverlayStateController.areEntryAnimationsFinished()
+                            && mIsAnimationEnabled) {
                         view.setVisibility(View.INVISIBLE);
                     }
                     mComplications.put(id, viewHolder);
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
index e39073b..ff1f312 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
@@ -28,6 +28,8 @@
 import com.android.systemui.CoreStartable;
 import com.android.systemui.dreams.DreamOverlayStateController;
 import com.android.systemui.dreams.smartspace.DreamSmartspaceController;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.BcSmartspaceDataPlugin;
 import com.android.systemui.shared.condition.Monitor;
 import com.android.systemui.util.condition.ConditionalCoreStartable;
@@ -68,6 +70,7 @@
         private final DreamSmartspaceController mSmartSpaceController;
         private final DreamOverlayStateController mDreamOverlayStateController;
         private final SmartSpaceComplication mComplication;
+        private final FeatureFlags mFeatureFlags;
 
         private final BcSmartspaceDataPlugin.SmartspaceTargetListener mSmartspaceListener =
                 new BcSmartspaceDataPlugin.SmartspaceTargetListener() {
@@ -85,15 +88,21 @@
                 DreamOverlayStateController dreamOverlayStateController,
                 SmartSpaceComplication smartSpaceComplication,
                 DreamSmartspaceController smartSpaceController,
-                @Named(DREAM_PRETEXT_MONITOR) Monitor monitor) {
+                @Named(DREAM_PRETEXT_MONITOR) Monitor monitor,
+                FeatureFlags featureFlags) {
             super(monitor);
             mDreamOverlayStateController = dreamOverlayStateController;
             mComplication = smartSpaceComplication;
             mSmartSpaceController = smartSpaceController;
+            mFeatureFlags = featureFlags;
         }
 
         @Override
         public void onStart() {
+            if (mFeatureFlags.isEnabled(Flags.HIDE_SMARTSPACE_ON_DREAM_OVERLAY)) {
+                return;
+            }
+
             mDreamOverlayStateController.addCallback(new DreamOverlayStateController.Callback() {
                 @Override
                 public void onStateChanged() {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java
index 9b954f5f..6808142 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java
@@ -51,6 +51,7 @@
     int DREAM_MEDIA_COMPLICATION_WEIGHT = 0;
     int DREAM_HOME_CONTROLS_CHIP_COMPLICATION_WEIGHT = 4;
     int DREAM_MEDIA_ENTRY_COMPLICATION_WEIGHT = 3;
+    int DREAM_WEATHER_COMPLICATION_WEIGHT = 0;
 
     /**
      * Provides layout parameters for the clock time complication.
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
index f598c36..f130026 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
@@ -23,6 +23,7 @@
 
 import com.android.dream.lowlight.dagger.LowLightDreamModule;
 import com.android.settingslib.dream.DreamBackend;
+import com.android.systemui.R;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dreams.DreamOverlayNotificationCountProvider;
@@ -66,6 +67,8 @@
     String DREAM_SUPPORTED = "dream_supported";
     String DREAM_PRETEXT_CONDITIONS = "dream_pretext_conditions";
     String DREAM_PRETEXT_MONITOR = "dream_prtext_monitor";
+    String DREAM_OVERLAY_WINDOW_TITLE = "dream_overlay_window_title";
+
 
     /**
      * Provides the dream component
@@ -139,4 +142,11 @@
             @Named(DREAM_PRETEXT_CONDITIONS) Set<Condition> pretextConditions) {
         return new Monitor(executor, pretextConditions);
     }
+
+    /** */
+    @Provides
+    @Named(DREAM_OVERLAY_WINDOW_TITLE)
+    static String providesDreamOverlayWindowTitle(@Main Resources resources) {
+        return resources.getString(R.string.app_label);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamSmartspaceController.kt
index 63f63a5..78e132f 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamSmartspaceController.kt
@@ -30,14 +30,15 @@
 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_DREAM
 import com.android.systemui.smartspace.SmartspacePrecondition
 import com.android.systemui.smartspace.SmartspaceTargetFilter
+import com.android.systemui.smartspace.dagger.SmartspaceModule
 import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.DREAM_SMARTSPACE_DATA_PLUGIN
 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.SmartspaceViewComponent
 import com.android.systemui.util.concurrency.Execution
-import java.lang.RuntimeException
 import java.util.Optional
 import java.util.concurrent.Executor
 import javax.inject.Inject
@@ -56,13 +57,16 @@
     @Named(DREAM_SMARTSPACE_PRECONDITION) private val precondition: SmartspacePrecondition,
     @Named(DREAM_SMARTSPACE_TARGET_FILTER)
     private val optionalTargetFilter: Optional<SmartspaceTargetFilter>,
-    @Named(DREAM_SMARTSPACE_DATA_PLUGIN) optionalPlugin: Optional<BcSmartspaceDataPlugin>
+    @Named(DREAM_SMARTSPACE_DATA_PLUGIN) optionalPlugin: Optional<BcSmartspaceDataPlugin>,
+    @Named(SmartspaceModule.WEATHER_SMARTSPACE_DATA_PLUGIN)
+    optionalWeatherPlugin: Optional<BcSmartspaceDataPlugin>,
 ) {
     companion object {
         private const val TAG = "DreamSmartspaceCtrlr"
     }
 
     private var session: SmartspaceSession? = null
+    private val weatherPlugin: BcSmartspaceDataPlugin? = optionalWeatherPlugin.orElse(null)
     private val plugin: BcSmartspaceDataPlugin? = optionalPlugin.orElse(null)
     private var targetFilter: SmartspaceTargetFilter? = optionalTargetFilter.orElse(null)
 
@@ -116,31 +120,54 @@
     private val sessionListener = SmartspaceSession.OnTargetsAvailableListener { targets ->
         execution.assertIsMainThread()
 
+        // The weather data plugin takes unfiltered targets and performs the filtering internally.
+        weatherPlugin?.onTargetsAvailable(targets)
+
         onTargetsAvailableUnfiltered(targets)
         val filteredTargets = targets.filter { targetFilter?.filterSmartspaceTarget(it) ?: true }
         plugin?.onTargetsAvailable(filteredTargets)
     }
 
     /**
+     * Constructs the weather view with custom layout and connects it to the weather plugin.
+     */
+    fun buildAndConnectWeatherView(parent: ViewGroup, customView: View?): View? {
+        return buildAndConnectViewWithPlugin(parent, weatherPlugin, customView)
+    }
+
+    /**
      * Constructs the smartspace view and connects it to the smartspace service.
      */
     fun buildAndConnectView(parent: ViewGroup): View? {
+        return buildAndConnectViewWithPlugin(parent, plugin, null)
+    }
+
+    private fun buildAndConnectViewWithPlugin(
+        parent: ViewGroup,
+        smartspaceDataPlugin: BcSmartspaceDataPlugin?,
+        customView: View?
+    ): View? {
         execution.assertIsMainThread()
 
         if (!precondition.conditionsMet()) {
             throw RuntimeException("Cannot build view when not enabled")
         }
 
-        val view = buildView(parent)
+        val view = buildView(parent, smartspaceDataPlugin, customView)
 
         connectSession()
 
         return view
     }
 
-    private fun buildView(parent: ViewGroup): View? {
-        return if (plugin != null) {
-            var view = smartspaceViewComponentFactory.create(parent, plugin, stateChangeListener)
+    private fun buildView(
+        parent: ViewGroup,
+        smartspaceDataPlugin: BcSmartspaceDataPlugin?,
+        customView: View?
+    ): View? {
+        return if (smartspaceDataPlugin != null) {
+            val view = smartspaceViewComponentFactory.create(parent, smartspaceDataPlugin,
+                stateChangeListener, customView)
                 .getView()
             if (view !is View) {
                 return null
@@ -157,7 +184,10 @@
     }
 
     private fun connectSession() {
-        if (plugin == null || session != null || !hasActiveSessionListeners()) {
+        if (plugin == null && weatherPlugin == null) {
+            return
+        }
+        if (session != null || !hasActiveSessionListeners()) {
             return
         }
 
@@ -166,13 +196,14 @@
         }
 
         val newSession = smartspaceManager.createSmartspaceSession(
-            SmartspaceConfig.Builder(context, "dream").build()
+            SmartspaceConfig.Builder(context, UI_SURFACE_DREAM).build()
         )
         Log.d(TAG, "Starting smartspace session for dream")
         newSession.addOnTargetsAvailableListener(uiExecutor, sessionListener)
         this.session = newSession
 
-        plugin.registerSmartspaceEventNotifier {
+        weatherPlugin?.registerSmartspaceEventNotifier { e -> session?.notifySmartspaceEvent(e) }
+        plugin?.registerSmartspaceEventNotifier {
                 e ->
             session?.notifySmartspaceEvent(e)
         }
@@ -199,22 +230,47 @@
 
         session = null
 
+        weatherPlugin?.registerSmartspaceEventNotifier(null)
+        weatherPlugin?.onTargetsAvailable(emptyList())
+
         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)
+    }
+
+    fun addListenerForWeatherPlugin(listener: SmartspaceTargetListener) {
+        addAndRegisterListener(listener, weatherPlugin)
+    }
+
+    fun removeListenerForWeatherPlugin(listener: SmartspaceTargetListener) {
+        removeAndUnregisterListener(listener, weatherPlugin)
+    }
+
+    private fun addAndRegisterListener(
+        listener: SmartspaceTargetListener,
+        smartspaceDataPlugin: BcSmartspaceDataPlugin?
+    ) {
         execution.assertIsMainThread()
-        plugin?.registerListener(listener)
+        smartspaceDataPlugin?.registerListener(listener)
         listeners.add(listener)
 
         connectSession()
     }
 
-    fun removeListener(listener: SmartspaceTargetListener) {
+    private fun removeAndUnregisterListener(
+        listener: SmartspaceTargetListener,
+        smartspaceDataPlugin: BcSmartspaceDataPlugin?
+    ) {
         execution.assertIsMainThread()
-        plugin?.unregisterListener(listener)
+        smartspaceDataPlugin?.unregisterListener(listener)
         listeners.remove(listener)
         disconnect()
     }
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
index 73c2289..a7b3bbc 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
@@ -254,7 +254,10 @@
         mCurrentScrimController = mScrimManager.getCurrentController();
 
         session.registerCallback(() -> {
-            mVelocityTracker.recycle();
+            if (mVelocityTracker != null) {
+                mVelocityTracker.recycle();
+                mVelocityTracker = null;
+            }
             mScrimManager.removeCallback(mScrimManagerCallback);
             mCapture = null;
             mNotificationShadeWindowController.setForcePluginOpen(false, this);
diff --git a/packages/SystemUI/src/com/android/systemui/flags/ConditionalRestarter.kt b/packages/SystemUI/src/com/android/systemui/flags/ConditionalRestarter.kt
new file mode 100644
index 0000000..b20e33a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/flags/ConditionalRestarter.kt
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.flags
+
+import android.util.Log
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import java.util.concurrent.TimeUnit
+import javax.inject.Inject
+import javax.inject.Named
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+/** Restarts the process after all passed in [Condition]s are true. */
+class ConditionalRestarter
+@Inject
+constructor(
+    private val systemExitRestarter: SystemExitRestarter,
+    private val conditions: Set<@JvmSuppressWildcards Condition>,
+    @Named(RESTART_DELAY) private val restartDelaySec: Long,
+    @Application private val applicationScope: CoroutineScope,
+    @Background private val backgroundDispatcher: CoroutineDispatcher,
+) : Restarter {
+
+    private var restartJob: Job? = null
+    private var pendingReason = ""
+    private var androidRestartRequested = false
+
+    override fun restartSystemUI(reason: String) {
+        Log.d(FeatureFlagsDebug.TAG, "SystemUI Restart requested. Restarting when idle.")
+        scheduleRestart(reason)
+    }
+
+    override fun restartAndroid(reason: String) {
+        Log.d(FeatureFlagsDebug.TAG, "Android Restart requested. Restarting when idle.")
+        androidRestartRequested = true
+        scheduleRestart(reason)
+    }
+
+    private fun scheduleRestart(reason: String = "") {
+        pendingReason = if (reason.isEmpty()) pendingReason else reason
+
+        if (conditions.all { c -> c.canRestartNow(this::scheduleRestart) }) {
+            if (restartJob == null) {
+                restartJob =
+                    applicationScope.launch(backgroundDispatcher) {
+                        delay(TimeUnit.SECONDS.toMillis(restartDelaySec))
+                        restartNow()
+                    }
+            }
+        } else {
+            restartJob?.cancel()
+            restartJob = null
+        }
+    }
+
+    private fun restartNow() {
+        if (androidRestartRequested) {
+            systemExitRestarter.restartAndroid(pendingReason)
+        } else {
+            systemExitRestarter.restartSystemUI(pendingReason)
+        }
+    }
+
+    interface Condition {
+        /**
+         * Should return true if the system is ready to restart.
+         *
+         * A call to this function means that we want to restart and are waiting for this condition
+         * to return true.
+         *
+         * retryFn should be cached if it is _not_ ready to restart, and later called when it _is_
+         * ready to restart. At that point, this method will be called again to verify that the
+         * system is ready.
+         *
+         * Multiple calls to an instance of this method may happen for a single restart attempt if
+         * multiple [Condition]s are being checked. If any one [Condition] returns false, all the
+         * [Condition]s will need to be rechecked on the next restart attempt.
+         */
+        fun canRestartNow(retryFn: () -> Unit): Boolean
+    }
+
+    companion object {
+        const val RESTART_DELAY = "restarter_restart_delay"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebugRestarter.kt b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebugRestarter.kt
deleted file mode 100644
index a6956a4..0000000
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebugRestarter.kt
+++ /dev/null
@@ -1,70 +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.flags
-
-import android.util.Log
-import com.android.systemui.keyguard.WakefulnessLifecycle
-import javax.inject.Inject
-
-/** Restarts SystemUI when the screen is locked. */
-class FeatureFlagsDebugRestarter
-@Inject
-constructor(
-    private val wakefulnessLifecycle: WakefulnessLifecycle,
-    private val systemExitRestarter: SystemExitRestarter,
-) : Restarter {
-
-    private var androidRestartRequested = false
-    private var pendingReason = ""
-
-    val observer =
-        object : WakefulnessLifecycle.Observer {
-            override fun onFinishedGoingToSleep() {
-                Log.d(FeatureFlagsDebug.TAG, "Restarting due to systemui flag change")
-                restartNow()
-            }
-        }
-
-    override fun restartSystemUI(reason: String) {
-        Log.d(FeatureFlagsDebug.TAG, "SystemUI Restart requested. Restarting on next screen off.")
-        Log.i(FeatureFlagsDebug.TAG, reason)
-        scheduleRestart(reason)
-    }
-
-    override fun restartAndroid(reason: String) {
-        Log.d(FeatureFlagsDebug.TAG, "Android Restart requested. Restarting on next screen off.")
-        androidRestartRequested = true
-        scheduleRestart(reason)
-    }
-
-    fun scheduleRestart(reason: String) {
-        pendingReason = reason
-        if (wakefulnessLifecycle.wakefulness == WakefulnessLifecycle.WAKEFULNESS_ASLEEP) {
-            restartNow()
-        } else {
-            wakefulnessLifecycle.addObserver(observer)
-        }
-    }
-
-    private fun restartNow() {
-        if (androidRestartRequested) {
-            systemExitRestarter.restartAndroid(pendingReason)
-        } else {
-            systemExitRestarter.restartSystemUI(pendingReason)
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsReleaseRestarter.kt b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsReleaseRestarter.kt
deleted file mode 100644
index c08266c..0000000
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsReleaseRestarter.kt
+++ /dev/null
@@ -1,101 +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.flags
-
-import android.util.Log
-import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.keyguard.WakefulnessLifecycle
-import com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP
-import com.android.systemui.statusbar.policy.BatteryController
-import com.android.systemui.util.concurrency.DelayableExecutor
-import java.util.concurrent.TimeUnit
-import javax.inject.Inject
-
-/** Restarts SystemUI when the device appears idle. */
-class FeatureFlagsReleaseRestarter
-@Inject
-constructor(
-    private val wakefulnessLifecycle: WakefulnessLifecycle,
-    private val batteryController: BatteryController,
-    @Background private val bgExecutor: DelayableExecutor,
-    private val systemExitRestarter: SystemExitRestarter
-) : Restarter {
-    var listenersAdded = false
-    var pendingRestart: Runnable? = null
-    private var pendingReason = ""
-    var androidRestartRequested = false
-
-    val observer =
-        object : WakefulnessLifecycle.Observer {
-            override fun onFinishedGoingToSleep() {
-                scheduleRestart(pendingReason)
-            }
-        }
-
-    val batteryCallback =
-        object : BatteryController.BatteryStateChangeCallback {
-            override fun onBatteryLevelChanged(level: Int, pluggedIn: Boolean, charging: Boolean) {
-                scheduleRestart(pendingReason)
-            }
-        }
-
-    override fun restartSystemUI(reason: String) {
-        Log.d(
-            FeatureFlagsDebug.TAG,
-            "SystemUI Restart requested. Restarting when plugged in and idle."
-        )
-        scheduleRestart(reason)
-    }
-
-    override fun restartAndroid(reason: String) {
-        Log.d(
-            FeatureFlagsDebug.TAG,
-            "Android Restart requested. Restarting when plugged in and idle."
-        )
-        androidRestartRequested = true
-        scheduleRestart(reason)
-    }
-
-    private fun scheduleRestart(reason: String) {
-        // Don't bother adding listeners twice.
-        pendingReason = reason
-        if (!listenersAdded) {
-            listenersAdded = true
-            wakefulnessLifecycle.addObserver(observer)
-            batteryController.addCallback(batteryCallback)
-        }
-        if (
-            wakefulnessLifecycle.wakefulness == WAKEFULNESS_ASLEEP && batteryController.isPluggedIn
-        ) {
-            if (pendingRestart == null) {
-                pendingRestart = bgExecutor.executeDelayed(this::restartNow, 30L, TimeUnit.SECONDS)
-            }
-        } else if (pendingRestart != null) {
-            pendingRestart?.run()
-            pendingRestart = null
-        }
-    }
-
-    private fun restartNow() {
-        Log.d(FeatureFlagsRelease.TAG, "Restarting due to systemui flag change")
-        if (androidRestartRequested) {
-            systemExitRestarter.restartAndroid(pendingReason)
-        } else {
-            systemExitRestarter.restartSystemUI(pendingReason)
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 2a1bca7..c202416 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -64,9 +64,6 @@
     // TODO(b/259130119): Tracking Bug
     val FSI_ON_DND_UPDATE = releasedFlag(259130119, "fsi_on_dnd_update")
 
-    // TODO(b/265804648): Tracking Bug
-    @JvmField val DISABLE_FSI = unreleasedFlag(265804648, "disable_fsi")
-
     // TODO(b/254512538): Tracking Bug
     val INSTANT_VOICE_REPLY = releasedFlag(111, "instant_voice_reply")
 
@@ -74,8 +71,12 @@
     val NOTIFICATION_MEMORY_MONITOR_ENABLED =
         releasedFlag(112, "notification_memory_monitor_enabled")
 
+    /**
+     * This flag is server-controlled and should stay as [unreleasedFlag] since we never want to
+     * enable it on release builds.
+     */
     val NOTIFICATION_MEMORY_LOGGING_ENABLED =
-        unreleasedFlag(119, "notification_memory_logging_enabled", teamfood = true)
+        unreleasedFlag(119, "notification_memory_logging_enabled")
 
     // TODO(b/254512731): Tracking Bug
     @JvmField val NOTIFICATION_DISMISSAL_FADE = releasedFlag(113, "notification_dismissal_fade")
@@ -87,9 +88,6 @@
     val NOTIFICATION_GROUP_DISMISSAL_ANIMATION =
         releasedFlag(259217907, "notification_group_dismissal_animation")
 
-    // TODO(b/257506350): Tracking Bug
-    @JvmField val FSI_CHROME = unreleasedFlag(117, "fsi_chrome")
-
     @JvmField
     val SIMPLIFIED_APPEAR_FRACTION =
         unreleasedFlag(259395680, "simplified_appear_fraction", teamfood = true)
@@ -110,6 +108,13 @@
     val NOTIFICATION_ANIMATE_BIG_PICTURE =
         releasedFlag(120, "notification_animate_big_picture", teamfood = true)
 
+    @JvmField
+    val ANIMATED_NOTIFICATION_SHADE_INSETS =
+        unreleasedFlag(270682168, "animated_notification_shade_insets", teamfood = true)
+
+    // TODO(b/268005230): Tracking Bug
+    @JvmField val SENSITIVE_REVEAL_ANIM = unreleasedFlag(268005230, "sensitive_reveal_anim")
+
     // 200 - keyguard/lockscreen
     // ** Flag retired **
     // public static final BooleanFlag KEYGUARD_LAYOUT =
@@ -132,7 +137,7 @@
      * the digits when the clock moves.
      */
     @JvmField
-    val STEP_CLOCK_ANIMATION = unreleasedFlag(212, "step_clock_animation", teamfood = true)
+    val STEP_CLOCK_ANIMATION = releasedFlag(212, "step_clock_animation")
 
     /**
      * Migration from the legacy isDozing/dozeAmount paths to the new KeyguardTransitionRepository
@@ -215,6 +220,11 @@
             "lock_screen_long_press_enabled"
         )
 
+    /** Whether to inflate the bouncer view on a background thread. */
+    // TODO(b/272091103): Tracking Bug
+    @JvmField
+    val ASYNC_INFLATE_BOUNCER = unreleasedFlag(229, "async_inflate_bouncer", teamfood = true)
+
     // 300 - power menu
     // TODO(b/254512600): Tracking Bug
     @JvmField val POWER_MENU_LITE = releasedFlag(300, "power_menu_lite")
@@ -230,6 +240,15 @@
     val SMARTSPACE_DATE_WEATHER_DECOUPLED =
         sysPropBooleanFlag(403, "persist.sysui.ss.dw_decoupled", default = true)
 
+    // TODO(b/270223352): Tracking Bug
+    @JvmField
+    val HIDE_SMARTSPACE_ON_DREAM_OVERLAY = unreleasedFlag(404, "hide_smartspace_on_dream_overlay")
+
+    // TODO(b/271460958): Tracking Bug
+    @JvmField
+    val SHOW_WEATHER_COMPLICATION_ON_DREAM_OVERLAY = unreleasedFlag(405,
+        "show_weather_complication_on_dream_overlay")
+
     // 500 - quick settings
 
     val PEOPLE_TILE = resourceBooleanFlag(502, R.bool.flag_conversations, "people_tile")
@@ -294,7 +313,8 @@
         unreleasedFlag(611, "new_status_bar_icons_debug_coloring")
 
     // TODO(b/265892345): Tracking Bug
-    val PLUG_IN_STATUS_BAR_CHIP = unreleasedFlag(265892345, "plug_in_status_bar_chip")
+    val PLUG_IN_STATUS_BAR_CHIP =
+            unreleasedFlag(265892345, "plug_in_status_bar_chip", teamfood = true)
 
     // 700 - dialer/calls
     // TODO(b/254512734): Tracking Bug
@@ -369,15 +389,27 @@
     // TODO(b/267166152) : Tracking Bug
     val MEDIA_RETAIN_RECOMMENDATIONS = releasedFlag(916, "media_retain_recommendations")
 
+    // TODO(b/270437894): Tracking Bug
+    val MEDIA_REMOTE_RESUME = unreleasedFlag(917, "media_remote_resume")
+
     // 1000 - dock
     val SIMULATE_DOCK_THROUGH_CHARGING = releasedFlag(1000, "simulate_dock_through_charging")
 
     // TODO(b/254512758): Tracking Bug
     @JvmField val ROUNDED_BOX_RIPPLE = releasedFlag(1002, "rounded_box_ripple")
 
+    // TODO(b/270882464): Tracking Bug
+    val ENABLE_DOCK_SETUP_V2 = unreleasedFlag(1005, "enable_dock_setup_v2", teamfood = true)
+
     // TODO(b/265045965): Tracking Bug
     val SHOW_LOWLIGHT_ON_DIRECT_BOOT = releasedFlag(1003, "show_lowlight_on_direct_boot")
 
+    @JvmField
+    // TODO(b/271428141): Tracking Bug
+    val ENABLE_LOW_LIGHT_CLOCK_UNDOCKED = unreleasedFlag(
+        1004,
+        "enable_low_light_clock_undocked", teamfood = true)
+
     // 1100 - windowing
     @Keep
     @JvmField
@@ -431,7 +463,9 @@
         )
 
     // TODO(b/256873975): Tracking Bug
-    @JvmField @Keep val WM_BUBBLE_BAR = unreleasedFlag(1111, "wm_bubble_bar")
+    @JvmField
+    @Keep
+    val WM_BUBBLE_BAR = sysPropBooleanFlag(1111, "persist.wm.debug.bubble_bar", default = false)
 
     // TODO(b/260271148): Tracking bug
     @Keep
@@ -454,13 +488,20 @@
     @Keep
     @JvmField
     val ENABLE_PIP_SIZE_LARGE_SCREEN =
-        sysPropBooleanFlag(1114, "persist.wm.debug.enable_pip_size_large_screen", default = false)
+        sysPropBooleanFlag(1114, "persist.wm.debug.enable_pip_size_large_screen", default = true)
 
     // TODO(b/265998256): Tracking bug
     @Keep
     @JvmField
     val ENABLE_PIP_APP_ICON_OVERLAY =
-        sysPropBooleanFlag(1115, "persist.wm.debug.enable_pip_app_icon_overlay", default = false)
+        sysPropBooleanFlag(1115, "persist.wm.debug.enable_pip_app_icon_overlay", default = true)
+
+    // TODO(b/272110828): Tracking bug
+    @Keep
+    @JvmField
+    val ENABLE_MOVE_FLOATING_WINDOW_IN_TABLETOP =
+        sysPropBooleanFlag(
+            1116, "persist.wm.debug.enable_move_floating_window_in_tabletop", default = false)
 
     // 1200 - predictive back
     @Keep
@@ -486,9 +527,9 @@
     val WM_ENABLE_PREDICTIVE_BACK_SYSUI =
         unreleasedFlag(1204, "persist.wm.debug.predictive_back_sysui_enable", teamfood = true)
 
-    // TODO(b/255697805): Tracking Bug
+    // TODO(b/270987164): Tracking Bug
     @JvmField
-    val TRACKPAD_GESTURE_BACK = unreleasedFlag(1205, "trackpad_gesture_back", teamfood = false)
+    val TRACKPAD_GESTURE_BACK = unreleasedFlag(1205, "trackpad_gesture_back", teamfood = true)
 
     // TODO(b/263826204): Tracking Bug
     @JvmField
@@ -562,7 +603,7 @@
     @JvmField
     val LEAVE_SHADE_OPEN_FOR_BUGREPORT = releasedFlag(1800, "leave_shade_open_for_bugreport")
     // TODO(b/265944639): Tracking Bug
-    @JvmField val DUAL_SHADE = releasedFlag(1801, "dual_shade")
+    @JvmField val DUAL_SHADE = unreleasedFlag(1801, "dual_shade")
 
     // 1900
     @JvmField val NOTE_TASKS = releasedFlag(1900, "keycode_flag")
@@ -593,14 +634,12 @@
     @JvmField val UDFPS_ELLIPSE_DETECTION = releasedFlag(2201, "udfps_ellipse_detection")
 
     // 2300 - stylus
+    @JvmField val TRACK_STYLUS_EVER_USED = releasedFlag(2300, "track_stylus_ever_used")
     @JvmField
-    val TRACK_STYLUS_EVER_USED = unreleasedFlag(2300, "track_stylus_ever_used", teamfood = true)
-    @JvmField
-    val ENABLE_STYLUS_CHARGING_UI =
-        unreleasedFlag(2301, "enable_stylus_charging_ui", teamfood = true)
+    val ENABLE_STYLUS_CHARGING_UI = releasedFlag(2301, "enable_stylus_charging_ui")
     @JvmField
     val ENABLE_USI_BATTERY_NOTIFICATIONS =
-        unreleasedFlag(2302, "enable_usi_battery_notifications", teamfood = true)
+        releasedFlag(2302, "enable_usi_battery_notifications")
     @JvmField val ENABLE_STYLUS_EDUCATION = unreleasedFlag(2303, "enable_stylus_education")
 
     // 2400 - performance tools and debugging info
@@ -618,11 +657,6 @@
     @JvmField
     val OUTPUT_SWITCHER_DEVICE_STATUS = releasedFlag(2502, "output_switcher_device_status")
 
-    // TODO(b/20911786): Tracking Bug
-    @JvmField
-    val OUTPUT_SWITCHER_SHOW_API_ENABLED =
-        releasedFlag(2503, "output_switcher_show_api_enabled", teamfood = true)
-
     // 2700 - unfold transitions
     // TODO(b/265764985): Tracking Bug
     @Keep
@@ -640,5 +674,11 @@
 
     // TODO(b/259428678): Tracking Bug
     @JvmField
-    val KEYBOARD_BACKLIGHT_INDICATOR = unreleasedFlag(2601, "keyboard_backlight_indicator")
+    val KEYBOARD_BACKLIGHT_INDICATOR =
+            unreleasedFlag(2601, "keyboard_backlight_indicator", teamfood = true)
+
+    // TODO(b/272036292): Tracking Bug
+    @JvmField
+    val LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION =
+            unreleasedFlag(2602, "large_shade_granular_alpha_interpolation", teamfood = true)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagsCommonModule.kt b/packages/SystemUI/src/com/android/systemui/flags/FlagsCommonModule.kt
index 0054d26..3c50125 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagsCommonModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/FlagsCommonModule.kt
@@ -15,6 +15,7 @@
  */
 package com.android.systemui.flags
 
+import dagger.Binds
 import dagger.Module
 import dagger.Provides
 import javax.inject.Named
@@ -22,6 +23,8 @@
 /** Module containing shared code for all FeatureFlag implementations. */
 @Module
 interface FlagsCommonModule {
+    @Binds fun bindsRestarter(impl: ConditionalRestarter): Restarter
+
     companion object {
         const val ALL_FLAGS = "all_flags"
 
diff --git a/packages/SystemUI/src/com/android/systemui/flags/PluggedInCondition.kt b/packages/SystemUI/src/com/android/systemui/flags/PluggedInCondition.kt
new file mode 100644
index 0000000..3120638
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/flags/PluggedInCondition.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.flags
+
+import com.android.systemui.statusbar.policy.BatteryController
+import javax.inject.Inject
+
+/** Returns true when the device is plugged in. */
+class PluggedInCondition
+@Inject
+constructor(
+    private val batteryController: BatteryController,
+) : ConditionalRestarter.Condition {
+
+    var listenersAdded = false
+    var retryFn: (() -> Unit)? = null
+
+    val batteryCallback =
+        object : BatteryController.BatteryStateChangeCallback {
+            override fun onBatteryLevelChanged(level: Int, pluggedIn: Boolean, charging: Boolean) {
+                retryFn?.invoke()
+            }
+        }
+
+    override fun canRestartNow(retryFn: () -> Unit): Boolean {
+        if (!listenersAdded) {
+            listenersAdded = true
+            batteryController.addCallback(batteryCallback)
+        }
+
+        this.retryFn = retryFn
+
+        return batteryController.isPluggedIn
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/ScreenIdleCondition.kt b/packages/SystemUI/src/com/android/systemui/flags/ScreenIdleCondition.kt
new file mode 100644
index 0000000..49e61af
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/flags/ScreenIdleCondition.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.flags
+
+import com.android.systemui.keyguard.WakefulnessLifecycle
+import javax.inject.Inject
+
+/** Returns true when the device is "asleep" as defined by the [WakefullnessLifecycle]. */
+class ScreenIdleCondition
+@Inject
+constructor(
+    private val wakefulnessLifecycle: WakefulnessLifecycle,
+) : ConditionalRestarter.Condition {
+
+    var listenersAdded = false
+    var retryFn: (() -> Unit)? = null
+
+    val observer =
+        object : WakefulnessLifecycle.Observer {
+            override fun onFinishedGoingToSleep() {
+                retryFn?.invoke()
+            }
+        }
+
+    override fun canRestartNow(retryFn: () -> Unit): Boolean {
+        if (!listenersAdded) {
+            listenersAdded = true
+            wakefulnessLifecycle.addObserver(observer)
+        }
+
+        this.retryFn = retryFn
+
+        return wakefulnessLifecycle.wakefulness == WakefulnessLifecycle.WAKEFULNESS_ASLEEP
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
index 949bcfb..07753ca 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
@@ -788,6 +788,11 @@
 
         @Override
         public boolean onLongPress() {
+            // don't actually trigger the reboot if we are running stability
+            // tests via monkey
+            if (ActivityManager.isUserAMonkey()) {
+                return false;
+            }
             mUiEventLogger.log(GlobalActionsEvent.GA_SHUTDOWN_LONG_PRESS);
             if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
                 mWindowManagerFuncs.reboot(true);
@@ -808,6 +813,11 @@
 
         @Override
         public void onPress() {
+            // don't actually trigger the shutdown if we are running stability
+            // tests via monkey
+            if (ActivityManager.isUserAMonkey()) {
+                return;
+            }
             mUiEventLogger.log(GlobalActionsEvent.GA_SHUTDOWN_PRESS);
             // shutdown by making sure radio and power are handled accordingly.
             mWindowManagerFuncs.shutdown();
@@ -919,6 +929,11 @@
 
         @Override
         public boolean onLongPress() {
+            // don't actually trigger the reboot if we are running stability
+            // tests via monkey
+            if (ActivityManager.isUserAMonkey()) {
+                return false;
+            }
             mUiEventLogger.log(GlobalActionsEvent.GA_REBOOT_LONG_PRESS);
             if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
                 mWindowManagerFuncs.reboot(true);
@@ -939,6 +954,11 @@
 
         @Override
         public void onPress() {
+            // don't actually trigger the reboot if we are running stability
+            // tests via monkey
+            if (ActivityManager.isUserAMonkey()) {
+                return;
+            }
             mUiEventLogger.log(GlobalActionsEvent.GA_REBOOT_PRESS);
             mWindowManagerFuncs.reboot(false);
         }
@@ -2056,6 +2076,10 @@
                     || Intent.ACTION_SCREEN_OFF.equals(action)) {
                 String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
                 if (!SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS.equals(reason)) {
+                    // These broadcasts are usually received when locking the device, swiping up to
+                    // home (which collapses the shade), etc. In those cases, we usually don't want
+                    // to animate this dialog back into the view, so we disable the exit animations.
+                    mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations();
                     mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISMISS, reason));
                 }
             } else if (TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED.equals(action)) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/PhysicalKeyboardCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/keyboard/PhysicalKeyboardCoreStartable.kt
index b0f9c4e..d078688 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/PhysicalKeyboardCoreStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/PhysicalKeyboardCoreStartable.kt
@@ -21,6 +21,7 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
+import com.android.systemui.keyboard.backlight.ui.KeyboardBacklightDialogCoordinator
 import javax.inject.Inject
 
 /** A [CoreStartable] that launches components interested in physical keyboard interaction. */
@@ -28,11 +29,12 @@
 class PhysicalKeyboardCoreStartable
 @Inject
 constructor(
+    private val keyboardBacklightDialogCoordinator: KeyboardBacklightDialogCoordinator,
     private val featureFlags: FeatureFlags,
 ) : CoreStartable {
     override fun start() {
         if (featureFlags.isEnabled(Flags.KEYBOARD_BACKLIGHT_INDICATOR)) {
-            // TODO(b/268645743) start listening for keyboard backlight brightness
+            keyboardBacklightDialogCoordinator.startListening()
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractor.kt
new file mode 100644
index 0000000..65e70b3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractor.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyboard.backlight.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyboard.data.repository.KeyboardRepository
+import com.android.systemui.keyboard.shared.model.BacklightModel
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
+
+/** Allows listening to changes to keyboard backlight level */
+@SysUISingleton
+class KeyboardBacklightInteractor
+@Inject
+constructor(
+    private val keyboardRepository: KeyboardRepository,
+) {
+
+    /** Emits current backlight level as [BacklightModel] or null if keyboard is not connected */
+    val backlight: Flow<BacklightModel?> =
+        keyboardRepository.keyboardConnected.flatMapLatest { connected ->
+            if (connected) keyboardRepository.backlight else flowOf(null)
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/KeyboardBacklightDialogCoordinator.kt b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/KeyboardBacklightDialogCoordinator.kt
new file mode 100644
index 0000000..5e806b6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/KeyboardBacklightDialogCoordinator.kt
@@ -0,0 +1,66 @@
+/*
+ * 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.keyboard.backlight.ui
+
+import android.content.Context
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyboard.backlight.ui.view.KeyboardBacklightDialog
+import com.android.systemui.keyboard.backlight.ui.viewmodel.BacklightDialogViewModel
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+
+/**
+ * Based on the state produced from [BacklightDialogViewModel] shows or hides keyboard backlight
+ * indicator
+ */
+@SysUISingleton
+class KeyboardBacklightDialogCoordinator
+@Inject
+constructor(
+    @Application private val applicationScope: CoroutineScope,
+    private val context: Context,
+    private val viewModel: BacklightDialogViewModel,
+) {
+
+    var dialog: KeyboardBacklightDialog? = null
+
+    fun startListening() {
+        applicationScope.launch {
+            viewModel.dialogContent.collect { dialogViewModel ->
+                if (dialogViewModel != null) {
+                    if (dialog == null) {
+                        dialog =
+                            KeyboardBacklightDialog(
+                                context,
+                                initialCurrentLevel = dialogViewModel.currentValue,
+                                initialMaxLevel = dialogViewModel.maxValue
+                            )
+                        dialog?.show()
+                    } else {
+                        dialog?.updateState(dialogViewModel.currentValue, dialogViewModel.maxValue)
+                    }
+                } else {
+                    dialog?.dismiss()
+                    dialog = null
+                }
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/view/KeyboardBacklightDialog.kt b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/view/KeyboardBacklightDialog.kt
new file mode 100644
index 0000000..a173f8b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/view/KeyboardBacklightDialog.kt
@@ -0,0 +1,276 @@
+/*
+ * 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.keyboard.backlight.ui.view
+
+import android.annotation.ColorInt
+import android.app.Dialog
+import android.content.Context
+import android.graphics.drawable.ShapeDrawable
+import android.graphics.drawable.shapes.RoundRectShape
+import android.os.Bundle
+import android.view.Gravity
+import android.view.Window
+import android.view.WindowManager
+import android.widget.FrameLayout
+import android.widget.ImageView
+import android.widget.LinearLayout
+import android.widget.LinearLayout.LayoutParams
+import android.widget.LinearLayout.LayoutParams.WRAP_CONTENT
+import com.android.systemui.R
+import com.android.systemui.util.children
+
+class KeyboardBacklightDialog(
+    context: Context,
+    initialCurrentLevel: Int,
+    initialMaxLevel: Int,
+) : Dialog(context) {
+
+    private data class RootProperties(
+        val cornerRadius: Float,
+        val verticalPadding: Int,
+        val horizontalPadding: Int,
+    )
+
+    private data class BacklightIconProperties(
+        val width: Int,
+        val height: Int,
+        val leftMargin: Int,
+    )
+
+    private data class StepViewProperties(
+        val width: Int,
+        val height: Int,
+        val horizontalMargin: Int,
+        val smallRadius: Float,
+        val largeRadius: Float,
+    )
+
+    private var currentLevel: Int = 0
+    private var maxLevel: Int = 0
+
+    private lateinit var rootView: LinearLayout
+
+    private var dialogBottomMargin = 208
+    private lateinit var rootProperties: RootProperties
+    private lateinit var iconProperties: BacklightIconProperties
+    private lateinit var stepProperties: StepViewProperties
+    @ColorInt var filledRectangleColor: Int = 0
+    @ColorInt var emptyRectangleColor: Int = 0
+    @ColorInt var backgroundColor: Int = 0
+
+    init {
+        currentLevel = initialCurrentLevel
+        maxLevel = initialMaxLevel
+    }
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        setUpWindowProperties(this)
+        setWindowTitle()
+        updateResources()
+        rootView = buildRootView()
+        setContentView(rootView)
+        super.onCreate(savedInstanceState)
+        updateState(currentLevel, maxLevel, forceRefresh = true)
+    }
+
+    private fun updateResources() {
+        context.resources.apply {
+            filledRectangleColor = getColor(R.color.backlight_indicator_step_filled)
+            emptyRectangleColor = getColor(R.color.backlight_indicator_step_empty)
+            backgroundColor = getColor(R.color.backlight_indicator_background)
+            rootProperties =
+                RootProperties(
+                    cornerRadius =
+                        getDimensionPixelSize(R.dimen.backlight_indicator_root_corner_radius)
+                            .toFloat(),
+                    verticalPadding =
+                        getDimensionPixelSize(R.dimen.backlight_indicator_root_vertical_padding),
+                    horizontalPadding =
+                        getDimensionPixelSize(R.dimen.backlight_indicator_root_horizontal_padding)
+                )
+            iconProperties =
+                BacklightIconProperties(
+                    width = getDimensionPixelSize(R.dimen.backlight_indicator_icon_width),
+                    height = getDimensionPixelSize(R.dimen.backlight_indicator_icon_height),
+                    leftMargin =
+                        getDimensionPixelSize(R.dimen.backlight_indicator_icon_left_margin),
+                )
+            stepProperties =
+                StepViewProperties(
+                    width = getDimensionPixelSize(R.dimen.backlight_indicator_step_width),
+                    height = getDimensionPixelSize(R.dimen.backlight_indicator_step_height),
+                    horizontalMargin =
+                        getDimensionPixelSize(R.dimen.backlight_indicator_step_horizontal_margin),
+                    smallRadius =
+                        getDimensionPixelSize(R.dimen.backlight_indicator_step_small_radius)
+                            .toFloat(),
+                    largeRadius =
+                        getDimensionPixelSize(R.dimen.backlight_indicator_step_large_radius)
+                            .toFloat(),
+                )
+        }
+    }
+
+    fun updateState(current: Int, max: Int, forceRefresh: Boolean = false) {
+        if (maxLevel != max || forceRefresh) {
+            maxLevel = max
+            rootView.removeAllViews()
+            buildStepViews().forEach { rootView.addView(it) }
+        }
+        currentLevel = current
+        updateLevel()
+    }
+
+    private fun updateLevel() {
+        rootView.children.forEachIndexed(
+            action = { index, v ->
+                val drawable = v.background as ShapeDrawable
+                if (index <= currentLevel) {
+                    updateColor(drawable, filledRectangleColor)
+                } else {
+                    updateColor(drawable, emptyRectangleColor)
+                }
+            }
+        )
+    }
+
+    private fun updateColor(drawable: ShapeDrawable, @ColorInt color: Int) {
+        if (drawable.paint.color != color) {
+            drawable.paint.color = color
+            drawable.invalidateSelf()
+        }
+    }
+
+    private fun buildRootView(): LinearLayout {
+        val linearLayout =
+            LinearLayout(context).apply {
+                orientation = LinearLayout.HORIZONTAL
+                layoutParams = LayoutParams(WRAP_CONTENT, WRAP_CONTENT)
+                setPadding(
+                    /* left= */ rootProperties.horizontalPadding,
+                    /* top= */ rootProperties.verticalPadding,
+                    /* right= */ rootProperties.horizontalPadding,
+                    /* bottom= */ rootProperties.verticalPadding
+                )
+            }
+        val drawable =
+            ShapeDrawable(
+                RoundRectShape(
+                    /* outerRadii= */ FloatArray(8) { rootProperties.cornerRadius },
+                    /* inset= */ null,
+                    /* innerRadii= */ null
+                )
+            )
+        drawable.paint.color = backgroundColor
+        linearLayout.background = drawable
+        return linearLayout
+    }
+
+    private fun buildStepViews(): List<FrameLayout> {
+        val stepViews = (0..maxLevel).map { i -> createStepViewAt(i) }
+        stepViews[0].addView(createBacklightIconView())
+        return stepViews
+    }
+
+    private fun createStepViewAt(i: Int): FrameLayout {
+        return FrameLayout(context).apply {
+            layoutParams =
+                FrameLayout.LayoutParams(stepProperties.width, stepProperties.height).apply {
+                    setMargins(
+                        /* left= */ stepProperties.horizontalMargin,
+                        /* top= */ 0,
+                        /* right= */ stepProperties.horizontalMargin,
+                        /* bottom= */ 0
+                    )
+                }
+            val drawable =
+                ShapeDrawable(
+                    RoundRectShape(
+                        /* outerRadii= */ radiiForIndex(i, maxLevel),
+                        /* inset= */ null,
+                        /* innerRadii= */ null
+                    )
+                )
+            drawable.paint.color = emptyRectangleColor
+            background = drawable
+        }
+    }
+
+    private fun createBacklightIconView(): ImageView {
+        return ImageView(context).apply {
+            setImageResource(R.drawable.ic_keyboard_backlight)
+            layoutParams =
+                FrameLayout.LayoutParams(iconProperties.width, iconProperties.height).apply {
+                    gravity = Gravity.CENTER
+                    leftMargin = iconProperties.leftMargin
+                }
+        }
+    }
+
+    private fun setWindowTitle() {
+        val attrs = window.attributes
+        // TODO(b/271796169): check if title needs to be a translatable resource.
+        attrs.title = "KeyboardBacklightDialog"
+        attrs?.y = dialogBottomMargin
+        window.attributes = attrs
+    }
+
+    private fun setUpWindowProperties(dialog: Dialog) {
+        val window = dialog.window
+        window.requestFeature(Window.FEATURE_NO_TITLE) // otherwise fails while creating actionBar
+        window.setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL)
+        window.addFlags(
+            WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM or
+                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+        )
+        window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
+        window.setBackgroundDrawableResource(android.R.color.transparent)
+        window.setGravity(Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL)
+        setCanceledOnTouchOutside(true)
+    }
+
+    private fun radiiForIndex(i: Int, last: Int): FloatArray {
+        val smallRadius = stepProperties.smallRadius
+        val largeRadius = stepProperties.largeRadius
+        return when (i) {
+            0 -> // left radii bigger
+            floatArrayOf(
+                    largeRadius,
+                    largeRadius,
+                    smallRadius,
+                    smallRadius,
+                    smallRadius,
+                    smallRadius,
+                    largeRadius,
+                    largeRadius
+                )
+            last -> // right radii bigger
+            floatArrayOf(
+                    smallRadius,
+                    smallRadius,
+                    largeRadius,
+                    largeRadius,
+                    largeRadius,
+                    largeRadius,
+                    smallRadius,
+                    smallRadius
+                )
+            else -> FloatArray(8) { smallRadius } // all radii equal
+        }
+    }
+}
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogContentViewModel.kt
similarity index 79%
copy from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
copy to packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogContentViewModel.kt
index 35d5c15..3ef0ca3 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogContentViewModel.kt
@@ -12,8 +12,9 @@
  * WITHOUT WARRANTIES 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.net.wifi.sharedconnectivity.app;
+package com.android.systemui.keyboard.backlight.ui.viewmodel
 
-parcelable DeviceInfo;
\ No newline at end of file
+data class BacklightDialogContentViewModel(val currentValue: Int, val maxValue: Int)
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogViewModel.kt
new file mode 100644
index 0000000..86abca5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogViewModel.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.keyboard.backlight.ui.viewmodel
+
+import android.view.accessibility.AccessibilityManager
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyboard.backlight.domain.interactor.KeyboardBacklightInteractor
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper
+import javax.inject.Inject
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.map
+
+/**
+ * Responsible for dialog visibility and content - emits [BacklightDialogContentViewModel] if dialog
+ * should be shown and hidden otherwise
+ */
+@SysUISingleton
+class BacklightDialogViewModel
+@Inject
+constructor(
+    interactor: KeyboardBacklightInteractor,
+    private val accessibilityManagerWrapper: AccessibilityManagerWrapper,
+) {
+
+    private val timeoutMillis: Long
+        get() =
+            accessibilityManagerWrapper
+                .getRecommendedTimeoutMillis(
+                    DEFAULT_DIALOG_TIMEOUT_MILLIS,
+                    AccessibilityManager.FLAG_CONTENT_ICONS
+                )
+                .toLong()
+
+    val dialogContent: Flow<BacklightDialogContentViewModel?> =
+        interactor.backlight
+            .filterNotNull()
+            .map { BacklightDialogContentViewModel(it.level, it.maxLevel) }
+            .timeout(timeoutMillis, emitAfterTimeout = null)
+
+    private fun <T> Flow<T>.timeout(timeoutMillis: Long, emitAfterTimeout: T): Flow<T> {
+        return flatMapLatest {
+            flow {
+                emit(it)
+                delay(timeoutMillis)
+                emit(emitAfterTimeout)
+            }
+        }
+    }
+
+    private companion object {
+        const val DEFAULT_DIALOG_TIMEOUT_MILLIS = 3000
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt
index 70faf40..b86083a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt
@@ -18,15 +18,19 @@
 package com.android.systemui.keyboard.data.repository
 
 import android.hardware.input.InputManager
+import android.hardware.input.InputManager.KeyboardBacklightListener
+import android.hardware.input.KeyboardBacklightState
 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.keyboard.data.model.BacklightModel
+import com.android.systemui.keyboard.shared.model.BacklightModel
+import java.util.concurrent.Executor
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.SendChannel
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.SharingStarted
@@ -51,24 +55,22 @@
 
     private val connectedDeviceIds: Flow<Set<Int>> =
         conflatedCallbackFlow {
-                fun send(element: Set<Int>) = trySendWithFailureLogging(element, TAG)
-
                 var connectedKeyboards = inputManager.inputDeviceIds.toSet()
                 val listener =
                     object : InputManager.InputDeviceListener {
                         override fun onInputDeviceAdded(deviceId: Int) {
                             connectedKeyboards = connectedKeyboards + deviceId
-                            send(connectedKeyboards)
+                            sendWithLogging(connectedKeyboards)
                         }
 
                         override fun onInputDeviceChanged(deviceId: Int) = Unit
 
                         override fun onInputDeviceRemoved(deviceId: Int) {
                             connectedKeyboards = connectedKeyboards - deviceId
-                            send(connectedKeyboards)
+                            sendWithLogging(connectedKeyboards)
                         }
                     }
-                send(connectedKeyboards)
+                sendWithLogging(connectedKeyboards)
                 inputManager.registerInputDeviceListener(listener, /* handler= */ null)
                 awaitClose { inputManager.unregisterInputDeviceListener(listener) }
             }
@@ -78,6 +80,16 @@
                 replay = 1,
             )
 
+    private val backlightStateListener: Flow<KeyboardBacklightState> = conflatedCallbackFlow {
+        val listener = KeyboardBacklightListener { _, state, isTriggeredByKeyPress ->
+            if (isTriggeredByKeyPress) {
+                sendWithLogging(state)
+            }
+        }
+        inputManager.registerKeyboardBacklightListener(Executor(Runnable::run), listener)
+        awaitClose { inputManager.unregisterKeyboardBacklightListener(listener) }
+    }
+
     override val keyboardConnected: Flow<Boolean> =
         connectedDeviceIds
             .map { it.any { deviceId -> isPhysicalFullKeyboard(deviceId) } }
@@ -85,9 +97,13 @@
             .flowOn(backgroundDispatcher)
 
     override val backlight: Flow<BacklightModel> =
-        conflatedCallbackFlow {
-            // TODO(b/268645734) register BacklightListener
-        }
+        backlightStateListener
+            .map { BacklightModel(it.brightnessLevel, it.maxBrightnessLevel) }
+            .flowOn(backgroundDispatcher)
+
+    private fun <T> SendChannel<T>.sendWithLogging(element: T) {
+        trySendWithFailureLogging(element, TAG)
+    }
 
     private fun isPhysicalFullKeyboard(deviceId: Int): Boolean {
         val device = inputManager.getInputDevice(deviceId)
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/data/model/BacklightModel.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shared/model/BacklightModel.kt
similarity index 94%
rename from packages/SystemUI/src/com/android/systemui/keyboard/data/model/BacklightModel.kt
rename to packages/SystemUI/src/com/android/systemui/keyboard/shared/model/BacklightModel.kt
index ea15a9f..4a32f79 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/data/model/BacklightModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shared/model/BacklightModel.kt
@@ -15,7 +15,7 @@
  *
  */
 
-package com.android.systemui.keyboard.data.model
+package com.android.systemui.keyboard.shared.model
 
 /**
  * Model for current state of keyboard backlight brightness. [level] indicates current level of
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
index 57c4b36..3e52ff2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
@@ -380,10 +380,7 @@
                 // If the launcher is underneath, but we're about to launch an activity, don't do
                 // the animations since they won't be visible.
                 !notificationShadeWindowController.isLaunchingActivity &&
-                launcherUnlockController != null &&
-                // Temporarily disable for foldables since foldable launcher has two first pages,
-                // which breaks the in-window animation.
-                !isFoldable(context)
+                launcherUnlockController != null
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 2ad1ab7..377a136 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -966,13 +966,24 @@
                 public void onAnimationStart(int transit, RemoteAnimationTarget[] apps,
                         RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
                         IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException {
+                    if (!handleOnAnimationStart(
+                                transit, apps, wallpapers, nonApps, finishedCallback)) {
+                        // Usually we rely on animation completion to synchronize occluded status,
+                        // but there was no animation to play, so just update it now.
+                        setOccluded(true /* isOccluded */, false /* animate */);
+                    }
+                }
+
+                private boolean handleOnAnimationStart(int transit, RemoteAnimationTarget[] apps,
+                        RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
+                        IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException {
                     if (apps == null || apps.length == 0 || apps[0] == null) {
                         if (DEBUG) {
                             Log.d(TAG, "No apps provided to the OccludeByDream runner; "
                                     + "skipping occluding animation.");
                         }
                         finishedCallback.onAnimationFinished();
-                        return;
+                        return false;
                     }
 
                     final RemoteAnimationTarget primary = apps[0];
@@ -982,7 +993,7 @@
                         Log.w(TAG, "The occluding app isn't Dream; "
                                 + "finishing up. Please check that the config is correct.");
                         finishedCallback.onAnimationFinished();
-                        return;
+                        return false;
                     }
 
                     final SyncRtSurfaceTransactionApplier applier =
@@ -1031,6 +1042,7 @@
 
                         mOccludeByDreamAnimator.start();
                     });
+                    return true;
                 }
             };
 
@@ -1917,20 +1929,24 @@
 
         // If the keyguard is already showing, see if we don't need to bother re-showing it. Check
         // flags in both files to account for the hiding animation which results in a delay and
-        // discrepancy between flags.
+        // discrepancy between flags. If we're in the middle of hiding, do not short circuit so that
+        // we explicitly re-set state.
         if (mShowing && mKeyguardStateController.isShowing()) {
-            if (mPM.isInteractive()) {
+            if (mPM.isInteractive() && !mHiding) {
                 // It's already showing, and we're not trying to show it while the screen is off.
                 // We can simply reset all of the views.
-                if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
+                if (DEBUG) Log.d(TAG, "doKeyguard: not showing (instead, resetting) because it is "
+                        + "already showing, we're interactive, and we were not previously hiding. "
+                        + "It should be safe to short-circuit here.");
                 resetStateLocked();
                 return;
             } else {
-                // We are trying to show the keyguard while the screen is off - this results from
-                // race conditions involving locking while unlocking. Don't short-circuit here and
-                // ensure the keyguard is fully re-shown.
+                // We are trying to show the keyguard while the screen is off or while we were in
+                // the middle of hiding - this results from race conditions involving locking while
+                // unlocking. Don't short-circuit here and ensure the keyguard is fully re-shown.
                 Log.e(TAG,
-                        "doKeyguard: already showing, but re-showing since we're not interactive");
+                        "doKeyguard: already showing, but re-showing because we're interactive or "
+                                + "were in the middle of hiding.");
             }
         }
 
@@ -2424,11 +2440,19 @@
                 if (DEBUG) Log.d(TAG, "handleShow");
             }
 
-            mHiding = false;
             mKeyguardExitAnimationRunner = null;
             mWakeAndUnlocking = false;
             setPendingLock(false);
-            setShowingLocked(true);
+
+            // Force if we we're showing in the middle of hiding, to ensure we end up in the correct
+            // state.
+            setShowingLocked(true, mHiding /* force */);
+            if (mHiding) {
+                Log.d(TAG, "Forcing setShowingLocked because mHiding=true, which means we're "
+                        + "showing in the middle of hiding.");
+            }
+            mHiding = false;
+
             mKeyguardViewControllerLazy.get().show(options);
             resetKeyguardDonePendingLocked();
             mHideAnimationRun = false;
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 47ef0fa..cb89106 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -46,6 +46,8 @@
 import com.android.systemui.keyguard.data.repository.KeyguardRepositoryModule;
 import com.android.systemui.keyguard.domain.interactor.StartKeyguardTransitionModule;
 import com.android.systemui.keyguard.domain.quickaffordance.KeyguardQuickAffordanceModule;
+import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancesMetricsLogger;
+import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancesMetricsLoggerImpl;
 import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shade.ShadeController;
@@ -64,6 +66,8 @@
 import dagger.Lazy;
 import dagger.Module;
 import dagger.Provides;
+import kotlinx.coroutines.CoroutineDispatcher;
+import kotlinx.coroutines.CoroutineScope;
 
 /**
  * Dagger Module providing keyguard.
@@ -153,4 +157,10 @@
     public ViewMediatorCallback providesViewMediatorCallback(KeyguardViewMediator viewMediator) {
         return viewMediator.getViewMediatorCallback();
     }
+
+    /** */
+    @Provides
+    public KeyguardQuickAffordancesMetricsLogger providesKeyguardQuickAffordancesMetricsLogger() {
+        return new KeyguardQuickAffordancesMetricsLoggerImpl();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/BouncerView.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/BouncerView.kt
index faeb485..871a3ff 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/BouncerView.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/BouncerView.kt
@@ -52,6 +52,8 @@
         cancelAction: Runnable?,
     )
     fun willDismissWithActions(): Boolean
+    fun willRunDismissFromKeyguard(): Boolean
     /** @return the {@link OnBackAnimationCallback} to animate Bouncer during a back gesture. */
     fun getBackCallback(): OnBackAnimationCallback
+    fun showPromptReason(reason: Int)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt
index be73f85..ef0c9a1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt
@@ -134,7 +134,9 @@
                 .flowOn(backgroundDispatcher)
                 .distinctUntilChanged()
                 .onEach { settingsValue = it }
-        ) { callbackFlowValue, _ -> callbackFlowValue }
+        ) { callbackFlowValue, _ ->
+            callbackFlowValue
+        }
 
     override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState {
         return if (controller.isZenAvailable) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt
index 0066785..356a8fb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt
@@ -102,7 +102,8 @@
                     // setup).
                     emit(Unit)
                 }
-            ) { _, _ -> }
+            ) { _, _ ->
+            }
             .flatMapLatest {
                 conflatedCallbackFlow {
                     // We want to instantiate a new SharedPreferences instance each time either the
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt
index baadc66..84abf57 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt
@@ -24,8 +24,10 @@
 import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback
 import android.os.Looper
 import android.os.UserHandle
+import android.util.Log
 import com.android.internal.widget.LockPatternUtils
 import com.android.systemui.Dumpable
+import com.android.systemui.R
 import com.android.systemui.biometrics.AuthController
 import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
@@ -35,6 +37,7 @@
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.dump.DumpManager
+import com.android.systemui.keyguard.shared.model.DevicePosture
 import com.android.systemui.user.data.repository.UserRepository
 import java.io.PrintWriter
 import javax.inject.Inject
@@ -47,8 +50,10 @@
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.flowOn
 import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.onStart
 import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.flow.transformLatest
@@ -82,6 +87,12 @@
 
     /** Whether fingerprint feature is enabled for the current user by the DevicePolicy */
     val isFingerprintEnabledByDevicePolicy: StateFlow<Boolean>
+
+    /**
+     * Whether face authentication is supported for the current device posture. Face auth can be
+     * restricted to specific postures using [R.integer.config_face_auth_supported_posture]
+     */
+    val isFaceAuthSupportedInCurrentPosture: Flow<Boolean>
 }
 
 @SysUISingleton
@@ -98,11 +109,27 @@
     @Background backgroundDispatcher: CoroutineDispatcher,
     biometricManager: BiometricManager?,
     @Main looper: Looper,
+    devicePostureRepository: DevicePostureRepository,
     dumpManager: DumpManager,
 ) : BiometricSettingsRepository, Dumpable {
 
+    override val isFaceAuthSupportedInCurrentPosture: Flow<Boolean>
+
     init {
         dumpManager.registerDumpable(this)
+        val configFaceAuthSupportedPosture =
+            DevicePosture.toPosture(
+                context.resources.getInteger(R.integer.config_face_auth_supported_posture)
+            )
+        isFaceAuthSupportedInCurrentPosture =
+            if (configFaceAuthSupportedPosture == DevicePosture.UNKNOWN) {
+                    flowOf(true)
+                } else {
+                    devicePostureRepository.currentDevicePosture.map {
+                        it == configFaceAuthSupportedPosture
+                    }
+                }
+                .onEach { Log.d(TAG, "isFaceAuthSupportedInCurrentPosture value changed to: $it") }
     }
 
     override fun dump(pw: PrintWriter, args: Array<String?>) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DevicePostureRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DevicePostureRepository.kt
new file mode 100644
index 0000000..adb1e01
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DevicePostureRepository.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.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.keyguard.shared.model.DevicePosture
+import com.android.systemui.statusbar.policy.DevicePostureController
+import javax.inject.Inject
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+
+/** Provide current device posture state. */
+interface DevicePostureRepository {
+    /** Provides the current device posture. */
+    val currentDevicePosture: Flow<DevicePosture>
+}
+
+@SysUISingleton
+class DevicePostureRepositoryImpl
+@Inject
+constructor(private val postureController: DevicePostureController) : DevicePostureRepository {
+    override val currentDevicePosture: Flow<DevicePosture>
+        get() = conflatedCallbackFlow {
+            val sendPostureUpdate = { posture: Int ->
+                val currentDevicePosture = DevicePosture.toPosture(posture)
+                trySendWithFailureLogging(
+                    currentDevicePosture,
+                    TAG,
+                    "Error sending posture update to $currentDevicePosture"
+                )
+            }
+            val callback = DevicePostureController.Callback { sendPostureUpdate(it) }
+            postureController.addCallback(callback)
+            sendPostureUpdate(postureController.devicePosture)
+
+            awaitClose { postureController.removeCallback(callback) }
+        }
+
+    companion object {
+        const val TAG = "PostureRepositoryImpl"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
index 0e85347..ae5b799 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
@@ -22,7 +22,6 @@
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
 import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
-import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
 import com.android.systemui.log.dagger.BouncerLog
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.log.table.logDiffsForTable
@@ -43,16 +42,15 @@
  */
 interface KeyguardBouncerRepository {
     /** Values associated with the PrimaryBouncer (pin/pattern/password) input. */
-    val primaryBouncerVisible: StateFlow<Boolean>
-    val primaryBouncerShow: StateFlow<KeyguardBouncerModel?>
+    val primaryBouncerShow: StateFlow<Boolean>
     val primaryBouncerShowingSoon: StateFlow<Boolean>
-    val primaryBouncerHide: StateFlow<Boolean>
     val primaryBouncerStartingToHide: StateFlow<Boolean>
     val primaryBouncerStartingDisappearAnimation: StateFlow<Runnable?>
     /** Determines if we want to instantaneously show the primary bouncer instead of translating. */
     val primaryBouncerScrimmed: StateFlow<Boolean>
     /**
      * Set how much of the notification panel is showing on the screen.
+     *
      * ```
      *      0f = panel fully hidden = bouncer fully showing
      *      1f = panel fully showing = bouncer fully hidden
@@ -75,14 +73,10 @@
 
     fun setPrimaryScrimmed(isScrimmed: Boolean)
 
-    fun setPrimaryVisible(isVisible: Boolean)
-
-    fun setPrimaryShow(keyguardBouncerModel: KeyguardBouncerModel?)
+    fun setPrimaryShow(isShowing: Boolean)
 
     fun setPrimaryShowingSoon(showingSoon: Boolean)
 
-    fun setPrimaryHide(hide: Boolean)
-
     fun setPrimaryStartingToHide(startingToHide: Boolean)
 
     fun setPrimaryStartDisappearAnimation(runnable: Runnable?)
@@ -116,14 +110,10 @@
     @BouncerLog private val buffer: TableLogBuffer,
 ) : KeyguardBouncerRepository {
     /** Values associated with the PrimaryBouncer (pin/pattern/password) input. */
-    private val _primaryBouncerVisible = MutableStateFlow(false)
-    override val primaryBouncerVisible = _primaryBouncerVisible.asStateFlow()
-    private val _primaryBouncerShow = MutableStateFlow<KeyguardBouncerModel?>(null)
+    private val _primaryBouncerShow = MutableStateFlow(false)
     override val primaryBouncerShow = _primaryBouncerShow.asStateFlow()
     private val _primaryBouncerShowingSoon = MutableStateFlow(false)
     override val primaryBouncerShowingSoon = _primaryBouncerShowingSoon.asStateFlow()
-    private val _primaryBouncerHide = MutableStateFlow(false)
-    override val primaryBouncerHide = _primaryBouncerHide.asStateFlow()
     private val _primaryBouncerStartingToHide = MutableStateFlow(false)
     override val primaryBouncerStartingToHide = _primaryBouncerStartingToHide.asStateFlow()
     private val _primaryBouncerDisappearAnimation = MutableStateFlow<Runnable?>(null)
@@ -134,6 +124,7 @@
     override val primaryBouncerScrimmed = _primaryBouncerScrimmed.asStateFlow()
     /**
      * Set how much of the notification panel is showing on the screen.
+     *
      * ```
      *      0f = panel fully hidden = bouncer fully showing
      *      1f = panel fully showing = bouncer fully hidden
@@ -175,10 +166,6 @@
         _primaryBouncerScrimmed.value = isScrimmed
     }
 
-    override fun setPrimaryVisible(isVisible: Boolean) {
-        _primaryBouncerVisible.value = isVisible
-    }
-
     override fun setAlternateVisible(isVisible: Boolean) {
         if (isVisible && !_alternateBouncerVisible.value) {
             lastAlternateBouncerVisibleTime = clock.uptimeMillis()
@@ -192,18 +179,14 @@
         _alternateBouncerUIAvailable.value = isAvailable
     }
 
-    override fun setPrimaryShow(keyguardBouncerModel: KeyguardBouncerModel?) {
-        _primaryBouncerShow.value = keyguardBouncerModel
+    override fun setPrimaryShow(isShowing: Boolean) {
+        _primaryBouncerShow.value = isShowing
     }
 
     override fun setPrimaryShowingSoon(showingSoon: Boolean) {
         _primaryBouncerShowingSoon.value = showingSoon
     }
 
-    override fun setPrimaryHide(hide: Boolean) {
-        _primaryBouncerHide.value = hide
-    }
-
     override fun setPrimaryStartingToHide(startingToHide: Boolean) {
         _primaryBouncerStartingToHide.value = startingToHide
     }
@@ -246,19 +229,12 @@
             return
         }
 
-        primaryBouncerVisible
-            .logDiffsForTable(buffer, "", "PrimaryBouncerVisible", false)
-            .launchIn(applicationScope)
         primaryBouncerShow
-            .map { it != null }
             .logDiffsForTable(buffer, "", "PrimaryBouncerShow", false)
             .launchIn(applicationScope)
         primaryBouncerShowingSoon
             .logDiffsForTable(buffer, "", "PrimaryBouncerShowingSoon", false)
             .launchIn(applicationScope)
-        primaryBouncerHide
-            .logDiffsForTable(buffer, "", "PrimaryBouncerHide", false)
-            .launchIn(applicationScope)
         primaryBouncerStartingToHide
             .logDiffsForTable(buffer, "", "PrimaryBouncerStartingToHide", false)
             .launchIn(applicationScope)
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 a3b3d0f..76f20d25 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
@@ -80,6 +80,9 @@
      */
     val isKeyguardShowing: Flow<Boolean>
 
+    /** Is the keyguard in a unlocked state? */
+    val isKeyguardUnlocked: Flow<Boolean>
+
     /** Is an activity showing over the keyguard? */
     val isKeyguardOccluded: Flow<Boolean>
 
@@ -278,6 +281,31 @@
             }
             .distinctUntilChanged()
 
+    override val isKeyguardUnlocked: Flow<Boolean> =
+        conflatedCallbackFlow {
+                val callback =
+                    object : KeyguardStateController.Callback {
+                        override fun onUnlockedChanged() {
+                            trySendWithFailureLogging(
+                                keyguardStateController.isUnlocked,
+                                TAG,
+                                "updated isKeyguardUnlocked"
+                            )
+                        }
+                    }
+
+                keyguardStateController.addCallback(callback)
+                // Adding the callback does not send an initial update.
+                trySendWithFailureLogging(
+                    keyguardStateController.isUnlocked,
+                    TAG,
+                    "initial isKeyguardUnlocked"
+                )
+
+                awaitClose { keyguardStateController.removeCallback(callback) }
+            }
+            .distinctUntilChanged()
+
     override val isKeyguardGoingAway: Flow<Boolean> = conflatedCallbackFlow {
         val callback =
             object : KeyguardStateController.Callback {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
index 4a262f5..f27f899 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
@@ -31,6 +31,8 @@
     @Binds
     fun lightRevealScrimRepository(impl: LightRevealScrimRepositoryImpl): LightRevealScrimRepository
 
+    @Binds fun devicePostureRepository(impl: DevicePostureRepositoryImpl): DevicePostureRepository
+
     @Binds
     fun biometricSettingsRepository(
         impl: BiometricSettingsRepositoryImpl
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
index 0c4bca6..100bc59 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
@@ -68,8 +68,11 @@
     /**
      * Begin a transition from one state to another. Transitions are interruptible, and will issue a
      * [TransitionStep] with state = [TransitionState.CANCELED] before beginning the next one.
+     *
+     * When canceled, there are two options: to continue from the current position of the prior
+     * transition, or to reset the position. When [resetIfCanceled] == true, it will do the latter.
      */
-    fun startTransition(info: TransitionInfo): UUID?
+    fun startTransition(info: TransitionInfo, resetIfCanceled: Boolean = false): UUID?
 
     /**
      * Allows manual control of a transition. When calling [startTransition], the consumer must pass
@@ -130,7 +133,10 @@
         )
     }
 
-    override fun startTransition(info: TransitionInfo): UUID? {
+    override fun startTransition(
+        info: TransitionInfo,
+        resetIfCanceled: Boolean,
+    ): UUID? {
         if (lastStep.from == info.from && lastStep.to == info.to) {
             Log.i(TAG, "Duplicate call to start the transition, rejecting: $info")
             return null
@@ -138,7 +144,11 @@
         val startingValue =
             if (lastStep.transitionState != TransitionState.FINISHED) {
                 Log.i(TAG, "Transition still active: $lastStep, canceling")
-                lastStep.value
+                if (resetIfCanceled) {
+                    0f
+                } else {
+                    lastStep.value
+                }
             } else {
                 0f
             }
@@ -227,10 +237,7 @@
     }
 
     private fun trace(step: TransitionStep, isManual: Boolean) {
-        if (
-            step.transitionState != TransitionState.STARTED &&
-                step.transitionState != TransitionState.FINISHED
-        ) {
+        if (step.transitionState == TransitionState.RUNNING) {
             return
         }
         val traceName =
@@ -243,7 +250,10 @@
         val traceCookie = traceName.hashCode()
         if (step.transitionState == TransitionState.STARTED) {
             Trace.beginAsyncSection(traceName, traceCookie)
-        } else if (step.transitionState == TransitionState.FINISHED) {
+        } else if (
+            step.transitionState == TransitionState.FINISHED ||
+                step.transitionState == TransitionState.CANCELED
+        ) {
             Trace.endAsyncSection(traceName, traceCookie)
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
index 0140529..eae40d6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
@@ -50,6 +50,7 @@
 
     /**
      * Sets the correct bouncer states to show the alternate bouncer if it can show.
+     *
      * @return whether alternateBouncer is visible
      */
     fun show(): Boolean {
@@ -74,6 +75,7 @@
      * Sets the correct bouncer states to hide the bouncer. Should only be called through
      * StatusBarKeyguardViewManager until ScrimController is refactored to use
      * alternateBouncerInteractor.
+     *
      * @return true if the alternate bouncer was newly hidden, else false.
      */
     fun hide(): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
index 310f44d..e6568f2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
@@ -71,8 +71,7 @@
                         isPrimaryBouncerShowing,
                         lastStartedTransitionStep,
                         wakefulnessState,
-                        isAodAvailable
-                    ) ->
+                        isAodAvailable) ->
                     if (
                         !isAlternateBouncerShowing &&
                             !isPrimaryBouncerShowing &&
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 8715d1f..3beac0b 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
@@ -34,7 +34,6 @@
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.launch
 
@@ -57,14 +56,7 @@
 
     private fun listenForDreamingToLockscreen() {
         scope.launch {
-            // Dependending on the dream, either dream state or occluded change will change first,
-            // so listen for both
-            combine(keyguardInteractor.isAbleToDream, keyguardInteractor.isKeyguardOccluded) {
-                    isAbleToDream,
-                    isKeyguardOccluded ->
-                    isAbleToDream && isKeyguardOccluded
-                }
-                .distinctUntilChanged()
+            keyguardInteractor.isAbleToDream
                 .sample(
                     combine(
                         keyguardInteractor.dozeTransitionModel,
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 d01f489..28cc697 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
@@ -64,7 +64,11 @@
                 .sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
                 .collect { pair ->
                     val (isAbleToDream, lastStartedTransition) = pair
-                    if (isAbleToDream && lastStartedTransition.to == KeyguardState.LOCKSCREEN) {
+                    if (
+                        isAbleToDream &&
+                            lastStartedTransition.to == KeyguardState.LOCKSCREEN &&
+                            lastStartedTransition.from != KeyguardState.AOD
+                    ) {
                         keyguardTransitionRepository.startTransition(
                             TransitionInfo(
                                 name,
@@ -130,55 +134,59 @@
             shadeRepository.shadeModel
                 .sample(
                     combine(
-                        keyguardTransitionInteractor.finishedKeyguardState,
+                        keyguardTransitionInteractor.startedKeyguardTransitionStep,
                         keyguardInteractor.statusBarState,
-                        ::Pair
+                        keyguardInteractor.isKeyguardUnlocked,
+                        ::toTriple
                     ),
-                    ::toTriple
+                    ::toQuad
                 )
-                .collect { (shadeModel, keyguardState, statusBarState) ->
+                .collect { (shadeModel, keyguardState, statusBarState, isKeyguardUnlocked) ->
                     val id = transitionId
                     if (id != null) {
-                        // 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) {
-                                TransitionState.FINISHED
-                            } else if (shadeModel.expansionAmount == 1f) {
-                                TransitionState.CANCELED
-                            } else {
-                                TransitionState.RUNNING
-                            }
-                        keyguardTransitionRepository.updateTransition(
-                            id,
-                            1f - shadeModel.expansionAmount,
-                            nextState,
-                        )
-
-                        if (
-                            nextState == TransitionState.CANCELED ||
-                                nextState == TransitionState.FINISHED
-                        ) {
-                            transitionId = null
-                        }
-
-                        // If canceled, just put the state back
-                        if (nextState == TransitionState.CANCELED) {
-                            keyguardTransitionRepository.startTransition(
-                                TransitionInfo(
-                                    ownerName = name,
-                                    from = KeyguardState.PRIMARY_BOUNCER,
-                                    to = KeyguardState.LOCKSCREEN,
-                                    animator = getAnimator(0.milliseconds)
-                                )
+                        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) {
+                                    TransitionState.FINISHED
+                                } else if (shadeModel.expansionAmount == 1f) {
+                                    TransitionState.CANCELED
+                                } else {
+                                    TransitionState.RUNNING
+                                }
+                            keyguardTransitionRepository.updateTransition(
+                                id,
+                                1f - shadeModel.expansionAmount,
+                                nextState,
                             )
+
+                            if (
+                                nextState == TransitionState.CANCELED ||
+                                    nextState == TransitionState.FINISHED
+                            ) {
+                                transitionId = null
+                            }
+
+                            // If canceled, just put the state back
+                            if (nextState == TransitionState.CANCELED) {
+                                keyguardTransitionRepository.startTransition(
+                                    TransitionInfo(
+                                        ownerName = name,
+                                        from = KeyguardState.PRIMARY_BOUNCER,
+                                        to = KeyguardState.LOCKSCREEN,
+                                        animator = getAnimator(0.milliseconds)
+                                    )
+                                )
+                            }
                         }
                     } else {
                         // TODO (b/251849525): Remove statusbarstate check when that state is
                         // integrated into KeyguardTransitionRepository
                         if (
-                            keyguardState == KeyguardState.LOCKSCREEN &&
+                            keyguardState.to == KeyguardState.LOCKSCREEN &&
                                 shadeModel.isUserDragging &&
+                                !isKeyguardUnlocked &&
                                 statusBarState == KEYGUARD
                         ) {
                             transitionId =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt
index 2dc8fee..1fbfff9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt
@@ -47,6 +47,7 @@
         listenForOccludedToLockscreen()
         listenForOccludedToDreaming()
         listenForOccludedToAodOrDozing()
+        listenForOccludedToGone()
     }
 
     private fun listenForOccludedToDreaming() {
@@ -72,11 +73,22 @@
     private fun listenForOccludedToLockscreen() {
         scope.launch {
             keyguardInteractor.isKeyguardOccluded
-                .sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
-                .collect { (isOccluded, lastStartedKeyguardState) ->
+                .sample(
+                    combine(
+                        keyguardInteractor.isKeyguardShowing,
+                        keyguardTransitionInteractor.startedKeyguardTransitionStep,
+                        ::Pair
+                    ),
+                    ::toTriple
+                )
+                .collect { (isOccluded, isShowing, lastStartedKeyguardState) ->
                     // Occlusion signals come from the framework, and should interrupt any
                     // existing transition
-                    if (!isOccluded && lastStartedKeyguardState.to == KeyguardState.OCCLUDED) {
+                    if (
+                        !isOccluded &&
+                            isShowing &&
+                            lastStartedKeyguardState.to == KeyguardState.OCCLUDED
+                    ) {
                         keyguardTransitionRepository.startTransition(
                             TransitionInfo(
                                 name,
@@ -90,6 +102,38 @@
         }
     }
 
+    private fun listenForOccludedToGone() {
+        scope.launch {
+            keyguardInteractor.isKeyguardOccluded
+                .sample(
+                    combine(
+                        keyguardInteractor.isKeyguardShowing,
+                        keyguardTransitionInteractor.startedKeyguardTransitionStep,
+                        ::Pair
+                    ),
+                    ::toTriple
+                )
+                .collect { (isOccluded, isShowing, lastStartedKeyguardState) ->
+                    // Occlusion signals come from the framework, and should interrupt any
+                    // existing transition
+                    if (
+                        !isOccluded &&
+                            !isShowing &&
+                            lastStartedKeyguardState.to == KeyguardState.OCCLUDED
+                    ) {
+                        keyguardTransitionRepository.startTransition(
+                            TransitionInfo(
+                                name,
+                                KeyguardState.OCCLUDED,
+                                KeyguardState.GONE,
+                                getAnimator(),
+                            )
+                        )
+                    }
+                }
+        }
+    }
+
     private fun listenForOccludedToAodOrDozing() {
         scope.launch {
             keyguardInteractor.wakefulnessModel
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt
index b59b413..94961cb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt
@@ -17,6 +17,9 @@
 package com.android.systemui.keyguard.domain.interactor
 
 import android.animation.ValueAnimator
+import com.android.keyguard.KeyguardSecurityModel
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode.Password
+import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.systemui.animation.Interpolators
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
@@ -26,6 +29,8 @@
 import com.android.systemui.keyguard.shared.model.WakefulnessState
 import com.android.systemui.util.kotlin.sample
 import javax.inject.Inject
+import kotlin.time.Duration
+import kotlin.time.Duration.Companion.milliseconds
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.launch
@@ -37,7 +42,8 @@
     @Application private val scope: CoroutineScope,
     private val keyguardInteractor: KeyguardInteractor,
     private val keyguardTransitionRepository: KeyguardTransitionRepository,
-    private val keyguardTransitionInteractor: KeyguardTransitionInteractor
+    private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
+    private val keyguardSecurityModel: KeyguardSecurityModel,
 ) : TransitionInteractor(FromPrimaryBouncerTransitionInteractor::class.simpleName!!) {
 
     override fun start() {
@@ -93,31 +99,47 @@
     private fun listenForPrimaryBouncerToGone() {
         scope.launch {
             keyguardInteractor.isKeyguardGoingAway
-                .sample(keyguardTransitionInteractor.finishedKeyguardState) { a, b -> Pair(a, b) }
-                .collect { pair ->
-                    val (isKeyguardGoingAway, keyguardState) = pair
-                    if (isKeyguardGoingAway && keyguardState == KeyguardState.PRIMARY_BOUNCER) {
+                .sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
+                .collect { (isKeyguardGoingAway, lastStartedTransitionStep) ->
+                    if (
+                        isKeyguardGoingAway &&
+                            lastStartedTransitionStep.to == KeyguardState.PRIMARY_BOUNCER
+                    ) {
+                        val securityMode =
+                            keyguardSecurityModel.getSecurityMode(
+                                KeyguardUpdateMonitor.getCurrentUser()
+                            )
+                        // IME for password requires a slightly faster animation
+                        val duration =
+                            if (securityMode == Password) {
+                                TO_GONE_SHORT_DURATION
+                            } else {
+                                TO_GONE_DURATION
+                            }
                         keyguardTransitionRepository.startTransition(
                             TransitionInfo(
                                 ownerName = name,
                                 from = KeyguardState.PRIMARY_BOUNCER,
                                 to = KeyguardState.GONE,
-                                animator = getAnimator(),
-                            )
+                                animator = getAnimator(duration),
+                            ),
+                            resetIfCanceled = true,
                         )
                     }
                 }
         }
     }
 
-    private fun getAnimator(): ValueAnimator {
+    private fun getAnimator(duration: Duration = DEFAULT_DURATION): ValueAnimator {
         return ValueAnimator().apply {
             setInterpolator(Interpolators.LINEAR)
-            setDuration(TRANSITION_DURATION_MS)
+            setDuration(duration.inWholeMilliseconds)
         }
     }
 
     companion object {
-        private const val TRANSITION_DURATION_MS = 300L
+        private val DEFAULT_DURATION = 300.milliseconds
+        val TO_GONE_DURATION = 250.milliseconds
+        val TO_GONE_SHORT_DURATION = 200.milliseconds
     }
 }
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 d25aff0a..1ac0c52 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
@@ -33,7 +33,9 @@
 import com.android.systemui.keyguard.shared.model.DozeTransitionModel
 import com.android.systemui.keyguard.shared.model.StatusBarState
 import com.android.systemui.keyguard.shared.model.WakefulnessModel
+import com.android.systemui.keyguard.shared.model.WakefulnessModel.Companion.isWakingOrStartingToWake
 import com.android.systemui.statusbar.CommandQueue
+import com.android.systemui.util.kotlin.sample
 import javax.inject.Inject
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.delay
@@ -95,6 +97,9 @@
         awaitClose { commandQueue.removeCallback(callback) }
     }
 
+    /** The device wake/sleep state */
+    val wakefulnessModel: Flow<WakefulnessModel> = repository.wakefulness
+
     /**
      * Dozing and dreaming have overlapping events. If the doze state remains in FINISH, it means
      * that doze mode is not running and DREAMING is ok to commence.
@@ -109,6 +114,12 @@
                     isDreaming && isDozeOff(dozeTransitionModel.to)
                 }
             )
+            .sample(
+                wakefulnessModel,
+                { isAbleToDream, wakefulnessModel ->
+                    isAbleToDream && isWakingOrStartingToWake(wakefulnessModel)
+                }
+            )
             .flatMapLatest { isAbleToDream ->
                 flow {
                     delay(50)
@@ -119,18 +130,20 @@
 
     /** Whether the keyguard is showing or not. */
     val isKeyguardShowing: Flow<Boolean> = repository.isKeyguardShowing
+    /** Whether the keyguard is unlocked or not. */
+    val isKeyguardUnlocked: Flow<Boolean> = repository.isKeyguardUnlocked
     /** Whether the keyguard is occluded (covered by an activity). */
     val isKeyguardOccluded: Flow<Boolean> = repository.isKeyguardOccluded
     /** Whether the keyguard is going away. */
     val isKeyguardGoingAway: Flow<Boolean> = repository.isKeyguardGoingAway
     /** Whether the primary bouncer is showing or not. */
-    val primaryBouncerShowing: Flow<Boolean> = bouncerRepository.primaryBouncerVisible
+    val primaryBouncerShowing: Flow<Boolean> = bouncerRepository.primaryBouncerShow
     /** Whether the alternate bouncer is showing or not. */
     val alternateBouncerShowing: Flow<Boolean> = bouncerRepository.alternateBouncerVisible
-    /** The device wake/sleep state */
-    val wakefulnessModel: Flow<WakefulnessModel> = repository.wakefulness
     /** Observable for the [StatusBarState] */
     val statusBarState: Flow<StatusBarState> = repository.statusBarState
+    /** Whether or not quick settings or quick quick settings are showing. */
+    val isQuickSettingsVisible: Flow<Boolean> = repository.isQuickSettingsVisible
     /**
      * Observable for [BiometricUnlockModel] when biometrics like face or any fingerprint (rear,
      * side, under display) is used to unlock the device.
@@ -146,7 +159,7 @@
         if (featureFlags.isEnabled(Flags.FACE_AUTH_REFACTOR)) {
             combine(
                     isKeyguardVisible,
-                    bouncerRepository.primaryBouncerVisible,
+                    primaryBouncerShowing,
                     onCameraLaunchDetected,
                 ) { isKeyguardVisible, isPrimaryBouncerShowing, cameraLaunchEvent ->
                     when {
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 dfbe1c2..7064827 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
@@ -26,6 +26,7 @@
 import com.android.systemui.animation.Expandable
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.devicepolicy.areKeyguardShortcutsDisabled
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig
@@ -36,6 +37,7 @@
 import com.android.systemui.keyguard.shared.model.KeyguardQuickAffordancePickerRepresentation
 import com.android.systemui.keyguard.shared.model.KeyguardSlotPickerRepresentation
 import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition
+import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancesMetricsLogger
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.shared.customization.data.content.CustomizationProviderContract as Contract
@@ -67,6 +69,7 @@
     private val featureFlags: FeatureFlags,
     private val repository: Lazy<KeyguardQuickAffordanceRepository>,
     private val launchAnimator: DialogLaunchAnimator,
+    private val logger: KeyguardQuickAffordancesMetricsLogger,
     private val devicePolicyManager: DevicePolicyManager,
     @Background private val backgroundDispatcher: CoroutineDispatcher,
 ) {
@@ -93,8 +96,9 @@
             quickAffordanceAlwaysVisible(position),
             keyguardInteractor.isDozing,
             keyguardInteractor.isKeyguardShowing,
-        ) { affordance, isDozing, isKeyguardShowing ->
-            if (!isDozing && isKeyguardShowing) {
+            keyguardInteractor.isQuickSettingsVisible
+        ) { affordance, isDozing, isKeyguardShowing, isQuickSettingsVisible ->
+            if (!isDozing && isKeyguardShowing && !isQuickSettingsVisible) {
                 affordance
             } else {
                 KeyguardQuickAffordanceModel.Hidden
@@ -119,12 +123,14 @@
      * Notifies that a quick affordance has been "triggered" (clicked) by the user.
      *
      * @param configKey The configuration key corresponding to the [KeyguardQuickAffordanceModel] of
-     * the affordance that was clicked
+     *   the affordance that was clicked
      * @param expandable An optional [Expandable] for the activity- or dialog-launch animation
+     * @param slotId The id of the lockscreen slot that the affordance is in
      */
     fun onQuickAffordanceTriggered(
         configKey: String,
         expandable: Expandable?,
+        slotId: String,
     ) {
         @Suppress("UNCHECKED_CAST")
         val config =
@@ -138,6 +144,7 @@
             Log.e(TAG, "Affordance config with key of \"$configKey\" not found!")
             return
         }
+        logger.logOnShortcutTriggered(slotId, configKey)
 
         when (val result = config.onTriggered(expandable)) {
             is KeyguardQuickAffordanceConfig.OnTriggeredResult.StartActivity ->
@@ -190,6 +197,7 @@
                 affordanceIds = selections,
             )
 
+        logger.logOnShortcutSelected(slotId, affordanceId)
         return true
     }
 
@@ -198,9 +206,9 @@
      *
      * @param slotId The ID of the slot.
      * @param affordanceId The ID of the affordance to remove; if `null`, removes all affordances
-     * from the slot.
+     *   from the slot.
      * @return `true` if the affordance was successfully removed; `false` otherwise (for example, if
-     * the affordance was not on the slot to begin with).
+     *   the affordance was not on the slot to begin with).
      */
     suspend fun unselect(slotId: String, affordanceId: String?): Boolean {
         check(isUsingRepository)
@@ -410,16 +418,10 @@
         )
     }
 
-    private suspend fun isFeatureDisabledByDevicePolicy(): Boolean {
-        val flags =
-            withContext(backgroundDispatcher) {
-                devicePolicyManager.getKeyguardDisabledFeatures(null, userTracker.userId)
-            }
-        val flagsToCheck =
-            DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL or
-                DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL
-        return flagsToCheck and flags != 0
-    }
+    private suspend fun isFeatureDisabledByDevicePolicy(): Boolean =
+        withContext(backgroundDispatcher) {
+            devicePolicyManager.areKeyguardShortcutsDisabled(userId = userTracker.userId)
+        }
 
     companion object {
         private const val TAG = "KeyguardQuickAffordanceInteractor"
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt
index 51b0277..e650b9f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt
@@ -61,7 +61,15 @@
         }
 
         scope.launch {
-            keyguardInteractor.isDreaming.collect { logger.log(TAG, VERBOSE, "isDreaming", it) }
+            keyguardInteractor.isAbleToDream.collect {
+                logger.log(TAG, VERBOSE, "isAbleToDream", it)
+            }
+        }
+
+        scope.launch {
+            keyguardInteractor.isKeyguardOccluded.collect {
+                logger.log(TAG, VERBOSE, "isOccluded", it)
+            }
         }
 
         scope.launch {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
index 1b7da5b..3c0ec35 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
@@ -78,6 +78,10 @@
     val occludedToLockscreenTransition: Flow<TransitionStep> =
         repository.transition(OCCLUDED, LOCKSCREEN)
 
+    /** PRIMARY_BOUNCER->GONE transition information. */
+    val primaryBouncerToGoneTransition: Flow<TransitionStep> =
+        repository.transition(PRIMARY_BOUNCER, GONE)
+
     /**
      * AOD<->LOCKSCREEN transition information, mapped to dozeAmount range of AOD (1f) <->
      * Lockscreen (0f).
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
index edd2897..b10aa90 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
@@ -21,12 +21,15 @@
 import android.hardware.biometrics.BiometricSourceType
 import android.os.Handler
 import android.os.Trace
-import android.view.View
+import android.os.UserHandle
+import android.os.UserManager
 import android.util.Log
+import android.view.View
 import com.android.keyguard.KeyguardConstants
 import com.android.keyguard.KeyguardSecurityModel
 import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.keyguard.KeyguardUpdateMonitorCallback
+import com.android.settingslib.Utils
 import com.android.systemui.DejankUtils
 import com.android.systemui.R
 import com.android.systemui.classifier.FalsingCollector
@@ -37,7 +40,6 @@
 import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
 import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants
 import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
-import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.shared.system.SysUiStatsLog
 import com.android.systemui.statusbar.phone.KeyguardBypassController
@@ -81,23 +83,21 @@
 
     /** Runnable to show the primary bouncer. */
     val showRunnable = Runnable {
-        repository.setPrimaryVisible(true)
-        repository.setPrimaryShow(
-            KeyguardBouncerModel(
-                promptReason = repository.bouncerPromptReason ?: 0,
-                errorMessage = repository.bouncerErrorMessage,
-                expansionAmount = repository.panelExpansionAmount.value
+        repository.setPrimaryShow(true)
+        primaryBouncerView.delegate?.showPromptReason(repository.bouncerPromptReason)
+        (repository.bouncerErrorMessage as? String)?.let {
+            repository.setShowMessage(
+                BouncerShowMessageModel(message = it, Utils.getColorError(context))
             )
-        )
+        }
         repository.setPrimaryShowingSoon(false)
         primaryBouncerCallbackInteractor.dispatchVisibilityChanged(View.VISIBLE)
     }
 
     val keyguardAuthenticated: Flow<Boolean> = repository.keyguardAuthenticated.filterNotNull()
-    val show: Flow<KeyguardBouncerModel> = repository.primaryBouncerShow.filterNotNull()
-    val hide: Flow<Unit> = repository.primaryBouncerHide.filter { it }.map {}
+    val show: Flow<Unit> = repository.primaryBouncerShow.filter { it }.map {}
+    val hide: Flow<Unit> = repository.primaryBouncerShow.filter { !it }.map {}
     val startingToHide: Flow<Unit> = repository.primaryBouncerStartingToHide.filter { it }.map {}
-    val isVisible: Flow<Boolean> = repository.primaryBouncerVisible
     val isBackButtonEnabled: Flow<Boolean> = repository.isBackButtonEnabled.filterNotNull()
     val showMessage: Flow<BouncerShowMessageModel> = repository.showMessage.filterNotNull()
     val startingDisappearAnimation: Flow<Runnable> =
@@ -107,10 +107,11 @@
     val panelExpansionAmount: Flow<Float> = repository.panelExpansionAmount
     /** 0f = bouncer fully hidden. 1f = bouncer fully visible. */
     val bouncerExpansion: Flow<Float> =
-        combine(repository.panelExpansionAmount, repository.primaryBouncerVisible) {
-            panelExpansion,
-            primaryBouncerVisible ->
-            if (primaryBouncerVisible) {
+        combine(
+            repository.panelExpansionAmount,
+            repository.primaryBouncerShow
+        ) { panelExpansion, primaryBouncerIsShowing ->
+            if (primaryBouncerIsShowing) {
                 1f - panelExpansion
             } else {
                 0f
@@ -120,21 +121,23 @@
     val isInteractable: Flow<Boolean> = bouncerExpansion.map { it > 0.9 }
     val sideFpsShowing: Flow<Boolean> = repository.sideFpsShowing
 
-    init {
-        keyguardUpdateMonitor.registerCallback(
-            object : KeyguardUpdateMonitorCallback() {
-                override fun onBiometricRunningStateChanged(
-                    running: Boolean,
-                    biometricSourceType: BiometricSourceType?
-                ) {
-                    updateSideFpsVisibility()
-                }
-
-                override fun onStrongAuthStateChanged(userId: Int) {
-                    updateSideFpsVisibility()
-                }
+    /** This callback needs to be a class field so it does not get garbage collected. */
+    val keyguardUpdateMonitorCallback =
+        object : KeyguardUpdateMonitorCallback() {
+            override fun onBiometricRunningStateChanged(
+                running: Boolean,
+                biometricSourceType: BiometricSourceType?
+            ) {
+                updateSideFpsVisibility()
             }
-        )
+
+            override fun onStrongAuthStateChanged(userId: Int) {
+                updateSideFpsVisibility()
+            }
+        }
+
+    init {
+        keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
     }
 
     // TODO(b/243685699): Move isScrimmed logic to data layer.
@@ -144,14 +147,13 @@
     fun show(isScrimmed: Boolean) {
         // Reset some states as we show the bouncer.
         repository.setKeyguardAuthenticated(null)
-        repository.setPrimaryHide(false)
         repository.setPrimaryStartingToHide(false)
 
         val resumeBouncer =
-            (repository.primaryBouncerVisible.value ||
-                repository.primaryBouncerShowingSoon.value) && needsFullscreenBouncer()
+            (isBouncerShowing() || repository.primaryBouncerShowingSoon.value) &&
+                needsFullscreenBouncer()
 
-        if (!resumeBouncer && repository.primaryBouncerShow.value != null) {
+        if (!resumeBouncer && isBouncerShowing()) {
             // If bouncer is visible, the bouncer is already showing.
             return
         }
@@ -198,9 +200,7 @@
         keyguardStateController.notifyPrimaryBouncerShowing(false /* showing */)
         cancelShowRunnable()
         repository.setPrimaryShowingSoon(false)
-        repository.setPrimaryVisible(false)
-        repository.setPrimaryHide(true)
-        repository.setPrimaryShow(null)
+        repository.setPrimaryShow(false)
         primaryBouncerCallbackInteractor.dispatchVisibilityChanged(View.INVISIBLE)
         Trace.endSection()
     }
@@ -317,9 +317,8 @@
         val fpsDetectionRunning: Boolean = keyguardUpdateMonitor.isFingerprintDetectionRunning
         val isUnlockingWithFpAllowed: Boolean =
             keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed
-        val bouncerVisible = repository.primaryBouncerVisible.value
         val toShow =
-            (repository.primaryBouncerVisible.value &&
+            (isBouncerShowing() &&
                 sfpsEnabled &&
                 fpsDetectionRunning &&
                 isUnlockingWithFpAllowed &&
@@ -329,7 +328,7 @@
             Log.d(
                 TAG,
                 ("sideFpsToShow=$toShow\n" +
-                    "bouncerVisible=$bouncerVisible\n" +
+                    "isBouncerShowing=${isBouncerShowing()}\n" +
                     "configEnabled=$sfpsEnabled\n" +
                     "fpsDetectionRunning=$fpsDetectionRunning\n" +
                     "isUnlockingWithFpAllowed=$isUnlockingWithFpAllowed\n" +
@@ -341,8 +340,7 @@
 
     /** Returns whether bouncer is fully showing. */
     fun isFullyShowing(): Boolean {
-        return (repository.primaryBouncerShowingSoon.value ||
-            repository.primaryBouncerVisible.value) &&
+        return (repository.primaryBouncerShowingSoon.value || isBouncerShowing()) &&
             repository.panelExpansionAmount.value == KeyguardBouncerConstants.EXPANSION_VISIBLE &&
             repository.primaryBouncerStartingDisappearAnimation.value == null
     }
@@ -369,6 +367,11 @@
         return primaryBouncerView.delegate?.willDismissWithActions() == true
     }
 
+    /** Will the dismissal run from the keyguard layout (instead of from bouncer) */
+    fun willRunDismissFromKeyguard(): Boolean {
+        return primaryBouncerView.delegate?.willRunDismissFromKeyguard() == true
+    }
+
     /** Returns whether the bouncer should be full screen. */
     private fun needsFullscreenBouncer(): Boolean {
         val mode: KeyguardSecurityModel.SecurityMode =
@@ -383,6 +386,10 @@
         mainHandler.removeCallbacks(showRunnable)
     }
 
+    private fun isBouncerShowing(): Boolean {
+        return repository.primaryBouncerShow.value
+    }
+
     companion object {
         private const val TAG = "PrimaryBouncerInteractor"
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/DevicePosture.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/DevicePosture.kt
new file mode 100644
index 0000000..fff7cfe
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/DevicePosture.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.shared.model
+
+import com.android.systemui.statusbar.policy.DevicePostureController
+
+/** Represents the possible posture states of the device. */
+enum class DevicePosture {
+    UNKNOWN,
+    CLOSED,
+    HALF_OPENED,
+    OPENED,
+    FLIPPED;
+
+    companion object {
+        fun toPosture(@DevicePostureController.DevicePostureInt posture: Int): DevicePosture {
+            return when (posture) {
+                DevicePostureController.DEVICE_POSTURE_CLOSED -> CLOSED
+                DevicePostureController.DEVICE_POSTURE_HALF_OPENED -> HALF_OPENED
+                DevicePostureController.DEVICE_POSTURE_OPENED -> OPENED
+                DevicePostureController.DEVICE_POSTURE_FLIPPED -> FLIPPED
+                DevicePostureController.DEVICE_POSTURE_UNKNOWN -> UNKNOWN
+                else -> UNKNOWN
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardBouncerModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/ScrimAlpha.kt
similarity index 70%
rename from packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardBouncerModel.kt
rename to packages/SystemUI/src/com/android/systemui/keyguard/shared/model/ScrimAlpha.kt
index ad783da..1db7733 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardBouncerModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/ScrimAlpha.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.
@@ -13,12 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License
  */
-
 package com.android.systemui.keyguard.shared.model
 
-/** Models the state of the lock-screen bouncer */
-data class KeyguardBouncerModel(
-    val promptReason: Int = 0,
-    val errorMessage: CharSequence? = null,
-    val expansionAmount: Float = 0f,
+/** Alpha values for scrim updates */
+data class ScrimAlpha(
+    val frontAlpha: Float = 0f,
+    val behindAlpha: Float = 0f,
+    val notificationsAlpha: Float = 0f,
 )
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/SysUiFaceAuthenticateOptions.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/SysUiFaceAuthenticateOptions.kt
new file mode 100644
index 0000000..a79513e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/SysUiFaceAuthenticateOptions.kt
@@ -0,0 +1,99 @@
+/*
+ * 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.shared.model
+
+import android.hardware.face.FaceAuthenticateOptions
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_ASSISTANT_VISIBLE
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_STARTED_WAKING_UP
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_UDFPS_POINTER_DOWN
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_UNKNOWN
+import android.hardware.face.FaceAuthenticateOptions.AuthenticateReason
+import android.os.PowerManager
+import android.os.PowerManager.WAKE_REASON_UNKNOWN
+import android.util.Log
+import com.android.internal.logging.UiEvent
+import com.android.internal.logging.UiEventLogger
+import com.android.keyguard.FaceAuthUiEvent
+
+/**
+ * Wrapper for [FaceAuthenticateOptions] to convert SystemUI values to their corresponding value in
+ * [FaceAuthenticateOptions].
+ */
+data class SysUiFaceAuthenticateOptions(
+        val userId: Int,
+        private val faceAuthUiEvent: UiEventLogger.UiEventEnum,
+        @PowerManager.WakeReason val wakeReason: Int = WAKE_REASON_UNKNOWN
+) {
+    val authenticateReason = setAuthenticateReason(faceAuthUiEvent)
+
+    /**
+     * The [FaceAuthUiEvent] for this operation. This method converts the UiEvent to the framework
+     * [AuthenticateReason].
+     */
+    @AuthenticateReason
+    fun setAuthenticateReason(uiEvent: UiEventLogger.UiEventEnum): Int {
+        return when (uiEvent) {
+            FaceAuthUiEvent.FACE_AUTH_UPDATED_STARTED_WAKING_UP -> {
+                AUTHENTICATE_REASON_STARTED_WAKING_UP
+            }
+            FaceAuthUiEvent.FACE_AUTH_UPDATED_PRIMARY_BOUNCER_SHOWN,
+            FaceAuthUiEvent.FACE_AUTH_UPDATED_PRIMARY_BOUNCER_SHOWN_OR_WILL_BE_SHOWN -> {
+                AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN
+            }
+            FaceAuthUiEvent.FACE_AUTH_UPDATED_ASSISTANT_VISIBILITY_CHANGED -> {
+                AUTHENTICATE_REASON_ASSISTANT_VISIBLE
+            }
+            FaceAuthUiEvent.FACE_AUTH_TRIGGERED_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN -> {
+                AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN
+            }
+            FaceAuthUiEvent.FACE_AUTH_TRIGGERED_NOTIFICATION_PANEL_CLICKED -> {
+                AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED
+            }
+            FaceAuthUiEvent.FACE_AUTH_TRIGGERED_OCCLUDING_APP_REQUESTED -> {
+                AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED
+            }
+            FaceAuthUiEvent.FACE_AUTH_TRIGGERED_PICK_UP_GESTURE_TRIGGERED -> {
+                AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED
+            }
+            FaceAuthUiEvent.FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER -> {
+                AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER
+            }
+            FaceAuthUiEvent.FACE_AUTH_TRIGGERED_UDFPS_POINTER_DOWN -> {
+                AUTHENTICATE_REASON_UDFPS_POINTER_DOWN
+            }
+            else -> {
+                Log.e("FaceAuthenticateOptions", " unmapped FaceAuthUiEvent $uiEvent")
+                AUTHENTICATE_REASON_UNKNOWN
+            }
+        }
+    }
+
+    /** Builds the instance. */
+    fun toFaceAuthenticateOptions(): FaceAuthenticateOptions {
+        return FaceAuthenticateOptions.Builder()
+            .setUserId(userId)
+            .setAuthenticateReason(authenticateReason)
+            .setWakeReason(wakeReason)
+            .build()
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/quickaffordance/KeyguardQuickAffordancesMetricsLogger.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/quickaffordance/KeyguardQuickAffordancesMetricsLogger.kt
new file mode 100644
index 0000000..0b0225a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/quickaffordance/KeyguardQuickAffordancesMetricsLogger.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.shared.quickaffordance
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.shared.system.SysUiStatsLog
+
+interface KeyguardQuickAffordancesMetricsLogger {
+
+    /**
+     * Logs shortcut Triggered
+     * @param slotId The id of the lockscreen slot that the affordance is in
+     * @param affordanceId The id of the lockscreen affordance
+     */
+    fun logOnShortcutTriggered(slotId: String, affordanceId: String)
+
+    /**
+     * Logs shortcut Selected
+     * @param slotId The id of the lockscreen slot that the affordance is in
+     * @param affordanceId The id of the lockscreen affordance
+     */
+    fun logOnShortcutSelected(slotId: String, affordanceId: String)
+
+}
+
+@SysUISingleton
+class KeyguardQuickAffordancesMetricsLoggerImpl : KeyguardQuickAffordancesMetricsLogger {
+
+    override fun logOnShortcutTriggered(slotId: String, affordanceId: String) {
+        SysUiStatsLog.write(
+                SysUiStatsLog.LOCKSCREEN_SHORTCUT_TRIGGERED,
+                slotId,
+                affordanceId,
+        )
+    }
+
+    override fun logOnShortcutSelected(slotId: String, affordanceId: String) {
+        SysUiStatsLog.write(
+                SysUiStatsLog.LOCKSCREEN_SHORTCUT_SELECTED,
+                slotId,
+                affordanceId,
+        )
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt
index ca1e27c..38b9d50 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt
@@ -47,6 +47,7 @@
         duration: Duration,
         onStep: (Float) -> Float,
         startTime: Duration = 0.milliseconds,
+        onStart: (() -> Unit)? = null,
         onCancel: (() -> Float)? = null,
         onFinish: (() -> Float)? = null,
         interpolator: Interpolator = LINEAR,
@@ -73,6 +74,7 @@
                 // the ViewModels of the last update
                 STARTED -> {
                     isComplete = false
+                    onStart?.invoke()
                     max(0f, min(1f, value))
                 }
                 // Always send a final value of 1. Because of rounding, [value] may never be
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
index ab009f4..d63636c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
@@ -342,7 +342,13 @@
         if (viewModel.isClickable) {
             if (viewModel.useLongPress) {
                 view.setOnTouchListener(
-                    OnTouchListener(view, viewModel, messageDisplayer, vibratorHelper)
+                    OnTouchListener(
+                        view,
+                        viewModel,
+                        messageDisplayer,
+                        vibratorHelper,
+                        falsingManager,
+                    )
                 )
             } else {
                 view.setOnClickListener(OnClickListener(viewModel, checkNotNull(falsingManager)))
@@ -371,6 +377,7 @@
         private val viewModel: KeyguardQuickAffordanceViewModel,
         private val messageDisplayer: (Int) -> Unit,
         private val vibratorHelper: VibratorHelper?,
+        private val falsingManager: FalsingManager?,
     ) : View.OnTouchListener {
 
         private val longPressDurationMs = ViewConfiguration.getLongPressTimeout().toLong()
@@ -395,7 +402,14 @@
                                     .scaleY(PRESSED_SCALE)
                                     .setDuration(longPressDurationMs)
                                     .withEndAction {
-                                        dispatchClick(viewModel.configKey)
+                                        if (
+                                            falsingManager
+                                                ?.isFalseLongTap(
+                                                    FalsingManager.MODERATE_PENALTY
+                                                ) == false
+                                        ) {
+                                            dispatchClick(viewModel.configKey)
+                                        }
                                         cancel()
                                     }
                         }
@@ -421,7 +435,8 @@
                         // the pointer performs a click.
                         if (
                             viewModel.configKey != null &&
-                                distanceMoved(event) <= ViewConfiguration.getTouchSlop()
+                                distanceMoved(event) <= ViewConfiguration.getTouchSlop() &&
+                                falsingManager?.isFalseTap(FalsingManager.NO_PENALTY) == false
                         ) {
                             dispatchClick(viewModel.configKey)
                         }
@@ -487,6 +502,7 @@
                     KeyguardQuickAffordanceViewModel.OnClickedParameters(
                         configKey = configKey,
                         expandable = Expandable.fromView(view),
+                        slotId = viewModel.slotId,
                     )
                 )
             }
@@ -553,6 +569,7 @@
                     KeyguardQuickAffordanceViewModel.OnClickedParameters(
                         configKey = viewModel.configKey,
                         expandable = Expandable.fromView(view),
+                        slotId = viewModel.slotId,
                     )
                 )
             }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
index 7db567b..d716784 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
@@ -27,10 +27,10 @@
 import com.android.keyguard.KeyguardSecurityView
 import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.keyguard.dagger.KeyguardBouncerComponent
-import com.android.settingslib.Utils
 import com.android.systemui.keyguard.data.BouncerViewDelegate
 import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
+import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel
 import com.android.systemui.lifecycle.repeatWhenAttached
 import com.android.systemui.plugins.ActivityStarter
 import kotlinx.coroutines.awaitCancellation
@@ -44,6 +44,7 @@
     fun bind(
         view: ViewGroup,
         viewModel: KeyguardBouncerViewModel,
+        primaryBouncerToGoneTransitionViewModel: PrimaryBouncerToGoneTransitionViewModel,
         componentFactory: KeyguardBouncerComponent.Factory
     ) {
         // Builds the KeyguardSecurityContainerController from bouncer view group.
@@ -95,6 +96,14 @@
                 override fun willDismissWithActions(): Boolean {
                     return securityContainerController.hasDismissActions()
                 }
+
+                override fun willRunDismissFromKeyguard(): Boolean {
+                    return securityContainerController.willRunDismissFromKeyguard()
+                }
+
+                override fun showPromptReason(reason: Int) {
+                    securityContainerController.showPromptReason(reason)
+                }
             }
         view.repeatWhenAttached {
             repeatOnLifecycle(Lifecycle.State.CREATED) {
@@ -103,14 +112,11 @@
                     launch {
                         viewModel.show.collect {
                             // Reset Security Container entirely.
+                            view.visibility = View.VISIBLE
+                            securityContainerController.onBouncerVisibilityChanged(
+                                /* isVisible= */ true
+                            )
                             securityContainerController.reinflateViewFlipper()
-                            securityContainerController.showPromptReason(it.promptReason)
-                            it.errorMessage?.let { errorMessage ->
-                                securityContainerController.showMessage(
-                                    errorMessage,
-                                    Utils.getColorError(view.context)
-                                )
-                            }
                             securityContainerController.showPrimarySecurityScreen(
                                 /* turningOff= */ false
                             )
@@ -121,8 +127,13 @@
 
                     launch {
                         viewModel.hide.collect {
+                            view.visibility = View.INVISIBLE
+                            securityContainerController.onBouncerVisibilityChanged(
+                                /* isVisible= */ false
+                            )
                             securityContainerController.cancelDismissAction()
                             securityContainerController.reset()
+                            securityContainerController.onPause()
                         }
                     }
 
@@ -145,6 +156,12 @@
                     }
 
                     launch {
+                        primaryBouncerToGoneTransitionViewModel.bouncerAlpha.collect { alpha ->
+                            securityContainerController.setAlpha(alpha)
+                        }
+                    }
+
+                    launch {
                         viewModel.bouncerExpansionAmount
                             .filter { it == EXPANSION_VISIBLE }
                             .collect {
@@ -154,19 +171,6 @@
                     }
 
                     launch {
-                        viewModel.isBouncerVisible.collect { isVisible ->
-                            view.visibility = if (isVisible) View.VISIBLE else View.INVISIBLE
-                            securityContainerController.onBouncerVisibilityChanged(isVisible)
-                        }
-                    }
-
-                    launch {
-                        viewModel.isBouncerVisible
-                            .filter { !it }
-                            .collect { securityContainerController.onPause() }
-                    }
-
-                    launch {
                         viewModel.isInteractable.collect { isInteractable ->
                             securityContainerController.setInteractable(isInteractable)
                         }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt
index ef3f242..8671753 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt
@@ -34,7 +34,7 @@
      * @param viewModel The view-model that models the UI state.
      * @param onSingleTap A callback to invoke when the system decides that there was a single tap.
      * @param falsingManager [FalsingManager] for making sure the long-press didn't just happen in
-     * the user's pocket.
+     *   the user's pocket.
      */
     @JvmStatic
     fun bind(
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 50722d5..6d95882 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
@@ -26,18 +26,21 @@
 import android.util.Log
 import androidx.annotation.VisibleForTesting
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.shared.quickaffordance.shared.model.KeyguardQuickAffordancePreviewConstants
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
 
 @SysUISingleton
 class KeyguardRemotePreviewManager
 @Inject
 constructor(
     private val previewRendererFactory: KeyguardPreviewRendererFactory,
+    @Application private val applicationScope: CoroutineScope,
     @Main private val mainDispatcher: CoroutineDispatcher,
     @Background private val backgroundHandler: Handler,
 ) {
@@ -55,7 +58,13 @@
 
             // Destroy any previous renderer associated with this token.
             activePreviews[renderer.hostToken]?.let { destroyObserver(it) }
-            observer = PreviewLifecycleObserver(renderer, mainDispatcher, ::destroyObserver)
+            observer =
+                PreviewLifecycleObserver(
+                    renderer,
+                    applicationScope,
+                    mainDispatcher,
+                    ::destroyObserver,
+                )
             activePreviews[renderer.hostToken] = observer
             renderer.render()
             renderer.hostToken?.linkToDeath(observer, 0)
@@ -92,13 +101,18 @@
 
     private class PreviewLifecycleObserver(
         private val renderer: KeyguardPreviewRenderer,
+        private val scope: CoroutineScope,
         private val mainDispatcher: CoroutineDispatcher,
         private val requestDestruction: (PreviewLifecycleObserver) -> Unit,
     ) : Handler.Callback, IBinder.DeathRecipient {
 
-        private var isDestroyed = false
+        private var isDestroyedOrDestroying = false
 
         override fun handleMessage(message: Message): Boolean {
+            if (isDestroyedOrDestroying) {
+                return true
+            }
+
             when (message.what) {
                 KeyguardQuickAffordancePreviewConstants.MESSAGE_ID_SLOT_SELECTED -> {
                     message.data
@@ -118,14 +132,14 @@
         }
 
         fun onDestroy(): IBinder? {
-            if (isDestroyed) {
+            if (isDestroyedOrDestroying) {
                 return null
             }
 
-            isDestroyed = true
+            isDestroyedOrDestroying = true
             val hostToken = renderer.hostToken
             hostToken?.unlinkToDeath(this, 0)
-            runBlocking(mainDispatcher) { renderer.destroy() }
+            scope.launch(mainDispatcher) { renderer.destroy() }
             return hostToken
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt
index 1e3b60c..a8e3464 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt
@@ -135,7 +135,7 @@
      *
      * @param initiallySelectedSlotId The ID of the initial slot to render as the selected one.
      * @param shouldHighlightSelectedAffordance Whether the selected quick affordance should be
-     * highlighted (while all others are dimmed to make the selected one stand out).
+     *   highlighted (while all others are dimmed to make the selected one stand out).
      */
     fun enablePreviewMode(
         initiallySelectedSlotId: String?,
@@ -175,7 +175,8 @@
                     areQuickAffordancesFullyOpaque,
                     selectedPreviewSlotId,
                 ) { model, animateReveal, isFullyOpaque, selectedPreviewSlotId ->
-                    val isSelected = selectedPreviewSlotId == position.toSlotId()
+                    val slotId = position.toSlotId()
+                    val isSelected = selectedPreviewSlotId == slotId
                     model.toViewModel(
                         animateReveal = !previewMode.isInPreviewMode && animateReveal,
                         isClickable = isFullyOpaque && !previewMode.isInPreviewMode,
@@ -187,6 +188,8 @@
                             previewMode.isInPreviewMode &&
                                 previewMode.shouldHighlightSelectedAffordance &&
                                 !isSelected,
+                        forceInactive = previewMode.isInPreviewMode,
+                        slotId = slotId,
                     )
                 }
                 .distinctUntilChanged()
@@ -198,6 +201,8 @@
         isClickable: Boolean,
         isSelected: Boolean,
         isDimmed: Boolean,
+        forceInactive: Boolean,
+        slotId: String,
     ): KeyguardQuickAffordanceViewModel {
         return when (this) {
             is KeyguardQuickAffordanceModel.Visible ->
@@ -210,15 +215,19 @@
                         quickAffordanceInteractor.onQuickAffordanceTriggered(
                             configKey = parameters.configKey,
                             expandable = parameters.expandable,
+                            slotId = parameters.slotId,
                         )
                     },
                     isClickable = isClickable,
-                    isActivated = activationState is ActivationState.Active,
+                    isActivated = !forceInactive && activationState is ActivationState.Active,
                     isSelected = isSelected,
                     useLongPress = quickAffordanceInteractor.useLongPress,
                     isDimmed = isDimmed,
+                    slotId = slotId,
                 )
-            is KeyguardQuickAffordanceModel.Hidden -> KeyguardQuickAffordanceViewModel()
+            is KeyguardQuickAffordanceModel.Hidden -> KeyguardQuickAffordanceViewModel(
+                slotId = slotId,
+            )
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt
index 97e94d8f3..68910c6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt
@@ -21,7 +21,6 @@
 import com.android.systemui.keyguard.data.BouncerViewDelegate
 import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
 import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
-import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.filterNotNull
@@ -38,14 +37,11 @@
     /** Observe on bouncer expansion amount. */
     val bouncerExpansionAmount: Flow<Float> = interactor.panelExpansionAmount
 
-    /** Observe on bouncer visibility. */
-    val isBouncerVisible: Flow<Boolean> = interactor.isVisible
-
     /** Can the user interact with the view? */
     val isInteractable: Flow<Boolean> = interactor.isInteractable
 
     /** Observe whether bouncer is showing. */
-    val show: Flow<KeyguardBouncerModel> = interactor.show
+    val show: Flow<Unit> = interactor.show
 
     /** Observe whether bouncer is hiding. */
     val hide: Flow<Unit> = interactor.hide
@@ -75,7 +71,7 @@
     val shouldUpdateSideFps: Flow<Unit> =
         merge(
             interactor.startingToHide,
-            interactor.isVisible.map {},
+            interactor.show,
             interactor.startingDisappearAnimation.filterNotNull().map {}
         )
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordanceViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordanceViewModel.kt
index cb68a82..38d1db6d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordanceViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordanceViewModel.kt
@@ -32,9 +32,11 @@
     val isSelected: Boolean = false,
     val useLongPress: Boolean = false,
     val isDimmed: Boolean = false,
+    val slotId: String,
 ) {
     data class OnClickedParameters(
         val configKey: String,
         val expandable: Expandable?,
+        val slotId: String,
     )
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
new file mode 100644
index 0000000..b23247c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor.Companion.TO_GONE_DURATION
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.keyguard.shared.model.ScrimAlpha
+import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.statusbar.SysuiStatusBarStateController
+import javax.inject.Inject
+import kotlin.time.Duration.Companion.milliseconds
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+
+/**
+ * Breaks down PRIMARY_BOUNCER->GONE transition into discrete steps for corresponding views to
+ * consume.
+ */
+@SysUISingleton
+class PrimaryBouncerToGoneTransitionViewModel
+@Inject
+constructor(
+    private val interactor: KeyguardTransitionInteractor,
+    private val statusBarStateController: SysuiStatusBarStateController,
+    private val primaryBouncerInteractor: PrimaryBouncerInteractor,
+) {
+    private val transitionAnimation =
+        KeyguardTransitionAnimationFlow(
+            transitionDuration = TO_GONE_DURATION,
+            transitionFlow = interactor.primaryBouncerToGoneTransition,
+        )
+
+    private var leaveShadeOpen: Boolean = false
+    private var willRunDismissFromKeyguard: Boolean = false
+
+    /** Bouncer container alpha */
+    val bouncerAlpha: Flow<Float> =
+        transitionAnimation.createFlow(
+            duration = 200.milliseconds,
+            onStart = {
+                willRunDismissFromKeyguard = primaryBouncerInteractor.willRunDismissFromKeyguard()
+            },
+            onStep = {
+                if (willRunDismissFromKeyguard) {
+                    0f
+                } else {
+                    1f - it
+                }
+            },
+        )
+
+    /** Scrim alpha values */
+    val scrimAlpha: Flow<ScrimAlpha> =
+        transitionAnimation
+            .createFlow(
+                duration = TO_GONE_DURATION,
+                interpolator = EMPHASIZED_ACCELERATE,
+                onStart = {
+                    leaveShadeOpen = statusBarStateController.leaveOpenOnKeyguardHide()
+                    willRunDismissFromKeyguard =
+                        primaryBouncerInteractor.willRunDismissFromKeyguard()
+                },
+                onStep = { 1f - it },
+            )
+            .map {
+                if (willRunDismissFromKeyguard) {
+                    ScrimAlpha(
+                        notificationsAlpha = 1f,
+                    )
+                } else if (leaveShadeOpen) {
+                    ScrimAlpha(
+                        behindAlpha = 1f,
+                        notificationsAlpha = 1f,
+                    )
+                } else {
+                    ScrimAlpha(behindAlpha = it)
+                }
+            }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
index d69ac7f..34a6740 100644
--- a/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
+++ b/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
@@ -47,13 +47,13 @@
  * fresh one.
  *
  * @param coroutineContext An optional [CoroutineContext] to replace the dispatcher [block] is
- * invoked on.
+ *   invoked on.
  * @param block The block of code that should be run when the view becomes attached. It can end up
- * being invoked multiple times if the view is reattached after being detached.
+ *   being invoked multiple times if the view is reattached after being detached.
  * @return A [DisposableHandle] to invoke when the caller of the function destroys its [View] and is
- * no longer interested in the [block] being run the next time its attached. Calling this is an
- * optional optimization as the logic will be properly cleaned up and destroyed each time the view
- * is detached. Using this is not *thread-safe* and should only be used on the main thread.
+ *   no longer interested in the [block] being run the next time its attached. Calling this is an
+ *   optional optimization as the logic will be properly cleaned up and destroyed each time the view
+ *   is detached. Using this is not *thread-safe* and should only be used on the main thread.
  */
 @MainThread
 fun View.repeatWhenAttached(
@@ -125,7 +125,6 @@
  * The implementation requires the caller to call [onCreate] and [onDestroy] when the view is
  * attached to or detached from a view hierarchy. After [onCreate] and before [onDestroy] is called,
  * the implementation monitors window state in the following way
- *
  * * If the window is not visible, we are in the [Lifecycle.State.CREATED] state
  * * If the window is visible but not focused, we are in the [Lifecycle.State.STARTED] state
  * * If the window is visible and focused, we are in the [Lifecycle.State.RESUMED] state
diff --git a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
index f7349a2..647e3a1 100644
--- a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
@@ -16,7 +16,6 @@
  * Helper class for logging for [com.android.keyguard.faceauth.KeyguardFaceAuthManager]
  *
  * To enable logcat echoing for an entire buffer:
- *
  * ```
  *   adb shell settings put global systemui/buffer/KeyguardFaceAuthManagerLog <logLevel>
  *
diff --git a/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt b/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt
index 5acaa46..edc278d 100644
--- a/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt
@@ -33,7 +33,6 @@
  * Helper class for logging for [com.android.systemui.ScreenDecorations]
  *
  * To enable logcat echoing for an entire buffer:
- *
  * ```
  *   adb shell settings put global systemui/buffer/ScreenDecorationsLog <logLevel>
  *
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl b/packages/SystemUI/src/com/android/systemui/log/dagger/DeviceStateAutoRotationLog.java
similarity index 66%
copy from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
copy to packages/SystemUI/src/com/android/systemui/log/dagger/DeviceStateAutoRotationLog.java
index 35d5c15..beb725e 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/DeviceStateAutoRotationLog.java
@@ -14,6 +14,17 @@
  * limitations under the License.
  */
 
-package android.net.wifi.sharedconnectivity.app;
+package com.android.systemui.log.dagger;
 
-parcelable DeviceInfo;
\ No newline at end of file
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface DeviceStateAutoRotationLog {
+}
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 220993f..d246b35e 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -62,6 +62,15 @@
         return factory.create("NotifLog", maxSize, false /* systrace */);
     }
 
+    /** Provides a logging buffer for all logs related to notifications on the lockscreen. */
+    @Provides
+    @SysUISingleton
+    @NotificationLockscreenLog
+    public static LogBuffer provideNotificationLockScreenLogBuffer(
+            LogBufferFactory factory) {
+        return factory.create("NotifLockscreenLog", 50, false /* systrace */);
+    }
+
     /** Provides a logging buffer for logs related to heads up presentation of notifications. */
     @Provides
     @SysUISingleton
@@ -361,6 +370,16 @@
     }
 
     /**
+     * Provides a {@link LogBuffer} for Device State Auto-Rotation logs.
+     */
+    @Provides
+    @SysUISingleton
+    @DeviceStateAutoRotationLog
+    public static LogBuffer provideDeviceStateAutoRotationLogBuffer(LogBufferFactory factory) {
+        return factory.create("DeviceStateAutoRotationLog", 100);
+    }
+
+    /**
      * Provides a {@link LogBuffer} for bluetooth-related logs.
      */
     @Provides
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLockscreenLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLockscreenLog.java
new file mode 100644
index 0000000..a2d381e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLockscreenLog.java
@@ -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.log.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.android.systemui.plugins.log.LogBuffer;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+/** A {@link LogBuffer} for notification & lockscreen related messages. */
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface NotificationLockscreenLog {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableChange.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableChange.kt
index 4880f80..b73ddc5 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableChange.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableChange.kt
@@ -59,6 +59,17 @@
         int = value
     }
 
+    /** Updates this to store the same value as [change]. */
+    fun updateTo(change: TableChange) {
+        reset(change.timestamp, change.columnPrefix, change.columnName)
+        when (change.type) {
+            DataType.STRING -> set(change.str)
+            DataType.INT -> set(change.int)
+            DataType.BOOLEAN -> set(change.bool)
+            DataType.EMPTY -> {}
+        }
+    }
+
     /** Returns true if this object has a change. */
     fun hasData(): Boolean {
         return columnName.isNotBlank() && type != DataType.EMPTY
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
index 1712dab..a0f1c95 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
@@ -16,20 +16,19 @@
 
 package com.android.systemui.log.table
 
+import android.os.Trace
 import com.android.systemui.Dumpable
 import com.android.systemui.plugins.util.RingBuffer
 import com.android.systemui.util.time.SystemClock
 import java.io.PrintWriter
 import java.text.SimpleDateFormat
 import java.util.Locale
-import kotlinx.coroutines.flow.Flow
 
 /**
  * A logger that logs changes in table format.
  *
  * Some parts of System UI maintain a lot of pieces of state at once.
  * [com.android.systemui.plugins.log.LogBuffer] allows us to easily log change events:
- *
  * - 10-10 10:10:10.456: state2 updated to newVal2
  * - 10-10 10:11:00.000: stateN updated to StateN(val1=true, val2=1)
  * - 10-10 10:11:02.123: stateN updated to StateN(val1=true, val2=2)
@@ -37,7 +36,6 @@
  * - 10-10 10:11:06.000: stateN updated to StateN(val1=false, val2=3)
  *
  * However, it can sometimes be more useful to view the state changes in table format:
- *
  * - timestamp--------- | state1- | state2- | ... | stateN.val1 | stateN.val2
  * - -------------------------------------------------------------------------
  * - 10-10 10:10:10.123 | val1--- | val2--- | ... | false------ | 0-----------
@@ -56,23 +54,18 @@
  * individual fields.
  *
  * How it works:
- *
  * 1) Create an instance of this buffer via [TableLogBufferFactory].
- *
  * 2) For any states being logged, implement [Diffable]. Implementing [Diffable] allows the state to
- * only log the fields that have *changed* since the previous update, instead of always logging all
- * fields.
- *
+ *    only log the fields that have *changed* since the previous update, instead of always logging
+ *    all fields.
  * 3) Each time a change in a state happens, call [logDiffs]. If your state is emitted using a
- * [Flow], you should use the [logDiffsForTable] extension function to automatically log diffs any
- * time your flow emits a new value.
+ *    [Flow], you should use the [logDiffsForTable] extension function to automatically log diffs
+ *    any time your flow emits a new value.
  *
  * When a dump occurs, there will be two dumps:
- *
  * 1) The change events under the dumpable name "$name-changes".
- *
  * 2) This class will coalesce all the diffs into a table format and log them under the dumpable
- * name "$name-table".
+ *    name "$name-table".
  *
  * @param maxSize the maximum size of the buffer. Must be > 0.
  */
@@ -89,6 +82,19 @@
 
     private val buffer = RingBuffer(maxSize) { TableChange() }
 
+    // Stores the most recently evicted value for each column name (indexed on column name).
+    //
+    // Why it's necessary: Because we use a RingBuffer of a fixed size, it's possible that a column
+    // that's logged infrequently will eventually get pushed out by a different column that's
+    // logged more frequently. Then, that infrequently-logged column isn't present in the RingBuffer
+    // at all and we have no logs that the column ever existed. This is a problem because the
+    // column's information is still relevant, valid, and may be critical to debugging issues.
+    //
+    // Fix: When a change is being evicted from the RingBuffer, we store it in this map (based on
+    // its [TableChange.getName()]. This ensures that we always have at least one value for every
+    // column ever logged. See b/272016422 for more details.
+    private val lastEvictedValues = mutableMapOf<String, TableChange>()
+
     // A [TableRowLogger] object, re-used each time [logDiffs] is called.
     // (Re-used to avoid object allocation.)
     private val tempRow = TableRowLoggerImpl(0, columnPrefix = "", this)
@@ -99,11 +105,10 @@
      * The [newVal] object's method [Diffable.logDiffs] will be used to fetch the diffs.
      *
      * @param columnPrefix a prefix that will be applied to every column name that gets logged. This
-     * ensures that all the columns related to the same state object will be grouped together in the
-     * table.
-     *
+     *   ensures that all the columns related to the same state object will be grouped together in
+     *   the table.
      * @throws IllegalArgumentException if [columnPrefix] or column name contain "|". "|" is used as
-     * the separator token for parsing, so it can't be present in any part of the column name.
+     *   the separator token for parsing, so it can't be present in any part of the column name.
      */
     @Synchronized
     fun <T : Diffable<T>> logDiffs(columnPrefix: String, prevVal: T, newVal: T) {
@@ -117,7 +122,7 @@
      * Logs change(s) to the buffer using [rowInitializer].
      *
      * @param rowInitializer a function that will be called immediately to store relevant data on
-     * the row.
+     *   the row.
      */
     @Synchronized
     fun logChange(columnPrefix: String, rowInitializer: (TableRowLogger) -> Unit) {
@@ -146,18 +151,24 @@
     // timestamps.)
 
     private fun logChange(timestamp: Long, prefix: String, columnName: String, value: String?) {
+        Trace.beginSection("TableLogBuffer#logChange(string)")
         val change = obtain(timestamp, prefix, columnName)
         change.set(value)
+        Trace.endSection()
     }
 
     private fun logChange(timestamp: Long, prefix: String, columnName: String, value: Boolean) {
+        Trace.beginSection("TableLogBuffer#logChange(boolean)")
         val change = obtain(timestamp, prefix, columnName)
         change.set(value)
+        Trace.endSection()
     }
 
     private fun logChange(timestamp: Long, prefix: String, columnName: String, value: Int?) {
+        Trace.beginSection("TableLogBuffer#logChange(int)")
         val change = obtain(timestamp, prefix, columnName)
         change.set(value)
+        Trace.endSection()
     }
 
     // TODO(b/259454430): Add additional change types here.
@@ -166,6 +177,9 @@
     private fun obtain(timestamp: Long, prefix: String, columnName: String): TableChange {
         verifyValidName(prefix, columnName)
         val tableChange = buffer.advance()
+        if (tableChange.hasData()) {
+            saveEvictedValue(tableChange)
+        }
         tableChange.reset(timestamp, prefix, columnName)
         return tableChange
     }
@@ -181,10 +195,23 @@
         }
     }
 
+    private fun saveEvictedValue(change: TableChange) {
+        Trace.beginSection("TableLogBuffer#saveEvictedValue")
+        val name = change.getName()
+        val previouslyEvicted =
+            lastEvictedValues[name] ?: TableChange().also { lastEvictedValues[name] = it }
+        // For recycling purposes, update the existing object in the map with the new information
+        // instead of creating a new object.
+        previouslyEvicted.updateTo(change)
+        Trace.endSection()
+    }
+
     @Synchronized
     override fun dump(pw: PrintWriter, args: Array<out String>) {
         pw.println(HEADER_PREFIX + name)
         pw.println("version $VERSION")
+
+        lastEvictedValues.values.sortedBy { it.timestamp }.forEach { it.dump(pw) }
         for (i in 0 until buffer.size) {
             buffer[i].dump(pw)
         }
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
index 7ccc43c..06668d3 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
@@ -38,7 +38,6 @@
      *
      * @param name a unique table name
      * @param maxSize the buffer max size. See [adjustMaxSize]
-     *
      * @return a new [TableLogBuffer] registered with [DumpManager]
      */
     fun create(
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarViewModel.kt
index a057c9f..2509f21 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarViewModel.kt
@@ -187,6 +187,7 @@
 
     /**
      * Handle request to change the current position in the media track.
+     *
      * @param position Place to seek to in the track.
      */
     @AnyThread
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt b/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt
index 0b57175..ae03f27 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt
@@ -52,6 +52,7 @@
      * Indicates if all the data is valid.
      *
      * TODO(b/230333302): Make MediaControlPanel more flexible so that we can display fewer than
+     *
      * ```
      *     [NUM_REQUIRED_RECOMMENDATIONS].
      * ```
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt
index 97717a6..207df6b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt
@@ -329,9 +329,8 @@
      * Return the time since last active for the most-recent media.
      *
      * @param sortedEntries userEntries sorted from the earliest to the most-recent.
-     *
      * @return The duration in milliseconds from the most-recent media's last active timestamp to
-     * the present. MAX_VALUE will be returned if there is no media.
+     *   the present. MAX_VALUE will be returned if there is no media.
      */
     private fun timeSinceActiveForMostRecentMedia(
         sortedEntries: SortedMap<String, MediaData>
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
index af60e0e..4cc0410 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
@@ -526,8 +526,8 @@
      * through the internal listener pipeline.
      *
      * @param immediately indicates should apply the UI changes immediately, otherwise wait until
-     * the next refresh-round before UI becomes visible. Should only be true if the update is
-     * initiated by user's interaction.
+     *   the next refresh-round before UI becomes visible. Should only be true if the update is
+     *   initiated by user's interaction.
      */
     private fun notifySmartspaceMediaDataRemoved(key: String, immediately: Boolean) {
         internalListeners.forEach { it.onSmartspaceMediaDataRemoved(key, immediately) }
@@ -536,6 +536,7 @@
     /**
      * Called whenever the player has been paused or stopped for a while, or swiped from QQS. This
      * will make the player not active anymore, hiding it from QQS and Keyguard.
+     *
      * @see MediaData.active
      */
     internal fun setTimedOut(key: String, timedOut: Boolean, forceUpdate: Boolean = false) {
@@ -1024,6 +1025,7 @@
      * @param packageName Package name for the media app
      * @param controller MediaController for the current session
      * @return a Pair consisting of a list of media actions, and a list of ints representing which
+     *
      * ```
      *      of those actions should be shown in the compact player
      * ```
@@ -1127,6 +1129,7 @@
      *      [PlaybackState.ACTION_SKIP_TO_NEXT]
      * @return
      * ```
+     *
      * A [MediaAction] with correct values set, or null if the state doesn't support it
      */
     private fun getStandardAction(
@@ -1229,6 +1232,7 @@
     }
     /**
      * Load a bitmap from a URI
+     *
      * @param uri the uri to load
      * @return bitmap, or null if couldn't be loaded
      */
@@ -1342,10 +1346,9 @@
     fun onNotificationRemoved(key: String) {
         Assert.isMainThread()
         val removed = mediaEntries.remove(key) ?: return
-
         if (keyguardUpdateMonitor.isUserInLockdown(removed.userId)) {
             logger.logMediaRemoved(removed.appUid, removed.packageName, removed.instanceId)
-        } else if (useMediaResumption && removed.resumeAction != null && removed.isLocalSession()) {
+        } else if (isAbleToResume(removed)) {
             convertToResumePlayer(key, removed)
         } else if (mediaFlags.isRetainingPlayersEnabled()) {
             handlePossibleRemoval(key, removed, notificationRemoved = true)
@@ -1365,6 +1368,14 @@
         handlePossibleRemoval(key, updated)
     }
 
+    private fun isAbleToResume(data: MediaData): Boolean {
+        val isEligibleForResume =
+            data.isLocalSession() ||
+                (mediaFlags.isRemoteResumeAllowed() &&
+                    data.playbackLocation != MediaData.PLAYBACK_CAST_REMOTE)
+        return useMediaResumption && data.resumeAction != null && isEligibleForResume
+    }
+
     /**
      * Convert to resume state if the player is no longer valid and active, then notify listeners
      * that the data was updated. Does not convert to resume state if the player is still valid, or
@@ -1387,8 +1398,9 @@
             if (DEBUG) Log.d(TAG, "Session destroyed but using notification actions $key")
             mediaEntries.put(key, removed)
             notifyMediaDataLoaded(key, key, removed)
-        } else if (removed.active) {
-            // This player was still active - it didn't last long enough to time out: remove
+        } else if (removed.active && !isAbleToResume(removed)) {
+            // This player was still active - it didn't last long enough to time out,
+            // and its app doesn't normally support resume: remove
             if (DEBUG) Log.d(TAG, "Removing still-active player $key")
             notifyMediaDataRemoved(key)
             logger.logMediaRemoved(removed.appUid, removed.packageName, removed.instanceId)
@@ -1519,15 +1531,13 @@
          * notification key) or vice versa.
          *
          * @param immediately indicates should apply the UI changes immediately, otherwise wait
-         * until the next refresh-round before UI becomes visible. True by default to take in place
-         * immediately.
-         *
+         *   until the next refresh-round before UI becomes visible. True by default to take in
+         *   place immediately.
          * @param receivedSmartspaceCardLatency is the latency between headphone connects and sysUI
-         * displays Smartspace media targets. Will be 0 if the data is not activated by Smartspace
-         * signal.
-         *
+         *   displays Smartspace media targets. Will be 0 if the data is not activated by Smartspace
+         *   signal.
          * @param isSsReactivated indicates resume media card is reactivated by Smartspace
-         * recommendation signal
+         *   recommendation signal
          */
         fun onMediaDataLoaded(
             key: String,
@@ -1542,8 +1552,8 @@
          * Called whenever there's new Smartspace media data loaded.
          *
          * @param shouldPrioritize indicates the sorting priority of the Smartspace card. If true,
-         * it will be prioritized as the first card. Otherwise, it will show up as the last card as
-         * default.
+         *   it will be prioritized as the first card. Otherwise, it will show up as the last card
+         *   as default.
          */
         fun onSmartspaceMediaDataLoaded(
             key: String,
@@ -1558,8 +1568,8 @@
          * Called whenever a previously existing Smartspace media data was removed.
          *
          * @param immediately indicates should apply the UI changes immediately, otherwise wait
-         * until the next refresh-round before UI becomes visible. True by default to take in place
-         * immediately.
+         *   until the next refresh-round before UI becomes visible. True by default to take in
+         *   place immediately.
          */
         fun onSmartspaceMediaDataRemoved(key: String, immediately: Boolean = true) {}
     }
@@ -1568,7 +1578,7 @@
      * Converts the pass-in SmartspaceTarget to SmartspaceMediaData
      *
      * @return An empty SmartspaceMediaData with the valid target Id is returned if the
-     * SmartspaceTarget's data is invalid.
+     *   SmartspaceTarget's data is invalid.
      */
     private fun toSmartspaceMediaData(target: SmartspaceTarget): SmartspaceMediaData {
         var dismissIntent: Intent? = null
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt
index 6a512be..120704c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt
@@ -408,9 +408,9 @@
  * [LocalMediaManager.DeviceCallback.onAboutToConnectDeviceAdded] for more information.
  *
  * @property fullMediaDevice a full-fledged [MediaDevice] object representing the device. If
- * non-null, prefer using [fullMediaDevice] over [backupMediaDeviceData].
+ *   non-null, prefer using [fullMediaDevice] over [backupMediaDeviceData].
  * @property backupMediaDeviceData a backup [MediaDeviceData] object containing the minimum
- * information required to display the device. Only use if [fullMediaDevice] is null.
+ *   information required to display the device. Only use if [fullMediaDevice] is null.
  */
 private data class AboutToConnectDevice(
     val fullMediaDevice: MediaDevice? = null,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListener.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListener.kt
index 878962d..a1d9214 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListener.kt
@@ -60,6 +60,7 @@
 
     /**
      * Callback representing that a media object is now expired:
+     *
      * @param key Media control unique identifier
      * @param timedOut True when expired for {@code PAUSED_MEDIA_TIMEOUT} for active media,
      * ```
@@ -70,6 +71,7 @@
 
     /**
      * Callback representing that a media object [PlaybackState] has changed.
+     *
      * @param key Media control unique identifier
      * @param state The new [PlaybackState]
      */
@@ -77,6 +79,7 @@
 
     /**
      * Callback representing that the [MediaSession] for an active control has been destroyed
+     *
      * @param key Media control unique identifier
      */
     lateinit var sessionCallback: (String) -> Unit
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt b/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt
index 2d10b82..b0389b5 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt
@@ -37,6 +37,7 @@
 import com.android.systemui.media.controls.models.player.MediaData
 import com.android.systemui.media.controls.pipeline.MediaDataManager
 import com.android.systemui.media.controls.pipeline.RESUME_MEDIA_TIMEOUT
+import com.android.systemui.media.controls.util.MediaFlags
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.tuner.TunerService
 import com.android.systemui.util.Utils
@@ -63,7 +64,8 @@
     private val tunerService: TunerService,
     private val mediaBrowserFactory: ResumeMediaBrowserFactory,
     dumpManager: DumpManager,
-    private val systemClock: SystemClock
+    private val systemClock: SystemClock,
+    private val mediaFlags: MediaFlags,
 ) : MediaDataManager.Listener, Dumpable {
 
     private var useMediaResumption: Boolean = Utils.useMediaResumption(context)
@@ -231,8 +233,14 @@
                 mediaBrowser = null
             }
             // If we don't have a resume action, check if we haven't already
-            if (data.resumeAction == null && !data.hasCheckedForResume && data.isLocalSession()) {
+            val isEligibleForResume =
+                data.isLocalSession() ||
+                    (mediaFlags.isRemoteResumeAllowed() &&
+                        data.playbackLocation != MediaData.PLAYBACK_CAST_REMOTE)
+            if (data.resumeAction == null && !data.hasCheckedForResume && isEligibleForResume) {
                 // TODO also check for a media button receiver intended for restarting (b/154127084)
+                // Set null action to prevent additional attempts to connect
+                mediaDataManager.setResumeAction(key, null)
                 Log.d(TAG, "Checking for service component for " + data.packageName)
                 val pm = context.packageManager
                 val serviceIntent = Intent(MediaBrowserService.SERVICE_INTERFACE)
@@ -243,9 +251,6 @@
                     backgroundExecutor.execute {
                         tryUpdateResumptionList(key, inf!!.get(0).componentInfo.componentName)
                     }
-                } else {
-                    // No service found
-                    mediaDataManager.setResumeAction(key, null)
                 }
             }
         }
@@ -257,8 +262,6 @@
      */
     private fun tryUpdateResumptionList(key: String, componentName: ComponentName) {
         Log.d(TAG, "Testing if we can connect to $componentName")
-        // Set null action to prevent additional attempts to connect
-        mediaDataManager.setResumeAction(key, null)
         mediaBrowser =
             mediaBrowserFactory.create(
                 object : ResumeMediaBrowser.Callback() {
@@ -291,6 +294,7 @@
     /**
      * Add the component to the saved list of media browser services, checking for duplicates and
      * removing older components that exceed the maximum limit
+     *
      * @param componentName
      */
     private fun updateResumptionList(componentName: ComponentName) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowser.java b/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowser.java
index 3493b24..d460b5b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowser.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowser.java
@@ -85,16 +85,13 @@
      * ResumeMediaBrowser#disconnect will be called automatically with this function.
      */
     public void findRecentMedia() {
-        disconnect();
         Bundle rootHints = new Bundle();
         rootHints.putBoolean(MediaBrowserService.BrowserRoot.EXTRA_RECENT, true);
-        mMediaBrowser = mBrowserFactory.create(
+        MediaBrowser browser = mBrowserFactory.create(
                 mComponentName,
                 mConnectionCallback,
                 rootHints);
-        updateMediaController();
-        mLogger.logConnection(mComponentName, "findRecentMedia");
-        mMediaBrowser.connect();
+        connectBrowser(browser, "findRecentMedia");
     }
 
     private final MediaBrowser.SubscriptionCallback mSubscriptionCallback =
@@ -202,6 +199,21 @@
     };
 
     /**
+     * Connect using a new media browser. Disconnects the existing browser first, if it exists.
+     * @param browser media browser to connect
+     * @param reason Reason to log for connection
+     */
+    private void connectBrowser(MediaBrowser browser, String reason) {
+        mLogger.logConnection(mComponentName, reason);
+        disconnect();
+        mMediaBrowser = browser;
+        if (browser != null) {
+            browser.connect();
+        }
+        updateMediaController();
+    }
+
+    /**
      * Disconnect the media browser. This should be done after callbacks have completed to
      * disconnect from the media browser service.
      */
@@ -222,10 +234,9 @@
      * getting a media update from the app
      */
     public void restart() {
-        disconnect();
         Bundle rootHints = new Bundle();
         rootHints.putBoolean(MediaBrowserService.BrowserRoot.EXTRA_RECENT, true);
-        mMediaBrowser = mBrowserFactory.create(mComponentName,
+        MediaBrowser browser = mBrowserFactory.create(mComponentName,
                 new MediaBrowser.ConnectionCallback() {
                     @Override
                     public void onConnected() {
@@ -265,9 +276,7 @@
                         disconnect();
                     }
                 }, rootHints);
-        updateMediaController();
-        mLogger.logConnection(mComponentName, "restart");
-        mMediaBrowser.connect();
+        connectBrowser(browser, "restart");
     }
 
     @VisibleForTesting
@@ -305,16 +314,13 @@
      * ResumeMediaBrowser#disconnect should be called after this to ensure the connection is closed.
      */
     public void testConnection() {
-        disconnect();
         Bundle rootHints = new Bundle();
         rootHints.putBoolean(MediaBrowserService.BrowserRoot.EXTRA_RECENT, true);
-        mMediaBrowser = mBrowserFactory.create(
+        MediaBrowser browser = mBrowserFactory.create(
                 mComponentName,
                 mConnectionCallback,
                 rootHints);
-        updateMediaController();
-        mLogger.logConnection(mComponentName, "testConnection");
-        mMediaBrowser.connect();
+        connectBrowser(browser, "testConnection");
     }
 
     /** Updates mMediaController based on our current browser values. */
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt b/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt
index 335ce1d..095cf09 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt
@@ -52,10 +52,12 @@
      * event.
      *
      * @param isBrowserConnected true if there's a currently connected
+     *
      * ```
      *     [android.media.browse.MediaBrowser] and false otherwise.
      * @param componentName
      * ```
+     *
      * the component name for the [ResumeMediaBrowser] that triggered this log.
      */
     fun logSessionDestroyed(isBrowserConnected: Boolean, componentName: ComponentName) =
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/AnimationBindHandler.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/AnimationBindHandler.kt
index d2793bc..f5cc043 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/AnimationBindHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/AnimationBindHandler.kt
@@ -24,10 +24,12 @@
  * and conflicts due to media notifications arriving at any time during an animation. It does this
  * in two parts.
  * - Exit animations fired as a result of user input are tracked. When these are running, any
+ *
  * ```
  *      bind actions are delayed until the animation completes (and then fired in sequence).
  * ```
  * - Continuous animations are tracked using their rebind id. Later calls using the same
+ *
  * ```
  *      rebind id will be totally ignored to prevent the continuous animation from restarting.
  * ```
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 4827a16..2b42604 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
@@ -201,7 +201,9 @@
         animatingColorTransitionFactory(
             loadDefaultColor(R.attr.textColorSecondary),
             ::textSecondaryFromScheme
-        ) { textSecondary -> mediaViewHolder.artistText.setTextColor(textSecondary) }
+        ) { textSecondary ->
+            mediaViewHolder.artistText.setTextColor(textSecondary)
+        }
 
     val textTertiary =
         animatingColorTransitionFactory(
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt
index 9f86cd8..3669493 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt
@@ -159,6 +159,7 @@
 
     /**
      * Cross fade background.
+     *
      * @see setTintList
      * @see backgroundColor
      */
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 6cf051a..67d3be4 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
@@ -197,7 +197,6 @@
 
     private val configListener =
         object : ConfigurationController.ConfigurationListener {
-            var lastOrientation = -1
 
             override fun onDensityOrFontScaleChanged() {
                 // System font changes should only happen when UMO is offscreen or a flicker may
@@ -214,13 +213,6 @@
             override fun onConfigChanged(newConfig: Configuration?) {
                 if (newConfig == null) return
                 isRtl = newConfig.layoutDirection == View.LAYOUT_DIRECTION_RTL
-                val newOrientation = newConfig.orientation
-                if (lastOrientation != newOrientation) {
-                    // The players actually depend on the orientation possibly, so we have to
-                    // recreate them (at least on large screen devices)
-                    lastOrientation = newOrientation
-                    updatePlayers(recreateMedia = true)
-                }
             }
 
             override fun onUiModeChanged() {
@@ -853,10 +845,12 @@
      * @param startLocation the start location of our state or -1 if this is directly set
      * @param endLocation the ending location of our state.
      * @param progress the progress of the transition between startLocation and endlocation. If
+     *
      * ```
      *                 this is not a guided transformation, this will be 1.0f
      * @param immediately
      * ```
+     *
      * should this state be applied immediately, canceling all animations?
      */
     fun setCurrentState(
@@ -1100,17 +1094,17 @@
      *
      * @param eventId UI event id (e.g. 800 for SMARTSPACE_CARD_SEEN)
      * @param instanceId id to uniquely identify a card, e.g. each headphone generates a new
-     * instanceId
+     *   instanceId
      * @param uid uid for the application that media comes from
      * @param surfaces list of display surfaces the media card is on (e.g. lockscreen, shade) when
-     * the event happened
+     *   the event happened
      * @param interactedSubcardRank the rank for interacted media item for recommendation card, -1
-     * for tapping on card but not on any media item, 0 for first media item, 1 for second, etc.
+     *   for tapping on card but not on any media item, 0 for first media item, 1 for second, etc.
      * @param interactedSubcardCardinality how many media items were shown to the user when there is
-     * user interaction
+     *   user interaction
      * @param rank the rank for media card in the media carousel, starting from 0
      * @param receivedLatencyMillis latency in milliseconds for card received events. E.g. latency
-     * between headphone connection to sysUI displays media recommendation card
+     *   between headphone connection to sysUI displays media recommendation card
      * @param isSwipeToDismiss whether is to log swipe-to-dismiss event
      */
     fun logSmartspaceCardReported(
@@ -1371,6 +1365,7 @@
 
     /**
      * Removes media player given the key.
+     *
      * @param isDismissed determines whether the media player is removed from the carousel.
      */
     fun removeMediaPlayer(key: String, isDismissed: Boolean = false) =
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
index 097cc3e..a31c1e5 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
@@ -32,12 +32,15 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.res.ColorStateList;
+import android.graphics.Bitmap;
 import android.graphics.BlendMode;
 import android.graphics.Color;
 import android.graphics.ColorMatrix;
 import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Matrix;
 import android.graphics.Rect;
 import android.graphics.drawable.Animatable;
+import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.GradientDrawable;
@@ -63,7 +66,6 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.UiThread;
-import androidx.appcompat.content.res.AppCompatResources;
 import androidx.constraintlayout.widget.ConstraintSet;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -146,6 +148,12 @@
     private static final int SMARTSPACE_CARD_CLICK_EVENT = 760;
     protected static final int SMARTSPACE_CARD_DISMISS_EVENT = 761;
 
+    private static final float REC_MEDIA_COVER_SCALE_FACTOR = 1.25f;
+    private static final float MEDIA_SCRIM_START_ALPHA = 0.25f;
+    private static final float MEDIA_REC_SCRIM_START_ALPHA = 0.15f;
+    private static final float MEDIA_PLAYER_SCRIM_END_ALPHA = 0.9f;
+    private static final float MEDIA_REC_SCRIM_END_ALPHA = 1.0f;
+
     private static final Intent SETTINGS_INTENT = new Intent(ACTION_MEDIA_CONTROLS_SETTINGS);
 
     // Buttons to show in small player when using semantic actions
@@ -779,7 +787,7 @@
             WallpaperColors wallpaperColors = getWallpaperColor(artworkIcon);
             if (wallpaperColors != null) {
                 mutableColorScheme = new ColorScheme(wallpaperColors, true, Style.CONTENT);
-                artwork = addGradientToIcon(artworkIcon, mutableColorScheme, width, height);
+                artwork = addGradientToPlayerAlbum(artworkIcon, mutableColorScheme, width, height);
                 isArtworkBound = true;
             } else {
                 // If there's no artwork, use colors from the app icon
@@ -869,8 +877,9 @@
         Trace.beginAsyncSection(traceName, traceCookie);
 
         // Capture width & height from views in foreground for artwork scaling in background
-        int width = mRecommendationViewHolder.getMediaCoverContainers().get(0).getMeasuredWidth();
-        int height = mRecommendationViewHolder.getMediaCoverContainers().get(0).getMeasuredHeight();
+        int width = mContext.getResources().getDimensionPixelSize(R.dimen.qs_media_rec_album_width);
+        int height = mContext.getResources().getDimensionPixelSize(
+                R.dimen.qs_media_rec_album_height_expanded);
 
         mBackgroundExecutor.execute(() -> {
             // Album art
@@ -880,7 +889,8 @@
             WallpaperColors wallpaperColors = getWallpaperColor(artworkIcon);
             if (wallpaperColors != null) {
                 mutableColorScheme = new ColorScheme(wallpaperColors, true, Style.CONTENT);
-                artwork = addGradientToIcon(artworkIcon, mutableColorScheme, width, height);
+                artwork = addGradientToRecommendationAlbum(artworkIcon, mutableColorScheme, width,
+                        height);
             } else {
                 artwork = new ColorDrawable(Color.TRANSPARENT);
             }
@@ -889,6 +899,11 @@
                 // Bind the artwork drawable to media cover.
                 ImageView mediaCover =
                         mRecommendationViewHolder.getMediaCoverItems().get(itemIndex);
+                // Rescale media cover
+                Matrix coverMatrix = new Matrix(mediaCover.getImageMatrix());
+                coverMatrix.postScale(REC_MEDIA_COVER_SCALE_FACTOR, REC_MEDIA_COVER_SCALE_FACTOR,
+                        0.5f * width, 0.5f * height);
+                mediaCover.setImageMatrix(coverMatrix);
                 mediaCover.setImageDrawable(artwork);
 
                 // Set up the app icon.
@@ -910,40 +925,62 @@
     // This method should be called from a background thread. WallpaperColors.fromBitmap takes a
     // good amount of time. We do that work on the background executor to avoid stalling animations
     // on the UI Thread.
-    private WallpaperColors getWallpaperColor(Icon artworkIcon) {
+    @VisibleForTesting
+    protected WallpaperColors getWallpaperColor(Icon artworkIcon) {
         if (artworkIcon != null) {
             if (artworkIcon.getType() == Icon.TYPE_BITMAP
                     || artworkIcon.getType() == Icon.TYPE_ADAPTIVE_BITMAP) {
                 // Avoids extra processing if this is already a valid bitmap
-                return WallpaperColors
-                        .fromBitmap(artworkIcon.getBitmap());
+                Bitmap artworkBitmap = artworkIcon.getBitmap();
+                if (artworkBitmap.isRecycled()) {
+                    Log.d(TAG, "Cannot load wallpaper color from a recycled bitmap");
+                    return null;
+                }
+                return WallpaperColors.fromBitmap(artworkBitmap);
             } else {
                 Drawable artworkDrawable = artworkIcon.loadDrawable(mContext);
                 if (artworkDrawable != null) {
-                    return WallpaperColors
-                            .fromDrawable(artworkIcon.loadDrawable(mContext));
+                    return WallpaperColors.fromDrawable(artworkDrawable);
                 }
             }
         }
         return null;
     }
 
-    private LayerDrawable addGradientToIcon(
-            Icon artworkIcon,
-            ColorScheme mutableColorScheme,
-            int width,
-            int height
-    ) {
+    @VisibleForTesting
+    protected LayerDrawable addGradientToPlayerAlbum(Icon artworkIcon,
+            ColorScheme mutableColorScheme, int width, int height) {
         Drawable albumArt = getScaledBackground(artworkIcon, width, height);
-        GradientDrawable gradient = (GradientDrawable) AppCompatResources
-                .getDrawable(mContext, R.drawable.qs_media_scrim);
+        GradientDrawable gradient = (GradientDrawable) mContext.getDrawable(
+                R.drawable.qs_media_scrim).mutate();
+        return setupGradientColorOnDrawable(albumArt, gradient, mutableColorScheme,
+                MEDIA_SCRIM_START_ALPHA, MEDIA_PLAYER_SCRIM_END_ALPHA);
+    }
+
+    @VisibleForTesting
+    protected LayerDrawable addGradientToRecommendationAlbum(Icon artworkIcon,
+            ColorScheme mutableColorScheme, int width, int height) {
+        // First try scaling rec card using bitmap drawable.
+        // If returns null, set drawable bounds.
+        Drawable albumArt = getScaledRecommendationCover(artworkIcon, width, height);
+        if (albumArt == null) {
+            albumArt = getScaledBackground(artworkIcon, width, height);
+        }
+        GradientDrawable gradient = (GradientDrawable) mContext.getDrawable(
+                R.drawable.qs_media_rec_scrim).mutate();
+        return setupGradientColorOnDrawable(albumArt, gradient, mutableColorScheme,
+                MEDIA_REC_SCRIM_START_ALPHA, MEDIA_REC_SCRIM_END_ALPHA);
+    }
+
+    private LayerDrawable setupGradientColorOnDrawable(Drawable albumArt, GradientDrawable gradient,
+            ColorScheme mutableColorScheme, float startAlpha, float endAlpha) {
         gradient.setColors(new int[] {
                 ColorUtilKt.getColorWithAlpha(
                         MediaColorSchemesKt.backgroundStartFromScheme(mutableColorScheme),
-                        0.25f),
+                        startAlpha),
                 ColorUtilKt.getColorWithAlpha(
                         MediaColorSchemesKt.backgroundEndFromScheme(mutableColorScheme),
-                        0.9f),
+                        endAlpha),
         });
         return new LayerDrawable(new Drawable[] { albumArt, gradient });
     }
@@ -1589,6 +1626,29 @@
     }
 
     /**
+     * Scale artwork to fill the background of media covers in recommendation card.
+     */
+    @UiThread
+    private Drawable getScaledRecommendationCover(Icon artworkIcon, int width, int height) {
+        if (width == 0 || height == 0) {
+            return null;
+        }
+        if (artworkIcon != null) {
+            Bitmap bitmap;
+            if (artworkIcon.getType() == Icon.TYPE_BITMAP
+                    || artworkIcon.getType() == Icon.TYPE_ADAPTIVE_BITMAP) {
+                Bitmap artworkBitmap = artworkIcon.getBitmap();
+                if (artworkBitmap != null) {
+                    bitmap = Bitmap.createScaledBitmap(artworkIcon.getBitmap(), width,
+                            height, false);
+                    return new BitmapDrawable(mContext.getResources(), bitmap);
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
      * Get the current media controller
      *
      * @return the controller
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt
index 66f12d6..e10d74d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt
@@ -28,7 +28,6 @@
 import android.os.Handler
 import android.os.UserHandle
 import android.provider.Settings
-import android.util.Log
 import android.util.MathUtils
 import android.view.View
 import android.view.ViewGroup
@@ -418,8 +417,8 @@
      * Calculate the alpha of the view when given a cross-fade progress.
      *
      * @param crossFadeProgress The current cross fade progress. 0.5f means it's just switching
-     * between the start and the end location and the content is fully faded, while 0.75f means that
-     * we're halfway faded in again in the target state.
+     *   between the start and the end location and the content is fully faded, while 0.75f means
+     *   that we're halfway faded in again in the target state.
      */
     private fun calculateAlphaFromCrossFade(crossFadeProgress: Float): Float {
         if (crossFadeProgress <= 0.5f) {
@@ -629,6 +628,7 @@
      *
      * @param forceNoAnimation optional parameter telling the system not to animate
      * @param forceStateUpdate optional parameter telling the system to update transition state
+     *
      * ```
      *                         even if location did not change
      * ```
@@ -639,7 +639,9 @@
     ) =
         traceSection("MediaHierarchyManager#updateDesiredLocation") {
             val desiredLocation = calculateLocation()
-            if (desiredLocation != this.desiredLocation || forceStateUpdate) {
+            if (
+                desiredLocation != this.desiredLocation || forceStateUpdate && !blockLocationChanges
+            ) {
                 if (this.desiredLocation >= 0 && desiredLocation != this.desiredLocation) {
                     // Only update previous location when it actually changes
                     previousLocation = this.desiredLocation
@@ -944,7 +946,7 @@
 
     /**
      * @return the current transformation progress if we're in a guided transformation and -1
-     * otherwise
+     *   otherwise
      */
     private fun getTransformationProgress(): Float {
         if (skipQqsOnExpansion) {
@@ -1055,17 +1057,6 @@
                     // This will either do a full layout pass and remeasure, or it will bypass
                     // that and directly set the mediaFrame's bounds within the premeasured host.
                     targetHost.addView(mediaFrame)
-
-                    if (mediaFrame.childCount > 0) {
-                        val child = mediaFrame.getChildAt(0)
-                        if (mediaFrame.height < child.height) {
-                            Log.wtf(
-                                TAG,
-                                "mediaFrame height is too small for child: " +
-                                    "${mediaFrame.height} vs ${child.height}"
-                            )
-                        }
-                    }
                 }
                 if (isCrossFadeAnimatorRunning) {
                     // When cross-fading with an animation, we only notify the media carousel of the
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt
index 455b7de..be570b4 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt
@@ -126,6 +126,7 @@
      * remeasurings later on.
      *
      * @param location the location this host name has. Used to identify the host during
+     *
      * ```
      *                 transitions.
      * ```
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt
index b9b0459..b4724dd 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt
@@ -154,9 +154,11 @@
             return transitionLayout?.translationY ?: 0.0f
         }
 
-    /** A callback for RTL config changes */
+    /** A callback for config changes */
     private val configurationListener =
         object : ConfigurationController.ConfigurationListener {
+            var lastOrientation = -1
+
             override fun onConfigChanged(newConfig: Configuration?) {
                 // Because the TransitionLayout is not always attached (and calculates/caches layout
                 // results regardless of attach state), we have to force the layoutDirection of the
@@ -169,6 +171,13 @@
                         transitionLayout?.layoutDirection = layoutDirection
                         refreshState()
                     }
+                    val newOrientation = newConfig.orientation
+                    if (lastOrientation != newOrientation) {
+                        // Layout dimensions are possibly changing, so we need to update them. (at
+                        // least on large screen devices)
+                        lastOrientation = newOrientation
+                        loadLayoutForType(type)
+                    }
                 }
             }
         }
@@ -195,13 +204,14 @@
      * The expanded constraint set used to render a expanded player. If it is modified, make sure to
      * call [refreshState]
      */
-    val collapsedLayout = ConstraintSet()
-
+    var collapsedLayout = ConstraintSet()
+        @VisibleForTesting set
     /**
      * The expanded constraint set used to render a collapsed player. If it is modified, make sure
      * to call [refreshState]
      */
-    val expandedLayout = ConstraintSet()
+    var expandedLayout = ConstraintSet()
+        @VisibleForTesting set
 
     /** Whether the guts are visible for the associated player. */
     var isGutsVisible = false
@@ -348,14 +358,17 @@
      * bottom of UMO reach the bottom of this group It will change to alpha 1.0 when the visible
      * bottom of UMO reach the top of the group below e.g.Album title, artist title and play-pause
      * button will change alpha together.
+     *
      * ```
      *     And their alpha becomes 1.0 when the visible bottom of UMO reach the top of controls,
      *     including progress bar, next button, previous button
      * ```
+     *
      * widgetGroupIds: a group of widgets have same state during UMO is squished,
      * ```
      *     e.g. Album title, artist title and play-pause button
      * ```
+     *
      * groupEndPosition: the height of UMO, when the height reaches this value,
      * ```
      *     widgets in this group should have 1.0 as alpha
@@ -363,6 +376,7 @@
      *         visible when the height of UMO reaches the top of controls group
      *         (progress bar, previous button and next button)
      * ```
+     *
      * squishedViewState: hold the widgetState of each widget, which will be modified
      * squishFraction: the squishFraction of UMO
      */
@@ -479,7 +493,7 @@
      */
     fun attach(transitionLayout: TransitionLayout, type: TYPE) =
         traceSection("MediaViewController#attach") {
-            updateMediaViewControllerType(type)
+            loadLayoutForType(type)
             logger.logMediaLocation("attach $type", currentStartLocation, currentEndLocation)
             this.transitionLayout = transitionLayout
             layoutController.attach(transitionLayout)
@@ -637,7 +651,7 @@
         return result
     }
 
-    private fun updateMediaViewControllerType(type: TYPE) {
+    private fun loadLayoutForType(type: TYPE) {
         this.type = type
 
         // These XML resources contain ConstraintSets that will apply to this player type's layout
@@ -665,7 +679,7 @@
      *
      * @param location Target
      * @param locationWhenHidden Location that will be used when the target is not
-     * [MediaHost.visible]
+     *   [MediaHost.visible]
      * @return State require for executing a transition, and also the respective [MediaHost].
      */
     private fun obtainViewStateForLocation(@MediaLocation location: Int): TransitionViewState? {
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
index c3fa76e..9bc66f6 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
@@ -61,4 +61,7 @@
 
     /** If true, do not automatically dismiss the recommendation card */
     fun isPersistentSsCardEnabled() = featureFlags.isEnabled(Flags.MEDIA_RETAIN_RECOMMENDATIONS)
+
+    /** Check whether we allow remote media to generate resume controls */
+    fun isRemoteResumeAllowed() = featureFlags.isEnabled(Flags.MEDIA_REMOTE_RESUME)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java
index e35575b..b5b1f0f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java
@@ -23,8 +23,6 @@
 
 import com.android.systemui.CoreStartable;
 import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.statusbar.CommandQueue;
 
 import javax.inject.Inject;
@@ -37,26 +35,19 @@
 
     private final CommandQueue mCommandQueue;
     private final MediaOutputDialogFactory mMediaOutputDialogFactory;
-    private final FeatureFlags mFeatureFlags;
 
     @Inject
     public MediaOutputSwitcherDialogUI(
             Context context,
             CommandQueue commandQueue,
-            MediaOutputDialogFactory mediaOutputDialogFactory,
-            FeatureFlags featureFlags) {
+            MediaOutputDialogFactory mediaOutputDialogFactory) {
         mCommandQueue = commandQueue;
         mMediaOutputDialogFactory = mediaOutputDialogFactory;
-        mFeatureFlags = featureFlags;
     }
 
     @Override
     public void start() {
-        if (mFeatureFlags.isEnabled(Flags.OUTPUT_SWITCHER_SHOW_API_ENABLED)) {
-            mCommandQueue.addCallback(this);
-        } else {
-            Log.w(TAG, "Show media output switcher is not enabled.");
-        }
+        mCommandQueue.addCallback(this);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt
index 720c44a..ee93c37 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt
@@ -43,7 +43,7 @@
          *
          * @param appPackageName the package name of the app playing the media.
          * @param onPackageNotFoundException a function run if a
-         * [PackageManager.NameNotFoundException] occurs.
+         *   [PackageManager.NameNotFoundException] occurs.
          * @param isReceiver indicates whether the icon is displayed in a receiver view.
          */
         fun getIconInfoFromPackageName(
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
index 537dbb9..d3efae4 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
@@ -23,7 +23,6 @@
 import com.android.internal.logging.UiEventLogger
 import com.android.systemui.R
 import com.android.systemui.common.shared.model.Text
-import com.android.systemui.temporarydisplay.DEFAULT_TIMEOUT_MILLIS
 
 /**
  * A class enumerating all the possible states of the media tap-to-transfer chip on the sender
@@ -34,8 +33,8 @@
  *   state should not have the chip be displayed.
  * @property transferStatus the transfer status that the chip state represents.
  * @property endItem the item that should be displayed in the end section of the chip.
- * @property timeout the amount of time this chip should display on the screen before it times out
- *   and disappears.
+ * @property timeoutLength how long the chip should display on the screen before it times out and
+ *   disappears.
  */
 enum class ChipStateSender(
     @StatusBarManager.MediaTransferSenderState val stateInt: Int,
@@ -43,7 +42,7 @@
     @StringRes val stringResId: Int?,
     val transferStatus: TransferStatus,
     val endItem: SenderEndItem?,
-    val timeout: Int = DEFAULT_TIMEOUT_MILLIS,
+    val timeoutLength: TimeoutLength = TimeoutLength.DEFAULT,
 ) {
     /**
      * A state representing that the two devices are close but not close enough to *start* a cast to
@@ -56,6 +55,9 @@
         R.string.media_move_closer_to_start_cast,
         transferStatus = TransferStatus.NOT_STARTED,
         endItem = null,
+        // Give this view more time in case the loading view takes a bit to come in. (We don't want
+        // this view to disappear and then the loading view to appear quickly afterwards.)
+        timeoutLength = TimeoutLength.LONG,
     ) {
         override fun isValidNextState(nextState: ChipStateSender): Boolean {
             return nextState == FAR_FROM_RECEIVER ||
@@ -75,6 +77,7 @@
         R.string.media_move_closer_to_end_cast,
         transferStatus = TransferStatus.NOT_STARTED,
         endItem = null,
+        timeoutLength = TimeoutLength.LONG,
     ) {
         override fun isValidNextState(nextState: ChipStateSender): Boolean {
             return nextState == FAR_FROM_RECEIVER ||
@@ -92,7 +95,9 @@
         R.string.media_transfer_playing_different_device,
         transferStatus = TransferStatus.IN_PROGRESS,
         endItem = SenderEndItem.Loading,
-        timeout = TRANSFER_TRIGGERED_TIMEOUT_MILLIS
+        // Give this view more time in case the succeeded/failed view takes a bit to come in. (We
+        // don't want this view to disappear and then the next view to appear quickly afterwards.)
+        timeoutLength = TimeoutLength.LONG,
     ) {
         override fun isValidNextState(nextState: ChipStateSender): Boolean {
             return nextState == FAR_FROM_RECEIVER ||
@@ -111,7 +116,7 @@
         R.string.media_transfer_playing_this_device,
         transferStatus = TransferStatus.IN_PROGRESS,
         endItem = SenderEndItem.Loading,
-        timeout = TRANSFER_TRIGGERED_TIMEOUT_MILLIS
+        timeoutLength = TimeoutLength.LONG,
     ) {
         override fun isValidNextState(nextState: ChipStateSender): Boolean {
             return nextState == FAR_FROM_RECEIVER ||
@@ -325,9 +330,16 @@
     ) : SenderEndItem()
 }
 
-// Give the Transfer*Triggered states a longer timeout since those states represent an active
-// process and we should keep the user informed about it as long as possible (but don't allow it to
-// continue indefinitely).
-private const val TRANSFER_TRIGGERED_TIMEOUT_MILLIS = 30000
+/** Represents how long the chip should be visible before it times out. */
+enum class TimeoutLength {
+    /** A default timeout used for temporary displays at the top of the screen. */
+    DEFAULT,
+    /**
+     * A longer timeout. Should be used when the status is pending (e.g. loading), so that the user
+     * remains informed about the process for longer and so that the UI has more time to resolve the
+     * pending state before disappearing.
+     */
+    LONG,
+}
 
 private const val TAG = "ChipStateSender"
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt
index 6bb6906..c7c72a9 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt
@@ -56,6 +56,9 @@
     private val uiEventLogger: MediaTttSenderUiEventLogger,
 ) : CoreStartable, Dumpable {
 
+    // Since the media transfer display is similar to a heads-up notification, use the same timeout.
+    private val defaultTimeout = context.resources.getInteger(R.integer.heads_up_notification_decay)
+
     // A map to store current chip state per id.
     private var stateMap: MutableMap<String, ChipStateSender> = mutableMapOf()
 
@@ -165,6 +168,12 @@
                 logger.logPackageNotFound(packageName)
             }
 
+        val timeout =
+            when (chipStateSender.timeoutLength) {
+                TimeoutLength.DEFAULT -> defaultTimeout
+                TimeoutLength.LONG -> 2 * defaultTimeout
+            }
+
         return ChipbarInfo(
             // Display the app's icon as the start icon
             startIcon = icon.toTintedIcon(),
@@ -191,7 +200,7 @@
             allowSwipeToDismiss = true,
             windowTitle = MediaTttUtils.WINDOW_TITLE_SENDER,
             wakeReason = MediaTttUtils.WAKE_REASON_SENDER,
-            timeoutMs = chipStateSender.timeout,
+            timeoutMs = timeout,
             id = routeInfo.id,
             priority = ViewPriority.NORMAL,
         )
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt
index 7a77c47..01398cf 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt
@@ -70,6 +70,8 @@
                 RECENT_IGNORE_UNAVAILABLE,
                 userTracker.userId,
                 backgroundExecutor
-            ) { tasks -> continuation.resume(tasks) }
+            ) { tasks ->
+                continuation.resume(tasks)
+            }
         }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProvider.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProvider.kt
index 1c90154..9bccb7d 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProvider.kt
@@ -24,6 +24,7 @@
 import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorScope
 import com.android.systemui.mediaprojection.appselector.view.TaskPreviewSizeProvider.TaskPreviewSizeListener
 import com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen
+import com.android.systemui.shared.system.QuickStepContract
 import com.android.systemui.statusbar.policy.CallbackController
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener
@@ -61,8 +62,15 @@
         val width = windowMetrics.bounds.width()
         var height = maximumWindowHeight
 
+        // TODO(b/271410803): Read isTransientTaskbar from Launcher
         val isLargeScreen = isLargeScreen(context)
-        if (isLargeScreen) {
+        val isTransientTaskbar =
+            QuickStepContract.isGesturalMode(
+                context.resources.getInteger(
+                    com.android.internal.R.integer.config_navBarInteractionMode
+                )
+            )
+        if (isLargeScreen && !isTransientTaskbar) {
             val taskbarSize =
                 context.resources.getDimensionPixelSize(AndroidR.dimen.taskbar_frame_height)
             height -= taskbarSize
diff --git a/packages/SystemUI/src/com/android/systemui/multishade/data/model/MultiShadeInteractionModel.kt b/packages/SystemUI/src/com/android/systemui/multishade/data/model/MultiShadeInteractionModel.kt
new file mode 100644
index 0000000..c48028c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/multishade/data/model/MultiShadeInteractionModel.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.multishade.data.model
+
+import com.android.systemui.multishade.shared.model.ShadeId
+
+/** Models the current interaction with one of the shades. */
+data class MultiShadeInteractionModel(
+    /** The ID of the shade that the user is currently interacting with. */
+    val shadeId: ShadeId,
+    /** Whether the interaction is proxied (as in: coming from an external app or different UI). */
+    val isProxied: Boolean,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/multishade/data/remoteproxy/MultiShadeInputProxy.kt b/packages/SystemUI/src/com/android/systemui/multishade/data/remoteproxy/MultiShadeInputProxy.kt
new file mode 100644
index 0000000..86f0c0d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/multishade/data/remoteproxy/MultiShadeInputProxy.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.multishade.data.remoteproxy
+
+import com.android.systemui.multishade.shared.model.ProxiedInputModel
+import javax.inject.Inject
+import javax.inject.Singleton
+import kotlinx.coroutines.channels.BufferOverflow
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.asSharedFlow
+
+/**
+ * Acts as a hub for routing proxied user input into the multi shade system.
+ *
+ * "Proxied" user input is coming through a proxy; typically from an external app or different UI.
+ * In other words: it's not user input that's occurring directly on the shade UI itself. This class
+ * is that proxy.
+ */
+@Singleton
+class MultiShadeInputProxy @Inject constructor() {
+    private val _proxiedTouch =
+        MutableSharedFlow<ProxiedInputModel>(
+            replay = 1,
+            onBufferOverflow = BufferOverflow.DROP_OLDEST,
+        )
+    val proxiedInput: Flow<ProxiedInputModel> = _proxiedTouch.asSharedFlow()
+
+    fun onProxiedInput(proxiedInput: ProxiedInputModel) {
+        _proxiedTouch.tryEmit(proxiedInput)
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/multishade/data/repository/MultiShadeRepository.kt b/packages/SystemUI/src/com/android/systemui/multishade/data/repository/MultiShadeRepository.kt
new file mode 100644
index 0000000..1172030
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/multishade/data/repository/MultiShadeRepository.kt
@@ -0,0 +1,157 @@
+/*
+ * 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.multishade.data.repository
+
+import android.content.Context
+import androidx.annotation.FloatRange
+import com.android.systemui.R
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.multishade.data.model.MultiShadeInteractionModel
+import com.android.systemui.multishade.data.remoteproxy.MultiShadeInputProxy
+import com.android.systemui.multishade.shared.model.ProxiedInputModel
+import com.android.systemui.multishade.shared.model.ShadeConfig
+import com.android.systemui.multishade.shared.model.ShadeId
+import com.android.systemui.multishade.shared.model.ShadeModel
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+
+/** Encapsulates application state for all shades. */
+@SysUISingleton
+class MultiShadeRepository
+@Inject
+constructor(
+    @Application private val applicationContext: Context,
+    inputProxy: MultiShadeInputProxy,
+) {
+    /**
+     * Remote input coming from sources outside of system UI (for example, swiping down on the
+     * Launcher or from the status bar).
+     */
+    val proxiedInput: Flow<ProxiedInputModel> = inputProxy.proxiedInput
+
+    /** Width of the left-hand side shade, in pixels. */
+    private val leftShadeWidthPx =
+        applicationContext.resources.getDimensionPixelSize(R.dimen.left_shade_width)
+
+    /** Width of the right-hand side shade, in pixels. */
+    private val rightShadeWidthPx =
+        applicationContext.resources.getDimensionPixelSize(R.dimen.right_shade_width)
+
+    /**
+     * The amount that the user must swipe up when the shade is fully expanded to automatically
+     * collapse once the user lets go of the shade. If the user swipes less than this amount, the
+     * shade will automatically revert back to fully expanded once the user stops swiping.
+     *
+     * This is a fraction between `0` and `1`.
+     */
+    private val swipeCollapseThreshold =
+        checkInBounds(applicationContext.resources.getFloat(R.dimen.shade_swipe_collapse_threshold))
+
+    /**
+     * The amount that the user must swipe down when the shade is fully collapsed to automatically
+     * expand once the user lets go of the shade. If the user swipes less than this amount, the
+     * shade will automatically revert back to fully collapsed once the user stops swiping.
+     *
+     * This is a fraction between `0` and `1`.
+     */
+    private val swipeExpandThreshold =
+        checkInBounds(applicationContext.resources.getFloat(R.dimen.shade_swipe_expand_threshold))
+
+    /**
+     * Maximum opacity when the scrim that shows up behind the dual shades is fully visible.
+     *
+     * This is a fraction between `0` and `1`.
+     */
+    private val dualShadeScrimAlpha =
+        checkInBounds(applicationContext.resources.getFloat(R.dimen.dual_shade_scrim_alpha))
+
+    /** The current configuration of the shade system. */
+    val shadeConfig: StateFlow<ShadeConfig> =
+        MutableStateFlow(
+                if (applicationContext.resources.getBoolean(R.bool.dual_shade_enabled)) {
+                    ShadeConfig.DualShadeConfig(
+                        leftShadeWidthPx = leftShadeWidthPx,
+                        rightShadeWidthPx = rightShadeWidthPx,
+                        swipeCollapseThreshold = swipeCollapseThreshold,
+                        swipeExpandThreshold = swipeExpandThreshold,
+                        splitFraction =
+                            applicationContext.resources.getFloat(
+                                R.dimen.dual_shade_split_fraction
+                            ),
+                        scrimAlpha = dualShadeScrimAlpha,
+                    )
+                } else {
+                    ShadeConfig.SingleShadeConfig(
+                        swipeCollapseThreshold = swipeCollapseThreshold,
+                        swipeExpandThreshold = swipeExpandThreshold,
+                    )
+                }
+            )
+            .asStateFlow()
+
+    private val _forceCollapseAll = MutableStateFlow(false)
+    /** Whether all shades should be collapsed. */
+    val forceCollapseAll: StateFlow<Boolean> = _forceCollapseAll.asStateFlow()
+
+    private val _shadeInteraction = MutableStateFlow<MultiShadeInteractionModel?>(null)
+    /** The current shade interaction or `null` if no shade is interacted with currently. */
+    val shadeInteraction: StateFlow<MultiShadeInteractionModel?> = _shadeInteraction.asStateFlow()
+
+    private val stateByShade = mutableMapOf<ShadeId, MutableStateFlow<ShadeModel>>()
+
+    /** The model for the shade with the given ID. */
+    fun getShade(
+        shadeId: ShadeId,
+    ): StateFlow<ShadeModel> {
+        return getMutableShade(shadeId).asStateFlow()
+    }
+
+    /** Sets the expansion amount for the shade with the given ID. */
+    fun setExpansion(
+        shadeId: ShadeId,
+        @FloatRange(from = 0.0, to = 1.0) expansion: Float,
+    ) {
+        getMutableShade(shadeId).let { mutableState ->
+            mutableState.value = mutableState.value.copy(expansion = expansion)
+        }
+    }
+
+    /** Sets whether all shades should be immediately forced to collapse. */
+    fun setForceCollapseAll(isForced: Boolean) {
+        _forceCollapseAll.value = isForced
+    }
+
+    /** Sets the current shade interaction; use `null` if no shade is interacted with currently. */
+    fun setShadeInteraction(shadeInteraction: MultiShadeInteractionModel?) {
+        _shadeInteraction.value = shadeInteraction
+    }
+
+    private fun getMutableShade(id: ShadeId): MutableStateFlow<ShadeModel> {
+        return stateByShade.getOrPut(id) { MutableStateFlow(ShadeModel(id)) }
+    }
+
+    /** Asserts that the given [Float] is in the range of `0` and `1`, inclusive. */
+    private fun checkInBounds(float: Float): Float {
+        check(float in 0f..1f) { "$float isn't between 0 and 1." }
+        return float
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/multishade/domain/interactor/MultiShadeInteractor.kt b/packages/SystemUI/src/com/android/systemui/multishade/domain/interactor/MultiShadeInteractor.kt
new file mode 100644
index 0000000..b9f6d83
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/multishade/domain/interactor/MultiShadeInteractor.kt
@@ -0,0 +1,322 @@
+/*
+ * 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.multishade.domain.interactor
+
+import androidx.annotation.FloatRange
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.multishade.data.model.MultiShadeInteractionModel
+import com.android.systemui.multishade.data.remoteproxy.MultiShadeInputProxy
+import com.android.systemui.multishade.data.repository.MultiShadeRepository
+import com.android.systemui.multishade.shared.model.ProxiedInputModel
+import com.android.systemui.multishade.shared.model.ShadeConfig
+import com.android.systemui.multishade.shared.model.ShadeId
+import com.android.systemui.multishade.shared.model.ShadeModel
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharedFlow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.shareIn
+import kotlinx.coroutines.yield
+
+/** Encapsulates business logic related to interactions with the multi-shade system. */
+@OptIn(ExperimentalCoroutinesApi::class)
+@SysUISingleton
+class MultiShadeInteractor
+@Inject
+constructor(
+    @Application private val applicationScope: CoroutineScope,
+    private val repository: MultiShadeRepository,
+    private val inputProxy: MultiShadeInputProxy,
+) {
+    /** The current configuration of the shade system. */
+    val shadeConfig: StateFlow<ShadeConfig> = repository.shadeConfig
+
+    /** The expansion of the shade that's most expanded. */
+    val maxShadeExpansion: Flow<Float> =
+        repository.shadeConfig.flatMapLatest { shadeConfig ->
+            combine(allShades(shadeConfig)) { shadeModels ->
+                shadeModels.maxOfOrNull { it.expansion } ?: 0f
+            }
+        }
+
+    /**
+     * A _processed_ version of the proxied input flow.
+     *
+     * All internal dependencies on the proxied input flow *must* use this one for two reasons:
+     * 1. It's a [SharedFlow] so we only do the upstream work once, no matter how many usages we
+     *    actually have.
+     * 2. It actually does some preprocessing as the proxied input events stream through, handling
+     *    common things like recording the current state of the system based on incoming input
+     *    events.
+     */
+    private val processedProxiedInput: SharedFlow<ProxiedInputModel> =
+        combine(
+                repository.shadeConfig,
+                repository.proxiedInput.distinctUntilChanged(),
+                ::Pair,
+            )
+            .map { (shadeConfig, proxiedInput) ->
+                if (proxiedInput !is ProxiedInputModel.OnTap) {
+                    // If the user is interacting with any other gesture type (for instance,
+                    // dragging),
+                    // we no longer want to force collapse all shades.
+                    repository.setForceCollapseAll(false)
+                }
+
+                when (proxiedInput) {
+                    is ProxiedInputModel.OnDrag -> {
+                        val affectedShadeId = affectedShadeId(shadeConfig, proxiedInput.xFraction)
+                        // This might be the start of a new drag gesture, let's update our
+                        // application
+                        // state to record that fact.
+                        onUserInteractionStarted(
+                            shadeId = affectedShadeId,
+                            isProxied = true,
+                        )
+                    }
+                    is ProxiedInputModel.OnTap -> {
+                        // Tapping outside any shade collapses all shades. This code path is not hit
+                        // for
+                        // taps that happen _inside_ a shade as that input event is directly applied
+                        // through the UI and is, hence, not a proxied input.
+                        collapseAll()
+                    }
+                    else -> Unit
+                }
+
+                proxiedInput
+            }
+            .shareIn(
+                scope = applicationScope,
+                started = SharingStarted.Eagerly,
+                replay = 1,
+            )
+
+    /** Whether the shade with the given ID should be visible. */
+    fun isVisible(shadeId: ShadeId): Flow<Boolean> {
+        return repository.shadeConfig.map { shadeConfig -> shadeConfig.shadeIds.contains(shadeId) }
+    }
+
+    /** Whether direct user input is allowed on the shade with the given ID. */
+    fun isNonProxiedInputAllowed(shadeId: ShadeId): Flow<Boolean> {
+        return combine(
+                isForceCollapsed(shadeId),
+                repository.shadeInteraction,
+                ::Pair,
+            )
+            .map { (isForceCollapsed, shadeInteraction) ->
+                !isForceCollapsed && shadeInteraction?.isProxied != true
+            }
+    }
+
+    /** Whether the shade with the given ID is forced to collapse. */
+    fun isForceCollapsed(shadeId: ShadeId): Flow<Boolean> {
+        return combine(
+                repository.forceCollapseAll,
+                repository.shadeInteraction.map { it?.shadeId },
+                ::Pair,
+            )
+            .map { (collapseAll, userInteractedShadeIdOrNull) ->
+                val counterpartShadeIdOrNull =
+                    when (shadeId) {
+                        ShadeId.SINGLE -> null
+                        ShadeId.LEFT -> ShadeId.RIGHT
+                        ShadeId.RIGHT -> ShadeId.LEFT
+                    }
+
+                when {
+                    // If all shades have been told to collapse (by a tap outside, for example),
+                    // then this shade is collapsed.
+                    collapseAll -> true
+                    // A shade that doesn't have a counterpart shade cannot be force-collapsed by
+                    // interactions on the counterpart shade.
+                    counterpartShadeIdOrNull == null -> false
+                    // If the current user interaction is on the counterpart shade, then this shade
+                    // should be force-collapsed.
+                    else -> userInteractedShadeIdOrNull == counterpartShadeIdOrNull
+                }
+            }
+    }
+
+    /**
+     * Proxied input affecting the shade with the given ID. This is input coming from sources
+     * outside of system UI (for example, swiping down on the Launcher or from the status bar) or
+     * outside the UI of any shade (for example, the scrim that's shown behind the shades).
+     */
+    fun proxiedInput(shadeId: ShadeId): Flow<ProxiedInputModel?> {
+        return combine(
+                processedProxiedInput,
+                isForceCollapsed(shadeId).distinctUntilChanged(),
+                repository.shadeInteraction,
+                ::Triple,
+            )
+            .map { (proxiedInput, isForceCollapsed, shadeInteraction) ->
+                when {
+                    // If the shade is force-collapsed, we ignored proxied input on it.
+                    isForceCollapsed -> null
+                    // If the proxied input does not belong to this shade, ignore it.
+                    shadeInteraction?.shadeId != shadeId -> null
+                    // If there is ongoing non-proxied user input on any shade, ignore the
+                    // proxied input.
+                    !shadeInteraction.isProxied -> null
+                    // Otherwise, send the proxied input downstream.
+                    else -> proxiedInput
+                }
+            }
+            .onEach { proxiedInput ->
+                // We use yield() to make sure that the following block of code happens _after_
+                // downstream collectors had a chance to process the proxied input. Otherwise, we
+                // might change our state to clear the current UserInteraction _before_ those
+                // downstream collectors get a chance to process the proxied input, which will make
+                // them ignore it (since they ignore proxied input when the current user interaction
+                // doesn't match their shade).
+                yield()
+
+                if (
+                    proxiedInput is ProxiedInputModel.OnDragEnd ||
+                        proxiedInput is ProxiedInputModel.OnDragCancel
+                ) {
+                    onUserInteractionEnded(shadeId = shadeId, isProxied = true)
+                }
+            }
+    }
+
+    /** Sets the expansion amount for the shade with the given ID. */
+    fun setExpansion(
+        shadeId: ShadeId,
+        @FloatRange(from = 0.0, to = 1.0) expansion: Float,
+    ) {
+        repository.setExpansion(shadeId, expansion)
+    }
+
+    /** Collapses all shades. */
+    fun collapseAll() {
+        repository.setForceCollapseAll(true)
+    }
+
+    /**
+     * Notifies that a new non-proxied interaction may have started. Safe to call multiple times for
+     * the same interaction as it won't overwrite an existing interaction.
+     *
+     * Existing interactions can be cleared by calling [onUserInteractionEnded].
+     */
+    fun onUserInteractionStarted(shadeId: ShadeId) {
+        onUserInteractionStarted(
+            shadeId = shadeId,
+            isProxied = false,
+        )
+    }
+
+    /**
+     * Notifies that the current non-proxied interaction has ended.
+     *
+     * Safe to call multiple times, even if there's no current interaction or even if the current
+     * interaction doesn't belong to the given shade or is proxied as the code is a no-op unless
+     * there's a match between the parameters and the current interaction.
+     */
+    fun onUserInteractionEnded(
+        shadeId: ShadeId,
+    ) {
+        onUserInteractionEnded(
+            shadeId = shadeId,
+            isProxied = false,
+        )
+    }
+
+    fun sendProxiedInput(proxiedInput: ProxiedInputModel) {
+        inputProxy.onProxiedInput(proxiedInput)
+    }
+
+    /**
+     * Notifies that a new interaction may have started. Safe to call multiple times for the same
+     * interaction as it won't overwrite an existing interaction.
+     *
+     * Existing interactions can be cleared by calling [onUserInteractionEnded].
+     */
+    private fun onUserInteractionStarted(
+        shadeId: ShadeId,
+        isProxied: Boolean,
+    ) {
+        if (repository.shadeInteraction.value != null) {
+            return
+        }
+
+        repository.setShadeInteraction(
+            MultiShadeInteractionModel(
+                shadeId = shadeId,
+                isProxied = isProxied,
+            )
+        )
+    }
+
+    /**
+     * Notifies that the current interaction has ended.
+     *
+     * Safe to call multiple times, even if there's no current interaction or even if the current
+     * interaction doesn't belong to the given shade or [isProxied] value as the code is a no-op
+     * unless there's a match between the parameters and the current interaction.
+     */
+    private fun onUserInteractionEnded(
+        shadeId: ShadeId,
+        isProxied: Boolean,
+    ) {
+        repository.shadeInteraction.value?.let { (interactionShadeId, isInteractionProxied) ->
+            if (shadeId == interactionShadeId && isProxied == isInteractionProxied) {
+                repository.setShadeInteraction(null)
+            }
+        }
+    }
+
+    /**
+     * Returns the ID of the shade that's affected by user input at a given coordinate.
+     *
+     * @param config The shade configuration being used.
+     * @param xFraction The horizontal position of the user input as a fraction along the width of
+     *   its container where `0` is all the way to the left and `1` is all the way to the right.
+     */
+    private fun affectedShadeId(
+        config: ShadeConfig,
+        @FloatRange(from = 0.0, to = 1.0) xFraction: Float,
+    ): ShadeId {
+        return if (config is ShadeConfig.DualShadeConfig) {
+            if (xFraction <= config.splitFraction) {
+                ShadeId.LEFT
+            } else {
+                ShadeId.RIGHT
+            }
+        } else {
+            ShadeId.SINGLE
+        }
+    }
+
+    /** Returns the list of flows of all the shades in the given configuration. */
+    private fun allShades(
+        config: ShadeConfig,
+    ): List<Flow<ShadeModel>> {
+        return config.shadeIds.map { shadeId -> repository.getShade(shadeId) }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/multishade/shared/model/ProxiedInputModel.kt b/packages/SystemUI/src/com/android/systemui/multishade/shared/model/ProxiedInputModel.kt
new file mode 100644
index 0000000..ee1dd65
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/multishade/shared/model/ProxiedInputModel.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.multishade.shared.model
+
+import androidx.annotation.FloatRange
+
+/**
+ * Models a part of an ongoing proxied user input gesture.
+ *
+ * "Proxied" user input is coming through a proxy; typically from an external app or different UI.
+ * In other words: it's not user input that's occurring directly on the shade UI itself.
+ */
+sealed class ProxiedInputModel {
+    /** The user is dragging their pointer. */
+    data class OnDrag(
+        /**
+         * The relative position of the pointer as a fraction of its container width where `0` is
+         * all the way to the left and `1` is all the way to the right.
+         */
+        @FloatRange(from = 0.0, to = 1.0) val xFraction: Float,
+        /** The amount that the pointer was dragged, in pixels. */
+        val yDragAmountPx: Float,
+    ) : ProxiedInputModel()
+
+    /** The user finished dragging by lifting up their pointer. */
+    object OnDragEnd : ProxiedInputModel()
+
+    /**
+     * The drag gesture has been canceled. Usually because the pointer exited the draggable area.
+     */
+    object OnDragCancel : ProxiedInputModel()
+
+    /** The user has tapped (clicked). */
+    object OnTap : ProxiedInputModel()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/multishade/shared/model/ShadeConfig.kt b/packages/SystemUI/src/com/android/systemui/multishade/shared/model/ShadeConfig.kt
new file mode 100644
index 0000000..a4cd35c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/multishade/shared/model/ShadeConfig.kt
@@ -0,0 +1,79 @@
+/*
+ * 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.multishade.shared.model
+
+import androidx.annotation.FloatRange
+
+/** Enumerates the various possible configurations of the shade system. */
+sealed class ShadeConfig(
+
+    /** IDs of the shade(s) in this configuration. */
+    open val shadeIds: List<ShadeId>,
+
+    /**
+     * The amount that the user must swipe up when the shade is fully expanded to automatically
+     * collapse once the user lets go of the shade. If the user swipes less than this amount, the
+     * shade will automatically revert back to fully expanded once the user stops swiping.
+     */
+    @FloatRange(from = 0.0, to = 1.0) open val swipeCollapseThreshold: Float,
+
+    /**
+     * The amount that the user must swipe down when the shade is fully collapsed to automatically
+     * expand once the user lets go of the shade. If the user swipes less than this amount, the
+     * shade will automatically revert back to fully collapsed once the user stops swiping.
+     */
+    @FloatRange(from = 0.0, to = 1.0) open val swipeExpandThreshold: Float,
+) {
+
+    /** There is a single shade. */
+    data class SingleShadeConfig(
+        @FloatRange(from = 0.0, to = 1.0) override val swipeCollapseThreshold: Float,
+        @FloatRange(from = 0.0, to = 1.0) override val swipeExpandThreshold: Float,
+    ) :
+        ShadeConfig(
+            shadeIds = listOf(ShadeId.SINGLE),
+            swipeCollapseThreshold = swipeCollapseThreshold,
+            swipeExpandThreshold = swipeExpandThreshold,
+        )
+
+    /** There are two shades arranged side-by-side. */
+    data class DualShadeConfig(
+        /** Width of the left-hand side shade. */
+        val leftShadeWidthPx: Int,
+        /** Width of the right-hand side shade. */
+        val rightShadeWidthPx: Int,
+        @FloatRange(from = 0.0, to = 1.0) override val swipeCollapseThreshold: Float,
+        @FloatRange(from = 0.0, to = 1.0) override val swipeExpandThreshold: Float,
+        /**
+         * The position of the "split" between interaction areas for each of the shades, as a
+         * fraction of the width of the container.
+         *
+         * Interactions that occur on the start-side (left-hand side in left-to-right languages like
+         * English) affect the start-side shade. Interactions that occur on the end-side (right-hand
+         * side in left-to-right languages like English) affect the end-side shade.
+         */
+        @FloatRange(from = 0.0, to = 1.0) val splitFraction: Float,
+        /** Maximum opacity when the scrim that shows up behind the dual shades is fully visible. */
+        @FloatRange(from = 0.0, to = 1.0) val scrimAlpha: Float,
+    ) :
+        ShadeConfig(
+            shadeIds = listOf(ShadeId.LEFT, ShadeId.RIGHT),
+            swipeCollapseThreshold = swipeCollapseThreshold,
+            swipeExpandThreshold = swipeExpandThreshold,
+        )
+}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ElevationTokens.kt b/packages/SystemUI/src/com/android/systemui/multishade/shared/model/ShadeId.kt
similarity index 63%
rename from packages/CredentialManager/src/com/android/credentialmanager/common/ui/ElevationTokens.kt
rename to packages/SystemUI/src/com/android/systemui/multishade/shared/model/ShadeId.kt
index e1e666e..9e02657 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ElevationTokens.kt
+++ b/packages/SystemUI/src/com/android/systemui/multishade/shared/model/ShadeId.kt
@@ -12,18 +12,17 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
+ *
  */
 
-package com.android.credentialmanager.common.ui
+package com.android.systemui.multishade.shared.model
 
-import androidx.compose.ui.unit.dp
-
-/** Copied from androidx.compose.material3.tokens. */
-internal object ElevationTokens {
-    val Level0 = 0.0.dp
-    val Level1 = 1.0.dp
-    val Level2 = 3.0.dp
-    val Level3 = 6.0.dp
-    val Level4 = 8.0.dp
-    val Level5 = 12.0.dp
-}
\ No newline at end of file
+/** Enumerates all known shade IDs. */
+enum class ShadeId {
+    /** ID of the shade on the left in dual shade configurations. */
+    LEFT,
+    /** ID of the shade on the right in dual shade configurations. */
+    RIGHT,
+    /** ID of the single shade in single shade configurations. */
+    SINGLE,
+}
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl b/packages/SystemUI/src/com/android/systemui/multishade/shared/model/ShadeModel.kt
similarity index 70%
copy from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
copy to packages/SystemUI/src/com/android/systemui/multishade/shared/model/ShadeModel.kt
index 35d5c15..49ac64c 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
+++ b/packages/SystemUI/src/com/android/systemui/multishade/shared/model/ShadeModel.kt
@@ -12,8 +12,15 @@
  * WITHOUT WARRANTIES 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.net.wifi.sharedconnectivity.app;
+package com.android.systemui.multishade.shared.model
 
-parcelable DeviceInfo;
\ No newline at end of file
+import androidx.annotation.FloatRange
+
+/** Models the current state of a shade. */
+data class ShadeModel(
+    val id: ShadeId,
+    @FloatRange(from = 0.0, to = 1.0) val expansion: Float = 0f,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/multishade/ui/viewmodel/MultiShadeViewModel.kt b/packages/SystemUI/src/com/android/systemui/multishade/ui/viewmodel/MultiShadeViewModel.kt
new file mode 100644
index 0000000..ce6ab97
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/multishade/ui/viewmodel/MultiShadeViewModel.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.multishade.ui.viewmodel
+
+import com.android.systemui.multishade.domain.interactor.MultiShadeInteractor
+import com.android.systemui.multishade.shared.model.ProxiedInputModel
+import com.android.systemui.multishade.shared.model.ShadeConfig
+import com.android.systemui.multishade.shared.model.ShadeId
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
+
+/** Models UI state for UI that supports multi (or single) shade. */
+@OptIn(ExperimentalCoroutinesApi::class)
+class MultiShadeViewModel(
+    viewModelScope: CoroutineScope,
+    private val interactor: MultiShadeInteractor,
+) {
+    /** Models UI state for the single shade. */
+    val singleShade =
+        ShadeViewModel(
+            viewModelScope,
+            ShadeId.SINGLE,
+            interactor,
+        )
+
+    /** Models UI state for the shade on the left-hand side. */
+    val leftShade =
+        ShadeViewModel(
+            viewModelScope,
+            ShadeId.LEFT,
+            interactor,
+        )
+
+    /** Models UI state for the shade on the right-hand side. */
+    val rightShade =
+        ShadeViewModel(
+            viewModelScope,
+            ShadeId.RIGHT,
+            interactor,
+        )
+
+    /** The amount of alpha that the scrim should have. This is a value between `0` and `1`. */
+    val scrimAlpha: StateFlow<Float> =
+        combine(
+                interactor.maxShadeExpansion,
+                interactor.shadeConfig
+                    .map { it as? ShadeConfig.DualShadeConfig }
+                    .map { dualShadeConfigOrNull -> dualShadeConfigOrNull?.scrimAlpha ?: 0f },
+                ::Pair,
+            )
+            .map { (anyShadeExpansion, scrimAlpha) ->
+                (anyShadeExpansion * scrimAlpha).coerceIn(0f, 1f)
+            }
+            .stateIn(
+                scope = viewModelScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = 0f,
+            )
+
+    /** Whether the scrim should accept touch events. */
+    val isScrimEnabled: StateFlow<Boolean> =
+        interactor.shadeConfig
+            .flatMapLatest { shadeConfig ->
+                when (shadeConfig) {
+                    // In the dual shade configuration, the scrim is enabled when the expansion is
+                    // greater than zero on any one of the shades.
+                    is ShadeConfig.DualShadeConfig ->
+                        interactor.maxShadeExpansion
+                            .map { expansion -> expansion > 0 }
+                            .distinctUntilChanged()
+                    // No scrim in the single shade configuration.
+                    is ShadeConfig.SingleShadeConfig -> flowOf(false)
+                }
+            }
+            .stateIn(
+                scope = viewModelScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = false,
+            )
+
+    /** Notifies that the scrim has been touched. */
+    fun onScrimTouched(proxiedInput: ProxiedInputModel) {
+        if (!isScrimEnabled.value) {
+            return
+        }
+
+        interactor.sendProxiedInput(proxiedInput)
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/multishade/ui/viewmodel/ShadeViewModel.kt b/packages/SystemUI/src/com/android/systemui/multishade/ui/viewmodel/ShadeViewModel.kt
new file mode 100644
index 0000000..e828dbd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/multishade/ui/viewmodel/ShadeViewModel.kt
@@ -0,0 +1,150 @@
+/*
+ * 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.multishade.ui.viewmodel
+
+import androidx.annotation.FloatRange
+import com.android.systemui.multishade.domain.interactor.MultiShadeInteractor
+import com.android.systemui.multishade.shared.model.ProxiedInputModel
+import com.android.systemui.multishade.shared.model.ShadeConfig
+import com.android.systemui.multishade.shared.model.ShadeId
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
+
+/** Models UI state for a single shade. */
+class ShadeViewModel(
+    viewModelScope: CoroutineScope,
+    private val shadeId: ShadeId,
+    private val interactor: MultiShadeInteractor,
+) {
+    /** Whether the shade is visible. */
+    val isVisible: StateFlow<Boolean> =
+        interactor
+            .isVisible(shadeId)
+            .stateIn(
+                scope = viewModelScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = false,
+            )
+
+    /** Whether swiping on the shade UI is currently enabled. */
+    val isSwipingEnabled: StateFlow<Boolean> =
+        interactor
+            .isNonProxiedInputAllowed(shadeId)
+            .stateIn(
+                scope = viewModelScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = false,
+            )
+
+    /** Whether the shade must be collapsed immediately. */
+    val isForceCollapsed: Flow<Boolean> =
+        interactor.isForceCollapsed(shadeId).distinctUntilChanged()
+
+    /** The width of the shade. */
+    val width: StateFlow<Size> =
+        interactor.shadeConfig
+            .map { shadeWidth(it) }
+            .stateIn(
+                scope = viewModelScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = shadeWidth(interactor.shadeConfig.value),
+            )
+
+    /**
+     * The amount that the user must swipe up when the shade is fully expanded to automatically
+     * collapse once the user lets go of the shade. If the user swipes less than this amount, the
+     * shade will automatically revert back to fully expanded once the user stops swiping.
+     */
+    val swipeCollapseThreshold: StateFlow<Float> =
+        interactor.shadeConfig
+            .map { it.swipeCollapseThreshold }
+            .stateIn(
+                scope = viewModelScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = interactor.shadeConfig.value.swipeCollapseThreshold,
+            )
+
+    /**
+     * The amount that the user must swipe down when the shade is fully collapsed to automatically
+     * expand once the user lets go of the shade. If the user swipes less than this amount, the
+     * shade will automatically revert back to fully collapsed once the user stops swiping.
+     */
+    val swipeExpandThreshold: StateFlow<Float> =
+        interactor.shadeConfig
+            .map { it.swipeExpandThreshold }
+            .stateIn(
+                scope = viewModelScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = interactor.shadeConfig.value.swipeExpandThreshold,
+            )
+
+    /**
+     * Proxied input affecting the shade. This is input coming from sources outside of system UI
+     * (for example, swiping down on the Launcher or from the status bar) or outside the UI of any
+     * shade (for example, the scrim that's shown behind the shades).
+     */
+    val proxiedInput: Flow<ProxiedInputModel?> =
+        interactor
+            .proxiedInput(shadeId)
+            .stateIn(
+                scope = viewModelScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = null,
+            )
+
+    /** Notifies that the expansion amount for the shade has changed. */
+    fun onExpansionChanged(
+        expansion: Float,
+    ) {
+        interactor.setExpansion(shadeId, expansion.coerceIn(0f, 1f))
+    }
+
+    /** Notifies that a drag gesture has started. */
+    fun onDragStarted() {
+        interactor.onUserInteractionStarted(shadeId)
+    }
+
+    /** Notifies that a drag gesture has ended. */
+    fun onDragEnded() {
+        interactor.onUserInteractionEnded(shadeId = shadeId)
+    }
+
+    private fun shadeWidth(shadeConfig: ShadeConfig): Size {
+        return when (shadeId) {
+            ShadeId.LEFT ->
+                Size.Pixels((shadeConfig as? ShadeConfig.DualShadeConfig)?.leftShadeWidthPx ?: 0)
+            ShadeId.RIGHT ->
+                Size.Pixels((shadeConfig as? ShadeConfig.DualShadeConfig)?.rightShadeWidthPx ?: 0)
+            ShadeId.SINGLE -> Size.Fraction(1f)
+        }
+    }
+
+    sealed class Size {
+        data class Fraction(
+            @FloatRange(from = 0.0, to = 1.0) val fraction: Float,
+        ) : Size()
+        data class Pixels(
+            val pixels: Int,
+        ) : Size()
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
index 1121e160..1da8718 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
@@ -41,11 +41,17 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.provider.Settings.Secure;
+import android.util.Log;
+import android.view.IRotationWatcher;
+import android.view.IWallpaperVisibilityListener;
+import android.view.IWindowManager;
 import android.view.View;
 import android.view.WindowInsets;
+import android.view.WindowManagerGlobal;
 import android.view.accessibility.AccessibilityManager;
 
 import androidx.annotation.NonNull;
@@ -57,7 +63,9 @@
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
 import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.settings.DisplayTracker;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.statusbar.CommandQueue;
@@ -90,6 +98,9 @@
         AccessibilityButtonTargetsObserver.TargetsChangedListener,
         OverviewProxyService.OverviewProxyListener, NavigationModeController.ModeChangedListener,
         Dumpable, CommandQueue.Callbacks {
+    private static final String TAG = NavBarHelper.class.getSimpleName();
+
+    private final Handler mHandler = new Handler(Looper.getMainLooper());
     private final AccessibilityManager mAccessibilityManager;
     private final Lazy<AssistManager> mAssistManagerLazy;
     private final Lazy<Optional<CentralSurfaces>> mCentralSurfacesOptionalLazy;
@@ -98,28 +109,60 @@
     private final SystemActions mSystemActions;
     private final AccessibilityButtonModeObserver mAccessibilityButtonModeObserver;
     private final AccessibilityButtonTargetsObserver mAccessibilityButtonTargetsObserver;
-    private final List<NavbarTaskbarStateUpdater> mA11yEventListeners = new ArrayList<>();
+    private final List<NavbarTaskbarStateUpdater> mStateListeners = new ArrayList<>();
     private final Context mContext;
     private final CommandQueue mCommandQueue;
     private final ContentResolver mContentResolver;
+    private final EdgeBackGestureHandler mEdgeBackGestureHandler;
+    private final IWindowManager mWm;
+    private final int mDefaultDisplayId;
     private boolean mAssistantAvailable;
     private boolean mLongPressHomeEnabled;
     private boolean mAssistantTouchGestureEnabled;
     private int mNavBarMode;
     private int mA11yButtonState;
+    private int mRotationWatcherRotation;
+    private boolean mTogglingNavbarTaskbar;
+    private boolean mWallpaperVisible;
 
     // Attributes used in NavBarHelper.CurrentSysuiState
     private int mWindowStateDisplayId;
     private @WindowVisibleState int mWindowState;
 
-    private final ContentObserver mAssistContentObserver = new ContentObserver(
-            new Handler(Looper.getMainLooper())) {
+    // Listens for changes to the assistant
+    private final ContentObserver mAssistContentObserver = new ContentObserver(mHandler) {
         @Override
         public void onChange(boolean selfChange, Uri uri) {
             updateAssistantAvailability();
         }
     };
 
+    // Listens for changes to the wallpaper visibility
+    private final IWallpaperVisibilityListener mWallpaperVisibilityListener =
+            new IWallpaperVisibilityListener.Stub() {
+                @Override
+                public void onWallpaperVisibilityChanged(boolean visible,
+                        int displayId) throws RemoteException {
+                    mHandler.post(() -> {
+                        mWallpaperVisible = visible;
+                        dispatchWallpaperVisibilityChanged(visible, displayId);
+                    });
+                }
+            };
+
+    // Listens for changes to display rotation
+    private final IRotationWatcher mRotationWatcher = new IRotationWatcher.Stub() {
+        @Override
+        public void onRotationChanged(final int rotation) {
+            // We need this to be scheduled as early as possible to beat the redrawing of
+            // window in response to the orientation change.
+            mHandler.postAtFrontOfQueue(() -> {
+                mRotationWatcherRotation = rotation;
+                dispatchRotationChanged(rotation);
+            });
+        }
+    };
+
     /**
      * @param context This is not display specific, then again neither is any of the code in
      *                this class. Once there's display specific code, we may want to create an
@@ -135,7 +178,10 @@
             Lazy<Optional<CentralSurfaces>> centralSurfacesOptionalLazy,
             KeyguardStateController keyguardStateController,
             NavigationModeController navigationModeController,
+            EdgeBackGestureHandler.Factory edgeBackGestureHandlerFactory,
+            IWindowManager wm,
             UserTracker userTracker,
+            DisplayTracker displayTracker,
             DumpManager dumpManager,
             CommandQueue commandQueue) {
         mContext = context;
@@ -147,18 +193,36 @@
         mKeyguardStateController = keyguardStateController;
         mUserTracker = userTracker;
         mSystemActions = systemActions;
-        accessibilityManager.addAccessibilityServicesStateChangeListener(this);
         mAccessibilityButtonModeObserver = accessibilityButtonModeObserver;
         mAccessibilityButtonTargetsObserver = accessibilityButtonTargetsObserver;
+        mWm = wm;
+        mDefaultDisplayId = displayTracker.getDefaultDisplayId();
+        mEdgeBackGestureHandler = edgeBackGestureHandlerFactory.create(context);
 
-        mAccessibilityButtonModeObserver.addListener(this);
-        mAccessibilityButtonTargetsObserver.addListener(this);
         mNavBarMode = navigationModeController.addListener(this);
+        mCommandQueue.addCallback(this);
         overviewProxyService.addCallback(this);
         dumpManager.registerDumpable(this);
     }
 
-    public void init() {
+    /**
+     * Hints to the helper that bars are being replaced, which is a signal to potentially suppress
+     * normal setup/cleanup when no bars are present.
+     */
+    public void setTogglingNavbarTaskbar(boolean togglingNavbarTaskbar) {
+        mTogglingNavbarTaskbar = togglingNavbarTaskbar;
+    }
+
+    /**
+     * Called when the first (non-replacing) bar is registered.
+     */
+    private void setupOnFirstBar() {
+        // Setup accessibility listeners
+        mAccessibilityManager.addAccessibilityServicesStateChangeListener(this);
+        mAccessibilityButtonModeObserver.addListener(this);
+        mAccessibilityButtonTargetsObserver.addListener(this);
+
+        // Setup assistant listener
         mContentResolver.registerContentObserver(
                 Settings.Secure.getUriFor(Settings.Secure.ASSISTANT),
                 false /* notifyForDescendants */, mAssistContentObserver, UserHandle.USER_ALL);
@@ -168,59 +232,114 @@
         mContentResolver.registerContentObserver(
                 Settings.Secure.getUriFor(Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED),
                 false, mAssistContentObserver, UserHandle.USER_ALL);
-        updateAssistantAvailability();
-        updateA11yState();
-        mCommandQueue.addCallback(this);
 
-    }
+        // Setup display rotation watcher
+        try {
+            mWm.watchRotation(mRotationWatcher, mDefaultDisplayId);
+        } catch (Exception e) {
+            Log.w(TAG, "Failed to register rotation watcher", e);
+        }
 
-    public void destroy() {
-        mContentResolver.unregisterContentObserver(mAssistContentObserver);
-        mCommandQueue.removeCallback(this);
+        // Setup wallpaper visibility listener
+        try {
+            mWallpaperVisible = mWm.registerWallpaperVisibilityListener(
+                    mWallpaperVisibilityListener, mDefaultDisplayId);
+        } catch (Exception e) {
+            Log.w(TAG, "Failed to register wallpaper visibility listener", e);
+        }
+
+        // Attach the back handler only when the first bar is registered
+        mEdgeBackGestureHandler.onNavBarAttached();
     }
 
     /**
+     * Called after the last (non-replacing) bar is unregistered.
+     */
+    private void cleanupAfterLastBar() {
+        // Clean up accessibility listeners
+        mAccessibilityManager.removeAccessibilityServicesStateChangeListener(this);
+        mAccessibilityButtonModeObserver.removeListener(this);
+        mAccessibilityButtonTargetsObserver.removeListener(this);
+
+        // Clean up assistant listeners
+        mContentResolver.unregisterContentObserver(mAssistContentObserver);
+
+        // Clean up display rotation watcher
+        try {
+            mWm.removeRotationWatcher(mRotationWatcher);
+        } catch (Exception e) {
+            Log.w(TAG, "Failed to unregister rotation watcher", e);
+        }
+
+        // Clean up wallpaper visibility listener
+        try {
+            mWm.unregisterWallpaperVisibilityListener(mWallpaperVisibilityListener,
+                    mDefaultDisplayId);
+        } catch (Exception e) {
+            Log.w(TAG, "Failed to register wallpaper visibility listener", e);
+        }
+
+        // No more bars, detach the back handler for now
+        mEdgeBackGestureHandler.onNavBarDetached();
+    }
+
+    /**
+     * Registers a listener for future updates to the shared navbar/taskbar state.
      * @param listener Will immediately get callbacks based on current state
      */
     public void registerNavTaskStateUpdater(NavbarTaskbarStateUpdater listener) {
-        mA11yEventListeners.add(listener);
-        listener.updateAccessibilityServicesState();
-        listener.updateAssistantAvailable(mAssistantAvailable, mLongPressHomeEnabled);
+        mStateListeners.add(listener);
+        if (!mTogglingNavbarTaskbar && mStateListeners.size() == 1) {
+            setupOnFirstBar();
+
+            // Update the state once the first bar is registered
+            updateAssistantAvailability();
+            updateA11yState();
+            mCommandQueue.recomputeDisableFlags(mContext.getDisplayId(), false /* animate */);
+        } else {
+            listener.updateAccessibilityServicesState();
+            listener.updateAssistantAvailable(mAssistantAvailable, mLongPressHomeEnabled);
+        }
+        listener.updateWallpaperVisibility(mWallpaperVisible, mDefaultDisplayId);
+        listener.updateRotationWatcherState(mRotationWatcherRotation);
     }
 
+    /**
+     * Removes a previously registered listener.
+     */
     public void removeNavTaskStateUpdater(NavbarTaskbarStateUpdater listener) {
-        mA11yEventListeners.remove(listener);
+        mStateListeners.remove(listener);
+        if (!mTogglingNavbarTaskbar && mStateListeners.isEmpty()) {
+            cleanupAfterLastBar();
+        }
     }
 
     private void dispatchA11yEventUpdate() {
-        for (NavbarTaskbarStateUpdater listener : mA11yEventListeners) {
+        for (NavbarTaskbarStateUpdater listener : mStateListeners) {
             listener.updateAccessibilityServicesState();
         }
     }
 
     private void dispatchAssistantEventUpdate(boolean assistantAvailable,
             boolean longPressHomeEnabled) {
-        for (NavbarTaskbarStateUpdater listener : mA11yEventListeners) {
+        for (NavbarTaskbarStateUpdater listener : mStateListeners) {
             listener.updateAssistantAvailable(assistantAvailable, longPressHomeEnabled);
         }
     }
 
     @Override
     public void onAccessibilityServicesStateChanged(AccessibilityManager manager) {
-        dispatchA11yEventUpdate();
         updateA11yState();
     }
 
     @Override
     public void onAccessibilityButtonModeChanged(int mode) {
         updateA11yState();
-        dispatchA11yEventUpdate();
     }
 
     @Override
     public void onAccessibilityButtonTargetsChanged(String targets) {
         updateA11yState();
-        dispatchA11yEventUpdate();
     }
 
     /**
@@ -262,6 +381,8 @@
             updateSystemAction(clickable, SYSTEM_ACTION_ID_ACCESSIBILITY_BUTTON);
             updateSystemAction(longClickable, SYSTEM_ACTION_ID_ACCESSIBILITY_BUTTON_CHOOSER);
         }
+
+        dispatchA11yEventUpdate();
     }
 
     /**
@@ -319,6 +440,10 @@
         return mLongPressHomeEnabled;
     }
 
+    public EdgeBackGestureHandler getEdgeBackGestureHandler() {
+        return mEdgeBackGestureHandler;
+    }
+
     @Override
     public void startAssistant(Bundle bundle) {
         mAssistManagerLazy.get().startAssist(bundle);
@@ -357,6 +482,18 @@
         mWindowState = state;
     }
 
+    private void dispatchWallpaperVisibilityChanged(boolean visible, int displayId) {
+        for (NavbarTaskbarStateUpdater listener : mStateListeners) {
+            listener.updateWallpaperVisibility(visible, displayId);
+        }
+    }
+
+    private void dispatchRotationChanged(int rotation) {
+        for (NavbarTaskbarStateUpdater listener : mStateListeners) {
+            listener.updateRotationWatcherState(rotation);
+        }
+    }
+
     public CurrentSysuiState getCurrentSysuiState() {
         return new CurrentSysuiState();
     }
@@ -368,6 +505,8 @@
     public interface NavbarTaskbarStateUpdater {
         void updateAccessibilityServicesState();
         void updateAssistantAvailable(boolean available, boolean longPressHomeEnabled);
+        default void updateWallpaperVisibility(boolean visible, int displayId) {}
+        default void updateRotationWatcherState(int rotation) {}
     }
 
     /** Data class to help Taskbar/Navbar initiate state correctly when switching between the two.*/
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index 4db1da3..8a5bac8 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -25,11 +25,6 @@
 import static android.app.StatusBarManager.WindowVisibleState;
 import static android.app.StatusBarManager.windowStateToString;
 import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
-import static android.view.InsetsState.ITYPE_BOTTOM_MANDATORY_GESTURES;
-import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
-import static android.view.InsetsState.ITYPE_LEFT_GESTURES;
-import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_RIGHT_GESTURES;
 import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
@@ -169,7 +164,6 @@
 import java.util.Map;
 import java.util.Optional;
 import java.util.concurrent.Executor;
-import java.util.function.Consumer;
 
 import javax.inject.Inject;
 
@@ -214,7 +208,6 @@
     private final Optional<Recents> mRecentsOptional;
     private final DeviceConfigProxy mDeviceConfigProxy;
     private final NavigationBarTransitions mNavigationBarTransitions;
-    private final EdgeBackGestureHandler mEdgeBackGestureHandler;
     private final Optional<BackAnimation> mBackAnimation;
     private final Handler mHandler;
     private final UiEventLogger mUiEventLogger;
@@ -226,6 +219,7 @@
     private final DisplayTracker mDisplayTracker;
     private final RegionSamplingHelper mRegionSamplingHelper;
     private final int mNavColorSampleMargin;
+    private EdgeBackGestureHandler mEdgeBackGestureHandler;
     private NavigationBarFrame mFrame;
 
     private @WindowVisibleState int mNavigationBarWindowState = WINDOW_STATE_SHOWING;
@@ -292,6 +286,7 @@
     private final DeadZone mDeadZone;
     private boolean mImeVisible;
     private final Rect mSamplingBounds = new Rect();
+    private final Binder mInsetsSourceOwner = new Binder();
 
     /**
      * When quickswitching between apps of different orientations, we draw a secondary home handle
@@ -361,6 +356,21 @@
                     mLongPressHomeEnabled = longPressHomeEnabled;
                     updateAssistantEntrypoints(available, longPressHomeEnabled);
                 }
+
+                @Override
+                public void updateWallpaperVisibility(boolean visible, int displayId) {
+                    mNavigationBarTransitions.setWallpaperVisibility(visible);
+                }
+
+                @Override
+                public void updateRotationWatcherState(int rotation) {
+                    if (mIsOnDefaultDisplay && mView != null) {
+                        mView.getRotationButtonController().onRotationWatcherChanged(rotation);
+                        if (mView.needsReorient(rotation)) {
+                            repositionNavigationBar(rotation);
+                        }
+                    }
+                }
             };
 
     private final OverviewProxyListener mOverviewProxyListener = new OverviewProxyListener() {
@@ -554,7 +564,6 @@
             DeadZone deadZone,
             DeviceConfigProxy deviceConfigProxy,
             NavigationBarTransitions navigationBarTransitions,
-            EdgeBackGestureHandler edgeBackGestureHandler,
             Optional<BackAnimation> backAnimation,
             UserContextProvider userContextProvider,
             WakefulnessLifecycle wakefulnessLifecycle,
@@ -584,7 +593,6 @@
         mDeadZone = deadZone;
         mDeviceConfigProxy = deviceConfigProxy;
         mNavigationBarTransitions = navigationBarTransitions;
-        mEdgeBackGestureHandler = edgeBackGestureHandler;
         mBackAnimation = backAnimation;
         mHandler = mainHandler;
         mUiEventLogger = uiEventLogger;
@@ -600,6 +608,7 @@
         mWakefulnessLifecycle = wakefulnessLifecycle;
         mTaskStackChangeListeners = taskStackChangeListeners;
         mDisplayTracker = displayTracker;
+        mEdgeBackGestureHandler = navBarHelper.getEdgeBackGestureHandler();
 
         mNavColorSampleMargin = getResources()
                 .getDimensionPixelSize(R.dimen.navigation_handle_sample_horizontal_margin);
@@ -692,13 +701,14 @@
         // start firing, since the latter is source of truth
         parseCurrentSysuiState();
         mCommandQueue.addCallback(this);
-        mLongPressHomeEnabled = mNavBarHelper.getLongPressHomeEnabled();
-        mNavBarHelper.init();
         mHomeButtonLongPressDurationMs = Optional.of(mDeviceConfigProxy.getLong(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 HOME_BUTTON_LONG_PRESS_DURATION_MS,
                 /* defaultValue = */ 0
         )).filter(duration -> duration != 0);
+        // This currently MUST be called after mHomeButtonLongPressDurationMs is initialized since
+        // the registration callbacks will trigger code that uses it
+        mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
         mDeviceConfigProxy.addOnPropertiesChangedListener(
                 DeviceConfig.NAMESPACE_SYSTEMUI, mHandler::post, mOnPropertiesChangedListener);
 
@@ -722,9 +732,9 @@
         mCommandQueue.removeCallback(this);
         mWindowManager.removeViewImmediate(mView.getRootView());
         mNavigationModeController.removeListener(mModeChangedListener);
+        mEdgeBackGestureHandler.setStateChangeCallback(null);
 
         mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
-        mNavBarHelper.destroy();
         mNotificationShadeDepthController.removeListener(mDepthListener);
 
         mDeviceConfigProxy.removeOnPropertiesChangedListener(mOnPropertiesChangedListener);
@@ -762,8 +772,6 @@
         mView.getViewRootImpl().addSurfaceChangedCallback(mSurfaceChangedCallback);
         notifyNavigationBarSurface();
 
-        mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
-
         mPipOptional.ifPresent(mView::addPipExclusionBoundsChangeListener);
         mBackAnimation.ifPresent(mView::registerBackAnimation);
 
@@ -781,7 +789,6 @@
         if (mIsOnDefaultDisplay) {
             final RotationButtonController rotationButtonController =
                     mView.getRotationButtonController();
-            rotationButtonController.setRotationCallback(mRotationWatcher);
 
             // Reset user rotation pref to match that of the WindowManager if starting in locked
             // mode. This will automatically happen when switching from auto-rotate to locked mode.
@@ -815,9 +822,6 @@
 
     @Override
     public void onViewDetached() {
-        final RotationButtonController rotationButtonController =
-                mView.getRotationButtonController();
-        rotationButtonController.setRotationCallback(null);
         mView.setUpdateActiveTouchRegionsCallback(null);
         getBarTransitions().destroy();
         mOverviewProxyService.removeCallback(mOverviewProxyListener);
@@ -843,6 +847,7 @@
         }
         mFrame = null;
         mOrientationHandle = null;
+        notifyNavigationBarSurface();
     }
 
     // TODO: Remove this when we update nav bar recreation
@@ -1007,7 +1012,12 @@
 
     private void notifyNavigationBarSurface() {
         ViewRootImpl viewRoot = mView.getViewRootImpl();
-        SurfaceControl surface = viewRoot != null ? viewRoot.getSurfaceControl() : null;
+        SurfaceControl surface = mView.getParent() != null 
+                && viewRoot != null
+                && viewRoot.getSurfaceControl() != null
+                && viewRoot.getSurfaceControl().isValid()
+                        ? viewRoot.getSurfaceControl()
+                        : null;
         mOverviewProxyService.onNavigationBarSurfaceChanged(surface);
     }
 
@@ -1501,6 +1511,7 @@
     }
 
     void updateAccessibilityStateFlags() {
+        mLongPressHomeEnabled = mNavBarHelper.getLongPressHomeEnabled();
         if (mView != null) {
             int a11yFlags = mNavBarHelper.getA11yButtonState();
             boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0;
@@ -1705,77 +1716,52 @@
     }
 
     private InsetsFrameProvider[] getInsetsFrameProvider(int insetsHeight, Context userContext) {
-        final InsetsFrameProvider navBarProvider;
+        final InsetsFrameProvider navBarProvider =
+                new InsetsFrameProvider(mInsetsSourceOwner, 0, WindowInsets.Type.navigationBars())
+                        .setInsetsSizeOverrides(new InsetsFrameProvider.InsetsSizeOverride[] {
+                                new InsetsFrameProvider.InsetsSizeOverride(
+                                        TYPE_INPUT_METHOD, null)});
         if (insetsHeight != -1 && !mIsButtonForceVisible) {
-            navBarProvider = new InsetsFrameProvider(
-                    ITYPE_NAVIGATION_BAR, Insets.of(0, 0, 0, insetsHeight));
-            // Use window frame for IME.
-            navBarProvider.insetsSizeOverrides = new InsetsFrameProvider.InsetsSizeOverride[] {
-                    new InsetsFrameProvider.InsetsSizeOverride(TYPE_INPUT_METHOD, null)
-            };
-        } else {
-            navBarProvider = new InsetsFrameProvider(ITYPE_NAVIGATION_BAR);
-            navBarProvider.insetsSizeOverrides = new InsetsFrameProvider.InsetsSizeOverride[]{
-                    new InsetsFrameProvider.InsetsSizeOverride(TYPE_INPUT_METHOD, null)
-            };
-        }
-        final boolean navBarTapThrough = userContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_navBarTapThrough);
-        final InsetsFrameProvider bottomTappableProvider;
-        if (navBarTapThrough) {
-            bottomTappableProvider = new InsetsFrameProvider(ITYPE_BOTTOM_TAPPABLE_ELEMENT,
-                    Insets.of(0, 0, 0, 0));
-        } else {
-            bottomTappableProvider = new InsetsFrameProvider(ITYPE_BOTTOM_TAPPABLE_ELEMENT);
+            navBarProvider.setInsetsSize(Insets.of(0, 0, 0, insetsHeight));
         }
 
-        if (!mEdgeBackGestureHandler.isHandlingGestures()) {
-            // 2/3 button navigation is on. Do not provide any gesture insets here. But need to keep
-            // the provider to support runtime update.
-            return new InsetsFrameProvider[] {
-                    navBarProvider,
-                    new InsetsFrameProvider(
-                            ITYPE_BOTTOM_MANDATORY_GESTURES, Insets.NONE),
-                    new InsetsFrameProvider(ITYPE_LEFT_GESTURES, InsetsFrameProvider.SOURCE_DISPLAY,
-                            Insets.NONE, null),
-                    new InsetsFrameProvider(ITYPE_RIGHT_GESTURES,
-                            InsetsFrameProvider.SOURCE_DISPLAY,
-                            Insets.NONE, null),
-                    bottomTappableProvider
-            };
-        } else {
-            // Gesture navigation
-            final int gestureHeight = userContext.getResources().getDimensionPixelSize(
-                    com.android.internal.R.dimen.navigation_bar_gesture_height);
-            final DisplayCutout cutout = userContext.getDisplay().getCutout();
-            final int safeInsetsLeft = cutout != null ? cutout.getSafeInsetLeft() : 0;
-            final int safeInsetsRight = cutout != null ? cutout.getSafeInsetRight() : 0;
-            return new InsetsFrameProvider[] {
-                    navBarProvider,
-                    new InsetsFrameProvider(
-                            ITYPE_BOTTOM_MANDATORY_GESTURES, Insets.of(0, 0, 0, gestureHeight)),
-                    new InsetsFrameProvider(ITYPE_LEFT_GESTURES, InsetsFrameProvider.SOURCE_DISPLAY,
-                            Insets.of(safeInsetsLeft
-                                    + mEdgeBackGestureHandler.getEdgeWidthLeft(), 0, 0, 0), null),
-                    new InsetsFrameProvider(ITYPE_RIGHT_GESTURES,
-                            InsetsFrameProvider.SOURCE_DISPLAY,
-                            Insets.of(0, 0, safeInsetsRight
-                                    + mEdgeBackGestureHandler.getEdgeWidthRight(), 0), null),
-                    bottomTappableProvider
-            };
+        final InsetsFrameProvider tappableElementProvider = new InsetsFrameProvider(
+                mInsetsSourceOwner, 0, WindowInsets.Type.tappableElement());
+        final boolean navBarTapThrough = userContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_navBarTapThrough);
+        if (navBarTapThrough) {
+            tappableElementProvider.setInsetsSize(Insets.NONE);
         }
+
+        final DisplayCutout cutout = userContext.getDisplay().getCutout();
+        final int safeInsetsLeft = cutout != null ? cutout.getSafeInsetLeft() : 0;
+        final int safeInsetsRight = cutout != null ? cutout.getSafeInsetRight() : 0;
+        final int gestureHeight = userContext.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.navigation_bar_gesture_height);
+        final boolean handlingGesture = mEdgeBackGestureHandler.isHandlingGestures();
+        final int gestureInsetsLeft = handlingGesture
+                ? mEdgeBackGestureHandler.getEdgeWidthLeft() + safeInsetsLeft : 0;
+        final int gestureInsetsRight = handlingGesture
+                ? mEdgeBackGestureHandler.getEdgeWidthRight() + safeInsetsRight : 0;
+        return new InsetsFrameProvider[] {
+                navBarProvider,
+                tappableElementProvider,
+                new InsetsFrameProvider(
+                        mInsetsSourceOwner, 0, WindowInsets.Type.mandatorySystemGestures())
+                        .setInsetsSize(Insets.of(0, 0, 0, gestureHeight)),
+                new InsetsFrameProvider(mInsetsSourceOwner, 0, WindowInsets.Type.systemGestures())
+                        .setSource(InsetsFrameProvider.SOURCE_DISPLAY)
+                        .setInsetsSize(Insets.of(gestureInsetsLeft, 0, 0, 0)),
+                new InsetsFrameProvider(mInsetsSourceOwner, 1, WindowInsets.Type.systemGestures())
+                        .setSource(InsetsFrameProvider.SOURCE_DISPLAY)
+                        .setInsetsSize(Insets.of(0, 0, gestureInsetsRight, 0))
+        };
     }
 
     private boolean canShowSecondaryHandle() {
         return mNavBarMode == NAV_BAR_MODE_GESTURAL && mOrientationHandle != null;
     }
 
-    private final Consumer<Integer> mRotationWatcher = rotation -> {
-        if (mView != null && mView.needsReorient(rotation)) {
-            repositionNavigationBar(rotation);
-        }
-    };
-
     private final UserTracker.Callback mUserChangedCallback =
             new UserTracker.Callback() {
                 @Override
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
index 63d977e..5b0a4bb 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -90,6 +90,7 @@
     private final DisplayTracker mDisplayTracker;
     private final DisplayManager mDisplayManager;
     private final TaskbarDelegate mTaskbarDelegate;
+    private final NavBarHelper mNavBarHelper;
     private int mNavMode;
     @VisibleForTesting boolean mIsLargeScreen;
 
@@ -133,6 +134,7 @@
         configurationController.addCallback(this);
         mConfigChanges.applyNewConfig(mContext.getResources());
         mNavMode = navigationModeController.addListener(this);
+        mNavBarHelper = navBarHelper;
         mTaskbarDelegate = taskbarDelegate;
         mTaskbarDelegate.setDependencies(commandQueue, overviewProxyService,
                 navBarHelper, navigationModeController, sysUiFlagsContainer,
@@ -241,10 +243,15 @@
 
         if (taskbarEnabled) {
             Trace.beginSection("NavigationBarController#initializeTaskbarIfNecessary");
+            final int displayId = mContext.getDisplayId();
+            // Hint to NavBarHelper if we are replacing an existing bar to skip extra work
+            mNavBarHelper.setTogglingNavbarTaskbar(mNavigationBars.contains(displayId));
             // Remove navigation bar when taskbar is showing
-            removeNavigationBar(mContext.getDisplayId());
-            mTaskbarDelegate.init(mContext.getDisplayId());
+            removeNavigationBar(displayId);
+            mTaskbarDelegate.init(displayId);
+            mNavBarHelper.setTogglingNavbarTaskbar(false);
             Trace.endSection();
+
         } else {
             mTaskbarDelegate.destroy();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java
index 20b5032..1d73bc20 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java
@@ -21,11 +21,7 @@
 import static com.android.systemui.util.Utils.isGesturalModeOnDefaultDisplay;
 
 import android.graphics.Rect;
-import android.os.Handler;
-import android.os.RemoteException;
 import android.util.SparseArray;
-import android.view.IWallpaperVisibilityListener;
-import android.view.IWindowManager;
 import android.view.View;
 
 import com.android.systemui.R;
@@ -36,7 +32,6 @@
 import com.android.systemui.statusbar.phone.LightBarTransitionsController;
 
 import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -63,8 +58,6 @@
     }
 
     private final NavigationBarView mView;
-    @org.jetbrains.annotations.NotNull
-    private final IWindowManager mWindowManagerService;
     private final LightBarTransitionsController mLightTransitionsController;
     private final DisplayTracker mDisplayTracker;
     private final boolean mAllowAutoDimWallpaperNotVisible;
@@ -76,51 +69,20 @@
     private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
     private List<DarkIntensityListener> mDarkIntensityListeners;
 
-    private final Handler mHandler = Handler.getMain();
-
-    static final class WallpaperVisibilityListener extends IWallpaperVisibilityListener.Stub {
-        private final WeakReference<NavigationBarTransitions> mSelf;
-
-        WallpaperVisibilityListener(NavigationBarTransitions self) {
-            mSelf = new WeakReference<>(self);
-        }
-
-        @Override
-        public void onWallpaperVisibilityChanged(boolean newVisibility,
-                int displayId) throws RemoteException {
-            NavigationBarTransitions self = mSelf.get();
-            if (self == null) {
-                return;
-            }
-            self.mWallpaperVisible = newVisibility;
-            self.mHandler.post(() -> self.applyLightsOut(true, false));
-        }
-    }
-
-    private final IWallpaperVisibilityListener mWallpaperVisibilityListener;
-
     @Inject
     public NavigationBarTransitions(
             NavigationBarView view,
-            IWindowManager windowManagerService,
             LightBarTransitionsController.Factory lightBarTransitionsControllerFactory,
             DisplayTracker displayTracker) {
         super(view, R.drawable.nav_background);
 
         mView = view;
-        mWindowManagerService = windowManagerService;
         mLightTransitionsController = lightBarTransitionsControllerFactory.create(this);
         mDisplayTracker = displayTracker;
         mAllowAutoDimWallpaperNotVisible = view.getContext().getResources()
                 .getBoolean(R.bool.config_navigation_bar_enable_auto_dim_no_visible_wallpaper);
         mDarkIntensityListeners = new ArrayList();
 
-        mWallpaperVisibilityListener = new WallpaperVisibilityListener(this);
-        try {
-            mWallpaperVisible = mWindowManagerService.registerWallpaperVisibilityListener(
-                    mWallpaperVisibilityListener, mDisplayTracker.getDefaultDisplayId());
-        } catch (RemoteException e) {
-        }
         mView.addOnLayoutChangeListener(
                 (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
                     View currentView = mView.getCurrentView();
@@ -142,14 +104,14 @@
 
     @Override
     public void destroy() {
-        try {
-            mWindowManagerService.unregisterWallpaperVisibilityListener(mWallpaperVisibilityListener,
-                    mDisplayTracker.getDefaultDisplayId());
-        } catch (RemoteException e) {
-        }
         mLightTransitionsController.destroy();
     }
 
+    void setWallpaperVisibility(boolean visible) {
+        mWallpaperVisible = visible;
+        applyLightsOut(true, false);
+    }
+
     @Override
     public void setAutoDim(boolean autoDim) {
         // Ensure we aren't in gestural nav if we are triggering auto dim
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index 63fb499..5d598e8 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -1093,13 +1093,10 @@
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
-        // This needs to happen first as it can changed the enabled state which can affect whether
-        // the back button is visible
-        mEdgeBackGestureHandler.onNavBarAttached();
         requestApplyInsets();
         reorient();
         if (mRotationButtonController != null) {
-            mRotationButtonController.registerListeners();
+            mRotationButtonController.registerListeners(false /* registerRotationWatcher */);
         }
 
         updateNavButtonIcons();
@@ -1115,8 +1112,6 @@
             mFloatingRotationButton.hide();
             mRotationButtonController.unregisterListeners();
         }
-
-        mEdgeBackGestureHandler.onNavBarDetached();
     }
 
     void dump(PrintWriter pw) {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
index 27e99f7..b96ca7a 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
@@ -92,7 +92,7 @@
         Dumpable {
     private static final String TAG = TaskbarDelegate.class.getSimpleName();
 
-    private final EdgeBackGestureHandler mEdgeBackGestureHandler;
+    private EdgeBackGestureHandler mEdgeBackGestureHandler;
     private final LightBarTransitionsController.Factory mLightBarTransitionsControllerFactory;
     private boolean mInitialized;
     private CommandQueue mCommandQueue;
@@ -170,15 +170,15 @@
     private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
     @Inject
     public TaskbarDelegate(Context context,
-            EdgeBackGestureHandler.Factory edgeBackGestureHandlerFactory,
             LightBarTransitionsController.Factory lightBarTransitionsControllerFactory,
             StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
         mLightBarTransitionsControllerFactory = lightBarTransitionsControllerFactory;
-        mEdgeBackGestureHandler = edgeBackGestureHandlerFactory.create(context);
 
         mContext = context;
         mDisplayManager = mContext.getSystemService(DisplayManager.class);
-        mPipListener = mEdgeBackGestureHandler::setPipStashExclusionBounds;
+        mPipListener = (bounds) -> {
+            mEdgeBackGestureHandler.setPipStashExclusionBounds(bounds);
+        };
         mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
         mStatusBarKeyguardViewManager.setTaskbarDelegate(this);
     }
@@ -206,6 +206,7 @@
         mBackAnimation = backAnimation;
         mLightBarTransitionsController = createLightBarTransitionsController();
         mTaskStackChangeListeners = taskStackChangeListeners;
+        mEdgeBackGestureHandler = navBarHelper.getEdgeBackGestureHandler();
     }
 
     // Separated into a method to keep setDependencies() clean/readable.
@@ -238,8 +239,6 @@
         mOverviewProxyService.addCallback(this);
         onNavigationModeChanged(mNavigationModeController.addListener(this));
         mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
-        mNavBarHelper.init();
-        mEdgeBackGestureHandler.onNavBarAttached();
         // Initialize component callback
         Display display = mDisplayManager.getDisplay(displayId);
         mWindowContext = mContext.createWindowContext(display, TYPE_APPLICATION, null);
@@ -263,8 +262,6 @@
         mOverviewProxyService.removeCallback(this);
         mNavigationModeController.removeListener(this);
         mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
-        mNavBarHelper.destroy();
-        mEdgeBackGestureHandler.onNavBarDetached();
         mScreenPinningNotify = null;
         mWindowContext = null;
         mAutoHideController.setNavigationBar(null);
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt
index f335733..70040c7 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt
@@ -2,19 +2,15 @@
 
 import android.content.Context
 import android.content.res.Configuration
-import android.content.res.TypedArray
 import android.graphics.Canvas
 import android.graphics.Paint
 import android.graphics.Path
 import android.graphics.RectF
 import android.util.MathUtils.min
-import android.util.TypedValue
 import android.view.View
-import androidx.appcompat.view.ContextThemeWrapper
 import androidx.dynamicanimation.animation.FloatPropertyCompat
 import androidx.dynamicanimation.animation.SpringAnimation
 import androidx.dynamicanimation.animation.SpringForce
-import com.android.internal.R.style.Theme_DeviceDefault
 import com.android.internal.util.LatencyTracker
 import com.android.settingslib.Utils
 import com.android.systemui.navigationbar.gestural.BackPanelController.DelayedOnAnimationEndListener
@@ -159,26 +155,21 @@
         val isDeviceInNightTheme = resources.configuration.uiMode and
                 Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
 
-        val colorControlActivated = ContextThemeWrapper(context, Theme_DeviceDefault)
-                .run {
-                    val typedValue = TypedValue()
-                    val a: TypedArray = obtainStyledAttributes(typedValue.data,
-                            intArrayOf(android.R.attr.colorControlActivated))
-                    val color = a.getColor(0, 0)
-                    a.recycle()
-                    color
+        arrowPaint.color = Utils.getColorAttrDefaultColor(context,
+                if (isDeviceInNightTheme) {
+                    com.android.internal.R.attr.colorAccentPrimary
+                } else {
+                    com.android.internal.R.attr.textColorPrimary
                 }
+        )
 
-        val colorPrimary =
-                Utils.getColorAttrDefaultColor(context, com.android.internal.R.attr.colorPrimary)
-
-        arrowPaint.color = Utils.getColorAccentDefaultColor(context)
-
-        arrowBackgroundPaint.color = if (isDeviceInNightTheme) {
-            colorPrimary
-        } else {
-            colorControlActivated
-        }
+        arrowBackgroundPaint.color = Utils.getColorAttrDefaultColor(context,
+                if (isDeviceInNightTheme) {
+                    com.android.internal.R.attr.materialColorOnSecondary
+                } else {
+                    com.android.internal.R.attr.colorAccentSecondary
+                }
+        )
     }
 
     inner class AnimatedFloat(
@@ -414,9 +405,9 @@
     ) {
         horizontalTranslation.updateRestingPosition(restingParams.horizontalTranslation)
         scale.updateRestingPosition(restingParams.scale)
-        arrowAlpha.updateRestingPosition(restingParams.arrowDimens.alpha)
         backgroundAlpha.updateRestingPosition(restingParams.backgroundDimens.alpha)
 
+        arrowAlpha.updateRestingPosition(restingParams.arrowDimens.alpha, animate)
         arrowLength.updateRestingPosition(restingParams.arrowDimens.length, animate)
         arrowHeight.updateRestingPosition(restingParams.arrowDimens.height, animate)
         scalePivotX.updateRestingPosition(restingParams.backgroundDimens.width, animate)
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
index f409b23..80ed08c 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
@@ -55,12 +55,12 @@
 
 internal const val MIN_DURATION_ACTIVE_ANIMATION = 300L
 private const val MIN_DURATION_CANCELLED_ANIMATION = 200L
-private const val MIN_DURATION_COMMITTED_ANIMATION = 200L
+private const val MIN_DURATION_COMMITTED_ANIMATION = 120L
 private const val MIN_DURATION_INACTIVE_BEFORE_FLUNG_ANIMATION = 50L
 private const val MIN_DURATION_CONSIDERED_AS_FLING = 100L
 
 private const val FAILSAFE_DELAY_MS = 350L
-private const val POP_ON_FLING_DELAY = 160L
+private const val POP_ON_FLING_DELAY = 140L
 
 internal val VIBRATE_ACTIVATED_EFFECT =
         VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK)
@@ -148,8 +148,6 @@
     private var gestureSinceActionDown = 0L
     private var gestureEntryTime = 0L
     private var gestureActiveTime = 0L
-    private var gestureInactiveOrEntryTime = 0L
-    private var gestureArrowStrokeVisibleTime = 0L
 
     private val elapsedTimeSinceActionDown
         get() = SystemClock.uptimeMillis() - gestureSinceActionDown
@@ -441,34 +439,44 @@
 
         updateArrowStateOnMove(yTranslation, xTranslation)
 
-        when (currentState) {
-            GestureState.ACTIVE -> {
-                stretchActiveBackIndicator(fullScreenProgress(xTranslation))
-            }
-            GestureState.ENTRY -> {
-                val progress = staticThresholdProgress(xTranslation)
-                stretchEntryBackIndicator(progress)
-
-                params.arrowStrokeAlphaSpring.get(progress).takeIf { it.isNewState }?.let {
-                    mView.popArrowAlpha(0f, it.value)
-                }
-            }
-            GestureState.INACTIVE -> {
-                val progress = reactivationThresholdProgress(totalTouchDelta)
-                stretchInactiveBackIndicator(progress)
-
-                params.arrowStrokeAlphaSpring.get(progress).takeIf { it.isNewState }?.let {
-                    gestureArrowStrokeVisibleTime = SystemClock.uptimeMillis()
-                    mView.popArrowAlpha(0f, it.value)
-                }
-            }
-            else -> {}
+        val gestureProgress = when (currentState) {
+            GestureState.ACTIVE -> fullScreenProgress(xTranslation)
+            GestureState.ENTRY -> staticThresholdProgress(xTranslation)
+            GestureState.INACTIVE -> reactivationThresholdProgress(totalTouchDelta)
+            else -> null
         }
 
-        // set y translation
+        gestureProgress?.let {
+            when (currentState) {
+                GestureState.ACTIVE -> stretchActiveBackIndicator(gestureProgress)
+                GestureState.ENTRY -> stretchEntryBackIndicator(gestureProgress)
+                GestureState.INACTIVE -> stretchInactiveBackIndicator(gestureProgress)
+                else -> {}
+            }
+        }
+
+        setArrowStrokeAlpha(gestureProgress)
         setVerticalTranslation(yOffset)
     }
 
+    private fun setArrowStrokeAlpha(gestureProgress: Float?) {
+        val strokeAlphaProgress = when (currentState) {
+            GestureState.ENTRY -> gestureProgress
+            GestureState.INACTIVE -> gestureProgress
+            GestureState.ACTIVE,
+            GestureState.FLUNG,
+            GestureState.COMMITTED -> 1f
+            GestureState.CANCELLED,
+            GestureState.GONE -> 0f
+        }
+
+        strokeAlphaProgress?.let { progress ->
+            params.arrowStrokeAlphaSpring.get(progress).takeIf { it.isNewState }?.let {
+                mView.popArrowAlpha(0f, it.value)
+            }
+        }
+    }
+
     private fun setVerticalTranslation(yOffset: Float) {
         val yTranslation = abs(yOffset)
         val maxYOffset = (mView.height - params.entryIndicator.backgroundDimens.height) / 2f
@@ -599,7 +607,7 @@
 
     private fun isFlungAwayFromEdge(endX: Float, startX: Float = touchDeltaStartX): Boolean {
         val minDistanceConsideredForFling = ViewConfiguration.get(context).scaledTouchSlop
-        val flingDistance = abs(endX - startX)
+        val flingDistance = if (mView.isLeftPanel) endX - startX else startX - endX
         val isPastFlingVelocity = isDragAwayFromEdge(
                 velocityPxPerSecThreshold =
                 ViewConfiguration.get(context).scaledMinimumFlingVelocity)
@@ -764,7 +772,7 @@
                             GestureState.ENTRY,
                             GestureState.INACTIVE -> params.entryIndicator.arrowDimens
                             GestureState.ACTIVE -> params.activeIndicator.arrowDimens
-                            GestureState.FLUNG,
+                            GestureState.FLUNG -> params.flungIndicator.arrowDimens
                             GestureState.COMMITTED -> params.committedIndicator.arrowDimens
                             GestureState.CANCELLED -> params.cancelledIndicator.arrowDimens
                         },
@@ -825,7 +833,6 @@
 
                 updateRestingArrowDimens()
                 gestureEntryTime = SystemClock.uptimeMillis()
-                gestureInactiveOrEntryTime = SystemClock.uptimeMillis()
             }
             GestureState.ACTIVE -> {
                 previousXTranslationOnActiveOffset = previousXTranslation
@@ -857,7 +864,13 @@
             }
 
             GestureState.INACTIVE -> {
-                gestureInactiveOrEntryTime = SystemClock.uptimeMillis()
+
+                // Typically entering INACTIVE means
+                // totalTouchDelta <= deactivationSwipeTriggerThreshold
+                // but because we can also independently enter this state
+                // if touch Y >> touch X, we force it to deactivationSwipeTriggerThreshold
+                // so that gesture progress in this state is consistent regardless of entry
+                totalTouchDelta = params.deactivationSwipeTriggerThreshold
 
                 val startingVelocity = convertVelocityToSpringStartingVelocity(
                         valueOnFastVelocity = -1.05f,
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 f3d6014..b454c23 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -28,6 +28,7 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.graphics.Insets;
 import android.graphics.PixelFormat;
 import android.graphics.Point;
 import android.graphics.PointF;
@@ -54,6 +55,7 @@
 import android.view.MotionEvent;
 import android.view.Surface;
 import android.view.ViewConfiguration;
+import android.view.WindowInsets;
 import android.view.WindowManager;
 import android.window.BackEvent;
 
@@ -234,6 +236,7 @@
     private boolean mLogGesture = false;
     private boolean mInRejectedExclusion = false;
     private boolean mIsOnLeftEdge;
+    private boolean mDeferSetIsOnLeftEdge;
 
     private boolean mIsAttached;
     private boolean mIsGesturalModeEnabled;
@@ -474,7 +477,7 @@
     }
 
     /**
-     * @see NavigationBarView#onAttachedToWindow()
+     * Called when the nav/task bar is attached.
      */
     public void onNavBarAttached() {
         mIsAttached = true;
@@ -486,7 +489,7 @@
     }
 
     /**
-     * @see NavigationBarView#onDetachedFromWindow()
+     * Called when the nav/task bar is detached.
      */
     public void onNavBarDetached() {
         mIsAttached = false;
@@ -775,6 +778,19 @@
         return true;
     }
 
+    private boolean isValidTrackpadBackGesture(boolean isTrackpadEvent) {
+        if (!isTrackpadEvent) {
+            return false;
+        }
+        // for trackpad gestures, unless the whole screen is excluded region, 3-finger swipe
+        // gestures are allowed even if the cursor is in the excluded region.
+        WindowInsets windowInsets = mWindowManager.getCurrentWindowMetrics().getWindowInsets();
+        Insets insets = windowInsets.getInsets(WindowInsets.Type.systemBars());
+        final Rect excludeBounds = mExcludeRegion.getBounds();
+        return !excludeBounds.contains(insets.left, insets.top, mDisplaySize.x - insets.right,
+                mDisplaySize.y - insets.bottom);
+    }
+
     private boolean isWithinTouchRegion(int x, int y) {
         // If the point is inside the PiP or Nav bar overlay excluded bounds, then ignore the back
         // gesture
@@ -878,7 +894,9 @@
             // either the bouncer is showing or the notification panel is hidden
             mInputEventReceiver.setBatchingEnabled(false);
             if (isTrackpadEvent) {
-                // TODO: show the back arrow based on the direction of the swipe.
+                // Since trackpad gestures don't have zones, this will be determined later by the
+                // direction of the gesture. {@code mIsOnLeftEdge} is set to false to begin with.
+                mDeferSetIsOnLeftEdge = true;
                 mIsOnLeftEdge = false;
             } else {
                 mIsOnLeftEdge = ev.getX() <= mEdgeWidthLeft + mLeftInset;
@@ -893,13 +911,14 @@
                     && (isTrackpadEvent || isWithinInsets)
                     && !mGestureBlockingActivityRunning
                     && !QuickStepContract.isBackGestureDisabled(mSysUiFlags)
-                    && (isTrackpadEvent || isWithinTouchRegion((int) ev.getX(), (int) ev.getY()));
+                    && (isValidTrackpadBackGesture(isTrackpadEvent) || isWithinTouchRegion(
+                    (int) ev.getX(), (int) ev.getY()));
             if (mAllowGesture) {
                 mEdgeBackPlugin.setIsLeftPanel(mIsOnLeftEdge);
                 mEdgeBackPlugin.onMotionEvent(ev);
                 dispatchToBackAnimation(ev);
             }
-            if (mLogGesture) {
+            if (mLogGesture || isTrackpadEvent) {
                 mDownPoint.set(ev.getX(), ev.getY());
                 mEndPoint.set(-1, -1);
                 mThresholdCrossed = false;
@@ -907,9 +926,9 @@
 
             // For debugging purposes, only log edge points
             (isWithinInsets ? mGestureLogInsideInsets : mGestureLogOutsideInsets).log(String.format(
-                    "Gesture [%d,alw=%B,%B,%B,%B,%B,disp=%s,wl=%d,il=%d,wr=%d,ir=%d,excl=%s]",
+                    "Gesture [%d,alw=%B,%B,%B,%B,%B,%B,disp=%s,wl=%d,il=%d,wr=%d,ir=%d,excl=%s]",
                     System.currentTimeMillis(), isTrackpadEvent, mAllowGesture, mIsOnLeftEdge,
-                    mIsBackGestureAllowed,
+                    mDeferSetIsOnLeftEdge, mIsBackGestureAllowed,
                     QuickStepContract.isBackGestureDisabled(mSysUiFlags), mDisplaySize,
                     mEdgeWidthLeft, mLeftInset, mEdgeWidthRight, mRightInset, mExcludeRegion));
         } else if (mAllowGesture || mLogGesture) {
@@ -928,6 +947,14 @@
                     mLogGesture = false;
                     return;
                 } else if (action == MotionEvent.ACTION_MOVE) {
+                    if (isTrackpadEvent && mDeferSetIsOnLeftEdge) {
+                        // mIsOnLeftEdge is determined by the relative position between the down
+                        // and the current motion event for trackpad gestures instead of zoning.
+                        mIsOnLeftEdge = mEndPoint.x > mDownPoint.x;
+                        mEdgeBackPlugin.setIsLeftPanel(mIsOnLeftEdge);
+                        mDeferSetIsOnLeftEdge = false;
+                    }
+
                     if ((ev.getEventTime() - ev.getDownTime()) > mLongPressTimeout) {
                         if (mAllowGesture) {
                             logGesture(SysUiStatsLog.BACK_GESTURE__TYPE__INCOMPLETE_LONG_PRESS);
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt
index 0c00022..d46333a 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt
@@ -9,8 +9,8 @@
 data class EdgePanelParams(private var resources: Resources) {
 
     data class ArrowDimens(
-            val length: Float = 0f,
-            val height: Float = 0f,
+            val length: Float? = 0f,
+            val height: Float? = 0f,
             val alpha: Float = 0f,
             var alphaSpring: SpringForce? = null,
             val heightSpring: SpringForce? = null,
@@ -139,17 +139,17 @@
 
         entryWidthInterpolator = PathInterpolator(.19f, 1.27f, .71f, .86f)
         entryWidthTowardsEdgeInterpolator = PathInterpolator(1f, -3f, 1f, 1.2f)
-        activeWidthInterpolator = PathInterpolator(.15f, .48f, .46f, .89f)
+        activeWidthInterpolator = PathInterpolator(.32f, 0f, .16f, .94f)
         arrowAngleInterpolator = entryWidthInterpolator
         translationInterpolator = PathInterpolator(0.2f, 1.0f, 1.0f, 1.0f)
         farCornerInterpolator = PathInterpolator(.03f, .19f, .14f, 1.09f)
         edgeCornerInterpolator = PathInterpolator(0f, 1.11f, .85f, .84f)
         heightInterpolator = PathInterpolator(1f, .05f, .9f, -0.29f)
 
-        val showArrowOnProgressValue = .2f
+        val showArrowOnProgressValue = .23f
         val showArrowOnProgressValueFactor = 1.05f
 
-        val entryActiveHorizontalTranslationSpring = createSpring(675f, 0.8f)
+        val entryActiveHorizontalTranslationSpring = createSpring(800f, 0.8f)
         val activeCommittedArrowLengthSpring = createSpring(1500f, 0.29f)
         val activeCommittedArrowHeightSpring = createSpring(1500f, 0.29f)
         val flungCommittedEdgeCornerSpring = createSpring(10000f, 1f)
@@ -178,7 +178,7 @@
                         height = getDimen(R.dimen.navigation_edge_entry_background_height),
                         edgeCornerRadius = getDimen(R.dimen.navigation_edge_entry_edge_corners),
                         farCornerRadius = getDimen(R.dimen.navigation_edge_entry_far_corners),
-                        alphaSpring = createSpring(900f, 1f),
+                        alphaSpring = createSpring(1100f, 1f),
                         widthSpring = createSpring(450f, 0.65f),
                         heightSpring = createSpring(1500f, 0.45f),
                         farCornerRadiusSpring = createSpring(300f, 0.5f),
@@ -232,7 +232,7 @@
                                 getDimen(R.dimen.navigation_edge_pre_threshold_edge_corners),
                         farCornerRadius =
                                 getDimen(R.dimen.navigation_edge_pre_threshold_far_corners),
-                        widthSpring = createSpring(200f, 0.65f),
+                        widthSpring = createSpring(250f, 0.65f),
                         heightSpring = createSpring(1500f, 0.45f),
                         farCornerRadiusSpring = createSpring(200f, 1f),
                         edgeCornerRadiusSpring = createSpring(150f, 0.5f),
@@ -244,6 +244,8 @@
                 arrowDimens = activeIndicator.arrowDimens.copy(
                         lengthSpring = activeCommittedArrowLengthSpring,
                         heightSpring = activeCommittedArrowHeightSpring,
+                        length = null,
+                        height = null,
                 ),
                 backgroundDimens = activeIndicator.backgroundDimens.copy(
                         alpha = 0f,
@@ -255,13 +257,15 @@
                         farCornerRadiusSpring = flungCommittedFarCornerSpring,
                 ),
                 scale = 0.85f,
-                scaleSpring = createSpring(650f, 1f),
+                scaleSpring = createSpring(1150f, 1f),
         )
 
         flungIndicator = committedIndicator.copy(
                 arrowDimens = committedIndicator.arrowDimens.copy(
                         lengthSpring = createSpring(850f, 0.46f),
                         heightSpring = createSpring(850f, 0.46f),
+                        length = activeIndicator.arrowDimens.length,
+                        height = activeIndicator.arrowDimens.height
                 ),
                 backgroundDimens = committedIndicator.backgroundDimens.copy(
                         widthSpring = flungCommittedWidthSpring,
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
index f7b7db4..ac22b7c 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
@@ -17,17 +17,23 @@
 package com.android.systemui.notetask
 
 import android.app.KeyguardManager
+import android.app.admin.DevicePolicyManager
 import android.content.ActivityNotFoundException
 import android.content.ComponentName
 import android.content.Context
 import android.content.Intent
+import android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK
+import android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT
+import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
 import android.content.pm.PackageManager
 import android.os.Build
 import android.os.UserManager
 import android.util.Log
 import androidx.annotation.VisibleForTesting
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.devicepolicy.areKeyguardShortcutsDisabled
 import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
+import com.android.systemui.settings.UserTracker
 import com.android.systemui.util.kotlin.getOrNull
 import com.android.wm.shell.bubbles.Bubble
 import com.android.wm.shell.bubbles.Bubbles
@@ -51,9 +57,11 @@
     private val resolver: NoteTaskInfoResolver,
     private val eventLogger: NoteTaskEventLogger,
     private val optionalBubbles: Optional<Bubbles>,
-    private val optionalUserManager: Optional<UserManager>,
-    private val optionalKeyguardManager: Optional<KeyguardManager>,
+    private val userManager: UserManager,
+    private val keyguardManager: KeyguardManager,
     @NoteTaskEnabledKey private val isEnabled: Boolean,
+    private val devicePolicyManager: DevicePolicyManager,
+    private val userTracker: UserTracker,
 ) {
 
     @VisibleForTesting val infoReference = AtomicReference<NoteTaskInfo?>()
@@ -81,39 +89,37 @@
     /**
      * Shows a note task. How the task is shown will depend on when the method is invoked.
      *
-     * If in multi-window mode, notes will open as a full screen experience. That is particularly
-     * important for Large screen devices. These devices may support a taskbar that let users to
-     * drag and drop a shortcut into multi-window mode, and notes should comply with this behaviour.
-     *
      * If the keyguard is locked, notes will open as a full screen experience. A locked device has
      * no contextual information which let us use the whole screen space available.
      *
-     * If not in multi-window or the keyguard is unlocked, notes will open as a bubble OR it will be
-     * collapsed if the notes bubble is already opened.
+     * If the keyguard is unlocked, notes will open as a bubble OR it will be collapsed if the notes
+     * bubble is already opened.
      *
      * That will let users open other apps in full screen, and take contextual notes.
      */
-    @JvmOverloads
     fun showNoteTask(
         entryPoint: NoteTaskEntryPoint,
-        isInMultiWindowMode: Boolean = false,
     ) {
         if (!isEnabled) return
 
         val bubbles = optionalBubbles.getOrNull() ?: return
-        val userManager = optionalUserManager.getOrNull() ?: return
-        val keyguardManager = optionalKeyguardManager.getOrNull() ?: return
 
         // TODO(b/249954038): We should handle direct boot (isUserUnlocked). For now, we do nothing.
         if (!userManager.isUserUnlocked) return
 
-        val info =
-            resolver.resolveInfo(
-                entryPoint = entryPoint,
-                isInMultiWindowMode = isInMultiWindowMode,
-                isKeyguardLocked = keyguardManager.isKeyguardLocked,
-            )
-                ?: return
+        val isKeyguardLocked = keyguardManager.isKeyguardLocked
+        // KeyguardQuickAffordanceInteractor blocks the quick affordance from showing in the
+        // keyguard if it is not allowed by the admin policy. Here we block any other way to show
+        // note task when the screen is locked.
+        if (
+            isKeyguardLocked &&
+                devicePolicyManager.areKeyguardShortcutsDisabled(userId = userTracker.userId)
+        ) {
+            logDebug { "Enterprise policy disallows launching note app when the screen is locked." }
+            return
+        }
+
+        val info = resolver.resolveInfo(entryPoint, isKeyguardLocked) ?: return
 
         infoReference.set(info)
 
@@ -123,12 +129,13 @@
             logDebug { "onShowNoteTask - start: $info" }
             when (info.launchMode) {
                 is NoteTaskLaunchMode.AppBubble -> {
+                    // TODO(b/267634412, b/268351693): Should use `showOrHideAppBubbleAsUser`
                     bubbles.showOrHideAppBubble(intent)
                     // App bubble logging happens on `onBubbleExpandChanged`.
                     logDebug { "onShowNoteTask - opened as app bubble: $info" }
                 }
                 is NoteTaskLaunchMode.Activity -> {
-                    context.startActivity(intent)
+                    context.startActivityAsUser(intent, userTracker.userHandle)
                     eventLogger.logNoteTaskOpened(info)
                     logDebug { "onShowNoteTask - opened as activity: $info" }
                 }
@@ -168,25 +175,25 @@
 
     companion object {
         val TAG = NoteTaskController::class.simpleName.orEmpty()
-
-        // TODO(b/254604589): Use final KeyEvent.KEYCODE_* instead.
-        const val NOTE_TASK_KEY_EVENT = 311
-
-        // TODO(b/265912743): Use Intent.ACTION_CREATE_NOTE instead.
-        const val ACTION_CREATE_NOTE = "android.intent.action.CREATE_NOTE"
-
-        // TODO(b/265912743): Use Intent.INTENT_EXTRA_USE_STYLUS_MODE instead.
-        const val INTENT_EXTRA_USE_STYLUS_MODE = "android.intent.extra.USE_STYLUS_MODE"
     }
 }
 
 private fun createNoteIntent(info: NoteTaskInfo): Intent =
-    Intent(NoteTaskController.ACTION_CREATE_NOTE)
-        .setPackage(info.packageName)
-        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+    Intent(Intent.ACTION_CREATE_NOTE).apply {
+        setPackage(info.packageName)
+
         // EXTRA_USE_STYLUS_MODE does not mean a stylus is in-use, but a stylus entrypoint
         // was used to start it.
-        .putExtra(NoteTaskController.INTENT_EXTRA_USE_STYLUS_MODE, true)
+        putExtra(Intent.EXTRA_USE_STYLUS_MODE, true)
+
+        addFlags(FLAG_ACTIVITY_NEW_TASK)
+        // We should ensure the note experience can be open both as a full screen (lock screen)
+        // and inside the app bubble (contextual). These additional flags will do that.
+        if (info.launchMode == NoteTaskLaunchMode.Activity) {
+            addFlags(FLAG_ACTIVITY_MULTIPLE_TASK)
+            addFlags(FLAG_ACTIVITY_NEW_DOCUMENT)
+        }
+    }
 
 private inline fun logDebug(message: () -> String) {
     if (Build.IS_DEBUGGABLE) {
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEntryPoint.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEntryPoint.kt
index acc537a..2fa8f9a 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEntryPoint.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEntryPoint.kt
@@ -17,7 +17,7 @@
 
 import com.android.systemui.notetask.quickaffordance.NoteTaskQuickAffordanceConfig
 import com.android.systemui.notetask.shortcut.LaunchNoteTaskActivity
-import com.android.systemui.screenshot.AppClipsTrampolineActivity
+import com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity
 
 /**
  * Supported entry points for [NoteTaskController.showNoteTask].
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt
index 28d7647..2b9f0af 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt
@@ -20,12 +20,11 @@
     val packageName: String,
     val uid: Int,
     val entryPoint: NoteTaskEntryPoint? = null,
-    val isInMultiWindowMode: Boolean = false,
     val isKeyguardLocked: Boolean = false,
 ) {
 
     val launchMode: NoteTaskLaunchMode =
-        if (isInMultiWindowMode || isKeyguardLocked) {
+        if (isKeyguardLocked) {
             NoteTaskLaunchMode.Activity
         } else {
             NoteTaskLaunchMode.AppBubble
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt
index b5d757c..8ecf081 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt
@@ -17,28 +17,29 @@
 package com.android.systemui.notetask
 
 import android.app.role.RoleManager
-import android.content.Context
 import android.content.pm.PackageManager
 import android.content.pm.PackageManager.ApplicationInfoFlags
 import android.os.UserHandle
 import android.util.Log
+import com.android.systemui.settings.UserTracker
 import javax.inject.Inject
 
 class NoteTaskInfoResolver
 @Inject
 constructor(
-    private val context: Context,
     private val roleManager: RoleManager,
     private val packageManager: PackageManager,
+    private val userTracker: UserTracker,
 ) {
+
     fun resolveInfo(
         entryPoint: NoteTaskEntryPoint? = null,
-        isInMultiWindowMode: Boolean = false,
         isKeyguardLocked: Boolean = false,
     ): NoteTaskInfo? {
         // TODO(b/267634412): Select UserHandle depending on where the user initiated note-taking.
-        val user = context.user
-        val packageName = roleManager.getRoleHoldersAsUser(ROLE_NOTES, user).firstOrNull()
+        val user = userTracker.userHandle
+        val packageName =
+            roleManager.getRoleHoldersAsUser(RoleManager.ROLE_NOTES, user).firstOrNull()
 
         if (packageName.isNullOrEmpty()) return null
 
@@ -46,7 +47,6 @@
             packageName = packageName,
             uid = packageManager.getUidOf(packageName, user),
             entryPoint = entryPoint,
-            isInMultiWindowMode = isInMultiWindowMode,
             isKeyguardLocked = isKeyguardLocked,
         )
     }
@@ -54,9 +54,6 @@
     companion object {
         private val TAG = NoteTaskInfoResolver::class.simpleName.orEmpty()
 
-        // TODO(b/265912743): Use RoleManager.NOTES_ROLE instead.
-        const val ROLE_NOTES = "android.app.role.NOTES"
-
         private val EMPTY_APPLICATION_INFO_FLAGS = ApplicationInfoFlags.of(0)!!
 
         /**
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt
index 3f4f8d5..fb3c0cb 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt
@@ -15,6 +15,7 @@
  */
 package com.android.systemui.notetask
 
+import android.view.KeyEvent
 import androidx.annotation.VisibleForTesting
 import com.android.systemui.statusbar.CommandQueue
 import com.android.wm.shell.bubbles.Bubbles
@@ -35,7 +36,7 @@
     val callbacks =
         object : CommandQueue.Callbacks {
             override fun handleSystemKey(keyCode: Int) {
-                if (keyCode == NoteTaskController.NOTE_TASK_KEY_EVENT) {
+                if (keyCode == KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL) {
                     controller.showNoteTask(NoteTaskEntryPoint.TAIL_BUTTON)
                 }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
index f16110d..6278c69 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
@@ -17,11 +17,7 @@
 package com.android.systemui.notetask
 
 import android.app.Activity
-import android.app.KeyguardManager
 import android.app.role.RoleManager
-import android.content.Context
-import android.os.UserManager
-import androidx.core.content.getSystemService
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
 import com.android.systemui.notetask.quickaffordance.NoteTaskQuickAffordanceModule
@@ -32,7 +28,6 @@
 import dagger.Provides
 import dagger.multibindings.ClassKey
 import dagger.multibindings.IntoMap
-import java.util.Optional
 
 /** Compose all dependencies required by Note Task feature. */
 @Module(includes = [NoteTaskQuickAffordanceModule::class])
@@ -51,19 +46,9 @@
             featureFlags: FeatureFlags,
             roleManager: RoleManager,
         ): Boolean {
-            val isRoleAvailable = roleManager.isRoleAvailable(NoteTaskInfoResolver.ROLE_NOTES)
+            val isRoleAvailable = roleManager.isRoleAvailable(RoleManager.ROLE_NOTES)
             val isFeatureEnabled = featureFlags.isEnabled(Flags.NOTE_TASKS)
             return isRoleAvailable && isFeatureEnabled
         }
-
-        @Provides
-        fun provideOptionalKeyguardManager(context: Context): Optional<KeyguardManager> {
-            return Optional.ofNullable(context.getSystemService())
-        }
-
-        @Provides
-        fun provideOptionalUserManager(context: Context): Optional<UserManager> {
-            return Optional.ofNullable(context.getSystemService())
-        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/OWNERS b/packages/SystemUI/src/com/android/systemui/notetask/OWNERS
index 7ccb316..0ec996b 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/OWNERS
+++ b/packages/SystemUI/src/com/android/systemui/notetask/OWNERS
@@ -5,4 +5,6 @@
 madym@google.com
 mgalhardo@google.com
 petrcermak@google.com
+stevenckng@google.com
+tkachenkoi@google.com
 vanjan@google.com
\ No newline at end of file
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 30660c4..8aed995 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.notetask.quickaffordance
 
 import android.content.Context
+import android.hardware.input.InputSettings
 import com.android.systemui.R
 import com.android.systemui.animation.Expandable
 import com.android.systemui.common.shared.model.ContentDescription
@@ -26,36 +27,52 @@
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.LockScreenState
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.OnTriggeredResult
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.PickerScreenState
+import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
 import com.android.systemui.notetask.NoteTaskController
 import com.android.systemui.notetask.NoteTaskEnabledKey
 import com.android.systemui.notetask.NoteTaskEntryPoint
+import com.android.systemui.stylus.StylusManager
+import dagger.Lazy
 import javax.inject.Inject
-import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.channels.trySendBlocking
+import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.map
 
 class NoteTaskQuickAffordanceConfig
 @Inject
 constructor(
     context: Context,
-    private val noteTaskController: NoteTaskController,
+    private val controller: NoteTaskController,
+    private val stylusManager: StylusManager,
+    private val lazyRepository: Lazy<KeyguardQuickAffordanceRepository>,
     @NoteTaskEnabledKey private val isEnabled: Boolean,
 ) : KeyguardQuickAffordanceConfig {
 
     override val key = BuiltInKeyguardQuickAffordanceKeys.CREATE_NOTE
 
-    override val pickerName: String = context.getString(R.string.note_task_button_label)
+    private val pickerNameResourceId = R.string.note_task_button_label
+
+    override val pickerName: String = context.getString(pickerNameResourceId)
 
     override val pickerIconResourceId = R.drawable.ic_note_task_shortcut_keyguard
 
-    override val lockScreenState = flowOf(getLockScreenState())
-
-    // TODO(b/265949213)
-    private fun getLockScreenState() =
-        if (isEnabled) {
-            val icon = Icon.Resource(pickerIconResourceId, ContentDescription.Loaded(pickerName))
-            LockScreenState.Visible(icon)
-        } else {
-            LockScreenState.Hidden
+    // Due to a dependency cycle with KeyguardQuickAffordanceRepository, we need to lazily access
+    // the repository when lockScreenState is accessed for the first time.
+    override val lockScreenState by lazy {
+        val stylusEverUsedFlow = createStylusEverUsedFlow(context, stylusManager)
+        val configSelectedFlow = createConfigSelectedFlow(lazyRepository.get(), key)
+        combine(configSelectedFlow, stylusEverUsedFlow) { isSelected, isStylusEverUsed ->
+            if (isEnabled && (isSelected || isStylusEverUsed)) {
+                val contentDescription = ContentDescription.Resource(pickerNameResourceId)
+                val icon = Icon.Resource(pickerIconResourceId, contentDescription)
+                LockScreenState.Visible(icon)
+            } else {
+                LockScreenState.Hidden
+            }
         }
+    }
 
     override suspend fun getPickerScreenState() =
         if (isEnabled) {
@@ -65,9 +82,27 @@
         }
 
     override fun onTriggered(expandable: Expandable?): OnTriggeredResult {
-        noteTaskController.showNoteTask(
+        controller.showNoteTask(
             entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE,
         )
         return OnTriggeredResult.Handled
     }
 }
+
+private fun createStylusEverUsedFlow(context: Context, stylusManager: StylusManager) =
+    callbackFlow {
+        trySendBlocking(InputSettings.isStylusEverUsed(context))
+        val callback =
+            object : StylusManager.StylusCallback {
+                override fun onStylusFirstUsed() {
+                    trySendBlocking(InputSettings.isStylusEverUsed(context))
+                }
+            }
+        stylusManager.registerCallback(callback)
+        awaitClose { stylusManager.unregisterCallback(callback) }
+    }
+
+private fun createConfigSelectedFlow(repository: KeyguardQuickAffordanceRepository, key: String) =
+    repository.selections.map { selected ->
+        selected.values.flatten().any { selectedConfig -> selectedConfig.key == key }
+    }
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
index 0a1d008..5c59532 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
@@ -17,8 +17,10 @@
 package com.android.systemui.notetask.shortcut
 
 import android.app.Activity
+import android.app.role.RoleManager
 import android.content.Intent
 import android.os.Bundle
+import android.os.PersistableBundle
 import androidx.activity.ComponentActivity
 import androidx.annotation.DrawableRes
 import androidx.core.content.pm.ShortcutInfoCompat
@@ -33,10 +35,14 @@
  * launched, creating a new shortcut for [CreateNoteTaskShortcutActivity], and will finish.
  *
  * @see <a
- * href="https://developer.android.com/develop/ui/views/launch/shortcuts/creating-shortcuts#custom-pinned">Creating
- * a custom shortcut activity</a>
+ *   href="https://developer.android.com/develop/ui/views/launch/shortcuts/creating-shortcuts#custom-pinned">Creating
+ *   a custom shortcut activity</a>
  */
-class CreateNoteTaskShortcutActivity @Inject constructor() : ComponentActivity() {
+class CreateNoteTaskShortcutActivity
+@Inject
+constructor(
+    private val roleManager: RoleManager,
+) : ComponentActivity() {
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
@@ -59,12 +65,19 @@
         intent: Intent,
         @DrawableRes iconResource: Int,
     ): Intent {
+        val extras = PersistableBundle()
+
+        roleManager.getRoleHoldersAsUser(RoleManager.ROLE_NOTES, user).firstOrNull()?.let { name ->
+            extras.putString(EXTRA_SHORTCUT_BADGE_OVERRIDE_PACKAGE, name)
+        }
+
         val shortcutInfo =
             ShortcutInfoCompat.Builder(this, id)
                 .setIntent(intent)
                 .setShortLabel(shortLabel)
                 .setLongLived(true)
                 .setIcon(IconCompat.createWithResource(this, iconResource))
+                .setExtras(extras)
                 .build()
 
         return ShortcutManagerCompat.createShortcutResultIntent(
@@ -75,5 +88,16 @@
 
     private companion object {
         private const val SHORTCUT_ID = "note-task-shortcut-id"
+
+        /**
+         * Shortcut extra which can point to a package name and can be used to indicate an alternate
+         * badge info. Launcher only reads this if the shortcut comes from a system app.
+         *
+         * Duplicated from [com.android.launcher3.icons.IconCache].
+         *
+         * @see com.android.launcher3.icons.IconCache.EXTRA_SHORTCUT_BADGE_OVERRIDE_PACKAGE
+         */
+        private const val EXTRA_SHORTCUT_BADGE_OVERRIDE_PACKAGE =
+            "extra_shortcut_badge_override_package"
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
index 2b84bf8..14b0779 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
@@ -28,17 +28,12 @@
 class LaunchNoteTaskActivity
 @Inject
 constructor(
-    private val noteTaskController: NoteTaskController,
+    private val controller: NoteTaskController,
 ) : ComponentActivity() {
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
-
-        noteTaskController.showNoteTask(
-            entryPoint = NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT,
-            isInMultiWindowMode = isInMultiWindowMode,
-        )
-
+        controller.showNoteTask(entryPoint = NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT)
         finish()
     }
 
@@ -49,7 +44,7 @@
             return Intent(context, LaunchNoteTaskActivity::class.java).apply {
                 // Intent's action must be set in shortcuts, or an exception will be thrown.
                 // TODO(b/254606432): Use Intent.ACTION_CREATE_NOTE instead.
-                action = NoteTaskController.ACTION_CREATE_NOTE
+                action = Intent.ACTION_CREATE_NOTE
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index 2522e1c..7a42642 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -154,6 +154,7 @@
     private final Intent mOpenBatterySettings = settings(Intent.ACTION_POWER_USAGE_SUMMARY);
     private final Intent mOpenBatterySaverSettings =
             settings(Settings.ACTION_BATTERY_SAVER_SETTINGS);
+    private final boolean mUseExtraSaverConfirmation;
 
     private int mBatteryLevel;
     private int mBucket;
@@ -197,6 +198,8 @@
         mDialogLaunchAnimator = dialogLaunchAnimator;
         mUiEventLogger = uiEventLogger;
         mUserTracker = userTracker;
+        mUseExtraSaverConfirmation =
+                mContext.getResources().getBoolean(R.bool.config_extra_battery_saver_confirmation);
     }
 
     @Override
@@ -644,7 +647,7 @@
     }
 
     private void showStartSaverConfirmation(Bundle extras) {
-        if (mSaverConfirmation != null) return;
+        if (mSaverConfirmation != null || mUseExtraSaverConfirmation) return;
         final SystemUIDialog d = new SystemUIDialog(mContext);
         final boolean confirmOnly = extras.getBoolean(BatterySaverUtils.EXTRA_CONFIRM_TEXT_ONLY);
         final int batterySaverTriggerMode =
@@ -679,6 +682,10 @@
                                 resolver,
                                 Secure.LOW_POWER_WARNING_ACKNOWLEDGED,
                                 1, mUserTracker.getUserId());
+                        Secure.putIntForUser(
+                                resolver,
+                                Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED,
+                                1, mUserTracker.getUserId());
                     });
         } else {
             d.setTitle(R.string.battery_saver_confirmation_title);
diff --git a/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt b/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt
index ff3ec72..d40112f 100644
--- a/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt
@@ -26,8 +26,7 @@
 @Module
 interface QRCodeScannerModule {
 
-    /**
-     */
+    /**  */
     @Binds
     @IntoMap
     @StringKey(QRCodeScannerTile.TILE_SPEC)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index e55445c..baa812c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -50,6 +50,8 @@
 import com.android.systemui.animation.ShadeInterpolation;
 import com.android.systemui.compose.ComposeFacade;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.media.controls.ui.MediaHost;
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.plugins.qs.QSContainerController;
@@ -59,6 +61,7 @@
 import com.android.systemui.qs.footer.ui.binder.FooterActionsViewBinder;
 import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel;
 import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -111,6 +114,8 @@
     private final MediaHost mQqsMediaHost;
     private final QSFragmentComponent.Factory mQsComponentFactory;
     private final QSFragmentDisableFlagsLogger mQsFragmentDisableFlagsLogger;
+    private final LargeScreenShadeInterpolator mLargeScreenShadeInterpolator;
+    private final FeatureFlags mFeatureFlags;
     private final QSLogger mLogger;
     private final FooterActionsController mFooterActionsController;
     private final FooterActionsViewModel.Factory mFooterActionsViewModelFactory;
@@ -158,12 +163,7 @@
     // visible;
     private boolean mQsVisible;
 
-    /**
-     * Whether the notification panel uses the full width of the screen.
-     *
-     * Usually {@code true} on small screens, and {@code false} on large screens.
-     */
-    private boolean mIsNotificationPanelFullWidth;
+    private boolean mIsSmallScreen;
 
     @Inject
     public QSFragment(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,
@@ -175,13 +175,17 @@
             QSFragmentDisableFlagsLogger qsFragmentDisableFlagsLogger,
             DumpManager dumpManager, QSLogger qsLogger,
             FooterActionsController footerActionsController,
-            FooterActionsViewModel.Factory footerActionsViewModelFactory) {
+            FooterActionsViewModel.Factory footerActionsViewModelFactory,
+            LargeScreenShadeInterpolator largeScreenShadeInterpolator,
+            FeatureFlags featureFlags) {
         mRemoteInputQuickSettingsDisabler = remoteInputQsDisabler;
         mQsMediaHost = qsMediaHost;
         mQqsMediaHost = qqsMediaHost;
         mQsComponentFactory = qsComponentFactory;
         mQsFragmentDisableFlagsLogger = qsFragmentDisableFlagsLogger;
         mLogger = qsLogger;
+        mLargeScreenShadeInterpolator = largeScreenShadeInterpolator;
+        mFeatureFlags = featureFlags;
         commandQueue.observe(getLifecycle(), this);
         mBypassController = keyguardBypassController;
         mStatusBarStateController = statusBarStateController;
@@ -606,7 +610,7 @@
 
     @Override
     public void setIsNotificationPanelFullWidth(boolean isFullWidth) {
-        mIsNotificationPanelFullWidth = isFullWidth;
+        mIsSmallScreen = isFullWidth;
     }
 
     @Override
@@ -709,7 +713,7 @@
     }
 
     private float calculateAlphaProgress(float panelExpansionFraction) {
-        if (mIsNotificationPanelFullWidth) {
+        if (mIsSmallScreen) {
             // Small screens. QS alpha is not animated.
             return 1;
         }
@@ -744,7 +748,12 @@
             // Alpha progress should be linear on lockscreen shade expansion.
             return progress;
         }
-        return ShadeInterpolation.getContentAlpha(progress);
+        if (mIsSmallScreen || !mFeatureFlags.isEnabled(
+                Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)) {
+            return ShadeInterpolation.getContentAlpha(progress);
+        } else {
+            return mLargeScreenShadeInterpolator.getQsAlpha(progress);
+        }
     }
 
     @VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 7c2536d..d4854e1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -328,7 +328,7 @@
             if (listening) {
                 updateDefaultTileAndIcon();
                 refreshState();
-                if (!mServiceManager.isActiveTile()) {
+                if (!mServiceManager.isActiveTile() || !isTileReady()) {
                     mServiceManager.setBindRequested(true);
                     mService.onStartListening();
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index e86bd7a..9f93e49 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -76,7 +76,8 @@
         this(tileServices, handler, userTracker, new TileLifecycleManager(handler,
                 tileServices.getContext(), tileServices,
                 new PackageManagerAdapter(tileServices.getContext()), broadcastDispatcher,
-                new Intent().setComponent(component), userTracker.getUserHandle()));
+                new Intent(TileService.ACTION_QS_TILE).setComponent(component),
+                userTracker.getUserHandle()));
     }
 
     @VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt
index 03bb7a0..8387c1d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt
@@ -71,8 +71,8 @@
     /**
      * Show the device monitoring dialog, expanded from [expandable] if it's not null.
      *
-     * Important: [quickSettingsContext] *must* be the [Context] associated to the [Quick Settings
-     * fragment][com.android.systemui.qs.QSFragment].
+     * Important: [quickSettingsContext] *must* be the [Context] associated to the
+     * [Quick Settings fragment][com.android.systemui.qs.QSFragment].
      */
     fun showDeviceMonitoringDialog(quickSettingsContext: Context, expandable: Expandable?)
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt
index fbf32b3..f170ac1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt
@@ -196,9 +196,9 @@
      * Observe the device monitoring dialog requests and show the dialog accordingly. This function
      * will suspend indefinitely and will need to be cancelled to stop observing.
      *
-     * Important: [quickSettingsContext] must be the [Context] associated to the [Quick Settings
-     * fragment][com.android.systemui.qs.QSFragment], and the call to this function must be
-     * cancelled when that fragment is destroyed.
+     * Important: [quickSettingsContext] must be the [Context] associated to the
+     * [Quick Settings fragment][com.android.systemui.qs.QSFragment], and the call to this function
+     * must be cancelled when that fragment is destroyed.
      */
     suspend fun observeDeviceMonitoringDialogRequests(quickSettingsContext: Context) {
         footerActionsInteractor.deviceMonitoringDialogRequests.collect {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 25ff308b..8a3ecc6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -31,6 +31,8 @@
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DOZING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DREAMING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_ON;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_TRANSITION;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TRACING_ENABLED;
@@ -121,7 +123,8 @@
 public class OverviewProxyService implements CallbackController<OverviewProxyListener>,
         NavigationModeController.ModeChangedListener, Dumpable {
 
-    private static final String ACTION_QUICKSTEP = "android.intent.action.QUICKSTEP_SERVICE";
+    @VisibleForTesting
+    static final String ACTION_QUICKSTEP = "android.intent.action.QUICKSTEP_SERVICE";
 
     public static final String TAG_OPS = "OverviewProxyService";
     private static final long BACKOFF_MILLIS = 1000;
@@ -548,6 +551,7 @@
         mUiEventLogger = uiEventLogger;
         mDisplayTracker = displayTracker;
         mUnfoldTransitionProgressForwarder = unfoldTransitionProgressForwarder;
+        mSysuiUnlockAnimationController = sysuiUnlockAnimationController;
 
         dumpManager.registerDumpable(getClass().getSimpleName(), this);
 
@@ -596,7 +600,6 @@
         // Connect to the service
         updateEnabledState();
         startConnectionToCurrentUser();
-        mSysuiUnlockAnimationController = sysuiUnlockAnimationController;
 
         // Listen for assistant changes
         assistUtils.registerVoiceInteractionSessionListener(mVoiceInteractionSessionListener);
@@ -631,7 +634,9 @@
         final NavigationBarView navBarView =
                 mNavBarControllerLazy.get().getNavigationBarView(mContext.getDisplayId());
         final NotificationPanelViewController panelController =
-                mCentralSurfacesOptionalLazy.get().get().getNotificationPanelViewController();
+                mCentralSurfacesOptionalLazy.get()
+                        .map(CentralSurfaces::getNotificationPanelViewController)
+                        .orElse(null);
         if (SysUiState.DEBUG) {
             Log.d(TAG_OPS, "Updating sysui state flags: navBarFragment=" + navBarFragment
                     + " navBarView=" + navBarView + " panelController=" + panelController);
@@ -724,10 +729,8 @@
             return;
         }
         mHandler.removeCallbacks(mConnectionRunnable);
-        Intent launcherServiceIntent = new Intent(ACTION_QUICKSTEP)
-                .setPackage(mRecentsComponentName.getPackageName());
         try {
-            mBound = mContext.bindServiceAsUser(launcherServiceIntent,
+            mBound = mContext.bindServiceAsUser(mQuickStepIntent,
                     mOverviewServiceConnection,
                     Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
                     UserHandle.of(mUserTracker.getUserId()));
@@ -860,6 +863,11 @@
          */
         @Override
         public void onScreenTurnedOn() {
+            mSysUiState
+                .setFlag(SYSUI_STATE_SCREEN_ON, true)
+                .setFlag(SYSUI_STATE_SCREEN_TRANSITION, false)
+                .commitUpdate(mContext.getDisplayId());
+
             try {
                 if (mOverviewProxy != null) {
                     mOverviewProxy.onScreenTurnedOn();
@@ -872,10 +880,26 @@
         }
 
         /**
+         * Notifies the Launcher that screen turned off.
+         */
+        @Override
+        public void onScreenTurnedOff() {
+            mSysUiState
+                .setFlag(SYSUI_STATE_SCREEN_ON, false)
+                .setFlag(SYSUI_STATE_SCREEN_TRANSITION, false)
+                .commitUpdate(mContext.getDisplayId());
+        }
+
+        /**
          * Notifies the Launcher that screen is starting to turn on.
          */
         @Override
         public void onScreenTurningOff() {
+            mSysUiState
+                .setFlag(SYSUI_STATE_SCREEN_ON, false)
+                .setFlag(SYSUI_STATE_SCREEN_TRANSITION, true)
+                .commitUpdate(mContext.getDisplayId());
+
             try {
                 if (mOverviewProxy != null) {
                     mOverviewProxy.onScreenTurningOff();
@@ -892,6 +916,11 @@
          */
         @Override
         public void onScreenTurningOn() {
+            mSysUiState
+                .setFlag(SYSUI_STATE_SCREEN_ON, true)
+                .setFlag(SYSUI_STATE_SCREEN_TRANSITION, true)
+                .commitUpdate(mContext.getDisplayId());
+
             try {
                 if (mOverviewProxy != null) {
                     mOverviewProxy.onScreenTurningOn();
@@ -1003,4 +1032,21 @@
         default void onAssistantGestureCompletion(float velocity) {}
         default void startAssistant(Bundle bundle) {}
     }
+
+    /**
+     * Shuts down this service at the end of a testcase.
+     * <p>
+     * The in-production service is never shuts down, and it was not designed with testing in mind.
+     * This unregisters the mechanisms by which the service will be revived after a testcase.
+     * <p>
+     * NOTE: This is a stop-gap introduced when first added some tests to this class. It should
+     * probably be replaced by proper lifecycle management on this class.
+     */
+    @VisibleForTesting()
+    void shutdownForTest() {
+        mContext.unregisterReceiver(mLauncherStateChangedReceiver);
+        mIsEnabled = false;
+        mHandler.removeCallbacks(mConnectionRunnable);
+        disconnectFromLauncherService();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
index dd21be9..30509e2 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
@@ -124,8 +124,9 @@
 
     /**
      * Starts screen capture after some countdown
+     *
      * @param captureTarget target to capture (could be e.g. a task) or null to record the whole
-     * screen
+     *   screen
      */
     private fun requestScreenCapture(captureTarget: MediaProjectionCaptureTarget?) {
         val userContext = userContextProvider.userContext
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt
index 310baaf..a8f99be 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt
@@ -70,7 +70,7 @@
 
     /**
      * @return an ACTION_EDIT intent for the given URI, directed to config_screenshotEditor if
-     * available.
+     *   available.
      */
     fun createEditIntent(uri: Uri, context: Context): Intent {
         val editIntent = Intent(Intent.ACTION_EDIT)
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/DraggableConstraintLayout.java b/packages/SystemUI/src/com/android/systemui/screenshot/DraggableConstraintLayout.java
index ead3b7b..0b4b7c6 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/DraggableConstraintLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/DraggableConstraintLayout.java
@@ -45,6 +45,7 @@
         implements ViewTreeObserver.OnComputeInternalInsetsListener {
 
     private static final float VELOCITY_DP_PER_MS = 1;
+    private static final int MAXIMUM_DISMISS_DISTANCE_DP = 400;
 
     private final SwipeDismissHandler mSwipeDismissHandler;
     private final GestureDetector mSwipeDetector;
@@ -347,14 +348,18 @@
             } else {
                 finalX = -1 * getBackgroundRight();
             }
-            float distance = Math.abs(finalX - startX);
+            float distance = Math.min(Math.abs(finalX - startX),
+                    FloatingWindowUtil.dpToPx(mDisplayMetrics, MAXIMUM_DISMISS_DISTANCE_DP));
+            // ensure that view dismisses in the right direction (right in LTR, left in RTL)
+            float distanceVector = Math.copySign(distance, finalX - startX);
 
             anim.addUpdateListener(animation -> {
-                float translation = MathUtils.lerp(startX, finalX, animation.getAnimatedFraction());
+                float translation = MathUtils.lerp(
+                        startX, startX + distanceVector, animation.getAnimatedFraction());
                 mView.setTranslationX(translation);
                 mView.setAlpha(1 - animation.getAnimatedFraction());
             });
-            anim.setDuration((long) (distance / Math.abs(velocity)));
+            anim.setDuration((long) (Math.abs(distance / velocity)));
             return anim;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java b/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java
index c8c1337..7cfe232 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java
@@ -57,7 +57,8 @@
 
 import javax.inject.Inject;
 
-class ImageExporter {
+/** A class to help with exporting screenshot to storage. */
+public class ImageExporter {
     private static final String TAG = LogConfig.logTag(ImageExporter.class);
 
     static final Duration PENDING_ENTRY_TTL = Duration.ofHours(24);
@@ -90,7 +91,7 @@
     private final FeatureFlags mFlags;
 
     @Inject
-    ImageExporter(ContentResolver resolver, FeatureFlags flags) {
+    public ImageExporter(ContentResolver resolver, FeatureFlags flags) {
         mResolver = resolver;
         mFlags = flags;
     }
@@ -148,7 +149,7 @@
      *
      * @return a listenable future result
      */
-    ListenableFuture<Result> export(Executor executor, UUID requestId, Bitmap bitmap,
+    public ListenableFuture<Result> export(Executor executor, UUID requestId, Bitmap bitmap,
             UserHandle owner) {
         return export(executor, requestId, bitmap, ZonedDateTime.now(), owner);
     }
@@ -181,13 +182,14 @@
         );
     }
 
-    static class Result {
-        Uri uri;
-        UUID requestId;
-        String fileName;
-        long timestamp;
-        CompressFormat format;
-        boolean published;
+    /** The result returned by the task exporting screenshots to storage. */
+    public static class Result {
+        public Uri uri;
+        public UUID requestId;
+        public String fileName;
+        public long timestamp;
+        public CompressFormat format;
+        public boolean published;
 
         @Override
         public String toString() {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 8721d71..557e95c 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -419,6 +419,10 @@
             return;
         }
 
+        mScreenBitmap = screenshot.getBitmap();
+        String oldPackageName = mPackageName;
+        mPackageName = screenshot.getPackageNameString();
+
         if (!isUserSetupComplete(Process.myUserHandle())) {
             Log.w(TAG, "User setup not complete, displaying toast only");
             // User setup isn't complete, so we don't want to show any UI beyond a toast, as editing
@@ -433,10 +437,6 @@
         mScreenshotTakenInPortrait =
                 mContext.getResources().getConfiguration().orientation == ORIENTATION_PORTRAIT;
 
-        String oldPackageName = mPackageName;
-        mPackageName = screenshot.getPackageNameString();
-
-        mScreenBitmap = screenshot.getBitmap();
         // Optimizations
         mScreenBitmap.setHasAlpha(false);
         mScreenBitmap.prepareToDraw();
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
index fc94aed..7a62bae 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
@@ -93,13 +93,7 @@
     @UiEvent(doc = "User has discarded the result of a long screenshot")
     SCREENSHOT_LONG_SCREENSHOT_EXIT(911),
     @UiEvent(doc = "A screenshot has been taken and saved to work profile")
-    SCREENSHOT_SAVED_TO_WORK_PROFILE(1240),
-    @UiEvent(doc = "Notes application triggered the screenshot for notes")
-    SCREENSHOT_FOR_NOTE_TRIGGERED(1308),
-    @UiEvent(doc = "User accepted the screenshot to be sent to the notes app")
-    SCREENSHOT_FOR_NOTE_ACCEPTED(1309),
-    @UiEvent(doc = "User cancelled the screenshot for notes app flow")
-    SCREENSHOT_FOR_NOTE_CANCELLED(1310);
+    SCREENSHOT_SAVED_TO_WORK_PROFILE(1240);
 
     private final int mId;
 
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt
index 1b728b8..236213c 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt
@@ -44,7 +44,7 @@
 
     /**
      * @return a populated WorkProfileFirstRunData object if a work profile first run message should
-     * be shown
+     *   be shown
      */
     fun onScreenshotTaken(userHandle: UserHandle?): WorkProfileFirstRunData? {
         if (userHandle == null) return null
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsActivity.java
index 3133924..4756cc8 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsActivity.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.systemui.screenshot;
+package com.android.systemui.screenshot.appclips;
 
-import static com.android.systemui.screenshot.AppClipsTrampolineActivity.ACTION_FINISH_FROM_TRAMPOLINE;
-import static com.android.systemui.screenshot.AppClipsTrampolineActivity.EXTRA_CALLING_PACKAGE_NAME;
-import static com.android.systemui.screenshot.AppClipsTrampolineActivity.EXTRA_RESULT_RECEIVER;
-import static com.android.systemui.screenshot.AppClipsTrampolineActivity.EXTRA_SCREENSHOT_URI;
-import static com.android.systemui.screenshot.AppClipsTrampolineActivity.PERMISSION_SELF;
-import static com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_FOR_NOTE_ACCEPTED;
-import static com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_FOR_NOTE_CANCELLED;
+import static com.android.systemui.screenshot.appclips.AppClipsEvent.SCREENSHOT_FOR_NOTE_ACCEPTED;
+import static com.android.systemui.screenshot.appclips.AppClipsEvent.SCREENSHOT_FOR_NOTE_CANCELLED;
+import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.ACTION_FINISH_FROM_TRAMPOLINE;
+import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.EXTRA_CALLING_PACKAGE_NAME;
+import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.EXTRA_RESULT_RECEIVER;
+import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.EXTRA_SCREENSHOT_URI;
+import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.PERMISSION_SELF;
 
 import android.app.Activity;
 import android.content.BroadcastReceiver;
@@ -52,6 +52,8 @@
 import com.android.internal.logging.UiEventLogger.UiEventEnum;
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
+import com.android.systemui.screenshot.CropView;
+import com.android.systemui.screenshot.MagnifierView;
 import com.android.systemui.settings.UserTracker;
 
 import javax.inject.Inject;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsCrossProcessHelper.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsCrossProcessHelper.java
index 65fb4c9..e1619dc 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsCrossProcessHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsCrossProcessHelper.java
@@ -32,12 +32,12 @@
 
 /** An intermediary singleton object to help communicating with the cross process service. */
 @SysUISingleton
-public class AppClipsCrossProcessHelper {
+class AppClipsCrossProcessHelper {
 
     private final ServiceConnector<IAppClipsScreenshotHelperService> mProxyConnector;
 
     @Inject
-    public AppClipsCrossProcessHelper(@Application Context context) {
+    AppClipsCrossProcessHelper(@Application Context context) {
         mProxyConnector = new ServiceConnector.Impl<IAppClipsScreenshotHelperService>(context,
                 new Intent(context, AppClipsScreenshotHelperService.class),
                 Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY
@@ -52,7 +52,7 @@
      * pass around but not a {@link Bitmap}.
      */
     @Nullable
-    public Bitmap takeScreenshot() {
+    Bitmap takeScreenshot() {
         try {
             AndroidFuture<ScreenshotHardwareBufferInternal> future =
                     mProxyConnector.postForResult(
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsEvent.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsEvent.java
new file mode 100644
index 0000000..7a085b9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsEvent.java
@@ -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.screenshot.appclips;
+
+import com.android.internal.logging.UiEvent;
+import com.android.internal.logging.UiEventLogger;
+
+enum AppClipsEvent implements UiEventLogger.UiEventEnum {
+
+    @UiEvent(doc = "Notes application triggered the screenshot for notes")
+    SCREENSHOT_FOR_NOTE_TRIGGERED(1308),
+    @UiEvent(doc = "User accepted the screenshot to be sent to the notes app")
+    SCREENSHOT_FOR_NOTE_ACCEPTED(1309),
+    @UiEvent(doc = "User cancelled the screenshot for notes app flow")
+    SCREENSHOT_FOR_NOTE_CANCELLED(1310);
+
+    private final int mId;
+
+    AppClipsEvent(int id) {
+        mId = id;
+    }
+
+    @Override
+    public int getId() {
+        return mId;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperService.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperService.java
index 6f8c365..83ff020 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsScreenshotHelperService.java
@@ -24,7 +24,6 @@
 
 import androidx.annotation.Nullable;
 
-import com.android.systemui.screenshot.AppClipsActivity;
 import com.android.wm.shell.bubbles.Bubbles;
 
 import java.util.Optional;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivity.java
index eda38e4..3cb1a34 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivity.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.screenshot;
+package com.android.systemui.screenshot.appclips;
 
 import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_BLOCKED_BY_ADMIN;
 import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_FAILED;
@@ -24,7 +24,7 @@
 import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
 
 import static com.android.systemui.flags.Flags.SCREENSHOT_APP_CLIPS;
-import static com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_FOR_NOTE_TRIGGERED;
+import static com.android.systemui.screenshot.appclips.AppClipsEvent.SCREENSHOT_FOR_NOTE_TRIGGERED;
 
 import android.app.Activity;
 import android.app.admin.DevicePolicyManager;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsViewModel.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsViewModel.java
index b2910fd..4cbca28a 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsViewModel.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsViewModel.java
@@ -14,12 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.systemui.screenshot;
+package com.android.systemui.screenshot.appclips;
 
 import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_FAILED;
 
-import static androidx.annotation.VisibleForTesting.PACKAGE_PRIVATE;
-
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.HardwareRenderer;
@@ -31,7 +29,6 @@
 import android.os.Process;
 
 import androidx.annotation.NonNull;
-import androidx.annotation.VisibleForTesting;
 import androidx.lifecycle.LiveData;
 import androidx.lifecycle.MutableLiveData;
 import androidx.lifecycle.ViewModel;
@@ -39,11 +36,10 @@
 
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.screenshot.appclips.AppClipsCrossProcessHelper;
+import com.android.systemui.screenshot.ImageExporter;
 
 import com.google.common.util.concurrent.ListenableFuture;
 
-import java.time.ZonedDateTime;
 import java.util.UUID;
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.ExecutionException;
@@ -52,8 +48,7 @@
 import javax.inject.Inject;
 
 /** A {@link ViewModel} to help with the App Clips screenshot flow. */
-@VisibleForTesting(otherwise = PACKAGE_PRIVATE)
-public final class AppClipsViewModel extends ViewModel {
+final class AppClipsViewModel extends ViewModel {
 
     private final AppClipsCrossProcessHelper mAppClipsCrossProcessHelper;
     private final ImageExporter mImageExporter;
@@ -80,8 +75,7 @@
     }
 
     /** Grabs a screenshot and updates the {@link Bitmap} set in screenshot {@link LiveData}. */
-    @VisibleForTesting(otherwise = PACKAGE_PRIVATE)
-    public void performScreenshot() {
+    void performScreenshot() {
         mBgExecutor.execute(() -> {
             Bitmap screenshot = mAppClipsCrossProcessHelper.takeScreenshot();
             mMainExecutor.execute(() -> {
@@ -95,14 +89,12 @@
     }
 
     /** Returns a {@link LiveData} that holds the captured screenshot. */
-    @VisibleForTesting(otherwise = PACKAGE_PRIVATE)
-    public LiveData<Bitmap> getScreenshot() {
+    LiveData<Bitmap> getScreenshot() {
         return mScreenshotLiveData;
     }
 
     /** Returns a {@link LiveData} that holds the {@link Uri} where screenshot is saved. */
-    @VisibleForTesting(otherwise = PACKAGE_PRIVATE)
-    public LiveData<Uri> getResultLiveData() {
+    LiveData<Uri> getResultLiveData() {
         return mResultLiveData;
     }
 
@@ -110,8 +102,7 @@
      * Returns a {@link LiveData} that holds the error codes for
      * {@link Intent#EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE}.
      */
-    @VisibleForTesting(otherwise = PACKAGE_PRIVATE)
-    public LiveData<Integer> getErrorLiveData() {
+    LiveData<Integer> getErrorLiveData() {
         return mErrorLiveData;
     }
 
@@ -119,8 +110,7 @@
      * Saves the provided {@link Drawable} to storage then informs the result {@link Uri} to
      * {@link LiveData}.
      */
-    @VisibleForTesting(otherwise = PACKAGE_PRIVATE)
-    public void saveScreenshotThenFinish(Drawable screenshotDrawable, Rect bounds) {
+    void saveScreenshotThenFinish(Drawable screenshotDrawable, Rect bounds) {
         mBgExecutor.execute(() -> {
             // Render the screenshot bitmap in background.
             Bitmap screenshotBitmap = renderBitmap(screenshotDrawable, bounds);
@@ -128,7 +118,7 @@
             // Export and save the screenshot in background.
             // TODO(b/267310185): Save to work profile UserHandle.
             ListenableFuture<ImageExporter.Result> exportFuture = mImageExporter.export(
-                    mBgExecutor, UUID.randomUUID(), screenshotBitmap, ZonedDateTime.now(),
+                    mBgExecutor, UUID.randomUUID(), screenshotBitmap,
                     Process.myUserHandle());
 
             // Get the result and update state on main thread.
@@ -160,8 +150,7 @@
     }
 
     /** Helper factory to help with injecting {@link AppClipsViewModel}. */
-    @VisibleForTesting(otherwise = PACKAGE_PRIVATE)
-    public static final class Factory implements ViewModelProvider.Factory {
+    static final class Factory implements ViewModelProvider.Factory {
 
         private final AppClipsCrossProcessHelper mAppClipsCrossProcessHelper;
         private final ImageExporter mImageExporter;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/ScreenshotHardwareBufferInternal.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/ScreenshotHardwareBufferInternal.java
index 3b107f1..1e53ebb 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/ScreenshotHardwareBufferInternal.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/ScreenshotHardwareBufferInternal.java
@@ -28,7 +28,7 @@
  * An internal version of {@link ScreenshotHardwareBuffer} that helps with parceling the information
  * necessary for creating a {@link Bitmap}.
  */
-public class ScreenshotHardwareBufferInternal implements Parcelable {
+class ScreenshotHardwareBufferInternal implements Parcelable {
 
     public static final Creator<ScreenshotHardwareBufferInternal> CREATOR =
             new Creator<>() {
@@ -45,7 +45,7 @@
     private final HardwareBuffer mHardwareBuffer;
     private final ParcelableColorSpace mParcelableColorSpace;
 
-    public ScreenshotHardwareBufferInternal(
+    ScreenshotHardwareBufferInternal(
             ScreenshotHardwareBuffer screenshotHardwareBuffer) {
         mHardwareBuffer = screenshotHardwareBuffer.getHardwareBuffer();
         mParcelableColorSpace = new ParcelableColorSpace(
@@ -65,7 +65,7 @@
      * {@link Bitmap#wrapHardwareBuffer(HardwareBuffer, ColorSpace)} and
      * {@link HardwareBuffer#close()} for more information.
      */
-    public Bitmap createBitmapThenCloseBuffer() {
+    Bitmap createBitmapThenCloseBuffer() {
         Bitmap bitmap = Bitmap.wrapHardwareBuffer(mHardwareBuffer,
                 mParcelableColorSpace.getColorSpace());
         mHardwareBuffer.close();
diff --git a/packages/SystemUI/src/com/android/systemui/scrim/ScrimDrawable.java b/packages/SystemUI/src/com/android/systemui/scrim/ScrimDrawable.java
index b36f0d7..10e2afe 100644
--- a/packages/SystemUI/src/com/android/systemui/scrim/ScrimDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/scrim/ScrimDrawable.java
@@ -27,6 +27,7 @@
 import android.graphics.Path;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
+import android.graphics.RectF;
 import android.graphics.Xfermode;
 import android.graphics.drawable.Drawable;
 import android.view.animation.DecelerateInterpolator;
@@ -41,7 +42,11 @@
 public class ScrimDrawable extends Drawable {
     private static final String TAG = "ScrimDrawable";
 
+    private boolean mShouldUseLargeScreenSize;
     private final Paint mPaint;
+    private final Path mPath = new Path();
+    private final RectF mBoundsRectF = new RectF();
+
     private int mAlpha = 255;
     private int mMainColor;
     private ValueAnimator mColorAnimation;
@@ -49,11 +54,13 @@
     private float mCornerRadius;
     private ConcaveInfo mConcaveInfo;
     private int mBottomEdgePosition;
+    private float mBottomEdgeRadius = -1;
     private boolean mCornerRadiusEnabled;
 
     public ScrimDrawable() {
         mPaint = new Paint();
         mPaint.setStyle(Paint.Style.FILL);
+        mShouldUseLargeScreenSize = false;
     }
 
     /**
@@ -133,6 +140,10 @@
         return PixelFormat.TRANSLUCENT;
     }
 
+    public void setShouldUseLargeScreenSize(boolean v) {
+        mShouldUseLargeScreenSize = v;
+    }
+
     /**
      * Corner radius used by either concave or convex corners.
      */
@@ -191,6 +202,10 @@
         invalidateSelf();
     }
 
+    public void setBottomEdgeRadius(float radius) {
+        mBottomEdgeRadius = radius;
+    }
+
     @Override
     public void draw(@NonNull Canvas canvas) {
         mPaint.setColor(mMainColor);
@@ -198,9 +213,46 @@
         if (mConcaveInfo != null) {
             drawConcave(canvas);
         } else if (mCornerRadiusEnabled && mCornerRadius > 0) {
-            canvas.drawRoundRect(getBounds().left, getBounds().top, getBounds().right,
-                    getBounds().bottom,
-                    /* x radius*/ mCornerRadius, /* y radius*/ mCornerRadius, mPaint);
+            float topEdgeRadius = mCornerRadius;
+            float bottomEdgeRadius = mBottomEdgeRadius == -1.0 ? mCornerRadius : mBottomEdgeRadius;
+
+            mBoundsRectF.set(getBounds());
+
+            // When the back gesture causes the notification scrim to be scaled down,
+            // this offset "reveals" the rounded bottom edge as it "pulls away".
+            // We must *not* make this adjustment on largescreen shades (where the corner is sharp).
+            if (!mShouldUseLargeScreenSize && mBottomEdgeRadius != -1) {
+                mBoundsRectF.bottom -= bottomEdgeRadius;
+            }
+
+            // We need a box with rounded corners but its lower corners are not rounded on large
+            // screen devices in "portrait" orientation.
+            // Thus, we cannot draw a symmetric rounded rectangle via canvas.drawRoundRect()
+            // and must build a box with different corner radii at the top and at the bottom.
+            // Additionally, when the scrim is pushed to the very bottom of the screen, do not draw
+            // anything (drawing a rounded box with these specifications is not possible).
+            // TODO(b/271030611) perhaps this could be accomplished via Path.addRoundRect instead?
+            if (mBoundsRectF.bottom - mBoundsRectF.top > bottomEdgeRadius) {
+                mPath.reset();
+                mPath.moveTo(mBoundsRectF.right, mBoundsRectF.top + topEdgeRadius);
+                mPath.cubicTo(mBoundsRectF.right, mBoundsRectF.top + topEdgeRadius,
+                        mBoundsRectF.right, mBoundsRectF.top,
+                        mBoundsRectF.right - topEdgeRadius, mBoundsRectF.top);
+                mPath.lineTo(mBoundsRectF.left + topEdgeRadius, mBoundsRectF.top);
+                mPath.cubicTo(mBoundsRectF.left + topEdgeRadius, mBoundsRectF.top,
+                        mBoundsRectF.left, mBoundsRectF.top,
+                        mBoundsRectF.left, mBoundsRectF.top + topEdgeRadius);
+                mPath.lineTo(mBoundsRectF.left, mBoundsRectF.bottom - bottomEdgeRadius);
+                mPath.cubicTo(mBoundsRectF.left, mBoundsRectF.bottom - bottomEdgeRadius,
+                        mBoundsRectF.left, mBoundsRectF.bottom,
+                        mBoundsRectF.left + bottomEdgeRadius, mBoundsRectF.bottom);
+                mPath.lineTo(mBoundsRectF.right - bottomEdgeRadius, mBoundsRectF.bottom);
+                mPath.cubicTo(mBoundsRectF.right - bottomEdgeRadius, mBoundsRectF.bottom,
+                        mBoundsRectF.right, mBoundsRectF.bottom,
+                        mBoundsRectF.right, mBoundsRectF.bottom - bottomEdgeRadius);
+                mPath.close();
+                canvas.drawPath(mPath, mPaint);
+            }
         } else {
             canvas.drawRect(getBounds().left, getBounds().top, getBounds().right,
                     getBounds().bottom, mPaint);
diff --git a/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java b/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java
index f68e042..fc89a9e 100644
--- a/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java
+++ b/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java
@@ -20,6 +20,7 @@
 
 import android.annotation.NonNull;
 import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.PorterDuff;
@@ -37,6 +38,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.colorextraction.ColorExtractor;
+import com.android.systemui.util.LargeScreenUtils;
 
 import java.util.concurrent.Executor;
 
@@ -102,6 +104,13 @@
     @Override
     protected void onDraw(Canvas canvas) {
         if (mDrawable.getAlpha() > 0) {
+            Resources res = getResources();
+            // Scrim behind notification shade has sharp (not rounded) corners on large screens
+            // which scrim itself cannot know, so we set it here.
+            if (mDrawable instanceof ScrimDrawable) {
+                ((ScrimDrawable) mDrawable).setShouldUseLargeScreenSize(
+                        LargeScreenUtils.shouldUseLargeScreenShadeHeader(res));
+            }
             mDrawable.draw(canvas);
         }
     }
@@ -170,6 +179,15 @@
         });
     }
 
+    /**
+     * Set corner radius of the bottom edge of the Notification scrim.
+     */
+    public void setBottomEdgeRadius(float radius) {
+        if (mDrawable instanceof ScrimDrawable) {
+            ((ScrimDrawable) mDrawable).setBottomEdgeRadius(radius);
+        }
+    }
+
     @VisibleForTesting
     Drawable getDrawable() {
         return mDrawable;
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
index 287e810..33a3125 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
@@ -19,6 +19,7 @@
 import android.content.Context
 import android.content.pm.UserInfo
 import android.os.UserHandle
+import java.util.concurrent.CountDownLatch
 import java.util.concurrent.Executor
 
 /**
@@ -67,14 +68,25 @@
     interface Callback {
 
         /**
+         * Same as {@link onUserChanging(Int, Context, CountDownLatch)} but the latch will be
+         * auto-decremented after the completion of this method.
+         */
+        @JvmDefault
+        fun onUserChanging(newUser: Int, userContext: Context) {}
+
+        /**
          * Notifies that the current user is being changed.
          * Override this method to run things while the screen is frozen for the user switch.
          * Please use {@link #onUserChanged} if the task doesn't need to push the unfreezing of the
          * screen further. Please be aware that code executed in this callback will lengthen the
-         * user switch duration.
+         * user switch duration. When overriding this method, countDown() MUST be called on the
+         * latch once execution is complete.
          */
         @JvmDefault
-        fun onUserChanging(newUser: Int, userContext: Context) {}
+        fun onUserChanging(newUser: Int, userContext: Context, latch: CountDownLatch) {
+            onUserChanging(newUser, userContext)
+            latch.countDown()
+        }
 
         /**
          * Notifies that the current user has changed.
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
index 3a5d0a7..0b2ae05 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
@@ -182,9 +182,22 @@
         Log.i(TAG, "Switching to user $newUserId")
 
         setUserIdInternal(newUserId)
-        notifySubscribers {
-            onUserChanging(newUserId, userContext)
-        }.await()
+
+        val list = synchronized(callbacks) {
+            callbacks.toList()
+        }
+        val latch = CountDownLatch(list.size)
+        list.forEach {
+            val callback = it.callback.get()
+            if (callback != null) {
+                it.executor.execute {
+                    callback.onUserChanging(userId, userContext, latch)
+                }
+            } else {
+                latch.countDown()
+            }
+        }
+        latch.await()
     }
 
     @WorkerThread
@@ -224,25 +237,18 @@
         }
     }
 
-    private inline fun notifySubscribers(
-            crossinline action: UserTracker.Callback.() -> Unit
-    ): CountDownLatch {
+    private inline fun notifySubscribers(crossinline action: UserTracker.Callback.() -> Unit) {
         val list = synchronized(callbacks) {
             callbacks.toList()
         }
-        val latch = CountDownLatch(list.size)
 
         list.forEach {
             if (it.callback.get() != null) {
                 it.executor.execute {
                     it.callback.get()?.action()
-                    latch.countDown()
                 }
-            } else {
-                latch.countDown()
             }
         }
-        return latch
     }
 
     override fun dump(pw: PrintWriter, args: Array<out String>) {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 95206e5..06426b3 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -17,12 +17,14 @@
 package com.android.systemui.shade;
 
 import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
+import static android.view.MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE;
 import static android.view.View.INVISIBLE;
 import static android.view.View.VISIBLE;
 
 import static androidx.constraintlayout.widget.ConstraintSet.END;
 import static androidx.constraintlayout.widget.ConstraintSet.PARENT_ID;
 
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION;
 import static com.android.keyguard.KeyguardClockSwitch.LARGE;
 import static com.android.keyguard.KeyguardClockSwitch.SMALL;
 import static com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE;
@@ -71,6 +73,7 @@
 import android.provider.Settings;
 import android.transition.ChangeBounds;
 import android.transition.Transition;
+import android.transition.TransitionListenerAdapter;
 import android.transition.TransitionManager;
 import android.transition.TransitionSet;
 import android.transition.TransitionValues;
@@ -98,6 +101,7 @@
 import androidx.constraintlayout.widget.ConstraintSet;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.jank.InteractionJankMonitor;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.policy.SystemBarUtils;
@@ -116,6 +120,7 @@
 import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
 import com.android.systemui.DejankUtils;
 import com.android.systemui.Dumpable;
+import com.android.systemui.Gefingerpoken;
 import com.android.systemui.R;
 import com.android.systemui.animation.ActivityLaunchAnimator;
 import com.android.systemui.animation.Interpolators;
@@ -159,14 +164,12 @@
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
-import com.android.systemui.screenrecord.RecordingController;
 import com.android.systemui.shade.transition.ShadeTransitionController;
 import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.GestureRecorder;
 import com.android.systemui.statusbar.KeyguardIndicationController;
 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
 import com.android.systemui.statusbar.NotificationShelfController;
@@ -293,7 +296,20 @@
      * custom clock animation is in use.
      */
     private static final int KEYGUARD_STATUS_VIEW_CUSTOM_CLOCK_MOVE_DURATION = 1000;
+    /**
+     * Whether the Shade should animate to reflect Back gesture progress.
+     * To minimize latency at runtime, we cache this, else we'd be reading it every time
+     * updateQsExpansion() is called... and it's called very often.
+     *
+     * Whenever we change this flag, SysUI is restarted, so it's never going to be "stale".
+     */
 
+    public final boolean mAnimateBack;
+    private final boolean mTrackpadGestureBack;
+    /**
+     * The minimum scale to "squish" the Shade and associated elements down to, for Back gesture
+     */
+    public static final float SHADE_BACK_ANIM_MIN_SCALE = 0.9f;
     private final StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
     private final Resources mResources;
     private final KeyguardStateController mKeyguardStateController;
@@ -353,6 +369,8 @@
     private final NotificationGutsManager mGutsManager;
     private final AlternateBouncerInteractor mAlternateBouncerInteractor;
     private final QuickSettingsController mQsController;
+    private final InteractionJankMonitor mInteractionJankMonitor;
+    private final TouchHandler mTouchHandler = new TouchHandler();
 
     private long mDownTime;
     private boolean mTouchSlopExceededBeforeDown;
@@ -361,6 +379,8 @@
     private CentralSurfaces mCentralSurfaces;
     private HeadsUpManagerPhone mHeadsUpManager;
     private float mExpandedHeight = 0;
+    /** The current squish amount for the predictive back animation */
+    private float mCurrentBackProgress = 0.0f;
     private boolean mTracking;
     private boolean mHintAnimationRunning;
     private KeyguardBottomAreaView mKeyguardBottomArea;
@@ -537,7 +557,7 @@
     private final KeyguardBottomAreaViewModel mKeyguardBottomAreaViewModel;
     private final KeyguardBottomAreaInteractor mKeyguardBottomAreaInteractor;
     private float mMinExpandHeight;
-    private ShadeHeightLogger mShadeHeightLogger;
+    private final ShadeHeightLogger mShadeHeightLogger;
     private boolean mPanelUpdateWhenAnimatorEnds;
     private boolean mHasVibratedOnOpen = false;
     private int mFixedDuration = NO_FIXED_DURATION;
@@ -582,15 +602,15 @@
     private boolean mGestureWaitForTouchSlop;
     private boolean mIgnoreXTouchSlop;
     private boolean mExpandLatencyTracking;
-    private DreamingToLockscreenTransitionViewModel mDreamingToLockscreenTransitionViewModel;
-    private OccludedToLockscreenTransitionViewModel mOccludedToLockscreenTransitionViewModel;
-    private LockscreenToDreamingTransitionViewModel mLockscreenToDreamingTransitionViewModel;
-    private GoneToDreamingTransitionViewModel mGoneToDreamingTransitionViewModel;
-    private LockscreenToOccludedTransitionViewModel mLockscreenToOccludedTransitionViewModel;
+    private final DreamingToLockscreenTransitionViewModel mDreamingToLockscreenTransitionViewModel;
+    private final OccludedToLockscreenTransitionViewModel mOccludedToLockscreenTransitionViewModel;
+    private final LockscreenToDreamingTransitionViewModel mLockscreenToDreamingTransitionViewModel;
+    private final GoneToDreamingTransitionViewModel mGoneToDreamingTransitionViewModel;
+    private final LockscreenToOccludedTransitionViewModel mLockscreenToOccludedTransitionViewModel;
 
-    private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
+    private final KeyguardTransitionInteractor mKeyguardTransitionInteractor;
     private final KeyguardInteractor mKeyguardInteractor;
-    private CoroutineDispatcher mMainDispatcher;
+    private final CoroutineDispatcher mMainDispatcher;
     private boolean mIsOcclusionTransitionRunning = false;
     private int mDreamingToLockscreenTransitionTranslationY;
     private int mOccludedToLockscreenTransitionTranslationY;
@@ -642,6 +662,19 @@
                     step.getTransitionState() == TransitionState.RUNNING;
             };
 
+    private final TransitionListenerAdapter mKeyguardStatusAlignmentTransitionListener =
+            new TransitionListenerAdapter() {
+                @Override
+                public void onTransitionCancel(Transition transition) {
+                    mInteractionJankMonitor.cancel(CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION);
+                }
+
+                @Override
+                public void onTransitionEnd(Transition transition) {
+                    mInteractionJankMonitor.end(CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION);
+                }
+            };
+
     @Inject
     public NotificationPanelViewController(NotificationPanelView view,
             @Main Handler handler,
@@ -691,12 +724,10 @@
             QuickSettingsController quickSettingsController,
             FragmentService fragmentService,
             ContentResolver contentResolver,
-            RecordingController recordingController,
             ShadeHeaderController shadeHeaderController,
             ScreenOffAnimationController screenOffAnimationController,
             LockscreenGestureLogger lockscreenGestureLogger,
             ShadeExpansionStateManager shadeExpansionStateManager,
-            NotificationRemoteInputManager remoteInputManager,
             Optional<SysUIUnfoldComponent> unfoldComponent,
             SysUiState sysUiState,
             Provider<KeyguardBottomAreaViewController> keyguardBottomAreaViewControllerProvider,
@@ -706,6 +737,7 @@
             NotificationStackSizeCalculator notificationStackSizeCalculator,
             UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
             ShadeTransitionController shadeTransitionController,
+            InteractionJankMonitor interactionJankMonitor,
             SystemClock systemClock,
             KeyguardBottomAreaViewModel keyguardBottomAreaViewModel,
             KeyguardBottomAreaInteractor keyguardBottomAreaInteractor,
@@ -720,6 +752,7 @@
             DumpManager dumpManager,
             KeyguardLongPressViewModel keyguardLongPressViewModel,
             KeyguardInteractor keyguardInteractor) {
+        mInteractionJankMonitor = interactionJankMonitor;
         keyguardStateController.addCallback(new KeyguardStateController.Callback() {
             @Override
             public void onKeyguardFadingAwayChanged() {
@@ -752,7 +785,7 @@
         });
 
         mView.addOnLayoutChangeListener(new ShadeLayoutChangeListener());
-        mView.setOnTouchListener(createTouchHandler());
+        mView.setOnTouchListener(getTouchHandler());
         mView.setOnConfigurationChangedListener(config -> loadDimens());
 
         mResources = mView.getResources();
@@ -815,6 +848,8 @@
         mShadeHeaderController = shadeHeaderController;
         mLayoutInflater = layoutInflater;
         mFeatureFlags = featureFlags;
+        mAnimateBack = mFeatureFlags.isEnabled(Flags.WM_SHADE_ANIMATE_BACK_GESTURE);
+        mTrackpadGestureBack = mFeatureFlags.isEnabled(Flags.TRACKPAD_GESTURE_BACK);
         mFalsingCollector = falsingCollector;
         mPowerManager = powerManager;
         mWakeUpCoordinator = coordinator;
@@ -1184,6 +1219,12 @@
 
     private void onSplitShadeEnabledChanged() {
         mShadeLog.logSplitShadeChanged(mSplitShadeEnabled);
+        // Reset any left over overscroll state. It is a rare corner case but can happen.
+        mQsController.setOverScrollAmount(0);
+        mScrimController.setNotificationsOverScrollAmount(0);
+        mNotificationStackScrollLayoutController.setOverExpansion(0);
+        mNotificationStackScrollLayoutController.setOverScrollAmount(0);
+
         // when we switch between split shade and regular shade we want to enforce setting qs to
         // the default state: expanded for split shade and collapsed otherwise
         if (!isOnKeyguard() && mPanelExpanded) {
@@ -1540,6 +1581,7 @@
             int statusConstraint = shouldBeCentered ? PARENT_ID : R.id.qs_edge_guideline;
             constraintSet.connect(R.id.keyguard_status_view, END, statusConstraint, END);
             if (animate) {
+                mInteractionJankMonitor.begin(mView, CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION);
                 ChangeBounds transition = new ChangeBounds();
                 if (mSplitShadeEnabled) {
                     // Excluding media from the transition on split-shade, as it doesn't transition
@@ -1563,6 +1605,7 @@
                     // The clock container can sometimes be null. If it is, just fall back to the
                     // old animation rather than setting up the custom animations.
                     if (clockContainerView == null || clockContainerView.getChildCount() == 0) {
+                        transition.addListener(mKeyguardStatusAlignmentTransitionListener);
                         TransitionManager.beginDelayedTransition(
                                 mNotificationContainerParent, transition);
                     } else {
@@ -1581,10 +1624,11 @@
                         adapter.setDuration(KEYGUARD_STATUS_VIEW_CUSTOM_CLOCK_MOVE_DURATION);
                         adapter.addTarget(clockView);
                         set.addTransition(adapter);
-
+                        set.addListener(mKeyguardStatusAlignmentTransitionListener);
                         TransitionManager.beginDelayedTransition(mNotificationContainerParent, set);
                     }
                 } else {
+                    transition.addListener(mKeyguardStatusAlignmentTransitionListener);
                     TransitionManager.beginDelayedTransition(
                             mNotificationContainerParent, transition);
                 }
@@ -1621,10 +1665,6 @@
         return mDozing && mDozeParameters.getAlwaysOn();
     }
 
-    boolean isDozing() {
-        return mDozing;
-    }
-
     private boolean hasVisibleNotifications() {
         return mNotificationStackScrollLayoutController
                 .getVisibleNotificationCount() != 0
@@ -1951,6 +1991,14 @@
             if (mFixedDuration != NO_FIXED_DURATION) {
                 animator.setDuration(mFixedDuration);
             }
+
+            // Reset Predictive Back animation's transform after Shade is completely hidden.
+            animator.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    resetBackTransformation();
+                }
+            });
         }
         animator.addListener(new AnimatorListenerAdapter() {
             private boolean mCancelled;
@@ -2175,6 +2223,53 @@
         }
     }
 
+    /**
+     * When the back gesture triggers a fully-expanded shade --> QQS shade collapse transition,
+     * the expansionFraction goes down from 1.0 --> 0.0 (collapsing), so the current "squish" amount
+     * (mCurrentBackProgress) must be un-applied from various UI elements in tandem, such that,
+     * as the shade ends up in its half-expanded state (with QQS above), it is back at 100% scale.
+     * Without this, the shade would collapse, and stay squished.
+     */
+    public void adjustBackAnimationScale(float expansionFraction) {
+        if (expansionFraction > 0.0f) { // collapsing
+            float animatedFraction = expansionFraction * mCurrentBackProgress;
+            applyBackScaling(animatedFraction);
+        } else {
+            // collapsed! reset, so that if we re-expand shade, it won't start off "squished"
+            mCurrentBackProgress = 0;
+        }
+    }
+
+    //TODO(b/270981268): allow cancelling back animation mid-flight
+    /** Called when Back gesture has been committed (i.e. a back event has definitely occurred) */
+    public void onBackPressed() {
+        closeQsIfPossible();
+    }
+    /** Sets back progress. */
+    public void onBackProgressed(float progressFraction) {
+        // TODO: non-linearly transform progress fraction into squish amount (ease-in, linear out)
+        mCurrentBackProgress = progressFraction;
+        applyBackScaling(progressFraction);
+    }
+
+    /** Resets back progress. */
+    public void resetBackTransformation() {
+        mCurrentBackProgress = 0.0f;
+        applyBackScaling(0.0f);
+    }
+
+    /** Scales multiple elements in tandem to achieve the illusion of the QS+Shade shrinking
+     *  as a single visual element (used by the Predictive Back Gesture preview animation).
+     *  fraction = 0 implies "no scaling", and 1 means "scale down to minimum size (90%)".
+     */
+    public void applyBackScaling(float fraction) {
+        if (mNotificationContainerParent == null) {
+            return;
+        }
+        float scale = MathUtils.lerp(1.0f, SHADE_BACK_ANIM_MIN_SCALE, fraction);
+        mNotificationContainerParent.applyBackScaling(scale, mSplitShadeEnabled);
+        mScrimController.applyBackScaling(scale);
+    }
     /** */
     public float getLockscreenShadeDragProgress() {
         // mTransitioningToFullShadeProgress > 0 means we're doing regular lockscreen to shade
@@ -2861,7 +2956,10 @@
         mHeadsUpStartHeight = startHeight;
         float scrimMinFraction;
         if (mSplitShadeEnabled) {
-            boolean highHun = mHeadsUpStartHeight * 2.5 > mSplitShadeScrimTransitionDistance;
+            boolean highHun = mHeadsUpStartHeight * 2.5
+                    >
+                    (mFeatureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)
+                    ? mSplitShadeFullTransitionDistance : mSplitShadeScrimTransitionDistance);
             // if HUN height is higher than 40% of predefined transition distance, it means HUN
             // is too high for regular transition. In that case we need to calculate transition
             // distance - here we take scrim transition distance as equal to shade transition
@@ -3311,8 +3409,8 @@
     }
 
     @VisibleForTesting
-    TouchHandler createTouchHandler() {
-        return new TouchHandler();
+    TouchHandler getTouchHandler() {
+        return mTouchHandler;
     }
 
     public NotificationStackScrollLayoutController getNotificationStackScrollLayoutController() {
@@ -3483,12 +3581,15 @@
     }
 
     private void endMotionEvent(MotionEvent event, float x, float y, boolean forceCancel) {
+        // don't fling while in keyguard to avoid jump in shade expand animation
+        boolean fullyExpandedInKeyguard = mBarState == KEYGUARD && mExpandedFraction >= 1.0;
         mTrackingPointer = -1;
         mAmbientState.setSwipingUp(false);
-        if ((mTracking && mTouchSlopExceeded) || Math.abs(x - mInitialExpandX) > mTouchSlop
+        if (!fullyExpandedInKeyguard && ((mTracking && mTouchSlopExceeded)
+                || Math.abs(x - mInitialExpandX) > mTouchSlop
                 || Math.abs(y - mInitialExpandY) > mTouchSlop
                 || (!isFullyExpanded() && !isFullyCollapsed())
-                || event.getActionMasked() == MotionEvent.ACTION_CANCEL || forceCancel) {
+                || event.getActionMasked() == MotionEvent.ACTION_CANCEL || forceCancel)) {
             mVelocityTracker.computeCurrentVelocity(1000);
             float vel = mVelocityTracker.getYVelocity();
             float vectorVel = (float) Math.hypot(
@@ -3536,9 +3637,9 @@
             if (mUpdateFlingOnLayout) {
                 mUpdateFlingVelocity = vel;
             }
-        } else if (!mCentralSurfaces.isBouncerShowing()
+        } else if (fullyExpandedInKeyguard || (!mCentralSurfaces.isBouncerShowing()
                 && !mAlternateBouncerInteractor.isVisibleState()
-                && !mKeyguardStateController.isKeyguardGoingAway()) {
+                && !mKeyguardStateController.isKeyguardGoingAway())) {
             onEmptySpaceClick();
             onTrackingStopped(true);
         }
@@ -3960,14 +4061,14 @@
         return mView.post(action);
     }
 
-    /** */
-    public boolean sendInterceptTouchEventToView(MotionEvent event) {
-        return mView.onInterceptTouchEvent(event);
+    /** Sends an external (e.g. Status Bar) intercept touch event to the Shade touch handler. */
+    public boolean handleExternalInterceptTouch(MotionEvent event) {
+        return mTouchHandler.onInterceptTouchEvent(event);
     }
 
-    /** */
-    public boolean sendTouchEventToView(MotionEvent event) {
-        return mView.dispatchTouchEvent(event);
+    /** Sends an external (e.g. Status Bar) touch event to the Shade touch handler. */
+    public boolean handleExternalTouch(MotionEvent event) {
+        return mTouchHandler.onTouchEvent(event);
     }
 
     /** */
@@ -3985,14 +4086,6 @@
         return mView.isEnabled();
     }
 
-    int getDisplayRightInset() {
-        return mDisplayRightInset;
-    }
-
-    int getDisplayLeftInset() {
-        return mDisplayLeftInset;
-    }
-
     float getOverStretchAmount() {
         return mOverStretchAmount;
     }
@@ -4001,10 +4094,6 @@
         return mMinFraction;
     }
 
-    boolean getCollapsedOnDown() {
-        return mCollapsedOnDown;
-    }
-
     int getNavigationBarBottomHeight() {
         return mNavigationBarBottomHeight;
     }
@@ -4568,7 +4657,7 @@
     }
 
     /** Handles MotionEvents for the Shade. */
-    public final class TouchHandler implements View.OnTouchListener {
+    public final class TouchHandler implements View.OnTouchListener, Gefingerpoken {
         private long mLastTouchDownTime = -1L;
 
         /** @see ViewGroup#onInterceptTouchEvent(MotionEvent) */
@@ -4666,6 +4755,9 @@
                     addMovement(event);
                     break;
                 case MotionEvent.ACTION_POINTER_UP:
+                    if (isTrackpadMotionEvent(event)) {
+                        break;
+                    }
                     final int upPointer = event.getPointerId(event.getActionIndex());
                     if (mTrackingPointer == upPointer) {
                         // gesture is ongoing, find a new pointer to track
@@ -4679,7 +4771,8 @@
                     mShadeLog.logMotionEventStatusBarState(event,
                             mStatusBarStateController.getState(),
                             "onInterceptTouchEvent: pointer down action");
-                    if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
+                    if (!isTrackpadMotionEvent(event)
+                            && mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
                         mMotionAborted = true;
                         mVelocityTracker.clear();
                     }
@@ -4714,6 +4807,11 @@
 
         @Override
         public boolean onTouch(View v, MotionEvent event) {
+            return onTouchEvent(event);
+        }
+
+        @Override
+        public boolean onTouchEvent(MotionEvent event) {
             if (event.getAction() == MotionEvent.ACTION_DOWN) {
                 if (event.getDownTime() == mLastTouchDownTime) {
                     // An issue can occur when swiping down after unlock, where multiple down
@@ -4851,6 +4949,11 @@
 
             switch (event.getActionMasked()) {
                 case MotionEvent.ACTION_DOWN:
+                    if (QuickStepContract.ALLOW_BACK_GESTURE_IN_SHADE && mAnimateBack) {
+                        // Cache the gesture insets now, so we can quickly query them during
+                        // ACTION_MOVE and decide whether to intercept events for back gesture anim.
+                        mQsController.updateGestureInsetsCache();
+                    }
                     mShadeLog.logMotionEvent(event, "onTouch: down action");
                     startExpandMotion(x, y, false /* startTracking */, mExpandedHeight);
                     mMinExpandHeight = 0.0f;
@@ -4877,6 +4980,9 @@
                     break;
 
                 case MotionEvent.ACTION_POINTER_UP:
+                    if (isTrackpadMotionEvent(event)) {
+                        break;
+                    }
                     final int upPointer = event.getPointerId(event.getActionIndex());
                     if (mTrackingPointer == upPointer) {
                         // gesture is ongoing, find a new pointer to track
@@ -4893,13 +4999,20 @@
                     mShadeLog.logMotionEventStatusBarState(event,
                             mStatusBarStateController.getState(),
                             "handleTouch: pointer down action");
-                    if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
+                    if (!isTrackpadMotionEvent(event)
+                            && mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
                         mMotionAborted = true;
                         endMotionEvent(event, x, y, true /* forceCancel */);
                         return false;
                     }
                     break;
                 case MotionEvent.ACTION_MOVE:
+                    // If the shade is half-collapsed, a horizontal swipe inwards from L/R edge
+                    // must be routed to the back gesture (which shows a preview animation).
+                    if (QuickStepContract.ALLOW_BACK_GESTURE_IN_SHADE && mAnimateBack
+                            && mQsController.shouldBackBypassQuickSettings(x)) {
+                        return false;
+                    }
                     if (isFullyCollapsed()) {
                         // If panel is fully collapsed, reset haptic effect before adding movement.
                         mHasVibratedOnOpen = false;
@@ -4961,6 +5074,11 @@
             }
             return !mGestureWaitForTouchSlop || mTracking;
         }
+
+        private boolean isTrackpadMotionEvent(MotionEvent ev) {
+            return mTrackpadGestureBack
+                    && ev.getClassification() == CLASSIFICATION_MULTI_FINGER_SWIPE;
+        }
     }
 
     static class SplitShadeTransitionAdapter extends Transition {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
index 87350b46..e2f31e8 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
@@ -36,6 +36,7 @@
 import com.android.keyguard.LockIconViewController;
 import com.android.keyguard.dagger.KeyguardBouncerComponent;
 import com.android.systemui.R;
+import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor;
 import com.android.systemui.classifier.FalsingCollector;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
@@ -45,6 +46,7 @@
 import com.android.systemui.keyguard.shared.model.TransitionStep;
 import com.android.systemui.keyguard.ui.binder.KeyguardBouncerViewBinder;
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
 import com.android.systemui.statusbar.DragDownHelper;
 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
 import com.android.systemui.statusbar.NotificationInsetsController;
@@ -85,7 +87,7 @@
     private final PulsingGestureListener mPulsingGestureListener;
     private final NotificationInsetsController mNotificationInsetsController;
     private final AlternateBouncerInteractor mAlternateBouncerInteractor;
-
+    private final UdfpsOverlayInteractor mUdfpsOverlayInteractor;
     private GestureDetector mPulsingWakeupGestureHandler;
     private View mBrightnessMirror;
     private boolean mTouchActive;
@@ -133,7 +135,9 @@
             KeyguardBouncerViewModel keyguardBouncerViewModel,
             KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory,
             AlternateBouncerInteractor alternateBouncerInteractor,
-            KeyguardTransitionInteractor keyguardTransitionInteractor
+            UdfpsOverlayInteractor udfpsOverlayInteractor,
+            KeyguardTransitionInteractor keyguardTransitionInteractor,
+            PrimaryBouncerToGoneTransitionViewModel primaryBouncerToGoneTransitionViewModel
     ) {
         mLockscreenShadeTransitionController = transitionController;
         mFalsingCollector = falsingCollector;
@@ -154,12 +158,14 @@
         mPulsingGestureListener = pulsingGestureListener;
         mNotificationInsetsController = notificationInsetsController;
         mAlternateBouncerInteractor = alternateBouncerInteractor;
+        mUdfpsOverlayInteractor = udfpsOverlayInteractor;
 
         // This view is not part of the newly inflated expanded status bar.
         mBrightnessMirror = mView.findViewById(R.id.brightness_mirror_container);
         KeyguardBouncerViewBinder.bind(
                 mView.findViewById(R.id.keyguard_bouncer_container),
                 keyguardBouncerViewModel,
+                primaryBouncerToGoneTransitionViewModel,
                 keyguardBouncerComponentFactory);
 
         collectFlow(mView, keyguardTransitionInteractor.getLockscreenToDreamingTransition(),
@@ -237,7 +243,6 @@
 
                 mFalsingCollector.onTouchEvent(ev);
                 mPulsingWakeupGestureHandler.onTouchEvent(ev);
-                mStatusBarKeyguardViewManager.onTouch(ev);
                 if (mBrightnessMirror != null
                         && mBrightnessMirror.getVisibility() == View.VISIBLE) {
                     // Disallow new pointers while the brightness mirror is visible. This is so that
@@ -313,8 +318,8 @@
                 }
 
                 if (mAlternateBouncerInteractor.isVisibleState()) {
-                    // capture all touches if the alt auth bouncer is showing
-                    return true;
+                    // If using UDFPS, don't intercept touches that are within its overlay bounds
+                    return mUdfpsOverlayInteractor.canInterceptTouchInUdfpsBounds(ev);
                 }
 
                 if (mLockIconViewController.onInterceptTouchEvent(ev)) {
@@ -339,7 +344,7 @@
                 MotionEvent cancellation = MotionEvent.obtain(ev);
                 cancellation.setAction(MotionEvent.ACTION_CANCEL);
                 mStackScrollLayout.onInterceptTouchEvent(cancellation);
-                mNotificationPanelViewController.sendInterceptTouchEventToView(cancellation);
+                mNotificationPanelViewController.handleExternalInterceptTouch(cancellation);
                 cancellation.recycle();
             }
 
@@ -352,6 +357,7 @@
 
                 if (mAlternateBouncerInteractor.isVisibleState()) {
                     // eat the touch
+                    mStatusBarKeyguardViewManager.onTouch(ev);
                     handled = true;
                 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java
index f73dde6..7dff6ea 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.Canvas;
+import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.WindowInsets;
@@ -55,6 +56,13 @@
     private QS mQs;
     private View mQSContainer;
 
+    /**
+     *  These are used to compute the bounding box containing the shade and the notification scrim,
+     *  which is then used to drive the Back gesture animation.
+     */
+    private final Rect mUpperRect = new Rect();
+    private final Rect mBoundingBoxRect = new Rect();
+
     @Nullable
     private Consumer<Configuration> mConfigurationChangedListener;
 
@@ -172,4 +180,37 @@
     public void applyConstraints(ConstraintSet constraintSet) {
         constraintSet.applyTo(this);
     }
+
+    /**
+     *  Scale multiple elements in tandem, for the predictive back animation.
+     *  This is how the Shade responds to the Back gesture (by scaling).
+     *  Without the common center, individual elements will scale about their respective centers.
+     *  Scaling the entire NotificationsQuickSettingsContainer will also resize the shade header
+     *  (which we don't want).
+     */
+    public void applyBackScaling(float scale, boolean usingSplitShade) {
+        if (mStackScroller == null || mQSContainer == null) {
+            return;
+        }
+
+        mQSContainer.getBoundsOnScreen(mUpperRect);
+        mStackScroller.getBoundsOnScreen(mBoundingBoxRect);
+        mBoundingBoxRect.union(mUpperRect);
+
+        float cx = mBoundingBoxRect.centerX();
+        float cy = mBoundingBoxRect.centerY();
+
+        mQSContainer.setPivotX(cx);
+        mQSContainer.setPivotY(cy);
+        mQSContainer.setScaleX(scale);
+        mQSContainer.setScaleY(scale);
+
+        // When in large-screen split-shade mode, the notification stack scroller scales correctly
+        // only if the pivot point is at the left edge of the screen (because of its dimensions).
+        // When not in large-screen split-shade mode, we can scale correctly via the (cx,cy) above.
+        mStackScroller.setPivotX(usingSplitShade ? 0.0f : cx);
+        mStackScroller.setPivotY(cy);
+        mStackScroller.setScaleX(scale);
+        mStackScroller.setScaleY(scale);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
index 099ad94..df8ae50 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
@@ -31,6 +31,7 @@
 import android.animation.ValueAnimator;
 import android.app.Fragment;
 import android.content.res.Resources;
+import android.graphics.Insets;
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.util.Log;
@@ -40,6 +41,9 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
 import android.view.accessibility.AccessibilityManager;
 import android.widget.FrameLayout;
 
@@ -63,6 +67,7 @@
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.screenrecord.RecordingController;
 import com.android.systemui.shade.transition.ShadeTransitionController;
+import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.NotificationShadeDepthController;
@@ -83,10 +88,10 @@
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.LargeScreenUtils;
 
-import javax.inject.Inject;
-
 import dagger.Lazy;
 
+import javax.inject.Inject;
+
 /** Handles QuickSettings touch handling, expansion and animation state
  * TODO (b/264460656) make this dumpable
  */
@@ -223,6 +228,13 @@
     private boolean mAnimatorExpand;
 
     /**
+     * The gesture inset currently in effect -- used to decide whether a back gesture should
+     * receive a horizontal swipe inwards from the left/right vertical edge of the screen.
+     * We cache this on ACTION_DOWN, and query it during both ACTION_DOWN and ACTION_MOVE events.
+     */
+    private Insets mCachedGestureInsets;
+
+    /**
      * The amount of progress we are currently in if we're transitioning to the full shade.
      * 0.0f means we're not transitioning yet, while 1 means we're all the way in the full
      * shade. This value can also go beyond 1.1 when we're overshooting!
@@ -406,6 +418,7 @@
         mQuickQsHeaderHeight = mLargeScreenShadeHeaderHeight;
 
         mEnableClipping = mResources.getBoolean(R.bool.qs_enable_clipping);
+        updateGestureInsetsCache();
     }
 
     // TODO (b/265054088): move this and others to a CoreStartable
@@ -469,6 +482,26 @@
                 || touchX > mQsFrame.getX() + mQsFrame.getWidth();
     }
 
+    /**
+     *  Computes (and caches) the gesture insets for the current window. Intended to be called
+     *  on ACTION_DOWN, and safely queried repeatedly thereafter during ACTION_MOVE events.
+     */
+    public void updateGestureInsetsCache() {
+        WindowManager wm = this.mPanelView.getContext().getSystemService(WindowManager.class);
+        WindowMetrics windowMetrics = wm.getCurrentWindowMetrics();
+        mCachedGestureInsets = windowMetrics.getWindowInsets().getInsets(
+                WindowInsets.Type.systemGestures());
+    }
+
+    /**
+     *  Returns whether x coordinate lies in the vertical edges of the screen
+     *  (the only place where a back gesture can be initiated).
+     */
+    public boolean shouldBackBypassQuickSettings(float touchX) {
+        return (touchX < mCachedGestureInsets.left)
+                || (touchX > mKeyguardStatusBar.getWidth() - mCachedGestureInsets.right);
+    }
+
     /** Returns whether touch is within QS area */
     private boolean isTouchInQsArea(float x, float y) {
         if (isSplitShadeAndTouchXOutsideQs(x)) {
@@ -926,6 +959,10 @@
                 getHeaderTranslation(),
                 squishiness
         );
+        if (QuickStepContract.ALLOW_BACK_GESTURE_IN_SHADE
+                && mPanelViewControllerLazy.get().mAnimateBack) {
+            mPanelViewControllerLazy.get().adjustBackAnimationScale(adjustedExpansionFraction);
+        }
         mMediaHierarchyManager.setQsExpansion(qsExpansionFraction);
         int qsPanelBottomY = calculateBottomPosition(qsExpansionFraction);
         mScrimController.setQsPosition(qsExpansionFraction, qsPanelBottomY);
@@ -1035,7 +1072,11 @@
     private void setClippingBounds() {
         float qsExpansionFraction = computeExpansionFraction();
         final int qsPanelBottomY = calculateBottomPosition(qsExpansionFraction);
-        final boolean qsVisible = (qsExpansionFraction > 0 || qsPanelBottomY > 0);
+        // Split shade has no QQS
+        final boolean qqsVisible =
+                !mSplitShadeEnabled && qsExpansionFraction == 0 && qsPanelBottomY > 0;
+        final boolean qsVisible = qsExpansionFraction > 0;
+        final boolean qsOrQqsVisible = qqsVisible || qsVisible;
         checkCorrectScrimVisibility(qsExpansionFraction);
 
         int top = calculateTopClippingBound(qsPanelBottomY);
@@ -1044,7 +1085,7 @@
         int right = calculateRightClippingBound();
         // top should never be lower than bottom, otherwise it will be invisible.
         top = Math.min(top, bottom);
-        applyClippingBounds(left, top, right, bottom, qsVisible);
+        applyClippingBounds(left, top, right, bottom, qsOrQqsVisible);
     }
 
     /**
@@ -1113,6 +1154,7 @@
             float screenCornerRadius = mRecordingController.isRecording() ? 0 : mScreenCornerRadius;
             radius = (int) MathUtils.lerp(screenCornerRadius, mScrimCornerRadius,
                     Math.min(top / (float) mScrimCornerRadius, 1f));
+            mScrimController.setNotificationBottomRadius(radius);
         }
         if (isQsFragmentCreated()) {
             float qsTranslation = 0;
@@ -1505,18 +1547,31 @@
     }
 
     private void handleDown(MotionEvent event) {
-        if (event.getActionMasked() == MotionEvent.ACTION_DOWN
-                && shouldQuickSettingsIntercept(event.getX(), event.getY(), -1)) {
-            mFalsingCollector.onQsDown();
-            mShadeLog.logMotionEvent(event, "handleQsDown: down action, QS tracking enabled");
-            mTracking = true;
-            onExpansionStarted();
-            mInitialHeightOnTouch = mExpansionHeight;
-            mInitialTouchY = event.getY();
-            mInitialTouchX = event.getX();
-            // TODO (b/265193930): remove dependency on NPVC
-            // If we interrupt an expansion gesture here, make sure to update the state correctly.
-            mPanelViewControllerLazy.get().notifyExpandingFinished();
+        if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+            // When the shade is fully-expanded, an inward swipe from the L/R edge should first
+            // allow the back gesture's animation to preview the shade animation (if enabled).
+            // (swipes starting closer to the center of the screen will not be affected)
+            if (QuickStepContract.ALLOW_BACK_GESTURE_IN_SHADE
+                    && mPanelViewControllerLazy.get().mAnimateBack) {
+                updateGestureInsetsCache();
+                if (shouldBackBypassQuickSettings(event.getX())) {
+                    return;
+                }
+            }
+            if (shouldQuickSettingsIntercept(event.getX(), event.getY(), -1)) {
+                mFalsingCollector.onQsDown();
+                mShadeLog.logMotionEvent(event,
+                        "handleQsDown: down action, QS tracking enabled");
+                mTracking = true;
+                onExpansionStarted();
+                mInitialHeightOnTouch = mExpansionHeight;
+                mInitialTouchY = event.getY();
+                mInitialTouchX = event.getX();
+                // TODO (b/265193930): remove dependency on NPVC
+                // If we interrupt an expansion gesture here, make sure to update the state
+                // correctly.
+                mPanelViewControllerLazy.get().notifyExpandingFinished();
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt
index a1767cc..f4b1cc5 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt
@@ -107,7 +107,7 @@
      *
      * @param fraction the fraction from the expansion in [0, 1]
      * @param expanded whether the panel is currently expanded; this is independent from the
-     * fraction as the panel also might be expanded if the fraction is 0.
+     *   fraction as the panel also might be expanded if the fraction is 0.
      * @param tracking whether we're currently tracking the user's gesture.
      */
     fun onPanelExpansionChanged(
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
index 37773e9..b79f32a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
@@ -70,9 +70,9 @@
  *
  * [header] is a [MotionLayout] that has two transitions:
  * * [HEADER_TRANSITION_ID]: [QQS_HEADER_CONSTRAINT] <-> [QS_HEADER_CONSTRAINT] for portrait
- * handheld device configuration.
+ *   handheld device configuration.
  * * [LARGE_SCREEN_HEADER_TRANSITION_ID]: [LARGE_SCREEN_HEADER_CONSTRAINT] for all other
- * configurations
+ *   configurations
  */
 @CentralSurfacesScope
 class ShadeHeaderController
diff --git a/packages/SystemUI/src/com/android/systemui/shade/transition/LargeScreenPortraitShadeInterpolator.kt b/packages/SystemUI/src/com/android/systemui/shade/transition/LargeScreenPortraitShadeInterpolator.kt
new file mode 100644
index 0000000..0519131
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/transition/LargeScreenPortraitShadeInterpolator.kt
@@ -0,0 +1,46 @@
+/*
+ * 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.shade.transition
+
+import android.util.MathUtils
+import com.android.systemui.animation.ShadeInterpolation
+import javax.inject.Inject
+
+/** Interpolator responsible for the shade when in portrait on a large screen. */
+internal class LargeScreenPortraitShadeInterpolator @Inject internal constructor() :
+    LargeScreenShadeInterpolator {
+
+    override fun getBehindScrimAlpha(fraction: Float): Float {
+        return MathUtils.constrainedMap(0f, 1f, 0f, 0.3f, fraction)
+    }
+
+    override fun getNotificationScrimAlpha(fraction: Float): Float {
+        return MathUtils.constrainedMap(0f, 1f, 0.3f, 0.75f, fraction)
+    }
+
+    override fun getNotificationContentAlpha(fraction: Float): Float {
+        return ShadeInterpolation.getContentAlpha(fraction)
+    }
+
+    override fun getNotificationFooterAlpha(fraction: Float): Float {
+        return ShadeInterpolation.getContentAlpha(fraction)
+    }
+
+    override fun getQsAlpha(fraction: Float): Float {
+        return ShadeInterpolation.getContentAlpha(fraction)
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/transition/LargeScreenShadeInterpolator.kt b/packages/SystemUI/src/com/android/systemui/shade/transition/LargeScreenShadeInterpolator.kt
new file mode 100644
index 0000000..671dfc9c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/transition/LargeScreenShadeInterpolator.kt
@@ -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 com.android.systemui.shade.transition
+
+/** An interpolator interface for the shade expansion. */
+interface LargeScreenShadeInterpolator {
+
+    /** Returns the alpha for the behind/back scrim. */
+    fun getBehindScrimAlpha(fraction: Float): Float
+
+    /** Returns the alpha for the notification scrim. */
+    fun getNotificationScrimAlpha(fraction: Float): Float
+
+    /** Returns the alpha for the notifications. */
+    fun getNotificationContentAlpha(fraction: Float): Float
+
+    /** Returns the alpha for the notifications footer (Manager, Clear All). */
+    fun getNotificationFooterAlpha(fraction: Float): Float
+
+    /** Returns the alpha for the QS panel. */
+    fun getQsAlpha(fraction: Float): Float
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/transition/LargeScreenShadeInterpolatorImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/transition/LargeScreenShadeInterpolatorImpl.kt
new file mode 100644
index 0000000..fd57f21
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/transition/LargeScreenShadeInterpolatorImpl.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.shade.transition
+
+import android.content.Context
+import android.content.res.Configuration
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.util.LargeScreenUtils
+import javax.inject.Inject
+
+/** Interpolator responsible for the shade when on large screens. */
+@SysUISingleton
+internal class LargeScreenShadeInterpolatorImpl
+@Inject
+internal constructor(
+    configurationController: ConfigurationController,
+    private val context: Context,
+    private val splitShadeInterpolator: SplitShadeInterpolator,
+    private val portraitShadeInterpolator: LargeScreenPortraitShadeInterpolator,
+) : LargeScreenShadeInterpolator {
+
+    private var inSplitShade = false
+
+    init {
+        configurationController.addCallback(
+            object : ConfigurationController.ConfigurationListener {
+                override fun onConfigChanged(newConfig: Configuration?) {
+                    updateResources()
+                }
+            }
+        )
+        updateResources()
+    }
+
+    private fun updateResources() {
+        inSplitShade = LargeScreenUtils.shouldUseSplitNotificationShade(context.resources)
+    }
+
+    private val impl: LargeScreenShadeInterpolator
+        get() =
+            if (inSplitShade) {
+                splitShadeInterpolator
+            } else {
+                portraitShadeInterpolator
+            }
+
+    override fun getBehindScrimAlpha(fraction: Float) = impl.getBehindScrimAlpha(fraction)
+
+    override fun getNotificationScrimAlpha(fraction: Float) =
+        impl.getNotificationScrimAlpha(fraction)
+
+    override fun getNotificationContentAlpha(fraction: Float) =
+        impl.getNotificationContentAlpha(fraction)
+
+    override fun getNotificationFooterAlpha(fraction: Float) =
+        impl.getNotificationFooterAlpha(fraction)
+
+    override fun getQsAlpha(fraction: Float) = impl.getQsAlpha(fraction)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt
index 218e897..4e1c272 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt
@@ -23,6 +23,8 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.dump.DumpManager
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
 import com.android.systemui.shade.PanelState
 import com.android.systemui.shade.STATE_OPENING
 import com.android.systemui.shade.ShadeExpansionChangeEvent
@@ -45,7 +47,8 @@
     private val scrimController: ScrimController,
     @Main private val resources: Resources,
     private val statusBarStateController: SysuiStatusBarStateController,
-    private val headsUpManager: HeadsUpManager
+    private val headsUpManager: HeadsUpManager,
+    private val featureFlags: FeatureFlags,
 ) {
 
     private var inSplitShade = false
@@ -106,7 +109,8 @@
                 // in case of HUN we can't always use predefined distances to manage scrim
                 // transition because dragDownPxAmount can start from value bigger than
                 // splitShadeScrimTransitionDistance
-                !headsUpManager.isTrackingHeadsUp
+                !headsUpManager.isTrackingHeadsUp &&
+                !featureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)
 
     private fun isScreenUnlocked() =
         statusBarStateController.currentOrUpcomingState == StatusBarState.SHADE
diff --git a/packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeInterpolator.kt b/packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeInterpolator.kt
new file mode 100644
index 0000000..423ba8d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeInterpolator.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade.transition
+
+import android.util.MathUtils
+import javax.inject.Inject
+
+/** Interpolator responsible for the split shade. */
+internal class SplitShadeInterpolator @Inject internal constructor() :
+    LargeScreenShadeInterpolator {
+
+    override fun getBehindScrimAlpha(fraction: Float): Float {
+        // Start delay: 0%
+        // Duration: 40%
+        // End: 40%
+        return mapFraction(start = 0f, end = 0.4f, fraction)
+    }
+
+    override fun getNotificationScrimAlpha(fraction: Float): Float {
+        // Start delay: 39%
+        // Duration: 27%
+        // End: 66%
+        return mapFraction(start = 0.39f, end = 0.66f, fraction)
+    }
+
+    override fun getNotificationContentAlpha(fraction: Float): Float {
+        return getNotificationScrimAlpha(fraction)
+    }
+
+    override fun getNotificationFooterAlpha(fraction: Float): Float {
+        // Start delay: 57.6%
+        // Duration: 32.1%
+        // End: 89.7%
+        return mapFraction(start = 0.576f, end = 0.897f, fraction)
+    }
+
+    override fun getQsAlpha(fraction: Float): Float {
+        return getNotificationScrimAlpha(fraction)
+    }
+
+    private fun mapFraction(start: Float, end: Float, fraction: Float) =
+        MathUtils.constrainedMap(
+            /* rangeMin= */ 0f,
+            /* rangeMax= */ 1f,
+            /* valueMin= */ start,
+            /* valueMax= */ end,
+            /* value= */ fraction
+        )
+}
diff --git a/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceViewComponent.kt b/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceViewComponent.kt
index 5736a5c..26149321 100644
--- a/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceViewComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceViewComponent.kt
@@ -37,7 +37,8 @@
         fun create(
             @BindsInstance parent: ViewGroup,
             @BindsInstance @Named(PLUGIN) plugin: BcSmartspaceDataPlugin,
-            @BindsInstance onAttachListener: View.OnAttachStateChangeListener
+            @BindsInstance onAttachListener: View.OnAttachStateChangeListener,
+            @BindsInstance viewWithCustomLayout: View? = null
         ): SmartspaceViewComponent
     }
 
@@ -53,10 +54,13 @@
             falsingManager: FalsingManager,
             parent: ViewGroup,
             @Named(PLUGIN) plugin: BcSmartspaceDataPlugin,
+            viewWithCustomLayout: View?,
             onAttachListener: View.OnAttachStateChangeListener
         ):
                 BcSmartspaceDataPlugin.SmartspaceView {
-            val ssView = plugin.getView(parent)
+            val ssView = viewWithCustomLayout
+                    as? BcSmartspaceDataPlugin.SmartspaceView
+                    ?: plugin.getView(parent)
             // Currently, this is only used to provide SmartspaceView on Dream surface.
             ssView.setUiSurface(UI_SURFACE_DREAM)
             ssView.registerDataProvider(plugin)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index d3927a2..779be2b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -178,10 +178,12 @@
     private boolean mVisible;
     private boolean mOrganizationOwnedDevice;
 
+    // these all assume the device is plugged in (wired/wireless/docked) AND chargingOrFull:
     private boolean mPowerPluggedIn;
     private boolean mPowerPluggedInWired;
     private boolean mPowerPluggedInWireless;
     private boolean mPowerPluggedInDock;
+
     private boolean mPowerCharged;
     private boolean mBatteryOverheated;
     private boolean mEnableBatteryDefender;
@@ -512,6 +514,7 @@
                 powerIndication += ",  " + (mChargingWattage / 1000) + " mW";
             }
 
+            mKeyguardLogger.logUpdateBatteryIndication(powerIndication, mPowerPluggedIn);
             mRotateTextViewController.updateIndication(
                     INDICATION_TYPE_BATTERY,
                     new KeyguardIndication.Builder()
@@ -520,6 +523,7 @@
                             .build(),
                     animate);
         } else {
+            mKeyguardLogger.log(TAG, LogLevel.DEBUG, "hide battery indication");
             // don't show the charging information if device isn't plugged in
             mRotateTextViewController.hideIndication(INDICATION_TYPE_BATTERY);
         }
@@ -898,6 +902,9 @@
         updateLockScreenIndications(animate, getCurrentUser());
     }
 
+    /**
+     * Assumption: device is charging
+     */
     protected String computePowerIndication() {
         int chargingId;
         if (mBatteryOverheated) {
@@ -1052,6 +1059,12 @@
             }
         }
 
+        /**
+         * KeyguardUpdateMonitor only sends "interesting" battery updates
+         * {@link KeyguardUpdateMonitor#isBatteryUpdateInteresting}.
+         * Therefore, make sure to always check plugged in state along with any charging status
+         * change, or else we could end up with stale state.
+         */
         @Override
         public void onRefreshBatteryInfo(BatteryStatus status) {
             boolean isChargingOrFull = status.status == BatteryManager.BATTERY_STATUS_CHARGING
@@ -1067,6 +1080,7 @@
             mBatteryLevel = status.level;
             mBatteryPresent = status.present;
             mBatteryOverheated = status.isOverheated();
+            // when the battery is overheated, device doesn't charge so only guard on pluggedIn:
             mEnableBatteryDefender = mBatteryOverheated && status.isPluggedIn();
             mIncompatibleCharger = status.incompatibleCharger.orElse(false);
             try {
@@ -1076,14 +1090,10 @@
                 mKeyguardLogger.log(TAG, ERROR, "Error calling IBatteryStats", e);
                 mChargingTimeRemaining = -1;
             }
+
+            mKeyguardLogger.logRefreshBatteryInfo(isChargingOrFull, mPowerPluggedIn, mBatteryLevel,
+                    mBatteryOverheated);
             updateDeviceEntryIndication(!wasPluggedIn && mPowerPluggedInWired);
-            if (mDozing) {
-                if (!wasPluggedIn && mPowerPluggedIn) {
-                    showTransientIndication(computePowerIndication());
-                } else if (wasPluggedIn && !mPowerPluggedIn) {
-                    hideTransientIndication();
-                }
-            }
         }
 
         @Override
@@ -1335,6 +1345,10 @@
         }
     }
 
+    protected boolean isPluggedInAndCharging() {
+        return mPowerPluggedIn;
+    }
+
     private boolean isCurrentUser(int userId) {
         return getCurrentUser() == userId;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt
index 62c225b..df8c6ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt
@@ -148,7 +148,8 @@
               qsDragFraction: $qsTransitionFraction
               qsSquishFraction: $qsSquishTransitionFraction
               isTransitioningToFullShade: $isTransitioningToFullShade
-        """.trimIndent()
+        """
+                .trimIndent()
         )
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index f0d064b..9a9503c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -572,8 +572,7 @@
             entry.setGroupExpansionChanging(true)
             userId = entry.sbn.userId
         }
-        var fullShadeNeedsBouncer = (!lockScreenUserManager.userAllowsPrivateNotificationsInPublic(
-                lockScreenUserManager.getCurrentUserId()) ||
+        var fullShadeNeedsBouncer = (
                 !lockScreenUserManager.shouldShowLockscreenNotifications() ||
                 falsingCollector.shouldEnforceBouncer())
         if (keyguardBypassController.bypassEnabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 8f1e0a1..3709a13 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -39,7 +39,10 @@
 import com.android.systemui.R;
 import com.android.systemui.animation.Interpolators;
 import com.android.systemui.animation.ShadeInterpolation;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
 import com.android.systemui.statusbar.notification.LegacySourceType;
 import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.SourceType;
@@ -216,7 +219,15 @@
                 if (ambientState.isBouncerInTransit()) {
                     viewState.setAlpha(aboutToShowBouncerProgress(expansion));
                 } else {
-                    viewState.setAlpha(ShadeInterpolation.getContentAlpha(expansion));
+                    FeatureFlags flags = ambientState.getFeatureFlags();
+                    if (ambientState.isSmallScreen() || !flags.isEnabled(
+                            Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)) {
+                        viewState.setAlpha(ShadeInterpolation.getContentAlpha(expansion));
+                    } else {
+                        LargeScreenShadeInterpolator interpolator =
+                                ambientState.getLargeScreenShadeInterpolator();
+                        viewState.setAlpha(interpolator.getNotificationContentAlpha(expansion));
+                    }
                 }
             } else {
                 viewState.setAlpha(1f - ambientState.getHideAmount());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index c35c5c5..7755003 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -93,6 +93,16 @@
     @IntDef({STATE_ICON, STATE_DOT, STATE_HIDDEN})
     public @interface VisibleState { }
 
+    /** Returns a human-readable string of {@link VisibleState}. */
+    public static String getVisibleStateString(@VisibleState int state) {
+        switch(state) {
+            case STATE_ICON: return "ICON";
+            case STATE_DOT: return "DOT";
+            case STATE_HIDDEN: return "HIDDEN";
+            default: return "UNKNOWN";
+        }
+    }
+
     private static final String TAG = "StatusBarIconView";
     private static final Property<StatusBarIconView, Float> ICON_APPEAR_AMOUNT
             = new FloatProperty<StatusBarIconView>("iconAppearAmount") {
@@ -561,7 +571,8 @@
     @Override
     public String toString() {
         return "StatusBarIconView("
-                + "slot='" + mSlot + " alpha=" + getAlpha() + " icon=" + mIcon
+                + "slot='" + mSlot + "' alpha=" + getAlpha() + " icon=" + mIcon
+                + " visibleState=" + getVisibleStateString(getVisibleState())
                 + " iconColor=#" + Integer.toHexString(mIconColor)
                 + " notification=" + mNotification + ')';
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt
index 42b874f..7297ae6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt
@@ -74,7 +74,7 @@
 
     /**
      * @return a context with the MCC/MNC [Configuration] values corresponding to this
-     * subscriptionId
+     *   subscriptionId
      */
     fun getMobileContextForSub(subId: Int, context: Context): Context {
         if (demoModeController.isInDemoMode) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt
index 64b7ac9..5fa83ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt
@@ -39,6 +39,7 @@
  *      - Simple prioritization: Privacy > Battery > connectivity (encoded in [StatusEvent])
  *      - Only schedules a single event, and throws away lowest priority events
  * ```
+ *
  * There are 4 basic stages of animation at play here:
  * ```
  *      1. System chrome animation OUT
@@ -46,6 +47,7 @@
  *      3. Chip animation OUT; potentially into a dot
  *      4. System chrome animation IN
  * ```
+ *
  * Thus we can keep all animations synchronized with two separate ValueAnimators, one for system
  * chrome and the other for the chip. These can animate from 0,1 and listeners can parameterize
  * their respective views based on the progress of the animator. Interpolation differences TBD
@@ -168,7 +170,7 @@
      * 3. Update the scheduler state so that clients know where we are
      * 4. Maybe: provide scaffolding such as: dot location, margins, etc
      * 5. Maybe: define a maximum animation length and enforce it. Probably only doable if we
-     * collect all of the animators and run them together.
+     *    collect all of the animators and run them together.
      */
     private fun runChipAnimation() {
         statusBarWindowController.setForceStatusBarVisible(true)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
index f395bea..826e289 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
@@ -334,9 +334,9 @@
         }
 
         val ssView = plugin.getView(parent)
+        configPlugin?.let { ssView.registerConfigProvider(it) }
         ssView.setUiSurface(BcSmartspaceDataPlugin.UI_SURFACE_LOCK_SCREEN_AOD)
         ssView.registerDataProvider(plugin)
-        configPlugin?.let { ssView.registerConfigProvider(it) }
 
         ssView.setIntentStarter(object : BcSmartspaceDataPlugin.IntentStarter {
             override fun startIntent(view: View, intent: Intent, showOnLockscreen: Boolean) {
@@ -501,8 +501,10 @@
 
     private fun updateTextColorFromRegionSampler() {
         smartspaceViews.forEach {
-            val textColor = regionSamplers.getValue(it).currentForegroundColor()
-            it.setPrimaryTextColor(textColor)
+            val textColor = regionSamplers.get(it)?.currentForegroundColor()
+            if (textColor != null) {
+                it.setPrimaryTextColor(textColor)
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
index 0a5e986..11582d7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -29,7 +29,6 @@
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
-import android.app.SynchronousUserSwitchObserver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -52,7 +51,9 @@
 import com.android.systemui.CoreStartable;
 import com.android.systemui.R;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dagger.qualifiers.UiBackground;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.NotificationChannels;
@@ -73,6 +74,8 @@
 
     private final Context mContext;
     private final Handler mHandler = new Handler();
+    private final UserTracker mUserTracker;
+    private final Executor mMainExecutor;
     private final Executor mUiBgExecutor;
     private final ArraySet<Pair<String, Integer>> mCurrentNotifs = new ArraySet<>();
     private final CommandQueue mCommandQueue;
@@ -82,10 +85,14 @@
     public InstantAppNotifier(
             Context context,
             CommandQueue commandQueue,
+            UserTracker userTracker,
+            @Main Executor mainExecutor,
             @UiBackground Executor uiBgExecutor,
             KeyguardStateController keyguardStateController) {
         mContext = context;
         mCommandQueue = commandQueue;
+        mUserTracker = userTracker;
+        mMainExecutor = mainExecutor;
         mUiBgExecutor = uiBgExecutor;
         mKeyguardStateController = keyguardStateController;
     }
@@ -93,11 +100,7 @@
     @Override
     public void start() {
         // listen for user / profile change.
-        try {
-            ActivityManager.getService().registerUserSwitchObserver(mUserSwitchListener, TAG);
-        } catch (RemoteException e) {
-            // Ignore
-        }
+        mUserTracker.addCallback(mUserSwitchListener, mMainExecutor);
 
         mCommandQueue.addCallback(this);
         mKeyguardStateController.addCallback(this);
@@ -129,13 +132,10 @@
         updateForegroundInstantApps();
     }
 
-    private final SynchronousUserSwitchObserver mUserSwitchListener =
-            new SynchronousUserSwitchObserver() {
+    private final UserTracker.Callback mUserSwitchListener =
+            new UserTracker.Callback() {
                 @Override
-                public void onUserSwitching(int newUserId) throws RemoteException {}
-
-                @Override
-                public void onUserSwitchComplete(int newUserId) throws RemoteException {
+                public void onUserChanged(int newUser, Context userContext) {
                     mHandler.post(
                             () -> {
                                 updateForegroundInstantApps();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
index fc89be2..00d8c42 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
@@ -28,10 +28,6 @@
     val featureFlags: FeatureFlags,
     val sysPropFlags: FlagResolver,
 ) {
-    init {
-        featureFlags.addListener(Flags.DISABLE_FSI) { event -> event.requestNoRestart() }
-    }
-
     fun isDevLoggingEnabled(): Boolean =
         featureFlags.isEnabled(Flags.NOTIFICATION_PIPELINE_DEVELOPER_LOGGING)
 
@@ -40,8 +36,6 @@
 
     fun fsiOnDNDUpdate(): Boolean = featureFlags.isEnabled(Flags.FSI_ON_DND_UPDATE)
 
-    fun disableFsi(): Boolean = featureFlags.isEnabled(Flags.DISABLE_FSI)
-
     fun forceDemoteFsi(): Boolean =
             sysPropFlags.isEnabled(NotificationFlags.FSI_FORCE_DEMOTE)
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
index 7e53d54..8874f59 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -18,6 +18,7 @@
 
 import android.animation.ObjectAnimator
 import android.util.FloatProperty
+import androidx.annotation.VisibleForTesting
 import com.android.systemui.Dumpable
 import com.android.systemui.animation.Interpolators
 import com.android.systemui.dagger.SysUISingleton
@@ -302,29 +303,29 @@
             // the doze amount to 0f (not dozing) so that the notifications are no longer hidden.
             // See: UnlockedScreenOffAnimationController.onFinishedWakingUp()
             setDozeAmount(0f, 0f, source = "Override: Shade->Shade (lock cancelled by unlock)")
+            this.state = newState
+            return
         }
 
         if (overrideDozeAmountIfAnimatingScreenOff(mLinearDozeAmount)) {
+            this.state = newState
             return
         }
 
         if (overrideDozeAmountIfBypass()) {
+            this.state = newState
             return
         }
 
         maybeClearDozeAmountOverrideHidingNotifs()
 
-        if (bypassController.bypassEnabled &&
-                newState == StatusBarState.KEYGUARD && state == StatusBarState.SHADE_LOCKED &&
-            (!statusBarStateController.isDozing || shouldAnimateVisibility())) {
-            // We're leaving shade locked. Let's animate the notifications away
-            setNotificationsVisible(visible = true, increaseSpeed = false, animate = false)
-            setNotificationsVisible(visible = false, increaseSpeed = false, animate = true)
-        }
-
         this.state = newState
     }
 
+    @VisibleForTesting
+    val statusBarState: Int
+        get() = state
+
     override fun onPanelExpansionChanged(event: ShadeExpansionChangeEvent) {
         val collapsedEnough = event.fraction <= 0.9f
         if (collapsedEnough != this.collapsedEnoughToHide) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt
index 4464531..88d9ffc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt
@@ -13,7 +13,7 @@
 
 package com.android.systemui.statusbar.notification
 
-import com.android.systemui.log.dagger.NotificationLog
+import com.android.systemui.log.dagger.NotificationLockscreenLog
 import com.android.systemui.plugins.log.LogBuffer
 import com.android.systemui.plugins.log.LogLevel.DEBUG
 import com.android.systemui.statusbar.StatusBarState
@@ -21,7 +21,12 @@
 
 class NotificationWakeUpCoordinatorLogger
 @Inject
-constructor(@NotificationLog private val buffer: LogBuffer) {
+constructor(@NotificationLockscreenLog private val buffer: LogBuffer) {
+    private var lastSetDozeAmountLogWasFractional = false
+    private var lastSetDozeAmountLogState = -1
+    private var lastSetDozeAmountLogSource = "undefined"
+    private var lastOnDozeAmountChangedLogWasFractional = false
+
     fun logSetDozeAmount(
         linear: Float,
         eased: Float,
@@ -29,6 +34,20 @@
         state: Int,
         changed: Boolean,
     ) {
+        // Avoid logging on every frame of the animation if important values are not changing
+        val isFractional = linear != 1f && linear != 0f
+        if (
+            lastSetDozeAmountLogWasFractional &&
+                isFractional &&
+                lastSetDozeAmountLogState == state &&
+                lastSetDozeAmountLogSource == source
+        ) {
+            return
+        }
+        lastSetDozeAmountLogWasFractional = isFractional
+        lastSetDozeAmountLogState = state
+        lastSetDozeAmountLogSource = source
+
         buffer.log(
             TAG,
             DEBUG,
@@ -66,6 +85,10 @@
     }
 
     fun logOnDozeAmountChanged(linear: Float, eased: Float) {
+        // Avoid logging on every frame of the animation when values are fractional
+        val isFractional = linear != 1f && linear != 0f
+        if (lastOnDozeAmountChangedLogWasFractional && isFractional) return
+        lastOnDozeAmountChangedLogWasFractional = isFractional
         buffer.log(
             TAG,
             DEBUG,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt
index a35617c..6deef2e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt
@@ -315,6 +315,7 @@
 
 /**
  * State object for a `Roundable` class.
+ *
  * @param targetView Will handle the [AnimatableProperty]
  * @param roundable Target of the radius animation
  * @param maxRadius Max corner radius in pixels
@@ -436,7 +437,6 @@
          * This is the most convenient way to define a new [SourceType].
          *
          * For example:
-         *
          * ```kotlin
          *     private val SECTION = SourceType.from("Section")
          * ```
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt
index 1fccf82..0a9dddc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt
@@ -46,6 +46,7 @@
 
     /**
      * Visits every entry and its children to mark the dismissible entries.
+     *
      * @param markedKeys set to store the marked entry keys
      * @param entries to visit
      * @param isLocked the locked state of the device
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupWhenCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupWhenCoordinator.kt
new file mode 100644
index 0000000..5ce1db2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupWhenCoordinator.kt
@@ -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.systemui.statusbar.notification.collection.coordinator
+
+import android.util.ArrayMap
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.statusbar.notification.collection.GroupEntry
+import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator
+import com.android.systemui.statusbar.notification.collection.render.NotifGroupController
+import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.time.SystemClock
+import javax.inject.Inject
+import kotlin.math.max
+import kotlin.math.min
+
+/** A small coordinator which finds, stores, and applies the closest notification time. */
+@CoordinatorScope
+class GroupWhenCoordinator
+@Inject
+constructor(
+    @Main private val delayableExecutor: DelayableExecutor,
+    private val systemClock: SystemClock
+) : Coordinator {
+
+    private val invalidator = object : Invalidator("GroupWhenCoordinator") {}
+    private val notificationGroupTimes = ArrayMap<GroupEntry, Long>()
+    private var cancelInvalidateListRunnable: Runnable? = null
+
+    private val invalidateListRunnable: Runnable = Runnable {
+        invalidator.invalidateList("future notification invalidation")
+    }
+
+    override fun attach(pipeline: NotifPipeline) {
+        pipeline.addOnBeforeFinalizeFilterListener(::onBeforeFinalizeFilterListener)
+        pipeline.addOnAfterRenderGroupListener(::onAfterRenderGroupListener)
+        pipeline.addPreRenderInvalidator(invalidator)
+    }
+
+    private fun onBeforeFinalizeFilterListener(entries: List<ListEntry>) {
+        cancelListInvalidation()
+        notificationGroupTimes.clear()
+
+        val now = systemClock.currentTimeMillis()
+        var closestFutureTime = Long.MAX_VALUE
+        entries.asSequence().filterIsInstance<GroupEntry>().forEach { groupEntry ->
+            val whenMillis = calculateGroupNotificationTime(groupEntry, now)
+            notificationGroupTimes[groupEntry] = whenMillis
+            if (whenMillis > now) {
+                closestFutureTime = min(closestFutureTime, whenMillis)
+            }
+        }
+
+        if (closestFutureTime != Long.MAX_VALUE) {
+            cancelInvalidateListRunnable =
+                delayableExecutor.executeDelayed(invalidateListRunnable, closestFutureTime - now)
+        }
+    }
+
+    private fun cancelListInvalidation() {
+        cancelInvalidateListRunnable?.run()
+        cancelInvalidateListRunnable = null
+    }
+
+    private fun onAfterRenderGroupListener(group: GroupEntry, controller: NotifGroupController) {
+        notificationGroupTimes[group]?.let(controller::setNotificationGroupWhen)
+    }
+
+    private fun calculateGroupNotificationTime(
+        groupEntry: GroupEntry,
+        currentTimeMillis: Long
+    ): Long {
+        var pastTime = Long.MIN_VALUE
+        var futureTime = Long.MAX_VALUE
+        groupEntry.children
+            .asSequence()
+            .mapNotNull { child -> child.sbn.notification.`when`.takeIf { it > 0 } }
+            .forEach { time ->
+                val isInThePast = currentTimeMillis - time > 0
+                if (isInThePast) {
+                    pastTime = max(pastTime, time)
+                } else {
+                    futureTime = min(futureTime, time)
+                }
+            }
+
+        if (pastTime == Long.MIN_VALUE && futureTime == Long.MAX_VALUE) {
+            return checkNotNull(groupEntry.summary).creationTime
+        }
+
+        return if (futureTime != Long.MAX_VALUE) futureTime else pastTime
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
index 1004ec1..4d0e746 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
@@ -389,11 +389,11 @@
             // First check whether this notification should launch a full screen intent, and
             // launch it if needed.
             val fsiDecision = mNotificationInterruptStateProvider.getFullScreenIntentDecision(entry)
-            if (fsiDecision != null && fsiDecision.shouldLaunch) {
-                mNotificationInterruptStateProvider.logFullScreenIntentDecision(entry, fsiDecision)
+            mNotificationInterruptStateProvider.logFullScreenIntentDecision(entry, fsiDecision)
+            if (fsiDecision.shouldLaunch) {
                 mLaunchFullScreenIntentProvider.launchFullScreenIntent(entry)
             } else if (mFlags.fsiOnDNDUpdate() &&
-                fsiDecision.equals(FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND)) {
+                fsiDecision == FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND) {
                 // If DND was the only reason this entry was suppressed, note it for potential
                 // reconsideration on later ranking updates.
                 addForFSIReconsideration(entry, mSystemClock.currentTimeMillis())
@@ -514,14 +514,24 @@
                         mNotificationInterruptStateProvider.getFullScreenIntentDecision(entry)
                     if (decision.shouldLaunch) {
                         // Log both the launch of the full screen and also that this was via a
-                        // ranking update.
-                        mLogger.logEntryUpdatedToFullScreen(entry.key)
+                        // ranking update, and finally revoke candidacy for FSI reconsideration
+                        mLogger.logEntryUpdatedToFullScreen(entry.key, decision.name)
                         mNotificationInterruptStateProvider.logFullScreenIntentDecision(
                             entry, decision)
                         mLaunchFullScreenIntentProvider.launchFullScreenIntent(entry)
+                        mFSIUpdateCandidates.remove(entry.key)
 
                         // if we launch the FSI then this is no longer a candidate for HUN
                         continue
+                    } else if (decision == FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND) {
+                        // decision has not changed; no need to log
+                    } else {
+                        // some other condition is now blocking FSI; log that and revoke candidacy
+                        // for FSI reconsideration
+                        mLogger.logEntryDisqualifiedFromFullScreen(entry.key, decision.name)
+                        mNotificationInterruptStateProvider.logFullScreenIntentDecision(
+                            entry, decision)
+                        mFSIUpdateCandidates.remove(entry.key)
                     }
                 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt
index 2c6bf6b..e936559 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt
@@ -70,11 +70,21 @@
         })
     }
 
-    fun logEntryUpdatedToFullScreen(key: String) {
+    fun logEntryUpdatedToFullScreen(key: String, reason: String) {
         buffer.log(TAG, LogLevel.DEBUG, {
             str1 = key
+            str2 = reason
         }, {
-            "updating entry to launch full screen intent: $str1"
+            "updating entry to launch full screen intent: $str1 because $str2"
+        })
+    }
+
+    fun logEntryDisqualifiedFromFullScreen(key: String, reason: String) {
+        buffer.log(TAG, LogLevel.DEBUG, {
+            str1 = key
+            str2 = reason
+        }, {
+            "updated entry no longer qualifies for full screen intent: $str1 because $str2"
         })
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
index 8a82bca..6bb5b92 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
@@ -31,31 +31,32 @@
 
 @CoordinatorScope
 class NotifCoordinatorsImpl @Inject constructor(
-    notifPipelineFlags: NotifPipelineFlags,
-    dataStoreCoordinator: DataStoreCoordinator,
-    hideLocallyDismissedNotifsCoordinator: HideLocallyDismissedNotifsCoordinator,
-    hideNotifsForOtherUsersCoordinator: HideNotifsForOtherUsersCoordinator,
-    keyguardCoordinator: KeyguardCoordinator,
-    rankingCoordinator: RankingCoordinator,
-    appOpsCoordinator: AppOpsCoordinator,
-    deviceProvisionedCoordinator: DeviceProvisionedCoordinator,
-    bubbleCoordinator: BubbleCoordinator,
-    headsUpCoordinator: HeadsUpCoordinator,
-    gutsCoordinator: GutsCoordinator,
-    conversationCoordinator: ConversationCoordinator,
-    debugModeCoordinator: DebugModeCoordinator,
-    groupCountCoordinator: GroupCountCoordinator,
-    mediaCoordinator: MediaCoordinator,
-    preparationCoordinator: PreparationCoordinator,
-    remoteInputCoordinator: RemoteInputCoordinator,
-    rowAppearanceCoordinator: RowAppearanceCoordinator,
-    stackCoordinator: StackCoordinator,
-    shadeEventCoordinator: ShadeEventCoordinator,
-    smartspaceDedupingCoordinator: SmartspaceDedupingCoordinator,
-    viewConfigCoordinator: ViewConfigCoordinator,
-    visualStabilityCoordinator: VisualStabilityCoordinator,
-    sensitiveContentCoordinator: SensitiveContentCoordinator,
-    dismissibilityCoordinator: DismissibilityCoordinator
+        notifPipelineFlags: NotifPipelineFlags,
+        dataStoreCoordinator: DataStoreCoordinator,
+        hideLocallyDismissedNotifsCoordinator: HideLocallyDismissedNotifsCoordinator,
+        hideNotifsForOtherUsersCoordinator: HideNotifsForOtherUsersCoordinator,
+        keyguardCoordinator: KeyguardCoordinator,
+        rankingCoordinator: RankingCoordinator,
+        appOpsCoordinator: AppOpsCoordinator,
+        deviceProvisionedCoordinator: DeviceProvisionedCoordinator,
+        bubbleCoordinator: BubbleCoordinator,
+        headsUpCoordinator: HeadsUpCoordinator,
+        gutsCoordinator: GutsCoordinator,
+        conversationCoordinator: ConversationCoordinator,
+        debugModeCoordinator: DebugModeCoordinator,
+        groupCountCoordinator: GroupCountCoordinator,
+        groupWhenCoordinator: GroupWhenCoordinator,
+        mediaCoordinator: MediaCoordinator,
+        preparationCoordinator: PreparationCoordinator,
+        remoteInputCoordinator: RemoteInputCoordinator,
+        rowAppearanceCoordinator: RowAppearanceCoordinator,
+        stackCoordinator: StackCoordinator,
+        shadeEventCoordinator: ShadeEventCoordinator,
+        smartspaceDedupingCoordinator: SmartspaceDedupingCoordinator,
+        viewConfigCoordinator: ViewConfigCoordinator,
+        visualStabilityCoordinator: VisualStabilityCoordinator,
+        sensitiveContentCoordinator: SensitiveContentCoordinator,
+        dismissibilityCoordinator: DismissibilityCoordinator
 ) : NotifCoordinators {
 
     private val mCoordinators: MutableList<Coordinator> = ArrayList()
@@ -82,6 +83,7 @@
         mCoordinators.add(debugModeCoordinator)
         mCoordinators.add(conversationCoordinator)
         mCoordinators.add(groupCountCoordinator)
+        mCoordinators.add(groupWhenCoordinator)
         mCoordinators.add(mediaCoordinator)
         mCoordinators.add(rowAppearanceCoordinator)
         mCoordinators.add(stackCoordinator)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGroupController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGroupController.kt
index e2edc01..061ef9e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGroupController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGroupController.kt
@@ -20,4 +20,7 @@
 interface NotifGroupController {
     /** Set the number of children that this group would have if not for the 8-child max */
     fun setUntruncatedChildCount(untruncatedChildCount: Int)
+
+    /** Set the when value of notification group that reflects most important closest notification time */
+    fun setNotificationGroupWhen(whenMillis: Long)
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepo.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepo.kt
deleted file mode 100644
index b483228..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepo.kt
+++ /dev/null
@@ -1,102 +0,0 @@
-package com.android.systemui.statusbar.notification.fsi
-
-import android.app.PendingIntent
-import android.content.Context
-import android.content.pm.PackageManager
-import android.graphics.drawable.Drawable
-import android.os.RemoteException
-import android.service.dreams.IDreamManager
-import com.android.systemui.CoreStartable
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.data.repository.KeyguardRepository
-import com.android.systemui.statusbar.notification.collection.NotificationEntry
-import com.android.systemui.statusbar.notification.collection.provider.LaunchFullScreenIntentProvider
-import com.android.systemui.statusbar.notification.fsi.FsiDebug.Companion.log
-import com.android.systemui.statusbar.phone.CentralSurfaces
-import java.util.concurrent.Executor
-import javax.inject.Inject
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-
-/**
- * Class that bridges the gap between clean app architecture and existing code. Provides new
- * implementation of StatusBarNotificationActivityStarter launchFullscreenIntent that pipes
- * one-directional data => FsiChromeViewModel => FsiChromeView.
- */
-@SysUISingleton
-class FsiChromeRepo
-@Inject
-constructor(
-    private val context: Context,
-    private val pm: PackageManager,
-    private val keyguardRepo: KeyguardRepository,
-    private val launchFullScreenIntentProvider: LaunchFullScreenIntentProvider,
-    private val featureFlags: FeatureFlags,
-    private val uiBgExecutor: Executor,
-    private val dreamManager: IDreamManager,
-    private val centralSurfaces: CentralSurfaces
-) : CoreStartable {
-
-    companion object {
-        private const val classTag = "FsiChromeRepo"
-    }
-
-    data class FSIInfo(
-        val appName: String,
-        val appIcon: Drawable,
-        val fullscreenIntent: PendingIntent
-    )
-
-    private val _infoFlow = MutableStateFlow<FSIInfo?>(null)
-    val infoFlow: StateFlow<FSIInfo?> = _infoFlow
-
-    override fun start() {
-        log("$classTag start listening for FSI notifications")
-
-        // Listen for FSI launch events for the lifetime of SystemUI.
-        launchFullScreenIntentProvider.registerListener { entry -> launchFullscreenIntent(entry) }
-    }
-
-    fun dismiss() {
-        _infoFlow.value = null
-    }
-
-    fun onFullscreen() {
-        // TODO(b/243421660) implement transition from container to fullscreen
-    }
-
-    fun stopScreenSaver() {
-        uiBgExecutor.execute {
-            try {
-                dreamManager.awaken()
-            } catch (e: RemoteException) {
-                e.printStackTrace()
-            }
-        }
-    }
-
-    fun launchFullscreenIntent(entry: NotificationEntry) {
-        if (!featureFlags.isEnabled(Flags.FSI_CHROME)) {
-            return
-        }
-        if (!keyguardRepo.isKeyguardShowing()) {
-            return
-        }
-        stopScreenSaver()
-
-        var appName = pm.getApplicationLabel(context.applicationInfo) as String
-        val appIcon = pm.getApplicationIcon(context.packageName)
-        val fullscreenIntent = entry.sbn.notification.fullScreenIntent
-
-        log("FsiChromeRepo launchFullscreenIntent appName=$appName appIcon $appIcon")
-        _infoFlow.value = FSIInfo(appName, appIcon, fullscreenIntent)
-
-        // If screen is off or we're showing AOD, show lockscreen.
-        centralSurfaces.wakeUpForFullScreenIntent()
-
-        // Don't show HUN since we're already showing FSI.
-        entry.notifyFullScreenIntentLaunched()
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeView.kt
deleted file mode 100644
index 6e5fcf4..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeView.kt
+++ /dev/null
@@ -1,83 +0,0 @@
-package com.android.systemui.statusbar.notification.fsi
-
-import android.content.Context
-import android.graphics.Color
-import android.graphics.Color.DKGRAY
-import android.graphics.Outline
-import android.util.AttributeSet
-import android.view.View
-import android.view.ViewOutlineProvider
-import android.widget.Button
-import android.widget.ImageView
-import android.widget.LinearLayout
-import android.widget.TextView
-import com.android.systemui.R
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.statusbar.notification.fsi.FsiDebug.Companion.log
-
-@SysUISingleton
-class FsiChromeView
-@JvmOverloads
-constructor(
-    context: Context?,
-    attrs: AttributeSet? = null,
-    defStyleAttr: Int = 0,
-    defStyleRes: Int = 0
-) : LinearLayout(context, attrs, defStyleAttr, defStyleRes) {
-
-    companion object {
-        private const val classTag = "FsiChromeView"
-    }
-
-    lateinit var chromeContainer: LinearLayout
-    lateinit var appIconImageView: ImageView
-    lateinit var appNameTextView: TextView
-    lateinit var dismissButton: Button
-    lateinit var fullscreenButton: Button
-
-    private val cornerRadius: Float =
-        resources.getDimensionPixelSize(R.dimen.notification_corner_radius).toFloat()
-    private val vertPadding: Int =
-        resources.getDimensionPixelSize(R.dimen.fsi_chrome_vertical_padding)
-    private val sidePadding: Int =
-        resources.getDimensionPixelSize(R.dimen.notification_side_paddings)
-
-    init {
-        log("$classTag init")
-    }
-
-    override fun onFinishInflate() {
-        log("$classTag onFinishInflate")
-        super.onFinishInflate()
-
-        setBackgroundColor(Color.TRANSPARENT)
-        setPadding(
-            sidePadding,
-            vertPadding,
-            sidePadding,
-            vertPadding
-        ) // Make smaller than fullscreen.
-
-        chromeContainer = findViewById(R.id.fsi_chrome)
-        chromeContainer.setBackgroundColor(DKGRAY)
-
-        appIconImageView = findViewById(R.id.fsi_app_icon)
-        appNameTextView = findViewById(R.id.fsi_app_name)
-        dismissButton = findViewById(R.id.fsi_dismiss_button)
-        fullscreenButton = findViewById(R.id.fsi_fullscreen_button)
-
-        outlineProvider =
-            object : ViewOutlineProvider() {
-                override fun getOutline(view: View, outline: Outline) {
-                    outline.setRoundRect(
-                        /* left */ sidePadding,
-                        /* top */ vertPadding,
-                        /* right */ view.width - sidePadding,
-                        /* bottom */ view.height - vertPadding,
-                        cornerRadius
-                    )
-                }
-            }
-        clipToOutline = true
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewBinder.kt
deleted file mode 100644
index 1a3927b..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewBinder.kt
+++ /dev/null
@@ -1,99 +0,0 @@
-package com.android.systemui.statusbar.notification.fsi
-
-import android.content.Context
-import android.view.LayoutInflater
-import android.view.WindowManager
-import com.android.systemui.CoreStartable
-import com.android.systemui.R
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.statusbar.notification.fsi.FsiDebug.Companion.log
-import com.android.systemui.statusbar.phone.CentralSurfaces
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.launch
-import java.util.concurrent.Executor
-import javax.inject.Inject
-
-@SysUISingleton
-class FsiChromeViewBinder
-@Inject
-constructor(
-    val context: Context,
-    val windowManager: WindowManager,
-    val viewModelFactory: FsiChromeViewModelFactory,
-    val layoutInflater: LayoutInflater,
-    val centralSurfaces: CentralSurfaces,
-    @Main val mainExecutor: Executor,
-    @Application val scope: CoroutineScope,
-) : CoreStartable {
-
-    companion object {
-        private const val classTag = "FsiChromeViewBinder"
-    }
-
-    private val fsiChromeView =
-        layoutInflater.inflate(R.layout.fsi_chrome_view, null /* root */, false /* attachToRoot */)
-            as FsiChromeView
-
-    var addedToWindowManager = false
-    var cornerRadius: Int = context.resources.getDimensionPixelSize(
-            R.dimen.notification_corner_radius)
-
-    override fun start() {
-        val methodTag = "start"
-        log("$classTag $methodTag ")
-
-        scope.launch {
-            log("$classTag $methodTag launch ")
-            viewModelFactory.viewModelFlow.collect { vm -> updateForViewModel(vm) }
-        }
-    }
-
-    private fun updateForViewModel(vm: FsiChromeViewModel?) {
-        val methodTag = "updateForViewModel"
-
-        if (vm == null) {
-            log("$classTag $methodTag viewModel is null, removing from window manager")
-
-            if (addedToWindowManager) {
-                windowManager.removeView(fsiChromeView)
-                addedToWindowManager = false
-            }
-            return
-        }
-
-        bindViewModel(vm, windowManager)
-
-        if (addedToWindowManager) {
-            log("$classTag $methodTag already addedToWindowManager")
-        } else {
-            windowManager.addView(fsiChromeView, FsiTaskViewConfig.getWmLayoutParams("PackageName"))
-            addedToWindowManager = true
-        }
-    }
-
-    private fun bindViewModel(
-        vm: FsiChromeViewModel,
-        windowManager: WindowManager,
-    ) {
-        log("$classTag bindViewModel")
-
-        fsiChromeView.appIconImageView.setImageDrawable(vm.appIcon)
-        fsiChromeView.appNameTextView.text = vm.appName
-
-        fsiChromeView.dismissButton.setOnClickListener { vm.onDismiss() }
-        fsiChromeView.fullscreenButton.setOnClickListener { vm.onFullscreen() }
-
-        vm.taskView.cornerRadius = cornerRadius.toFloat()
-        vm.taskView.startActivity(
-            vm.fsi,
-            FsiTaskViewConfig.getFillInIntent(),
-            FsiTaskViewConfig.getActivityOptions(context, windowManager),
-            FsiTaskViewConfig.getLaunchBounds(windowManager)
-        )
-
-        log("$classTag bindViewModel started taskview activity")
-        fsiChromeView.addView(vm.taskView)
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactory.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactory.kt
deleted file mode 100644
index 1ca698b..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactory.kt
+++ /dev/null
@@ -1,87 +0,0 @@
-package com.android.systemui.statusbar.notification.fsi
-
-import android.annotation.UiContext
-import android.app.PendingIntent
-import android.content.Context
-import android.graphics.drawable.Drawable
-import com.android.systemui.CoreStartable
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.statusbar.notification.fsi.FsiDebug.Companion.log
-import com.android.wm.shell.TaskView
-import com.android.wm.shell.TaskViewFactory
-import java.util.Optional
-import java.util.concurrent.Executor
-import javax.inject.Inject
-import kotlin.coroutines.resume
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.mapLatest
-import kotlinx.coroutines.suspendCancellableCoroutine
-
-/**
- * Handle view-related data for fullscreen intent container on lockscreen. Wraps FsiChromeRepo,
- * transforms events/state into view-relevant representation for FsiChromeView. Alive for lifetime
- * of SystemUI.
- */
-@SysUISingleton
-class FsiChromeViewModelFactory
-@Inject
-constructor(
-    val repo: FsiChromeRepo,
-    val taskViewFactory: Optional<TaskViewFactory>,
-    @UiContext val context: Context,
-    @Main val mainExecutor: Executor,
-) : CoreStartable {
-
-    companion object {
-        private const val classTag = "FsiChromeViewModelFactory"
-    }
-
-    val viewModelFlow: Flow<FsiChromeViewModel?> =
-        repo.infoFlow.mapLatest { fsiInfo ->
-            fsiInfo?.let {
-                log("$classTag viewModelFlow got new fsiInfo")
-
-                // mapLatest emits null when FSIInfo is null
-                FsiChromeViewModel(
-                    fsiInfo.appName,
-                    fsiInfo.appIcon,
-                    createTaskView(),
-                    fsiInfo.fullscreenIntent,
-                    repo
-                )
-            }
-        }
-
-    override fun start() {
-        log("$classTag start")
-    }
-
-    private suspend fun createTaskView(): TaskView = suspendCancellableCoroutine { k ->
-        log("$classTag createTaskView")
-
-        taskViewFactory.get().create(context, mainExecutor) { taskView -> k.resume(taskView) }
-    }
-}
-
-// Alive for lifetime of FSI.
-data class FsiChromeViewModel(
-    val appName: String,
-    val appIcon: Drawable,
-    val taskView: TaskView,
-    val fsi: PendingIntent,
-    val repo: FsiChromeRepo
-) {
-    companion object {
-        private const val classTag = "FsiChromeViewModel"
-    }
-
-    fun onDismiss() {
-        log("$classTag onDismiss")
-        repo.dismiss()
-    }
-    fun onFullscreen() {
-        log("$classTag onFullscreen")
-        repo.onFullscreen()
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiDebug.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiDebug.kt
deleted file mode 100644
index d9e3f8f..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiDebug.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.android.systemui.statusbar.notification.fsi
-
-class FsiDebug {
-
-    companion object {
-        private const val debugTag = "FsiDebug"
-        private const val debug = true
-
-        fun log(s: Any) {
-            if (!debug) {
-                return
-            }
-            android.util.Log.d(debugTag, "$s")
-        }
-    }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiTaskViewConfig.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiTaskViewConfig.kt
deleted file mode 100644
index 034ab56..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiTaskViewConfig.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.android.systemui.statusbar.notification.fsi
-
-import android.app.ActivityOptions
-import android.content.Context
-import android.content.Intent
-import android.graphics.PixelFormat
-import android.graphics.Rect
-import android.os.Binder
-import android.view.ViewGroup
-import android.view.WindowManager
-
-/**
- * Config for adding the FsiChromeView window to WindowManager and starting the FSI activity.
- */
-class FsiTaskViewConfig {
-
-    companion object {
-
-        private const val classTag = "FsiTaskViewConfig"
-
-        fun getWmLayoutParams(packageName: String): WindowManager.LayoutParams {
-            val params: WindowManager.LayoutParams?
-            params =
-                WindowManager.LayoutParams(
-                    ViewGroup.LayoutParams.MATCH_PARENT,
-                    ViewGroup.LayoutParams.MATCH_PARENT,
-                    WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
-                    WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE or
-                        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED or
-                            WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER,
-                    PixelFormat.TRANSLUCENT
-                )
-            params.setTrustedOverlay()
-            params.fitInsetsTypes = 0
-            params.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
-            params.token = Binder()
-            params.packageName = packageName
-            params.layoutInDisplayCutoutMode =
-                WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
-            params.privateFlags =
-                params.privateFlags or WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS
-            return params
-        }
-
-        fun getFillInIntent(): Intent {
-            val fillInIntent = Intent()
-            fillInIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
-            fillInIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
-            // FLAG_ACTIVITY_NEW_TASK is auto-applied because
-            // we're starting the FSI activity from a non-Activity context
-            return fillInIntent
-        }
-
-        fun getLaunchBounds(windowManager: WindowManager): Rect {
-            // TODO(b/243421660) check this works for non-resizeable activity
-            return Rect()
-        }
-
-        fun getActivityOptions(context: Context, windowManager: WindowManager): ActivityOptions {
-            // Custom options so there is no activity transition animation
-            val options =
-                ActivityOptions.makeCustomAnimation(context, 0 /* enterResId */, 0 /* exitResId */)
-
-            options.taskAlwaysOnTop = true
-
-            options.pendingIntentLaunchFlags =
-                Intent.FLAG_ACTIVITY_NEW_DOCUMENT or
-                    Intent.FLAG_ACTIVITY_MULTIPLE_TASK or
-                    Intent.FLAG_ACTIVITY_NEW_TASK
-
-            options.launchBounds = getLaunchBounds(windowManager)
-            return options
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java
index ae19feb..5ba8801 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.notification.interruption;
 
+import androidx.annotation.NonNull;
+
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 
 /**
@@ -35,10 +37,6 @@
          */
         NO_FSI_SHOW_STICKY_HUN(false),
         /**
-         * Full screen intents are disabled.
-         */
-        NO_FSI_DISABLED(false),
-        /**
          * No full screen intent included, so there is nothing to show.
          */
         NO_FULL_SCREEN_INTENT(false),
@@ -157,7 +155,8 @@
      * @param entry the entry to evaluate
      * @return FullScreenIntentDecision representing the decision for whether to show the intent
      */
-    FullScreenIntentDecision getFullScreenIntentDecision(NotificationEntry entry);
+    @NonNull
+    FullScreenIntentDecision getFullScreenIntentDecision(@NonNull NotificationEntry entry);
 
     /**
      * Write the full screen launch decision for the given entry to logs.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
index 0163dbe..274377f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
@@ -35,6 +35,8 @@
 import android.service.notification.StatusBarNotification;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.UiEvent;
 import com.android.internal.logging.UiEventLogger;
@@ -232,6 +234,7 @@
     // suppressor.
     //
     // If the entry was not suppressed by DND, just returns the given decision.
+    @NonNull
     private FullScreenIntentDecision getDecisionGivenSuppression(FullScreenIntentDecision decision,
             boolean suppressedByDND) {
         if (suppressedByDND) {
@@ -243,11 +246,7 @@
     }
 
     @Override
-    public FullScreenIntentDecision getFullScreenIntentDecision(NotificationEntry entry) {
-        if (mFlags.disableFsi()) {
-            return FullScreenIntentDecision.NO_FSI_DISABLED;
-        }
-
+    public FullScreenIntentDecision getFullScreenIntentDecision(@NonNull NotificationEntry entry) {
         if (entry.getSbn().getNotification().fullScreenIntent == null) {
             if (entry.isStickyAndNotDemoted()) {
                 return FullScreenIntentDecision.NO_FSI_SHOW_STICKY_HUN;
@@ -340,55 +339,30 @@
         final int uid = entry.getSbn().getUid();
         final String packageName = entry.getSbn().getPackageName();
         switch (decision) {
-            case NO_FSI_SHOW_STICKY_HUN:
-                mLogger.logNoFullscreen(entry, "Permission denied, show sticky HUN");
-                return;
-            case NO_FSI_DISABLED:
-                mLogger.logNoFullscreen(entry, "Disabled");
-                return;
             case NO_FULL_SCREEN_INTENT:
-                return;
-            case NO_FSI_SUPPRESSED_BY_DND:
-            case NO_FSI_SUPPRESSED_ONLY_BY_DND:
-                mLogger.logNoFullscreen(entry, "Suppressed by DND");
-                return;
-            case NO_FSI_NOT_IMPORTANT_ENOUGH:
-                mLogger.logNoFullscreen(entry, "Not important enough");
+                // explicitly prevent logging for this (frequent) case
                 return;
             case NO_FSI_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR:
                 android.util.EventLog.writeEvent(0x534e4554, "231322873", uid,
                         "groupAlertBehavior");
                 mUiEventLogger.log(FSI_SUPPRESSED_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR, uid,
                         packageName);
-                mLogger.logNoFullscreenWarning(entry, "GroupAlertBehavior will prevent HUN");
-                return;
-            case FSI_DEVICE_NOT_INTERACTIVE:
-                mLogger.logFullscreen(entry, "Device is not interactive");
-                return;
-            case FSI_DEVICE_IS_DREAMING:
-                mLogger.logFullscreen(entry, "Device is dreaming");
-                return;
-            case FSI_KEYGUARD_SHOWING:
-                mLogger.logFullscreen(entry, "Keyguard is showing");
-                return;
-            case NO_FSI_EXPECTED_TO_HUN:
-                mLogger.logNoFullscreen(entry, "Expected to HUN");
-                return;
-            case FSI_KEYGUARD_OCCLUDED:
-                mLogger.logFullscreen(entry,
-                        "Expected not to HUN while keyguard occluded");
-                return;
-            case FSI_LOCKED_SHADE:
-                mLogger.logFullscreen(entry, "Keyguard is showing and not occluded");
+                mLogger.logNoFullscreenWarning(entry,
+                        decision + ": GroupAlertBehavior will prevent HUN");
                 return;
             case NO_FSI_NO_HUN_OR_KEYGUARD:
                 android.util.EventLog.writeEvent(0x534e4554, "231322873", uid,
                         "no hun or keyguard");
                 mUiEventLogger.log(FSI_SUPPRESSED_NO_HUN_OR_KEYGUARD, uid, packageName);
-                mLogger.logNoFullscreenWarning(entry, "Expected not to HUN while not on keyguard");
+                mLogger.logNoFullscreenWarning(entry,
+                        decision + ": Expected not to HUN while not on keyguard");
                 return;
-            case FSI_EXPECTED_NOT_TO_HUN:
-                mLogger.logFullscreen(entry, "Expected not to HUN");
+            default:
+                if (decision.shouldLaunch) {
+                    mLogger.logFullscreen(entry, decision.name());
+                } else {
+                    mLogger.logNoFullscreen(entry, decision.name());
+                }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 2affa77..33cbf06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -26,10 +26,8 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.app.INotificationManager;
 import android.app.Notification;
 import android.app.NotificationChannel;
-import android.app.role.RoleManager;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -38,12 +36,9 @@
 import android.graphics.Point;
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.graphics.drawable.AnimationDrawable;
-import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.Trace;
 import android.service.notification.StatusBarNotification;
 import android.util.ArraySet;
@@ -86,7 +81,6 @@
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.RemoteInputController;
 import com.android.systemui.statusbar.SmartReplyController;
 import com.android.systemui.statusbar.StatusBarIconView;
@@ -141,8 +135,6 @@
     private static final boolean DEBUG = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.DEBUG);
     private static final boolean DEBUG_ONMEASURE =
             Compile.IS_DEBUG && Log.isLoggable(TAG, Log.VERBOSE);
-    private static final int DEFAULT_DIVIDER_ALPHA = 0x29;
-    private static final int COLORED_DIVIDER_ALPHA = 0x7B;
     private static final int MENU_VIEW_INDEX = 0;
     public static final float DEFAULT_HEADER_VISIBLE_AMOUNT = 1.0f;
     private static final long RECENTLY_ALERTED_THRESHOLD_MS = TimeUnit.SECONDS.toMillis(30);
@@ -153,7 +145,6 @@
     // We don't correctly track dark mode until the content views are inflated, so always update
     // the background on first content update just in case it happens to be during a theme change.
     private boolean mUpdateSelfBackgroundOnUpdate = true;
-    private boolean mNotificationTranslationFinished = false;
     private boolean mIsSnoozed;
     private boolean mIsFaded;
     private boolean mAnimatePinnedRoundness = false;
@@ -192,9 +183,7 @@
     private int mMaxSmallHeightBeforeS;
     private int mMaxSmallHeight;
     private int mMaxSmallHeightLarge;
-    private int mMaxSmallHeightMedia;
     private int mMaxExpandedHeight;
-    private int mIncreasedPaddingBetweenElements;
     private int mNotificationLaunchHeight;
     private boolean mMustStayOnScreen;
 
@@ -211,11 +200,6 @@
      */
     private boolean mUserExpanded;
     /**
-     * Whether the blocking helper is showing on this notification (even if dismissed)
-     */
-    private boolean mIsBlockingHelperShowing;
-
-    /**
      * Has this notification been expanded while it was pinned
      */
     private boolean mExpandedWhenPinned;
@@ -285,7 +269,6 @@
     private boolean mShowNoBackground;
     private ExpandableNotificationRow mNotificationParent;
     private OnExpandClickListener mOnExpandClickListener;
-    private View.OnClickListener mOnAppClickListener;
     private View.OnClickListener mOnFeedbackClickListener;
     private Path mExpandingClipPath;
     private boolean mIsInlineReplyAnimationFlagEnabled = false;
@@ -378,7 +361,6 @@
     private float mTranslationWhenRemoved;
     private boolean mWasChildInGroupWhenRemoved;
     private NotificationInlineImageResolver mImageResolver;
-    private NotificationMediaManager mMediaManager;
     @Nullable
     private OnExpansionChangedListener mExpansionChangedListener;
     @Nullable
@@ -388,32 +370,6 @@
     private float mBottomRoundnessDuringLaunchAnimation;
     private float mSmallRoundness;
 
-    /**
-     * Returns whether the given {@code statusBarNotification} is a system notification.
-     * <b>Note</b>, this should be run in the background thread if possible as it makes multiple IPC
-     * calls.
-     */
-    private static Boolean isSystemNotification(Context context, StatusBarNotification sbn) {
-        INotificationManager iNm = INotificationManager.Stub.asInterface(
-                ServiceManager.getService(Context.NOTIFICATION_SERVICE));
-
-        boolean isSystem = false;
-        try {
-            isSystem = iNm.isPermissionFixed(sbn.getPackageName(), sbn.getUserId());
-        } catch (RemoteException e) {
-            Log.e(TAG, "cannot reach NMS");
-        }
-        RoleManager rm = context.getSystemService(RoleManager.class);
-        List<String> fixedRoleHolders = new ArrayList<>();
-        fixedRoleHolders.addAll(rm.getRoleHolders(RoleManager.ROLE_DIALER));
-        fixedRoleHolders.addAll(rm.getRoleHolders(RoleManager.ROLE_EMERGENCY));
-        if (fixedRoleHolders.contains(sbn.getPackageName())) {
-            isSystem = true;
-        }
-
-        return isSystem;
-    }
-
     public NotificationContentView[] getLayouts() {
         return Arrays.copyOf(mLayouts, mLayouts.length);
     }
@@ -801,11 +757,6 @@
         mPrivateLayout.setRemoteInputController(r);
     }
 
-
-    String getAppName() {
-        return mAppName;
-    }
-
     public void addChildNotification(ExpandableNotificationRow row) {
         addChildNotification(row, -1);
     }
@@ -853,6 +804,19 @@
     }
 
     /**
+     * @see NotificationChildrenContainer#setNotificationGroupWhen(long)
+     */
+    public void setNotificationGroupWhen(long whenMillis) {
+        if (mIsSummaryWithChildren) {
+            mChildrenContainer.setNotificationGroupWhen(whenMillis);
+        } else {
+            Log.w(TAG, "setNotificationGroupWhen( whenMillis: " + whenMillis + ")"
+                    + " mIsSummaryWithChildren: false"
+                    + " mChildrenContainer has not been inflated yet.");
+        }
+    }
+
+    /**
      * Called after children have been attached to set the expansion states
      */
     public void resetChildSystemExpandedStates() {
@@ -1266,10 +1230,6 @@
         }
     }
 
-    public HeadsUpManager getHeadsUpManager() {
-        return mHeadsUpManager;
-    }
-
     public void setGutsView(MenuItem item) {
         if (getGuts() != null && item.getGutsView() instanceof NotificationGuts.GutsContent) {
             getGuts().setGutsContent((NotificationGuts.GutsContent) item.getGutsView());
@@ -1567,18 +1527,6 @@
         }
     }
 
-    public void setBlockingHelperShowing(boolean isBlockingHelperShowing) {
-        mIsBlockingHelperShowing = isBlockingHelperShowing;
-    }
-
-    public boolean isBlockingHelperShowing() {
-        return mIsBlockingHelperShowing;
-    }
-
-    public boolean isBlockingHelperShowingAndTranslationFinished() {
-        return mIsBlockingHelperShowing && mNotificationTranslationFinished;
-    }
-
     @Override
     public View getShelfTransformationTarget() {
         if (mIsSummaryWithChildren && !shouldShowPublic()) {
@@ -1711,7 +1659,6 @@
             HeadsUpManager headsUpManager,
             RowContentBindStage rowContentBindStage,
             OnExpandClickListener onExpandClickListener,
-            NotificationMediaManager notificationMediaManager,
             CoordinateOnClickListener onFeedbackClickListener,
             FalsingManager falsingManager,
             FalsingCollector falsingCollector,
@@ -1742,7 +1689,6 @@
         mHeadsUpManager = headsUpManager;
         mRowContentBindStage = rowContentBindStage;
         mOnExpandClickListener = onExpandClickListener;
-        mMediaManager = notificationMediaManager;
         setOnFeedbackClickListener(onFeedbackClickListener);
         mFalsingManager = falsingManager;
         mFalsingCollector = falsingCollector;
@@ -1774,8 +1720,6 @@
                 R.dimen.notification_min_height);
         mMaxSmallHeightLarge = NotificationUtils.getFontScaledHeight(mContext,
                 R.dimen.notification_min_height_increased);
-        mMaxSmallHeightMedia = NotificationUtils.getFontScaledHeight(mContext,
-                R.dimen.notification_min_height_media);
         mMaxExpandedHeight = NotificationUtils.getFontScaledHeight(mContext,
                 R.dimen.notification_max_height);
         mMaxHeadsUpHeightBeforeN = NotificationUtils.getFontScaledHeight(mContext,
@@ -2161,10 +2105,7 @@
     @Override
     public void setTranslation(float translationX) {
         invalidate();
-        if (isBlockingHelperShowingAndTranslationFinished()) {
-            mGuts.setTranslationX(translationX);
-            return;
-        } else if (mDismissUsingRowTranslationX) {
+        if (mDismissUsingRowTranslationX) {
             setTranslationX(translationX);
         } else if (mTranslateableViews != null) {
             // Translate the group of views
@@ -2192,10 +2133,6 @@
             return getTranslationX();
         }
 
-        if (isBlockingHelperShowingAndCanTranslate()) {
-            return mGuts.getTranslationX();
-        }
-
         if (mTranslateableViews != null && mTranslateableViews.size() > 0) {
             // All of the views in the list should have same translation, just use first one.
             return mTranslateableViews.get(0).getTranslationX();
@@ -2204,10 +2141,6 @@
         return 0;
     }
 
-    private boolean isBlockingHelperShowingAndCanTranslate() {
-        return areGutsExposed() && mIsBlockingHelperShowing && mNotificationTranslationFinished;
-    }
-
     public Animator getTranslateViewAnimator(final float leftTarget,
                                              AnimatorUpdateListener listener) {
         if (mTranslateAnim != null) {
@@ -2229,9 +2162,6 @@
 
             @Override
             public void onAnimationEnd(Animator anim) {
-                if (mIsBlockingHelperShowing) {
-                    mNotificationTranslationFinished = true;
-                }
                 if (!cancelled && leftTarget == 0) {
                     if (mMenuRow != null) {
                         mMenuRow.resetMenu();
@@ -2644,7 +2574,7 @@
      * except for legacy use cases.
      */
     public boolean canShowHeadsUp() {
-        if (mOnKeyguard && !isDozing() && !isBypassEnabled()) {
+        if (mOnKeyguard && !isDozing() && !isBypassEnabled() && !mEntry.isStickyAndNotDemoted()) {
             return false;
         }
         return true;
@@ -2811,9 +2741,10 @@
         int intrinsicBefore = getIntrinsicHeight();
         mSensitive = sensitive;
         mSensitiveHiddenInGeneral = hideSensitive;
-        if (intrinsicBefore != getIntrinsicHeight()) {
-            // The animation has a few flaws and is highly visible, so jump cut instead.
-            notifyHeightChanged(false /* needsAnimation */);
+        int intrinsicAfter = getIntrinsicHeight();
+        if (intrinsicBefore != intrinsicAfter) {
+            boolean needsAnimation = mFeatureFlags.isEnabled(Flags.SENSITIVE_REVEAL_ANIM);
+            notifyHeightChanged(needsAnimation);
         }
     }
 
@@ -2870,13 +2801,19 @@
         View[] publicViews = new View[]{mPublicLayout};
         View[] hiddenChildren = showingPublic ? privateViews : publicViews;
         View[] shownChildren = showingPublic ? publicViews : privateViews;
+        // disappear/appear overlap: 10 percent of duration
+        long overlap = duration / 10;
+        // disappear duration: 1/3 of duration + half of overlap
+        long disappearDuration = duration / 3 + overlap / 2;
+        // appear duration: 2/3 of duration + half of overlap
+        long appearDuration = (duration - disappearDuration) + overlap / 2;
         for (final View hiddenView : hiddenChildren) {
             hiddenView.setVisibility(View.VISIBLE);
             hiddenView.animate().cancel();
             hiddenView.animate()
                     .alpha(0f)
                     .setStartDelay(delay)
-                    .setDuration(duration)
+                    .setDuration(disappearDuration)
                     .withEndAction(() -> {
                         hiddenView.setVisibility(View.INVISIBLE);
                         resetAllContentAlphas();
@@ -2888,8 +2825,8 @@
             showView.animate().cancel();
             showView.animate()
                     .alpha(1f)
-                    .setStartDelay(delay)
-                    .setDuration(duration);
+                    .setStartDelay(delay + duration - appearDuration)
+                    .setDuration(appearDuration);
         }
     }
 
@@ -2940,22 +2877,6 @@
         updateClickAndFocus();
     }
 
-    public static void applyTint(View v, int color) {
-        int alpha;
-        if (color != 0) {
-            alpha = COLORED_DIVIDER_ALPHA;
-        } else {
-            color = 0xff000000;
-            alpha = DEFAULT_DIVIDER_ALPHA;
-        }
-        if (v.getBackground() instanceof ColorDrawable) {
-            ColorDrawable background = (ColorDrawable) v.getBackground();
-            background.mutate();
-            background.setColor(color);
-            background.setAlpha(alpha);
-        }
-    }
-
     public int getMaxExpandHeight() {
         return mPrivateLayout.getExpandHeight();
     }
@@ -3143,14 +3064,6 @@
         return showingLayout != null && showingLayout.requireRowToHaveOverlappingRendering();
     }
 
-    @Override
-    public int getExtraBottomPadding() {
-        if (mIsSummaryWithChildren && isGroupExpanded()) {
-            return mIncreasedPaddingBetweenElements;
-        }
-        return 0;
-    }
-
     public void setInlineReplyAnimationFlagEnabled(boolean isEnabled) {
         mIsInlineReplyAnimationFlagEnabled = isEnabled;
     }
@@ -3272,10 +3185,6 @@
         return shouldShowPublic() ? mPublicLayout : mPrivateLayout;
     }
 
-    public View getExpandedContentView() {
-        return getPrivateLayout().getExpandedChild();
-    }
-
     public void setLegacy(boolean legacy) {
         for (NotificationContentView l : mLayouts) {
             l.setLegacy(legacy);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
index 2dda6fd..e2a3111 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
@@ -36,7 +36,6 @@
 import com.android.systemui.plugins.PluginManager;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.SmartReplyController;
 import com.android.systemui.statusbar.notification.FeedbackIcon;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -74,7 +73,6 @@
     private final NotificationListContainer mListContainer;
     private final RemoteInputViewSubcomponent.Factory mRemoteInputViewSubcomponentFactory;
     private final ActivatableNotificationViewController mActivatableNotificationViewController;
-    private final NotificationMediaManager mMediaManager;
     private final PluginManager mPluginManager;
     private final SystemClock mClock;
     private final String mAppName;
@@ -136,7 +134,6 @@
             MetricsLogger metricsLogger,
             NotificationRowLogger logBufferLogger,
             NotificationListContainer listContainer,
-            NotificationMediaManager mediaManager,
             SmartReplyConstants smartReplyConstants,
             SmartReplyController smartReplyController,
             PluginManager pluginManager,
@@ -165,7 +162,6 @@
         mListContainer = listContainer;
         mRemoteInputViewSubcomponentFactory = rivSubcomponentFactory;
         mActivatableNotificationViewController = activatableNotificationViewController;
-        mMediaManager = mediaManager;
         mPluginManager = pluginManager;
         mClock = clock;
         mAppName = appName;
@@ -212,7 +208,6 @@
                 mHeadsUpManager,
                 mRowContentBindStage,
                 mOnExpandClickListener,
-                mMediaManager,
                 mOnFeedbackClickListener,
                 mFalsingManager,
                 mFalsingCollector,
@@ -349,6 +344,15 @@
     }
 
     @Override
+    public void setNotificationGroupWhen(long whenMillis) {
+        if (mView.isSummaryWithChildren()) {
+            mView.setNotificationGroupWhen(whenMillis);
+        } else {
+            Log.w(TAG, "Called setNotificationTime(" + whenMillis + ") on a leaf row");
+        }
+    }
+
+    @Override
     public void setSystemExpanded(boolean systemExpanded) {
         mView.setSystemExpanded(systemExpanded);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
index 25c7264..9df6ba9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
@@ -451,7 +451,7 @@
     protected void updateClipping() {
         if (mClipToActualHeight && shouldClipToActualHeight()) {
             int top = getClipTopAmount();
-            int bottom = Math.max(Math.max(getActualHeight() + getExtraBottomPadding()
+            int bottom = Math.max(Math.max(getActualHeight()
                     - mClipBottomAmount, top), mMinimumHeightForClipping);
             mClipRect.set(Integer.MIN_VALUE, top, Integer.MAX_VALUE, bottom);
             setClipBounds(mClipRect);
@@ -592,13 +592,6 @@
     }
 
     /**
-     * @return padding used to alter how much of the view is clipped.
-     */
-    public int getExtraBottomPadding() {
-        return 0;
-    }
-
-    /**
      * @return true if the group's expansion state is changing, false otherwise.
      */
     public boolean isGroupExpansionChanging() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
index 39e4000..4522e41 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
@@ -443,6 +443,7 @@
         CancellationSignal cancellationSignal = new CancellationSignal();
         cancellationSignal.setOnCancelListener(
                 () -> runningInflations.values().forEach(CancellationSignal::cancel));
+
         return cancellationSignal;
     }
 
@@ -783,6 +784,7 @@
     public static class AsyncInflationTask extends AsyncTask<Void, Void, InflationProgress>
             implements InflationCallback, InflationTask {
 
+        private static final long IMG_PRELOAD_TIMEOUT_MS = 1000L;
         private final NotificationEntry mEntry;
         private final Context mContext;
         private final boolean mInflateSynchronously;
@@ -876,7 +878,7 @@
                         recoveredBuilder, mIsLowPriority, mUsesIncreasedHeight,
                         mUsesIncreasedHeadsUpHeight, packageContext);
                 InflatedSmartReplyState previousSmartReplyState = mRow.getExistingSmartReplyState();
-                return inflateSmartReplyViews(
+                InflationProgress result = inflateSmartReplyViews(
                         inflationProgress,
                         mReInflateFlags,
                         mEntry,
@@ -884,6 +886,11 @@
                         packageContext,
                         previousSmartReplyState,
                         mSmartRepliesInflater);
+
+                // wait for image resolver to finish preloading
+                mRow.getImageResolver().waitForPreloadedImages(IMG_PRELOAD_TIMEOUT_MS);
+
+                return result;
             } catch (Exception e) {
                 mError = e;
                 return null;
@@ -918,6 +925,9 @@
                 mCallback.handleInflationException(mRow.getEntry(),
                         new InflationException("Couldn't inflate contentViews" + e));
             }
+
+            // Cancel any image loading tasks, not useful any more
+            mRow.getImageResolver().cancelRunningTasks();
         }
 
         @Override
@@ -944,6 +954,9 @@
             // Notify the resolver that the inflation task has finished,
             // try to purge unnecessary cached entries.
             mRow.getImageResolver().purgeCache();
+
+            // Cancel any image loading tasks that have not completed at this point
+            mRow.getImageResolver().cancelRunningTasks();
         }
 
         private static class RtlEnabledContext extends ContextWrapper {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
index 93f0812..596bdc0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
@@ -238,12 +238,11 @@
     }
 
     public void openControls(
-            boolean shouldDoCircularReveal,
             int x,
             int y,
             boolean needsFalsingProtection,
             @Nullable Runnable onAnimationEnd) {
-        animateOpen(shouldDoCircularReveal, x, y, onAnimationEnd);
+        animateOpen(x, y, onAnimationEnd);
         setExposed(true /* exposed */, needsFalsingProtection);
     }
 
@@ -300,7 +299,7 @@
         if (mGutsContent == null
                 || !mGutsContent.handleCloseControls(save, force)) {
             // We only want to do a circular reveal if we're not showing the blocking helper.
-            animateClose(x, y, true /* shouldDoCircularReveal */);
+            animateClose(x, y);
 
             setExposed(false, mNeedsFalsingProtection);
             if (mClosedListener != null) {
@@ -309,66 +308,45 @@
         }
     }
 
-    /** Animates in the guts view via either a fade or a circular reveal. */
-    private void animateOpen(
-            boolean shouldDoCircularReveal, int x, int y, @Nullable Runnable onAnimationEnd) {
+    /** Animates in the guts view with a circular reveal. */
+    private void animateOpen(int x, int y, @Nullable Runnable onAnimationEnd) {
         if (isAttachedToWindow()) {
-            if (shouldDoCircularReveal) {
-                double horz = Math.max(getWidth() - x, x);
-                double vert = Math.max(getHeight() - y, y);
-                float r = (float) Math.hypot(horz, vert);
-                // Make sure we'll be visible after the circular reveal
-                setAlpha(1f);
-                // Circular reveal originating at (x, y)
-                Animator a = ViewAnimationUtils.createCircularReveal(this, x, y, 0, r);
-                a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
-                a.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
-                a.addListener(new AnimateOpenListener(onAnimationEnd));
-                a.start();
-            } else {
-                // Fade in content
-                this.setAlpha(0f);
-                this.animate()
-                        .alpha(1f)
-                        .setDuration(StackStateAnimator.ANIMATION_DURATION_BLOCKING_HELPER_FADE)
-                        .setInterpolator(Interpolators.ALPHA_IN)
-                        .setListener(new AnimateOpenListener(onAnimationEnd))
-                        .start();
-            }
+            double horz = Math.max(getWidth() - x, x);
+            double vert = Math.max(getHeight() - y, y);
+            float r = (float) Math.hypot(horz, vert);
+            // Make sure we'll be visible after the circular reveal
+            setAlpha(1f);
+            // Circular reveal originating at (x, y)
+            Animator a = ViewAnimationUtils.createCircularReveal(this, x, y, 0, r);
+            a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+            a.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+            a.addListener(new AnimateOpenListener(onAnimationEnd));
+            a.start();
+
         } else {
             Log.w(TAG, "Failed to animate guts open");
         }
     }
 
 
-    /** Animates out the guts view via either a fade or a circular reveal. */
+    /** Animates out the guts view with a circular reveal. */
     @VisibleForTesting
-    void animateClose(int x, int y, boolean shouldDoCircularReveal) {
+    void animateClose(int x, int y) {
         if (isAttachedToWindow()) {
-            if (shouldDoCircularReveal) {
-                // Circular reveal originating at (x, y)
-                if (x == -1 || y == -1) {
-                    x = (getLeft() + getRight()) / 2;
-                    y = (getTop() + getHeight() / 2);
-                }
-                double horz = Math.max(getWidth() - x, x);
-                double vert = Math.max(getHeight() - y, y);
-                float r = (float) Math.hypot(horz, vert);
-                Animator a = ViewAnimationUtils.createCircularReveal(this,
-                        x, y, r, 0);
-                a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
-                a.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
-                a.addListener(new AnimateCloseListener(this /* view */, mGutsContent));
-                a.start();
-            } else {
-                // Fade in the blocking helper.
-                this.animate()
-                        .alpha(0f)
-                        .setDuration(StackStateAnimator.ANIMATION_DURATION_BLOCKING_HELPER_FADE)
-                        .setInterpolator(Interpolators.ALPHA_OUT)
-                        .setListener(new AnimateCloseListener(this, /* view */mGutsContent))
-                        .start();
+            // Circular reveal originating at (x, y)
+            if (x == -1 || y == -1) {
+                x = (getLeft() + getRight()) / 2;
+                y = (getTop() + getHeight() / 2);
             }
+            double horz = Math.max(getWidth() - x, x);
+            double vert = Math.max(getHeight() - y, y);
+            float r = (float) Math.hypot(horz, vert);
+            Animator a = ViewAnimationUtils.createCircularReveal(this,
+                    x, y, r, 0);
+            a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+            a.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
+            a.addListener(new AnimateCloseListener(this /* view */, mGutsContent));
+            a.start();
         } else {
             Log.w(TAG, "Failed to animate guts close");
             mGutsContent.onFinishedClosing();
@@ -449,7 +427,7 @@
         return mGutsContent != null && mGutsContent.isLeavebehind();
     }
 
-    /** Listener for animations executed in {@link #animateOpen(boolean, int, int, Runnable)}. */
+    /** Listener for animations executed in {@link #animateOpen(int, int, Runnable)}. */
     private static class AnimateOpenListener extends AnimatorListenerAdapter {
         final Runnable mOnAnimationEnd;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 06d4080..46f1bb5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -629,7 +629,6 @@
                                 !mAccessibilityManager.isTouchExplorationEnabled());
 
                 guts.openControls(
-                        !row.isBlockingHelperShowing(),
                         x,
                         y,
                         needsFalsingProtection,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageCache.java
index 41eeada0..fe0b312 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageCache.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageCache.java
@@ -22,8 +22,11 @@
 import android.util.Log;
 
 import java.util.Set;
+import java.util.concurrent.CancellationException;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 /**
  * A cache for inline images of image messages.
@@ -56,12 +59,13 @@
     }
 
     @Override
-    public Drawable get(Uri uri) {
+    public Drawable get(Uri uri, long timeoutMs) {
         Drawable result = null;
         try {
-            result = mCache.get(uri).get();
-        } catch (InterruptedException | ExecutionException ex) {
-            Log.d(TAG, "get: Failed get image from " + uri);
+            result = mCache.get(uri).get(timeoutMs, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException | ExecutionException
+                | TimeoutException | CancellationException ex) {
+            Log.d(TAG, "get: Failed get image from " + uri + " " + ex);
         }
         return result;
     }
@@ -72,6 +76,15 @@
         mCache.entrySet().removeIf(entry -> !wantedSet.contains(entry.getKey()));
     }
 
+    @Override
+    public void cancelRunningTasks() {
+        mCache.forEach((key, value) -> {
+            if (value.getStatus() != AsyncTask.Status.FINISHED) {
+                value.cancel(true);
+            }
+        });
+    }
+
     private static class PreloadImageTask extends AsyncTask<Uri, Void, Drawable> {
         private final NotificationInlineImageResolver mResolver;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java
index b05e64ab..c620f44 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java
@@ -23,6 +23,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Parcelable;
+import android.os.SystemClock;
 import android.util.Log;
 
 import com.android.internal.R;
@@ -45,6 +46,9 @@
 public class NotificationInlineImageResolver implements ImageResolver {
     private static final String TAG = NotificationInlineImageResolver.class.getSimpleName();
 
+    // Timeout for loading images from ImageCache when calling from UI thread
+    private static final long MAX_UI_THREAD_TIMEOUT_MS = 100L;
+
     private final Context mContext;
     private final ImageCache mImageCache;
     private Set<Uri> mWantedUriSet;
@@ -123,17 +127,25 @@
         return null;
     }
 
+    /**
+     * Loads an image from the Uri.
+     * This method is synchronous and is usually called from the Main thread.
+     * It will time-out after MAX_UI_THREAD_TIMEOUT_MS.
+     *
+     * @param uri Uri of the target image.
+     * @return drawable of the image, null if loading failed/timeout
+     */
     @Override
     public Drawable loadImage(Uri uri) {
-        return hasCache() ? loadImageFromCache(uri) : resolveImage(uri);
+        return hasCache() ? loadImageFromCache(uri, MAX_UI_THREAD_TIMEOUT_MS) : resolveImage(uri);
     }
 
-    private Drawable loadImageFromCache(Uri uri) {
+    private Drawable loadImageFromCache(Uri uri, long timeoutMs) {
         // if the uri isn't currently cached, try caching it first
         if (!mImageCache.hasEntry(uri)) {
             mImageCache.preload((uri));
         }
-        return mImageCache.get(uri);
+        return mImageCache.get(uri, timeoutMs);
     }
 
     /**
@@ -208,6 +220,30 @@
     }
 
     /**
+     * Wait for a maximum timeout for images to finish preloading
+     * @param timeoutMs total timeout time
+     */
+    void waitForPreloadedImages(long timeoutMs) {
+        if (!hasCache()) {
+            return;
+        }
+        Set<Uri> preloadedUris = getWantedUriSet();
+        if (preloadedUris != null) {
+            // Decrement remaining timeout after each image check
+            long endTimeMs = SystemClock.elapsedRealtime() + timeoutMs;
+            preloadedUris.forEach(
+                    uri -> loadImageFromCache(uri, endTimeMs - SystemClock.elapsedRealtime()));
+        }
+    }
+
+    void cancelRunningTasks() {
+        if (!hasCache()) {
+            return;
+        }
+        mImageCache.cancelRunningTasks();
+    }
+
+    /**
      * A interface for internal cache implementation of this resolver.
      */
     interface ImageCache {
@@ -216,7 +252,7 @@
          * @param uri The uri of the image.
          * @return Drawable of the image.
          */
-        Drawable get(Uri uri);
+        Drawable get(Uri uri, long timeoutMs);
 
         /**
          * Set the image resolver that actually resolves image from specified uri.
@@ -241,6 +277,11 @@
          * Purge unnecessary entries in the cache.
          */
         void purge();
+
+        /**
+         * Cancel all unfinished image loading tasks
+         */
+        void cancelRunningTasks();
     }
 
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
index 1f664cb..9a777ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
@@ -27,6 +27,7 @@
 import android.view.ViewGroup;
 import android.view.animation.Interpolator;
 import android.view.animation.PathInterpolator;
+import android.widget.DateTimeView;
 import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.TextView;
@@ -344,6 +345,21 @@
         mTransformationHelper.setVisible(visible);
     }
 
+    /***
+     * Set Notification when value
+     * @param whenMillis
+     */
+    public void setNotificationWhen(long whenMillis) {
+        if (mNotificationHeader == null) {
+            return;
+        }
+
+        final View timeView = mNotificationHeader.findViewById(com.android.internal.R.id.time);
+
+        if (timeView instanceof DateTimeView) {
+            ((DateTimeView) timeView).setTime(whenMillis);
+        }
+    }
     protected void addTransformedViews(View... views) {
         for (View view : views) {
             if (view != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
index 6f4d6d9..77ede04 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
@@ -29,6 +29,8 @@
 import com.android.systemui.R;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -55,6 +57,8 @@
 
     private final SectionProvider mSectionProvider;
     private final BypassController mBypassController;
+    private final LargeScreenShadeInterpolator mLargeScreenShadeInterpolator;
+    private final FeatureFlags mFeatureFlags;
     /**
      *  Used to read bouncer states.
      */
@@ -84,7 +88,7 @@
     private float mExpandingVelocity;
     private boolean mPanelTracking;
     private boolean mExpansionChanging;
-    private boolean mPanelFullWidth;
+    private boolean mIsSmallScreen;
     private boolean mPulsing;
     private boolean mUnlockHintRunning;
     private float mHideAmount;
@@ -252,10 +256,14 @@
             @NonNull DumpManager dumpManager,
             @NonNull SectionProvider sectionProvider,
             @NonNull BypassController bypassController,
-            @Nullable StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
+            @Nullable StatusBarKeyguardViewManager statusBarKeyguardViewManager,
+            @NonNull LargeScreenShadeInterpolator largeScreenShadeInterpolator,
+            @NonNull FeatureFlags featureFlags) {
         mSectionProvider = sectionProvider;
         mBypassController = bypassController;
         mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
+        mLargeScreenShadeInterpolator = largeScreenShadeInterpolator;
+        mFeatureFlags = featureFlags;
         reload(context);
         dumpManager.registerDumpable(this);
     }
@@ -574,12 +582,12 @@
         return mPanelTracking;
     }
 
-    public boolean isPanelFullWidth() {
-        return mPanelFullWidth;
+    public boolean isSmallScreen() {
+        return mIsSmallScreen;
     }
 
-    public void setPanelFullWidth(boolean panelFullWidth) {
-        mPanelFullWidth = panelFullWidth;
+    public void setSmallScreen(boolean smallScreen) {
+        mIsSmallScreen = smallScreen;
     }
 
     public void setUnlockHintRunning(boolean unlockHintRunning) {
@@ -736,6 +744,14 @@
         return mIsClosing;
     }
 
+    public LargeScreenShadeInterpolator getLargeScreenShadeInterpolator() {
+        return mLargeScreenShadeInterpolator;
+    }
+
+    public FeatureFlags getFeatureFlags() {
+        return mFeatureFlags;
+    }
+
     @Override
     public void dump(PrintWriter pw, String[] args) {
         pw.println("mTopPadding=" + mTopPadding);
@@ -751,7 +767,7 @@
         pw.println("mDimmed=" + mDimmed);
         pw.println("mStatusBarState=" + mStatusBarState);
         pw.println("mExpansionChanging=" + mExpansionChanging);
-        pw.println("mPanelFullWidth=" + mPanelFullWidth);
+        pw.println("mPanelFullWidth=" + mIsSmallScreen);
         pw.println("mPulsing=" + mPulsing);
         pw.println("mPulseHeight=" + mPulseHeight);
         pw.println("mTrackedHeadsUpRow.key=" + logKey(mTrackedHeadsUpRow));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index 9b93d7b..40f55bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -296,6 +296,19 @@
     }
 
     /**
+     * Set the notification time in the group so that the view can show the latest event in the UI
+     * appropriately.
+     */
+    public void setNotificationGroupWhen(long whenMillis) {
+        if (mNotificationHeaderWrapper != null) {
+            mNotificationHeaderWrapper.setNotificationWhen(whenMillis);
+        }
+        if (mNotificationHeaderWrapperLowPriority != null) {
+            mNotificationHeaderWrapperLowPriority.setNotificationWhen(whenMillis);
+        }
+    }
+
+    /**
      * Add a child notification to this view.
      *
      * @param row        the row to add
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index e09b94b..2c088fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -67,6 +67,7 @@
 import android.view.ViewOutlineProvider;
 import android.view.ViewTreeObserver;
 import android.view.WindowInsets;
+import android.view.WindowInsetsAnimation;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.AnimationUtils;
@@ -199,6 +200,7 @@
     private final boolean mDebugRemoveAnimation;
     private final boolean mSimplifiedAppearFraction;
     private final boolean mUseRoundnessSourceTypes;
+    private boolean mAnimatedInsets;
 
     private int mContentHeight;
     private float mIntrinsicContentHeight;
@@ -207,7 +209,8 @@
     private int mTopPadding;
     private boolean mAnimateNextTopPaddingChange;
     private int mBottomPadding;
-    private int mBottomInset = 0;
+    @VisibleForTesting
+    int mBottomInset = 0;
     private float mQsExpansionFraction;
     private final int mSplitShadeMinContentHeight;
 
@@ -388,9 +391,33 @@
             }
         }
     };
+
     private boolean mPulsing;
     private boolean mScrollable;
     private View mForcedScroll;
+    private boolean mIsInsetAnimationRunning;
+
+    private final WindowInsetsAnimation.Callback mInsetsCallback =
+            new WindowInsetsAnimation.Callback(
+                    WindowInsetsAnimation.Callback.DISPATCH_MODE_CONTINUE_ON_SUBTREE) {
+
+                @Override
+                public void onPrepare(WindowInsetsAnimation animation) {
+                    mIsInsetAnimationRunning = true;
+                }
+
+                @Override
+                public WindowInsets onProgress(WindowInsets windowInsets,
+                        List<WindowInsetsAnimation> list) {
+                    updateBottomInset(windowInsets);
+                    return windowInsets;
+                }
+
+                @Override
+                public void onEnd(WindowInsetsAnimation animation) {
+                    mIsInsetAnimationRunning = false;
+                }
+            };
 
     /**
      * @see #setHideAmount(float, float)
@@ -584,6 +611,7 @@
         mDebugRemoveAnimation = featureFlags.isEnabled(Flags.NSSL_DEBUG_REMOVE_ANIMATION);
         mSimplifiedAppearFraction = featureFlags.isEnabled(Flags.SIMPLIFIED_APPEAR_FRACTION);
         mUseRoundnessSourceTypes = featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES);
+        setAnimatedInsetsEnabled(featureFlags.isEnabled(Flags.ANIMATED_NOTIFICATION_SHADE_INSETS));
         mSectionsManager = Dependency.get(NotificationSectionsManager.class);
         mScreenOffAnimationController =
                 Dependency.get(ScreenOffAnimationController.class);
@@ -622,6 +650,9 @@
         mGroupMembershipManager = Dependency.get(GroupMembershipManager.class);
         mGroupExpansionManager = Dependency.get(GroupExpansionManager.class);
         setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
+        if (mAnimatedInsets) {
+            setWindowInsetsAnimationCallback(mInsetsCallback);
+        }
     }
 
     /**
@@ -690,6 +721,11 @@
     }
 
     @VisibleForTesting
+    void setAnimatedInsetsEnabled(boolean enabled) {
+        mAnimatedInsets = enabled;
+    }
+
+    @VisibleForTesting
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void updateFooter() {
         if (mFooterView == null) {
@@ -1781,7 +1817,11 @@
             return;
         }
         mForcedScroll = v;
-        scrollTo(v);
+        if (mAnimatedInsets) {
+            updateForcedScroll();
+        } else {
+            scrollTo(v);
+        }
     }
 
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
@@ -1813,26 +1853,46 @@
                 + ((!isExpanded() && isPinnedHeadsUp(v)) ? mHeadsUpInset : getTopPadding());
     }
 
+    private void updateBottomInset(WindowInsets windowInsets) {
+        mBottomInset = windowInsets.getInsets(WindowInsets.Type.ime()).bottom;
+
+        if (mForcedScroll != null) {
+            updateForcedScroll();
+        }
+
+        int range = getScrollRange();
+        if (mOwnScrollY > range) {
+            setOwnScrollY(range);
+        }
+    }
+
     @Override
     @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
-        mBottomInset = insets.getInsets(WindowInsets.Type.ime()).bottom;
+        if (!mAnimatedInsets) {
+            mBottomInset = insets.getInsets(WindowInsets.Type.ime()).bottom;
+        }
         mWaterfallTopInset = 0;
         final DisplayCutout cutout = insets.getDisplayCutout();
         if (cutout != null) {
             mWaterfallTopInset = cutout.getWaterfallInsets().top;
         }
-
-        int range = getScrollRange();
-        if (mOwnScrollY > range) {
-            // HACK: We're repeatedly getting staggered insets here while the IME is
-            // animating away. To work around that we'll wait until things have settled.
-            removeCallbacks(mReclamp);
-            postDelayed(mReclamp, 50);
-        } else if (mForcedScroll != null) {
-            // The scroll was requested before we got the actual inset - in case we need
-            // to scroll up some more do so now.
-            scrollTo(mForcedScroll);
+        if (mAnimatedInsets && !mIsInsetAnimationRunning) {
+            // update bottom inset e.g. after rotation
+            updateBottomInset(insets);
+        }
+        if (!mAnimatedInsets) {
+            int range = getScrollRange();
+            if (mOwnScrollY > range) {
+                // HACK: We're repeatedly getting staggered insets here while the IME is
+                // animating away. To work around that we'll wait until things have settled.
+                removeCallbacks(mReclamp);
+                postDelayed(mReclamp, 50);
+            } else if (mForcedScroll != null) {
+                // The scroll was requested before we got the actual inset - in case we need
+                // to scroll up some more do so now.
+                scrollTo(mForcedScroll);
+            }
         }
         return insets;
     }
@@ -4439,7 +4499,7 @@
                 expandableView.setFakeShadowIntensity(0.0f, 0.0f, 0, 0);
             } else {
                 float yLocation = previous.getTranslationY() + previous.getActualHeight() -
-                        expandableView.getTranslationY() - previous.getExtraBottomPadding();
+                        expandableView.getTranslationY();
                 expandableView.setFakeShadowIntensity(
                         diff / FakeShadowView.SHADOW_SIBLING_TRESHOLD,
                         previous.getOutlineAlpha(), (int) yLocation,
@@ -5163,7 +5223,7 @@
 
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setIsFullWidth(boolean isFullWidth) {
-        mAmbientState.setPanelFullWidth(isFullWidth);
+        mAmbientState.setSmallScreen(isFullWidth);
     }
 
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 2868116..e8058b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -70,7 +70,6 @@
 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.shade.ShadeController;
-import com.android.systemui.shade.transition.ShadeTransitionController;
 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
@@ -172,7 +171,6 @@
     private final CentralSurfaces mCentralSurfaces;
     private final SectionHeaderController mSilentHeaderController;
     private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
-    private final ShadeTransitionController mShadeTransitionController;
     private final InteractionJankMonitor mJankMonitor;
     private final NotificationStackSizeCalculator mNotificationStackSizeCalculator;
     private final StackStateLogger mStackStateLogger;
@@ -211,7 +209,11 @@
                 public void onViewAttachedToWindow(View v) {
                     mConfigurationController.addCallback(mConfigurationListener);
                     mZenModeController.addCallback(mZenModeControllerCallback);
-                    mBarState = mStatusBarStateController.getState();
+                    final int newBarState = mStatusBarStateController.getState();
+                    if (newBarState != mBarState) {
+                        mStateListener.onStateChanged(newBarState);
+                        mStateListener.onStatePostChange();
+                    }
                     mStatusBarStateController.addCallback(
                             mStateListener, SysuiStatusBarStateController.RANK_STACK_SCROLLER);
                 }
@@ -660,7 +662,6 @@
             NotifPipelineFlags notifPipelineFlags,
             NotifCollection notifCollection,
             LockscreenShadeTransitionController lockscreenShadeTransitionController,
-            ShadeTransitionController shadeTransitionController,
             UiEventLogger uiEventLogger,
             NotificationRemoteInputManager remoteInputManager,
             VisibilityLocationProviderDelegator visibilityLocationProviderDelegator,
@@ -693,7 +694,6 @@
         mMetricsLogger = metricsLogger;
         mDumpManager = dumpManager;
         mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
-        mShadeTransitionController = shadeTransitionController;
         mFalsingCollector = falsingCollector;
         mFalsingManager = falsingManager;
         mResources = resources;
@@ -777,7 +777,6 @@
         mScrimController.setScrimBehindChangeRunnable(mView::updateBackgroundDimming);
 
         mLockscreenShadeTransitionController.setStackScroller(this);
-        mShadeTransitionController.setNotificationStackScrollLayoutController(this);
 
         mLockscreenUserManager.addUserChangedListener(mLockscreenUserChangeListener);
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt
index 25f99c6..0922428 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt
@@ -264,12 +264,18 @@
         onLockscreen: Boolean
     ): Float {
         assert(view.isShowable(onLockscreen))
+
         var size =
             if (onLockscreen) {
-                view.getMinHeight(/* ignoreTemporaryStates= */ true).toFloat()
+                if (view is ExpandableNotificationRow && view.entry.isStickyAndNotDemoted) {
+                    view.intrinsicHeight.toFloat()
+                } else {
+                    view.getMinHeight(/* ignoreTemporaryStates= */ true).toFloat()
+                }
             } else {
                 view.intrinsicHeight.toFloat()
             }
+
         size += calculateGapAndDividerHeight(stack, previousView, current = view, visibleIndex)
         return size
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
index aaf9300..c6f56d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
@@ -251,13 +251,13 @@
                 || (isFastNonDismissGesture && isAbleToShowMenu);
         int menuSnapTarget = menuRow.getMenuSnapTarget();
         boolean isNonFalseMenuRevealingGesture =
-                !isFalseGesture() && isMenuRevealingGestureAwayFromMenu;
+                isMenuRevealingGestureAwayFromMenu && !isFalseGesture();
         if ((isNonDismissGestureTowardsMenu || isNonFalseMenuRevealingGesture)
                 && menuSnapTarget != 0) {
             // Menu has not been snapped to previously and this is menu revealing gesture
             snapOpen(animView, menuSnapTarget, velocity);
             menuRow.onSnapOpen();
-        } else if (isDismissGesture(ev) && !gestureTowardsMenu) {
+        } else if (isDismissGesture && !gestureTowardsMenu) {
             dismiss(animView, velocity);
             menuRow.onDismiss();
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt
index 548d1a1..8b6d6a4f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt
@@ -25,9 +25,10 @@
     /**
      * This method looks for views that can be rounded (and implement [Roundable]) during a
      * notification swipe.
+     *
      * @return The [Roundable] targets above/below the [viewSwiped] (if available). The
-     * [RoundableTargets.before] and [RoundableTargets.after] parameters can be `null` if there is
-     * no above/below notification or the notification is not part of the same section.
+     *   [RoundableTargets.before] and [RoundableTargets.after] parameters can be `null` if there is
+     *   no above/below notification or the notification is not part of the same section.
      */
     fun findRoundableTargets(
         viewSwiped: ExpandableNotificationRow,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index d2bff0e..b1fb13e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -29,6 +29,9 @@
 import com.android.keyguard.BouncerPanelExpansionCalculator;
 import com.android.systemui.R;
 import com.android.systemui.animation.ShadeInterpolation;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
 import com.android.systemui.statusbar.EmptyShadeView;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.notification.LegacySourceType;
@@ -135,7 +138,6 @@
                                   AmbientState ambientState) {
         for (ExpandableView view : algorithmState.visibleChildren) {
             final ViewState viewState = view.getViewState();
-
             final boolean isHunGoingToShade = ambientState.isShadeExpanded()
                     && view == ambientState.getTrackedHeadsUpRow();
 
@@ -148,9 +150,14 @@
             } else if (ambientState.isExpansionChanging()) {
                 // Adjust alpha for shade open & close.
                 float expansion = ambientState.getExpansionFraction();
-                viewState.setAlpha(ambientState.isBouncerInTransit()
-                        ? BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion)
-                        : ShadeInterpolation.getContentAlpha(expansion));
+                if (ambientState.isBouncerInTransit()) {
+                    viewState.setAlpha(
+                            BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion));
+                } else if (view instanceof FooterView) {
+                    viewState.setAlpha(interpolateFooterAlpha(ambientState));
+                } else {
+                    viewState.setAlpha(interpolateNotificationContentAlpha(ambientState));
+                }
             }
 
             // For EmptyShadeView if on keyguard, we need to control the alpha to create
@@ -182,6 +189,28 @@
         }
     }
 
+    private float interpolateFooterAlpha(AmbientState ambientState) {
+        float expansion = ambientState.getExpansionFraction();
+        FeatureFlags flags = ambientState.getFeatureFlags();
+        if (ambientState.isSmallScreen()
+                || !flags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)) {
+            return ShadeInterpolation.getContentAlpha(expansion);
+        }
+        LargeScreenShadeInterpolator interpolator = ambientState.getLargeScreenShadeInterpolator();
+        return interpolator.getNotificationFooterAlpha(expansion);
+    }
+
+    private float interpolateNotificationContentAlpha(AmbientState ambientState) {
+        float expansion = ambientState.getExpansionFraction();
+        FeatureFlags flags = ambientState.getFeatureFlags();
+        if (ambientState.isSmallScreen()
+                || !flags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)) {
+            return ShadeInterpolation.getContentAlpha(expansion);
+        }
+        LargeScreenShadeInterpolator interpolator = ambientState.getLargeScreenShadeInterpolator();
+        return interpolator.getNotificationContentAlpha(expansion);
+    }
+
     /**
      * How expanded or collapsed notifications are when pulling down the shade.
      *
@@ -734,7 +763,7 @@
             float unmodifiedEndLocation = childState.getYTranslation() + childState.height;
             if (mIsExpanded) {
                 if (row.mustStayOnScreen() && !childState.headsUpIsVisible
-                        && !row.showingPulsing()) {
+                        && !row.showingPulsing() && !ambientState.isOnKeyguard()) {
                     // Ensure that the heads up is always visible even when scrolled off
                     clampHunToTop(mQuickQsOffsetHeight, ambientState.getStackTranslation(),
                             row.getCollapsedHeight(), childState);
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 9f38361..cf5ecdd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -374,10 +374,24 @@
     }
 
     @Override
+    public void onBiometricDetected(int userId, BiometricSourceType biometricSourceType,
+            boolean isStrongBiometric) {
+        Trace.beginSection("BiometricUnlockController#onBiometricDetected");
+        if (mUpdateMonitor.isGoingToSleep()) {
+            Trace.endSection();
+            return;
+        }
+        startWakeAndUnlock(MODE_SHOW_BOUNCER);
+    }
+
+    @Override
     public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType,
             boolean isStrongBiometric) {
         Trace.beginSection("BiometricUnlockController#onBiometricAuthenticated");
         if (mUpdateMonitor.isGoingToSleep()) {
+            mLogger.deferringAuthenticationDueToSleep(userId,
+                    biometricSourceType,
+                    mPendingAuthenticated != null);
             mPendingAuthenticated = new PendingAuthenticated(userId, biometricSourceType,
                     isStrongBiometric);
             Trace.endSection();
@@ -784,6 +798,7 @@
                 public void onFinishedGoingToSleep() {
                     Trace.beginSection("BiometricUnlockController#onFinishedGoingToSleep");
                     if (mPendingAuthenticated != null) {
+                        mLogger.finishedGoingToSleepWithPendingAuth();
                         PendingAuthenticated pendingAuthenticated = mPendingAuthenticated;
                         // Post this to make sure it's executed after the device is fully locked.
                         mHandler.post(() -> onBiometricAuthenticated(pendingAuthenticated.userId,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
index 9e62817..55fa479 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
@@ -122,7 +122,6 @@
         options.setLaunchDisplayId(displayId);
         options.setCallerDisplayId(displayId);
         options.setPendingIntentBackgroundActivityLaunchAllowed(true);
-        options.setInteractive(true);
         return options.toBundle();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index ae97407..5438a59 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -104,6 +104,8 @@
 import android.view.WindowManagerGlobal;
 import android.view.accessibility.AccessibilityManager;
 import android.widget.DateTimeView;
+import android.window.BackEvent;
+import android.window.OnBackAnimationCallback;
 import android.window.OnBackInvokedCallback;
 import android.window.OnBackInvokedDispatcher;
 
@@ -508,6 +510,7 @@
     protected final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
     private final BrightnessSliderController.Factory mBrightnessSliderFactory;
     private final FeatureFlags mFeatureFlags;
+    private final boolean mAnimateBack;
     private final FragmentService mFragmentService;
     private final ScreenOffAnimationController mScreenOffAnimationController;
     private final WallpaperController mWallpaperController;
@@ -610,7 +613,6 @@
 
     private Runnable mLaunchTransitionEndRunnable;
     private Runnable mLaunchTransitionCancelRunnable;
-    private boolean mLaunchingAffordance;
     private boolean mLaunchCameraWhenFinishedWaking;
     private boolean mLaunchCameraOnFinishedGoingToSleep;
     private boolean mLaunchEmergencyActionWhenFinishedWaking;
@@ -654,6 +656,7 @@
 
     private final InteractionJankMonitor mJankMonitor;
 
+    /** Existing callback that handles back gesture invoked for the Shade. */
     private final OnBackInvokedCallback mOnBackInvokedCallback = () -> {
         if (DEBUG) {
             Log.d(TAG, "mOnBackInvokedCallback() called");
@@ -661,6 +664,33 @@
         onBackPressed();
     };
 
+    private boolean shouldBackBeHandled() {
+        return (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED
+                && !isBouncerShowingOverDream());
+    }
+
+    /**
+     *  New callback that handles back gesture invoked, cancel, progress
+     *  and provides feedback via Shade animation.
+     *  (enabled via the WM_SHADE_ANIMATE_BACK_GESTURE flag)
+     */
+    private final OnBackAnimationCallback mOnBackAnimationCallback = new OnBackAnimationCallback() {
+        @Override
+        public void onBackInvoked() {
+            onBackPressed();
+        }
+
+        @Override
+        public void onBackProgressed(BackEvent event) {
+            if (shouldBackBeHandled()) {
+                if (mNotificationPanelViewController.canPanelBeCollapsed()) {
+                    float fraction = event.getProgress();
+                    mNotificationPanelViewController.onBackProgressed(fraction);
+                }
+            }
+        }
+    };
+
     /**
      * Public constructor for CentralSurfaces.
      *
@@ -882,6 +912,8 @@
         if (mFeatureFlags.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_SYSUI)) {
             mContext.getApplicationInfo().setEnableOnBackInvokedCallback(true);
         }
+        // Based on teamfood flag, enable predictive back animation for the Shade.
+        mAnimateBack = mFeatureFlags.isEnabled(Flags.WM_SHADE_ANIMATE_BACK_GESTURE);
     }
 
     private void initBubbles(Bubbles bubbles) {
@@ -2221,10 +2253,10 @@
             pw.println("Current Status Bar state:");
             pw.println("  mExpandedVisible=" + mShadeController.isExpandedVisible());
             pw.println("  mDisplayMetrics=" + mDisplayMetrics);
-            pw.println("  mStackScroller: " + CentralSurfaces.viewInfo(mStackScroller));
-            pw.println("  mStackScroller: " + CentralSurfaces.viewInfo(mStackScroller)
-                    + " scroll " + mStackScroller.getScrollX()
+            pw.print("  mStackScroller: " + CentralSurfaces.viewInfo(mStackScroller));
+            pw.print(" scroll " + mStackScroller.getScrollX()
                     + "," + mStackScroller.getScrollY());
+            pw.println(" translationX " + mStackScroller.getTranslationX());
         }
 
         pw.print("  mInteractingWindows="); pw.println(mInteractingWindows);
@@ -2706,7 +2738,8 @@
                 if (viewRootImpl != null) {
                     viewRootImpl.getOnBackInvokedDispatcher()
                             .registerOnBackInvokedCallback(OnBackInvokedDispatcher.PRIORITY_DEFAULT,
-                                    mOnBackInvokedCallback);
+                                    mAnimateBack ? mOnBackAnimationCallback
+                                            : mOnBackInvokedCallback);
                     mIsBackCallbackRegistered = true;
                     if (DEBUG) Log.d(TAG, "is now VISIBLE to user AND callback registered");
                 }
@@ -2721,7 +2754,9 @@
                 ViewRootImpl viewRootImpl = getViewRootImpl();
                 if (viewRootImpl != null) {
                     viewRootImpl.getOnBackInvokedDispatcher()
-                            .unregisterOnBackInvokedCallback(mOnBackInvokedCallback);
+                            .unregisterOnBackInvokedCallback(
+                                    mAnimateBack ? mOnBackAnimationCallback
+                                            : mOnBackInvokedCallback);
                     mIsBackCallbackRegistered = false;
                     if (DEBUG) Log.d(TAG, "is NOT VISIBLE to user, AND callback unregistered");
                 }
@@ -3253,9 +3288,10 @@
         if (mNotificationPanelViewController.closeUserSwitcherIfOpen()) {
             return true;
         }
-        if (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED
-                && !isBouncerShowingOverDream()) {
+        if (shouldBackBeHandled()) {
             if (mNotificationPanelViewController.canPanelBeCollapsed()) {
+                // this is the Shade dismiss animation, so make sure QQS closes when it ends.
+                mNotificationPanelViewController.onBackPressed();
                 mShadeController.animateCollapseShade();
             }
             return true;
@@ -3586,7 +3622,8 @@
         boolean goingToSleepWithoutAnimation = isGoingToSleep()
                 && !mDozeParameters.shouldControlScreenOff();
         boolean disabled = (!mDeviceInteractive && !mDozeServiceHost.isPulsing())
-                || goingToSleepWithoutAnimation;
+                || goingToSleepWithoutAnimation
+                || mDeviceProvisionedController.isFrpActive();
         mNotificationPanelViewController.setTouchAndAnimationDisabled(disabled);
         mNotificationIconAreaController.setAnimationsEnabled(!disabled);
     }
@@ -3710,6 +3747,12 @@
     @Override
     public void notifyBiometricAuthModeChanged() {
         mDozeServiceHost.updateDozing();
+        if (mBiometricUnlockController.getMode()
+                == BiometricUnlockController.MODE_DISMISS_BOUNCER) {
+            // Don't update the scrim controller at this time, in favor of the transition repository
+            // updating the scrim
+            return;
+        }
         updateScrimController();
     }
 
@@ -3752,16 +3795,17 @@
 
         mScrimController.setExpansionAffectsAlpha(!unlocking);
 
-        boolean launchingAffordanceWithPreview = mLaunchingAffordance;
-        mScrimController.setLaunchingAffordanceWithPreview(launchingAffordanceWithPreview);
-
         if (mAlternateBouncerInteractor.isVisibleState()) {
-            if (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED
-                    || mTransitionToFullShadeProgress > 0f) {
+            if ((!isOccluded() || isPanelExpanded())
+                    && (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED
+                    || mTransitionToFullShadeProgress > 0f)) {
                 mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED_SHADE);
             } else {
                 mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED);
             }
+            // This will cancel the keyguardFadingAway animation if it is running. We need to do
+            // this as otherwise it can remain pending and leave keyguard in a weird state.
+            mUnlockScrimCallback.onCancelled();
         } else if (mBouncerShowing && !unlocking) {
             // Bouncer needs the front scrim when it's on top of an activity,
             // tapping on a notification, editing QS or being dismissed by
@@ -3769,9 +3813,6 @@
             ScrimState state = mStatusBarKeyguardViewManager.primaryBouncerNeedsScrimming()
                     ? ScrimState.BOUNCER_SCRIMMED : ScrimState.BOUNCER;
             mScrimController.transitionTo(state);
-        } else if (launchingAffordanceWithPreview) {
-            // We want to avoid animating when launching with a preview.
-            mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
         } else if (mBrightnessMirrorVisible) {
             mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
         } else if (mState == StatusBarState.SHADE_LOCKED) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
index c72eb05..39b5b5a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
@@ -40,6 +40,7 @@
 import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider;
 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
+import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger;
 import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView;
 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel;
 import com.android.systemui.statusbar.pipeline.wifi.ui.view.ModernStatusBarWifiView;
@@ -288,10 +289,14 @@
      * @param mobileContext possibly mcc/mnc overridden mobile context
      * @param subId the subscriptionId for this mobile view
      */
-    public void addModernMobileView(Context mobileContext, int subId) {
+    public void addModernMobileView(
+            Context mobileContext,
+            MobileViewLogger mobileViewLogger,
+            int subId) {
         Log.d(TAG, "addModernMobileView (subId=" + subId + ")");
         ModernStatusBarMobileView view = ModernStatusBarMobileView.constructAndBind(
                 mobileContext,
+                mobileViewLogger,
                 "mobile",
                 mMobileIconsViewModel.viewModelForSub(subId, mLocation)
         );
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index b88531e..ae715b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -429,7 +429,6 @@
         }
 
         dispatchAlwaysOnEvent();
-        mScreenOffAnimationController.onAlwaysOnChanged(getAlwaysOn());
     }
 
     @Override
@@ -469,6 +468,7 @@
         for (Callback callback : mCallbacks) {
             callback.onAlwaysOnChange();
         }
+        mScreenOffAnimationController.onAlwaysOnChanged(getAlwaysOn());
     }
 
     private boolean getPostureSpecificBool(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
index b1553b0..9d30cb4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
@@ -76,6 +76,7 @@
         if (mLastAnimator != null) {
             mLastAnimator.cancel();
         }
+        mMessage = "";
         setText("");
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
index 753032c..3268032 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
@@ -59,7 +59,7 @@
 import com.android.systemui.statusbar.notification.stack.AnimationProperties;
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 import com.android.systemui.statusbar.phone.fragment.StatusBarIconBlocklistKt;
-import com.android.systemui.statusbar.phone.fragment.StatusBarSystemEventAnimator;
+import com.android.systemui.statusbar.phone.fragment.StatusBarSystemEventDefaultAnimator;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -75,6 +75,8 @@
 
 import javax.inject.Inject;
 
+import kotlin.Unit;
+
 /** View Controller for {@link com.android.systemui.statusbar.phone.KeyguardStatusBarView}. */
 public class KeyguardStatusBarViewController extends ViewController<KeyguardStatusBarView> {
     private static final String TAG = "KeyguardStatusBarViewController";
@@ -123,7 +125,8 @@
                 public void onDensityOrFontScaleChanged() {
                     mView.loadDimens();
                     // The animator is dependent on resources for offsets
-                    mSystemEventAnimator = new StatusBarSystemEventAnimator(mView, getResources());
+                    mSystemEventAnimator =
+                            getSystemEventAnimator(mSystemEventAnimator.isAnimationRunning());
                 }
 
                 @Override
@@ -248,7 +251,8 @@
     private int mStatusBarState;
     private boolean mDozing;
     private boolean mShowingKeyguardHeadsUp;
-    private StatusBarSystemEventAnimator mSystemEventAnimator;
+    private StatusBarSystemEventDefaultAnimator mSystemEventAnimator;
+    private float mSystemEventAnimatorAlpha = 1;
 
     /**
      * The alpha value to be set on the View. If -1, this value is to be ignored.
@@ -324,7 +328,7 @@
 
         mView.setKeyguardUserAvatarEnabled(
                 !mStatusBarUserChipViewModel.getChipEnabled());
-        mSystemEventAnimator = new StatusBarSystemEventAnimator(mView, r);
+        mSystemEventAnimator = getSystemEventAnimator(/* isAnimationRunning */ false);
 
         mDisableStateTracker = new DisableStateTracker(
                 /* mask1= */ DISABLE_SYSTEM_INFO,
@@ -480,6 +484,10 @@
                     * (1.0f - mKeyguardHeadsUpShowingAmount);
         }
 
+        if (mSystemEventAnimator.isAnimationRunning()) {
+            newAlpha = Math.min(newAlpha, mSystemEventAnimatorAlpha);
+        }
+
         boolean hideForBypass =
                 mFirstBypassAttempt && mKeyguardUpdateMonitor.shouldListenForFace()
                         || mDelayShowingKeyguardStatusBar;
@@ -488,7 +496,7 @@
                         && !mDozing
                         && !hideForBypass
                         && !mDisableStateTracker.isDisabled()
-                ? View.VISIBLE : View.INVISIBLE;
+                        ? View.VISIBLE : View.INVISIBLE;
 
         updateViewState(newAlpha, newVisibility);
     }
@@ -614,4 +622,15 @@
             updateBlockedIcons();
         }
     };
+
+    private StatusBarSystemEventDefaultAnimator getSystemEventAnimator(boolean isAnimationRunning) {
+        return new StatusBarSystemEventDefaultAnimator(getResources(), (alpha) -> {
+            mSystemEventAnimatorAlpha = alpha;
+            updateViewState();
+            return Unit.INSTANCE;
+        }, (translationX) -> {
+            mView.setTranslationX(translationX);
+            return Unit.INSTANCE;
+        }, isAnimationRunning);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 6c532a5..e6b76ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -22,8 +22,6 @@
 import android.app.ActivityTaskManager;
 import android.app.AlarmManager;
 import android.app.AlarmManager.AlarmClockInfo;
-import android.app.IActivityManager;
-import android.app.SynchronousUserSwitchObserver;
 import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -134,7 +132,6 @@
     private final NextAlarmController mNextAlarmController;
     private final AlarmManager mAlarmManager;
     private final UserInfoController mUserInfoController;
-    private final IActivityManager mIActivityManager;
     private final UserManager mUserManager;
     private final UserTracker mUserTracker;
     private final DevicePolicyManager mDevicePolicyManager;
@@ -149,6 +146,7 @@
     private final KeyguardStateController mKeyguardStateController;
     private final LocationController mLocationController;
     private final PrivacyItemController mPrivacyItemController;
+    private final Executor mMainExecutor;
     private final Executor mUiBgExecutor;
     private final SensorPrivacyController mSensorPrivacyController;
     private final RecordingController mRecordingController;
@@ -168,16 +166,17 @@
     @Inject
     public PhoneStatusBarPolicy(StatusBarIconController iconController,
             CommandQueue commandQueue, BroadcastDispatcher broadcastDispatcher,
-            @UiBackground Executor uiBgExecutor, @Main Looper looper, @Main Resources resources,
-            CastController castController, HotspotController hotspotController,
-            BluetoothController bluetoothController, NextAlarmController nextAlarmController,
-            UserInfoController userInfoController, RotationLockController rotationLockController,
-            DataSaverController dataSaverController, ZenModeController zenModeController,
+            @Main Executor mainExecutor, @UiBackground Executor uiBgExecutor, @Main Looper looper,
+            @Main Resources resources, CastController castController,
+            HotspotController hotspotController, BluetoothController bluetoothController,
+            NextAlarmController nextAlarmController, UserInfoController userInfoController,
+            RotationLockController rotationLockController, DataSaverController dataSaverController,
+            ZenModeController zenModeController,
             DeviceProvisionedController deviceProvisionedController,
             KeyguardStateController keyguardStateController,
             LocationController locationController,
-            SensorPrivacyController sensorPrivacyController, IActivityManager iActivityManager,
-            AlarmManager alarmManager, UserManager userManager, UserTracker userTracker,
+            SensorPrivacyController sensorPrivacyController, AlarmManager alarmManager,
+            UserManager userManager, UserTracker userTracker,
             DevicePolicyManager devicePolicyManager, RecordingController recordingController,
             @Nullable TelecomManager telecomManager, @DisplayId int displayId,
             @Main SharedPreferences sharedPreferences, DateFormatUtil dateFormatUtil,
@@ -195,7 +194,6 @@
         mNextAlarmController = nextAlarmController;
         mAlarmManager = alarmManager;
         mUserInfoController = userInfoController;
-        mIActivityManager = iActivityManager;
         mUserManager = userManager;
         mUserTracker = userTracker;
         mDevicePolicyManager = devicePolicyManager;
@@ -208,6 +206,7 @@
         mPrivacyItemController = privacyItemController;
         mSensorPrivacyController = sensorPrivacyController;
         mRecordingController = recordingController;
+        mMainExecutor = mainExecutor;
         mUiBgExecutor = uiBgExecutor;
         mTelecomManager = telecomManager;
         mRingerModeTracker = ringerModeTracker;
@@ -256,11 +255,7 @@
         mRingerModeTracker.getRingerModeInternal().observeForever(observer);
 
         // listen for user / profile change.
-        try {
-            mIActivityManager.registerUserSwitchObserver(mUserSwitchListener, TAG);
-        } catch (RemoteException e) {
-            // Ignore
-        }
+        mUserTracker.addCallback(mUserSwitchListener, mMainExecutor);
 
         // TTY status
         updateTTY();
@@ -555,15 +550,15 @@
         });
     }
 
-    private final SynchronousUserSwitchObserver mUserSwitchListener =
-            new SynchronousUserSwitchObserver() {
+    private final UserTracker.Callback mUserSwitchListener =
+            new UserTracker.Callback() {
                 @Override
-                public void onUserSwitching(int newUserId) throws RemoteException {
+                public void onUserChanging(int newUser, Context userContext) {
                     mHandler.post(() -> mUserInfoController.reloadUserInfo());
                 }
 
                 @Override
-                public void onUserSwitchComplete(int newUserId) throws RemoteException {
+                public void onUserChanged(int newUser, Context userContext) {
                     mHandler.post(() -> {
                         updateAlarm();
                         updateManagedProfile();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 28bc64d..d546a84 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -35,6 +35,7 @@
 
 import com.android.internal.policy.SystemBarUtils;
 import com.android.systemui.Dependency;
+import com.android.systemui.Gefingerpoken;
 import com.android.systemui.R;
 import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
@@ -60,7 +61,7 @@
     private Rect mDisplaySize;
     private int mStatusBarHeight;
     @Nullable
-    private TouchEventHandler mTouchEventHandler;
+    private Gefingerpoken mTouchEventHandler;
 
     /**
      * Draw this many pixels into the left/right side of the cutout to optimally use the space
@@ -72,7 +73,7 @@
         mContentInsetsProvider = Dependency.get(StatusBarContentInsetsProvider.class);
     }
 
-    void setTouchEventHandler(TouchEventHandler handler) {
+    void setTouchEventHandler(Gefingerpoken handler) {
         mTouchEventHandler = handler;
     }
 
@@ -185,7 +186,7 @@
             );
             return true;
         }
-        return mTouchEventHandler.handleTouchEvent(event);
+        return mTouchEventHandler.onTouchEvent(event);
     }
 
     @Override
@@ -267,28 +268,4 @@
                 insets.second,
                 getPaddingBottom());
     }
-
-    /**
-     * A handler responsible for all touch event handling on the status bar.
-     *
-     * Touches that occur on the status bar view may have ramifications for the notification
-     * panel (e.g. a touch that pulls down the shade could start on the status bar), so this
-     * interface provides a way to notify the panel controller when these touches occur.
-     *
-     * The handler will be notified each time {@link PhoneStatusBarView#onTouchEvent} and
-     * {@link PhoneStatusBarView#onInterceptTouchEvent} are called.
-     **/
-    public interface TouchEventHandler {
-        /** Called each time {@link PhoneStatusBarView#onInterceptTouchEvent} is called. */
-        void onInterceptTouchEvent(MotionEvent event);
-
-        /**
-         * Called each time {@link PhoneStatusBarView#onTouchEvent} is called.
-         *
-         * Should return true if the touch was handled by this handler and false otherwise. The
-         * return value from the handler will be returned from
-         * {@link PhoneStatusBarView#onTouchEvent}.
-         */
-        boolean handleTouchEvent(MotionEvent event);
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
index 11bc490..9a5d1b5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
@@ -24,11 +24,11 @@
 import android.view.View
 import android.view.ViewGroup
 import android.view.ViewTreeObserver
+import com.android.systemui.Gefingerpoken
 import com.android.systemui.R
 import com.android.systemui.shade.ShadeController
 import com.android.systemui.shade.ShadeLogger
 import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator
-import com.android.systemui.statusbar.phone.PhoneStatusBarView.TouchEventHandler
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.unfold.SysUIUnfoldComponent
 import com.android.systemui.unfold.UNFOLD_STATUS_BAR
@@ -131,7 +131,7 @@
     }
 
     /** Called when a touch event occurred on {@link PhoneStatusBarView}. */
-    fun onTouchEvent(event: MotionEvent) {
+    fun onTouch(event: MotionEvent) {
         if (centralSurfaces.statusBarWindowState == WINDOW_STATE_SHOWING) {
             val upOrCancel =
                     event.action == MotionEvent.ACTION_UP ||
@@ -141,13 +141,14 @@
         }
     }
 
-    inner class PhoneStatusBarViewTouchHandler : TouchEventHandler {
-        override fun onInterceptTouchEvent(event: MotionEvent) {
-            onTouchEvent(event)
+    inner class PhoneStatusBarViewTouchHandler : Gefingerpoken {
+        override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
+            onTouch(event)
+            return false
         }
 
-        override fun handleTouchEvent(event: MotionEvent): Boolean {
-            onTouchEvent(event)
+        override fun onTouchEvent(event: MotionEvent): Boolean {
+            onTouch(event)
 
             // If panels aren't enabled, ignore the gesture and don't pass it down to the
             // panel view.
@@ -174,7 +175,7 @@
                     return true
                 }
             }
-            return centralSurfaces.notificationPanelViewController.sendTouchEventToView(event)
+            return centralSurfaces.notificationPanelViewController.handleExternalTouch(event)
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 8e0ec284..0bded73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
+
 import static java.lang.Float.isNaN;
 
 import android.animation.Animator;
@@ -52,10 +54,18 @@
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dock.DockManager;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
 import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants;
+import com.android.systemui.keyguard.shared.model.ScrimAlpha;
+import com.android.systemui.keyguard.shared.model.TransitionState;
+import com.android.systemui.keyguard.shared.model.TransitionStep;
+import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
 import com.android.systemui.scrim.ScrimView;
 import com.android.systemui.shade.NotificationPanelViewController;
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
 import com.android.systemui.statusbar.notification.stack.ViewState;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -71,6 +81,8 @@
 
 import javax.inject.Inject;
 
+import kotlinx.coroutines.CoroutineDispatcher;
+
 /**
  * Controls both the scrim behind the notifications and in front of the notifications (when a
  * security method gets shown).
@@ -235,6 +247,8 @@
     private boolean mWallpaperVisibilityTimedOut;
     private int mScrimsVisibility;
     private final TriConsumer<ScrimState, Float, GradientColors> mScrimStateListener;
+    private final LargeScreenShadeInterpolator mLargeScreenShadeInterpolator;
+    private final FeatureFlags mFeatureFlags;
     private Consumer<Integer> mScrimVisibleListener;
     private boolean mBlankScreen;
     private boolean mScreenBlankingCallbackCalled;
@@ -251,6 +265,24 @@
     private boolean mWakeLockHeld;
     private boolean mKeyguardOccluded;
 
+    private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
+    private CoroutineDispatcher mMainDispatcher;
+    private boolean mIsBouncerToGoneTransitionRunning = false;
+    private PrimaryBouncerToGoneTransitionViewModel mPrimaryBouncerToGoneTransitionViewModel;
+    private final Consumer<ScrimAlpha> mScrimAlphaConsumer =
+            (ScrimAlpha alphas) -> {
+                mInFrontAlpha = alphas.getFrontAlpha();
+                mScrimInFront.setViewAlpha(mInFrontAlpha);
+
+                mNotificationsAlpha = alphas.getNotificationsAlpha();
+                mNotificationsScrim.setViewAlpha(mNotificationsAlpha);
+
+                mBehindAlpha = alphas.getBehindAlpha();
+                mScrimBehind.setViewAlpha(mBehindAlpha);
+            };
+
+    Consumer<TransitionStep> mPrimaryBouncerToGoneTransition;
+
     @Inject
     public ScrimController(
             LightBarController lightBarController,
@@ -265,8 +297,15 @@
             @Main Executor mainExecutor,
             ScreenOffAnimationController screenOffAnimationController,
             KeyguardUnlockAnimationController keyguardUnlockAnimationController,
-            StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
+            StatusBarKeyguardViewManager statusBarKeyguardViewManager,
+            PrimaryBouncerToGoneTransitionViewModel primaryBouncerToGoneTransitionViewModel,
+            KeyguardTransitionInteractor keyguardTransitionInteractor,
+            @Main CoroutineDispatcher mainDispatcher,
+            LargeScreenShadeInterpolator largeScreenShadeInterpolator,
+            FeatureFlags featureFlags) {
         mScrimStateListener = lightBarController::setScrimState;
+        mLargeScreenShadeInterpolator = largeScreenShadeInterpolator;
+        mFeatureFlags = featureFlags;
         mDefaultScrimAlpha = BUSY_SCRIM_ALPHA;
 
         mKeyguardStateController = keyguardStateController;
@@ -304,6 +343,9 @@
             }
         });
         mColors = new GradientColors();
+        mPrimaryBouncerToGoneTransitionViewModel = primaryBouncerToGoneTransitionViewModel;
+        mKeyguardTransitionInteractor = keyguardTransitionInteractor;
+        mMainDispatcher = mainDispatcher;
     }
 
     /**
@@ -343,11 +385,45 @@
         for (ScrimState state : ScrimState.values()) {
             state.prepare(state);
         }
+
+        // Directly control transition to UNLOCKED scrim state from PRIMARY_BOUNCER, and make sure
+        // to report back that keyguard has faded away. This fixes cases where the scrim state was
+        // rapidly switching on unlock, due to shifts in state in CentralSurfacesImpl
+        mPrimaryBouncerToGoneTransition =
+                (TransitionStep step) -> {
+                    TransitionState state = step.getTransitionState();
+
+                    mIsBouncerToGoneTransitionRunning = state == TransitionState.RUNNING;
+
+                    if (state == TransitionState.STARTED) {
+                        setExpansionAffectsAlpha(false);
+                        transitionTo(ScrimState.UNLOCKED);
+                    }
+
+                    if (state == TransitionState.FINISHED || state == TransitionState.CANCELED) {
+                        setExpansionAffectsAlpha(true);
+                        if (mKeyguardStateController.isKeyguardFadingAway()) {
+                            mStatusBarKeyguardViewManager.onKeyguardFadedAway();
+                        }
+                    }
+                };
+
+        collectFlow(behindScrim, mKeyguardTransitionInteractor.getPrimaryBouncerToGoneTransition(),
+                mPrimaryBouncerToGoneTransition, mMainDispatcher);
+        collectFlow(behindScrim, mPrimaryBouncerToGoneTransitionViewModel.getScrimAlpha(),
+                mScrimAlphaConsumer, mMainDispatcher);
     }
 
-    /**
-     * Sets corner radius of scrims.
-     */
+    // TODO(b/270984686) recompute scrim height accurately, based on shade contents.
+    /** Set corner radius of the bottom edge of the Notification scrim. */
+    public void setNotificationBottomRadius(float radius) {
+        if (mNotificationsScrim == null) {
+            return;
+        }
+        mNotificationsScrim.setBottomEdgeRadius(radius);
+    }
+
+    /** Sets corner radius of scrims. */
     public void setScrimCornerRadius(int radius) {
         if (mScrimBehind == null || mNotificationsScrim == null) {
             return;
@@ -365,6 +441,11 @@
     }
 
     public void transitionTo(ScrimState state, Callback callback) {
+        if (mIsBouncerToGoneTransitionRunning) {
+            Log.i(TAG, "Skipping transition to: " + state
+                    + " while mIsBouncerToGoneTransitionRunning");
+            return;
+        }
         if (state == mState) {
             // Call the callback anyway, unless it's already enqueued
             if (callback != null && mCallback != callback) {
@@ -511,6 +592,12 @@
         scheduleUpdate();
     }
 
+    /** This is used by the predictive back gesture animation to scale the Shade. */
+    public void applyBackScaling(float scale) {
+        mNotificationsScrim.setScaleX(scale);
+        mNotificationsScrim.setScaleY(scale);
+    }
+
     public void onTrackingStarted() {
         mDarkenWhileDragging = !mKeyguardStateController.canDismissLockScreen();
         if (!mKeyguardUnlockAnimationController.isPlayingCannedUnlockAnimation()) {
@@ -773,16 +860,21 @@
             if (!mScreenOffAnimationController.shouldExpandNotifications()
                     && !mAnimatingPanelExpansionOnUnlock
                     && !occluding) {
-                if (mClipsQsScrim) {
+                if (mTransparentScrimBackground) {
+                    mBehindAlpha = 0;
+                    mNotificationsAlpha = 0;
+                } else if (mClipsQsScrim) {
                     float behindFraction = getInterpolatedFraction();
                     behindFraction = (float) Math.pow(behindFraction, 0.8f);
-                    mBehindAlpha = mTransparentScrimBackground ? 0 : 1;
-                    mNotificationsAlpha =
-                            mTransparentScrimBackground ? 0 : behindFraction * mDefaultScrimAlpha;
+                    mBehindAlpha = 1;
+                    mNotificationsAlpha = behindFraction * mDefaultScrimAlpha;
                 } else {
-                    if (mTransparentScrimBackground) {
-                        mBehindAlpha = 0;
-                        mNotificationsAlpha = 0;
+                    if (mFeatureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)) {
+                        mBehindAlpha = mLargeScreenShadeInterpolator.getBehindScrimAlpha(
+                                mPanelExpansionFraction * mDefaultScrimAlpha);
+                        mNotificationsAlpha =
+                                mLargeScreenShadeInterpolator.getNotificationScrimAlpha(
+                                        mPanelExpansionFraction);
                     } else {
                         // Behind scrim will finish fading in at 30% expansion.
                         float behindFraction = MathUtils
@@ -1125,7 +1217,9 @@
             Trace.traceCounter(Trace.TRACE_TAG_APP, getScrimName(scrimView) + "_tint",
                     Color.alpha(tint));
             scrimView.setTint(tint);
-            scrimView.setViewAlpha(alpha);
+            if (!mIsBouncerToGoneTransitionRunning) {
+                scrimView.setViewAlpha(alpha);
+            }
         } else {
             scrim.setAlpha(alpha);
         }
@@ -1473,6 +1567,9 @@
     }
 
     public void setKeyguardOccluded(boolean keyguardOccluded) {
+        if (mKeyguardOccluded == keyguardOccluded) {
+            return;
+        }
         mKeyguardOccluded = keyguardOccluded;
         updateScrims();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 11863627..04cc8ce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -569,7 +569,10 @@
             mGroup.addView(view, index, onCreateLayoutParams());
 
             if (mIsInDemoMode) {
-                mDemoStatusIcons.addModernMobileView(mContext, subId);
+                mDemoStatusIcons.addModernMobileView(
+                        mContext,
+                        mMobileIconsViewModel.getLogger(),
+                        subId);
             }
 
             return view;
@@ -601,6 +604,7 @@
             return ModernStatusBarMobileView
                     .constructAndBind(
                             mobileContext,
+                            mMobileIconsViewModel.getLogger(),
                             slot,
                             mMobileIconsViewModel.viewModelForSub(subId, mLocation)
                         );
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
index f6c0da8..833cb93 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
@@ -79,6 +79,18 @@
     private @IconType int mType = TYPE_ICON;
     private int mTag = 0;
 
+    /** Returns a human-readable string representing the given type. */
+    public static String getTypeString(@IconType int type) {
+        switch(type) {
+            case TYPE_ICON: return "ICON";
+            case TYPE_WIFI: return "WIFI_OLD";
+            case TYPE_MOBILE: return "MOBILE_OLD";
+            case TYPE_MOBILE_NEW: return "MOBILE_NEW";
+            case TYPE_WIFI_NEW: return "WIFI_NEW";
+            default: return "UNKNOWN";
+        }
+    }
+
     private StatusBarIconHolder() {
     }
 
@@ -230,4 +242,11 @@
     public int getTag() {
         return mTag;
     }
+
+    @Override
+    public String toString() {
+        return "StatusBarIconHolder(type=" + getTypeString(mType)
+                + " tag=" + getTag()
+                + " visible=" + isVisible() + ")";
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
index 8800b05..565481a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
@@ -27,6 +27,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /** A class holding the list of all the system icons that could be shown in the status bar. */
 public class StatusBarIconList {
@@ -302,7 +303,7 @@
 
         @Override
         public String toString() {
-            return String.format("(%s) %s", mName, subSlotsString());
+            return String.format("(%s) holder=%s %s", mName, mHolder, subSlotsString());
         }
 
         private String subSlotsString() {
@@ -310,7 +311,10 @@
                 return "";
             }
 
-            return "" + mSubSlots.size() + " subSlots";
+            return "| " + mSubSlots.size() + " subSlots: "
+                    + mSubSlots.stream()
+                    .map(StatusBarIconHolder::toString)
+                    .collect(Collectors.joining("|"));
         }
     }
 }
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 66f5b65..69b683b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -85,6 +85,8 @@
 import com.android.systemui.unfold.FoldAodAnimationController;
 import com.android.systemui.unfold.SysUIUnfoldComponent;
 
+import dagger.Lazy;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -94,8 +96,6 @@
 
 import javax.inject.Inject;
 
-import dagger.Lazy;
-
 /**
  * Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back
  * via {@link ViewMediatorCallback} to poke the wake lock and report that the keyguard is done,
@@ -405,14 +405,14 @@
     }
 
     /**
-     * Sets a new legacy alternate bouncer. Only used if mdoern alternate bouncer is NOT enable.
+     * Sets a new legacy alternate bouncer. Only used if modern alternate bouncer is NOT enabled.
      */
     public void setLegacyAlternateBouncer(@NonNull LegacyAlternateBouncer alternateBouncerLegacy) {
         if (!mIsModernAlternateBouncerEnabled) {
             if (!Objects.equals(mAlternateBouncerInteractor.getLegacyAlternateBouncer(),
                     alternateBouncerLegacy)) {
                 mAlternateBouncerInteractor.setLegacyAlternateBouncer(alternateBouncerLegacy);
-                hideAlternateBouncer(false);
+                hideAlternateBouncer(true);
             }
         }
 
@@ -640,8 +640,7 @@
      */
     public void showPrimaryBouncer(boolean scrimmed) {
         hideAlternateBouncer(false);
-
-        if (mKeyguardStateController.isShowing()  && !isBouncerShowing()) {
+        if (mKeyguardStateController.isShowing() && !isBouncerShowing()) {
             mPrimaryBouncerInteractor.show(scrimmed);
         }
         updateStates();
@@ -733,15 +732,17 @@
             } else {
                 showBouncerOrKeyguard(hideBouncerWhenShowing);
             }
-            hideAlternateBouncer(false);
+            if (hideBouncerWhenShowing) {
+                hideAlternateBouncer(true);
+            }
             mKeyguardUpdateManager.sendKeyguardReset();
             updateStates();
         }
     }
 
     @Override
-    public void hideAlternateBouncer(boolean forceUpdateScrim) {
-        updateAlternateBouncerShowing(mAlternateBouncerInteractor.hide() || forceUpdateScrim);
+    public void hideAlternateBouncer(boolean updateScrim) {
+        updateAlternateBouncerShowing(mAlternateBouncerInteractor.hide() && updateScrim);
     }
 
     private void updateAlternateBouncerShowing(boolean updateScrim) {
@@ -1445,16 +1446,21 @@
      * For any touches on the NPVC, show the primary bouncer if the alternate bouncer is currently
      * showing.
      */
-    public void onTouch(MotionEvent event) {
-        if (mAlternateBouncerInteractor.isVisibleState()
+    public boolean onTouch(MotionEvent event) {
+        boolean handledTouch = false;
+        if (event.getAction() == MotionEvent.ACTION_UP
+                && mAlternateBouncerInteractor.isVisibleState()
                 && mAlternateBouncerInteractor.hasAlternateBouncerShownWithMinTime()) {
             showPrimaryBouncer(true);
+            handledTouch = true;
         }
 
         // Forward NPVC touches to callbacks in case they want to respond to touches
         for (KeyguardViewManagerCallback callback: mCallbacks) {
             callback.onTouch(event);
         }
+
+        return handledTouch;
     }
 
     /** Update keyguard position based on a tapped X coordinate. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationController.kt
index 79c0984..d30d0e25 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationController.kt
@@ -22,6 +22,7 @@
 import com.android.systemui.statusbar.phone.PhoneStatusBarViewController.StatusBarViewsCenterProvider
 import com.android.systemui.unfold.SysUIUnfoldScope
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
+import com.android.systemui.unfold.util.CurrentActivityTypeProvider
 import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
 import javax.inject.Inject
 import kotlin.math.max
@@ -29,9 +30,13 @@
 @SysUIUnfoldScope
 class StatusBarMoveFromCenterAnimationController @Inject constructor(
     private val progressProvider: ScopedUnfoldTransitionProgressProvider,
+    private val currentActivityTypeProvider: CurrentActivityTypeProvider,
     windowManager: WindowManager
 ) {
 
+    // Whether we're on home activity. Updated only when the animation starts.
+    private var isOnHomeActivity: Boolean? = null
+
     private val transitionListener = TransitionListener()
     private val moveFromCenterAnimator = UnfoldMoveFromCenterAnimator(
         windowManager,
@@ -60,6 +65,10 @@
     }
 
     private inner class TransitionListener : TransitionProgressListener {
+        override fun onTransitionStarted() {
+            isOnHomeActivity = currentActivityTypeProvider.isHomeActivity
+        }
+
         override fun onTransitionProgress(progress: Float) {
             moveFromCenterAnimator.onTransitionProgress(progress)
         }
@@ -68,11 +77,23 @@
             // Reset translations when transition is stopped/cancelled
             // (e.g. the transition could be cancelled mid-way when rotating the screen)
             moveFromCenterAnimator.onTransitionProgress(1f)
+            isOnHomeActivity = null
         }
     }
 
-    private class StatusBarIconsAlphaProvider : AlphaProvider {
+
+    /**
+     * In certain cases, an alpha is applied based on the progress.
+     *
+     * This mainly happens to hide the statusbar during the unfold animation while on apps, as the
+     * bounds of the app "collapse" to the center, but the statusbar doesn't.
+     * While on launcher, this alpha is not applied.
+     */
+    private inner class StatusBarIconsAlphaProvider : AlphaProvider {
         override fun getAlpha(progress: Float): Float {
+            if (isOnHomeActivity == true) {
+                return 1.0f
+            }
             return max(
                 0f,
                 (progress - ICONS_START_APPEARING_PROGRESS) / (1 - ICONS_START_APPEARING_PROGRESS)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 3471a46..edfc95f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -16,11 +16,13 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED;
 import static android.service.notification.NotificationListenerService.REASON_CLICK;
 
 import static com.android.systemui.statusbar.phone.CentralSurfaces.getActivityOptions;
 
 import android.app.ActivityManager;
+import android.app.ActivityOptions;
 import android.app.KeyguardManager;
 import android.app.Notification;
 import android.app.PendingIntent;
@@ -561,10 +563,6 @@
             mLogger.logFullScreenIntentSuppressedByVR(entry);
             return;
         }
-        if (mFeatureFlags.isEnabled(Flags.FSI_CHROME)) {
-            // FsiChromeRepo runs its own implementation of launchFullScreenIntent
-            return;
-        }
         // Stop screensaver if the notification has a fullscreen intent.
         // (like an incoming phone call)
         mUiBgExecutor.execute(() -> {
@@ -583,8 +581,14 @@
             EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
                     entry.getKey());
             mCentralSurfaces.wakeUpForFullScreenIntent();
-            fullScreenIntent.send();
+
+            ActivityOptions options = ActivityOptions.makeBasic();
+            options.setPendingIntentBackgroundActivityStartMode(
+                    MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
+            fullScreenIntent.sendAndReturnResult(null, 0, null, null, null, null,
+                    options.toBundle());
             entry.notifyFullScreenIntentLaunched();
+
             mMetricsLogger.count("note_fullscreen", 1);
 
             String activityName;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt
index c04ea36..5903fa3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt
@@ -26,19 +26,39 @@
 import com.android.systemui.statusbar.events.STATUS_BAR_X_MOVE_OUT
 import com.android.systemui.statusbar.events.SystemStatusAnimationCallback
 import com.android.systemui.util.animation.AnimationUtil.Companion.frames
+import com.android.systemui.util.doOnCancel
+import com.android.systemui.util.doOnEnd
+
+/**
+ * An implementation of [StatusBarSystemEventDefaultAnimator], applying the onAlphaChanged and
+ * onTranslationXChanged callbacks directly to the provided animatedView.
+ */
+class StatusBarSystemEventAnimator @JvmOverloads constructor(
+        val animatedView: View,
+        resources: Resources,
+        isAnimationRunning: Boolean = false
+) : StatusBarSystemEventDefaultAnimator(
+        resources = resources,
+        onAlphaChanged = animatedView::setAlpha,
+        onTranslationXChanged = animatedView::setTranslationX,
+        isAnimationRunning = isAnimationRunning
+)
 
 /**
  * Tied directly to [SystemStatusAnimationScheduler]. Any StatusBar-like thing (keyguard, collapsed
- * status bar fragment), can just feed this an animatable view to get the default system status
- * animation.
+ * status bar fragment), can use this Animator to get the default system status animation. It simply
+ * needs to implement the onAlphaChanged and onTranslationXChanged callbacks.
  *
  * This animator relies on resources, and should be recreated whenever resources are updated. While
  * this class could be used directly as the animation callback, it's probably best to forward calls
  * to it so that it can be recreated at any moment without needing to remove/add callback.
  */
-class StatusBarSystemEventAnimator(
-    val animatedView: View,
-    resources: Resources
+
+open class StatusBarSystemEventDefaultAnimator @JvmOverloads constructor(
+        resources: Resources,
+        private val onAlphaChanged: (Float) -> Unit,
+        private val onTranslationXChanged: (Float) -> Unit,
+        var isAnimationRunning: Boolean = false
 ) : SystemStatusAnimationCallback {
     private val translationXIn: Int = resources.getDimensionPixelSize(
             R.dimen.ongoing_appops_chip_animation_in_status_bar_translation_x)
@@ -46,18 +66,19 @@
             R.dimen.ongoing_appops_chip_animation_out_status_bar_translation_x)
 
     override fun onSystemEventAnimationBegin(): Animator {
+        isAnimationRunning = true
         val moveOut = ValueAnimator.ofFloat(0f, 1f).apply {
             duration = 23.frames
             interpolator = STATUS_BAR_X_MOVE_OUT
             addUpdateListener {
-                animatedView.translationX = -(translationXIn * animatedValue as Float)
+                onTranslationXChanged(-(translationXIn * animatedValue as Float))
             }
         }
         val alphaOut = ValueAnimator.ofFloat(1f, 0f).apply {
             duration = 8.frames
             interpolator = null
             addUpdateListener {
-                animatedView.alpha = animatedValue as Float
+                onAlphaChanged(animatedValue as Float)
             }
         }
 
@@ -67,13 +88,13 @@
     }
 
     override fun onSystemEventAnimationFinish(hasPersistentDot: Boolean): Animator {
-        animatedView.translationX = translationXOut.toFloat()
+        onTranslationXChanged(translationXOut.toFloat())
         val moveIn = ValueAnimator.ofFloat(1f, 0f).apply {
             duration = 23.frames
             startDelay = 7.frames
             interpolator = STATUS_BAR_X_MOVE_IN
             addUpdateListener {
-                animatedView.translationX = translationXOut * animatedValue as Float
+                onTranslationXChanged(translationXOut * animatedValue as Float)
             }
         }
         val alphaIn = ValueAnimator.ofFloat(0f, 1f).apply {
@@ -81,13 +102,14 @@
             startDelay = 11.frames
             interpolator = null
             addUpdateListener {
-                animatedView.alpha = animatedValue as Float
+                onAlphaChanged(animatedValue as Float)
             }
         }
 
         val animatorSet = AnimatorSet()
         animatorSet.playTogether(moveIn, alphaIn)
-
+        animatorSet.doOnEnd { isAnimationRunning = false }
+        animatorSet.doOnCancel { isAnimationRunning = false }
         return animatorSet
     }
 }
\ No newline at end of file
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/MobileViewLog.kt
similarity index 70%
copy from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
copy to packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/MobileViewLog.kt
index 35d5c15..e594a8a 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/MobileViewLog.kt
@@ -14,6 +14,12 @@
  * limitations under the License.
  */
 
-package android.net.wifi.sharedconnectivity.app;
+package com.android.systemui.statusbar.pipeline.dagger
 
-parcelable DeviceInfo;
\ No newline at end of file
+import javax.inject.Qualifier
+
+/** Logs for changes with the new mobile views. */
+@Qualifier
+@MustBeDocumented
+@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
+annotation class MobileViewLog
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
index 4464751..adfea80 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
@@ -148,5 +148,19 @@
         fun provideMobileInputLogBuffer(factory: LogBufferFactory): LogBuffer {
             return factory.create("MobileInputLog", 100)
         }
+
+        @Provides
+        @SysUISingleton
+        @MobileViewLog
+        fun provideMobileViewLogBuffer(factory: LogBufferFactory): LogBuffer {
+            return factory.create("MobileViewLog", 100)
+        }
+
+        @Provides
+        @SysUISingleton
+        @VerboseMobileViewLog
+        fun provideVerboseMobileViewLogBuffer(factory: LogBufferFactory): LogBuffer {
+            return factory.create("VerboseMobileViewLog", 100)
+        }
     }
 }
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/VerboseMobileViewLog.kt
similarity index 68%
copy from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
copy to packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/VerboseMobileViewLog.kt
index 35d5c15..b987898 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/VerboseMobileViewLog.kt
@@ -14,6 +14,12 @@
  * limitations under the License.
  */
 
-package android.net.wifi.sharedconnectivity.app;
+package com.android.systemui.statusbar.pipeline.dagger
 
-parcelable DeviceInfo;
\ No newline at end of file
+import javax.inject.Qualifier
+
+/** Logs for **verbose** changes with the new mobile views. */
+@Qualifier
+@MustBeDocumented
+@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
+annotation class VerboseMobileViewLog
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/shared/MobileInputLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt
similarity index 88%
rename from packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/shared/MobileInputLogger.kt
rename to packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt
index 3cbd2b7..4156fc1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/shared/MobileInputLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.pipeline.mobile.shared
+package com.android.systemui.statusbar.pipeline.mobile.data
 
 import android.net.Network
 import android.net.NetworkCapabilities
@@ -51,8 +51,8 @@
         )
     }
 
-    fun logOnLost(network: Network) {
-        LoggerHelper.logOnLost(buffer, TAG, network)
+    fun logOnLost(network: Network, isDefaultNetworkCallback: Boolean) {
+        LoggerHelper.logOnLost(buffer, TAG, network, isDefaultNetworkCallback)
     }
 
     fun logOnServiceStateChanged(serviceState: ServiceState, subId: Int) {
@@ -133,24 +133,6 @@
         )
     }
 
-    fun logUiAdapterSubIdsUpdated(subs: List<Int>) {
-        buffer.log(
-            TAG,
-            LogLevel.INFO,
-            { str1 = subs.toString() },
-            { "Sub IDs in MobileUiAdapter updated internally: $str1" },
-        )
-    }
-
-    fun logUiAdapterSubIdsSentToIconController(subs: List<Int>) {
-        buffer.log(
-            TAG,
-            LogLevel.INFO,
-            { str1 = subs.toString() },
-            { "Sub IDs in MobileUiAdapter being sent to icon controller: $str1" },
-        )
-    }
-
     fun logCarrierConfigChanged(subId: Int) {
         buffer.log(
             TAG,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/DataConnectionState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/DataConnectionState.kt
index 85729c1..19f0242 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/DataConnectionState.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/DataConnectionState.kt
@@ -24,9 +24,11 @@
 import android.telephony.TelephonyManager.DATA_SUSPENDED
 import android.telephony.TelephonyManager.DATA_UNKNOWN
 import android.telephony.TelephonyManager.DataState
+import com.android.systemui.log.table.Diffable
+import com.android.systemui.log.table.TableRowLogger
 
 /** Internal enum representation of the telephony data connection states */
-enum class DataConnectionState {
+enum class DataConnectionState : Diffable<DataConnectionState> {
     Connected,
     Connecting,
     Disconnected,
@@ -34,7 +36,17 @@
     Suspended,
     HandoverInProgress,
     Unknown,
-    Invalid,
+    Invalid;
+
+    override fun logDiffs(prevVal: DataConnectionState, row: TableRowLogger) {
+        if (prevVal != this) {
+            row.logChange(COL_CONNECTION_STATE, name)
+        }
+    }
+
+    companion object {
+        private const val COL_CONNECTION_STATE = "connectionState"
+    }
 }
 
 fun @receiver:DataState Int.toDataConnectionType(): DataConnectionState =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModel.kt
deleted file mode 100644
index ed7f60b..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModel.kt
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.pipeline.mobile.data.model
-
-import android.annotation.IntRange
-import android.telephony.CellSignalStrength
-import android.telephony.TelephonyCallback.CarrierNetworkListener
-import android.telephony.TelephonyCallback.DataActivityListener
-import android.telephony.TelephonyCallback.DataConnectionStateListener
-import android.telephony.TelephonyCallback.DisplayInfoListener
-import android.telephony.TelephonyCallback.ServiceStateListener
-import android.telephony.TelephonyCallback.SignalStrengthsListener
-import android.telephony.TelephonyDisplayInfo
-import android.telephony.TelephonyManager
-import androidx.annotation.VisibleForTesting
-import com.android.systemui.log.table.Diffable
-import com.android.systemui.log.table.TableRowLogger
-import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState.Disconnected
-import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
-
-/**
- * Data class containing all of the relevant information for a particular line of service, known as
- * a Subscription in the telephony world. These models are the result of a single telephony listener
- * which has many callbacks which each modify some particular field on this object.
- *
- * The design goal here is to de-normalize fields from the system into our model fields below. So
- * any new field that needs to be tracked should be copied into this data class rather than
- * threading complex system objects through the pipeline.
- */
-data class MobileConnectionModel(
-    /** Fields below are from [ServiceStateListener.onServiceStateChanged] */
-    val isEmergencyOnly: Boolean = false,
-    val isRoaming: Boolean = false,
-    /**
-     * See [android.telephony.ServiceState.getOperatorAlphaShort], this value is defined as the
-     * current registered operator name in short alphanumeric format. In some cases this name might
-     * be preferred over other methods of calculating the network name
-     */
-    val operatorAlphaShort: String? = null,
-
-    /**
-     * TODO (b/263167683): Clarify this field
-     *
-     * This check comes from [com.android.settingslib.Utils.isInService]. It is intended to be a
-     * mapping from a ServiceState to a notion of connectivity. Notably, it will consider a
-     * connection to be in-service if either the voice registration state is IN_SERVICE or the data
-     * registration state is IN_SERVICE and NOT IWLAN.
-     */
-    val isInService: Boolean = false,
-
-    /** Fields below from [SignalStrengthsListener.onSignalStrengthsChanged] */
-    val isGsm: Boolean = false,
-    @IntRange(from = 0, to = 4)
-    val cdmaLevel: Int = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN,
-    @IntRange(from = 0, to = 4)
-    val primaryLevel: Int = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN,
-
-    /** Fields below from [DataConnectionStateListener.onDataConnectionStateChanged] */
-    val dataConnectionState: DataConnectionState = Disconnected,
-
-    /**
-     * Fields below from [DataActivityListener.onDataActivity]. See [TelephonyManager] for the
-     * values
-     */
-    val dataActivityDirection: DataActivityModel =
-        DataActivityModel(
-            hasActivityIn = false,
-            hasActivityOut = false,
-        ),
-
-    /** Fields below from [CarrierNetworkListener.onCarrierNetworkChange] */
-    val carrierNetworkChangeActive: Boolean = false,
-
-    /** Fields below from [DisplayInfoListener.onDisplayInfoChanged]. */
-
-    /**
-     * [resolvedNetworkType] is the [TelephonyDisplayInfo.getOverrideNetworkType] if it exists or
-     * [TelephonyDisplayInfo.getNetworkType]. This is used to look up the proper network type icon
-     */
-    val resolvedNetworkType: ResolvedNetworkType = ResolvedNetworkType.UnknownNetworkType,
-) : Diffable<MobileConnectionModel> {
-    override fun logDiffs(prevVal: MobileConnectionModel, row: TableRowLogger) {
-        if (prevVal.dataConnectionState != dataConnectionState) {
-            row.logChange(COL_CONNECTION_STATE, dataConnectionState.name)
-        }
-
-        if (prevVal.isEmergencyOnly != isEmergencyOnly) {
-            row.logChange(COL_EMERGENCY, isEmergencyOnly)
-        }
-
-        if (prevVal.isRoaming != isRoaming) {
-            row.logChange(COL_ROAMING, isRoaming)
-        }
-
-        if (prevVal.operatorAlphaShort != operatorAlphaShort) {
-            row.logChange(COL_OPERATOR, operatorAlphaShort)
-        }
-
-        if (prevVal.isInService != isInService) {
-            row.logChange(COL_IS_IN_SERVICE, isInService)
-        }
-
-        if (prevVal.isGsm != isGsm) {
-            row.logChange(COL_IS_GSM, isGsm)
-        }
-
-        if (prevVal.cdmaLevel != cdmaLevel) {
-            row.logChange(COL_CDMA_LEVEL, cdmaLevel)
-        }
-
-        if (prevVal.primaryLevel != primaryLevel) {
-            row.logChange(COL_PRIMARY_LEVEL, primaryLevel)
-        }
-
-        if (prevVal.dataActivityDirection.hasActivityIn != dataActivityDirection.hasActivityIn) {
-            row.logChange(COL_ACTIVITY_DIRECTION_IN, dataActivityDirection.hasActivityIn)
-        }
-
-        if (prevVal.dataActivityDirection.hasActivityOut != dataActivityDirection.hasActivityOut) {
-            row.logChange(COL_ACTIVITY_DIRECTION_OUT, dataActivityDirection.hasActivityOut)
-        }
-
-        if (prevVal.carrierNetworkChangeActive != carrierNetworkChangeActive) {
-            row.logChange(COL_CARRIER_NETWORK_CHANGE, carrierNetworkChangeActive)
-        }
-
-        if (prevVal.resolvedNetworkType != resolvedNetworkType) {
-            row.logChange(COL_RESOLVED_NETWORK_TYPE, resolvedNetworkType.toString())
-        }
-    }
-
-    override fun logFull(row: TableRowLogger) {
-        row.logChange(COL_CONNECTION_STATE, dataConnectionState.name)
-        row.logChange(COL_EMERGENCY, isEmergencyOnly)
-        row.logChange(COL_ROAMING, isRoaming)
-        row.logChange(COL_OPERATOR, operatorAlphaShort)
-        row.logChange(COL_IS_IN_SERVICE, isInService)
-        row.logChange(COL_IS_GSM, isGsm)
-        row.logChange(COL_CDMA_LEVEL, cdmaLevel)
-        row.logChange(COL_PRIMARY_LEVEL, primaryLevel)
-        row.logChange(COL_ACTIVITY_DIRECTION_IN, dataActivityDirection.hasActivityIn)
-        row.logChange(COL_ACTIVITY_DIRECTION_OUT, dataActivityDirection.hasActivityOut)
-        row.logChange(COL_CARRIER_NETWORK_CHANGE, carrierNetworkChangeActive)
-        row.logChange(COL_RESOLVED_NETWORK_TYPE, resolvedNetworkType.toString())
-    }
-
-    @VisibleForTesting
-    companion object {
-        const val COL_EMERGENCY = "EmergencyOnly"
-        const val COL_ROAMING = "Roaming"
-        const val COL_OPERATOR = "OperatorName"
-        const val COL_IS_IN_SERVICE = "IsInService"
-        const val COL_IS_GSM = "IsGsm"
-        const val COL_CDMA_LEVEL = "CdmaLevel"
-        const val COL_PRIMARY_LEVEL = "PrimaryLevel"
-        const val COL_CONNECTION_STATE = "ConnectionState"
-        const val COL_ACTIVITY_DIRECTION_IN = "DataActivity.In"
-        const val COL_ACTIVITY_DIRECTION_OUT = "DataActivity.Out"
-        const val COL_CARRIER_NETWORK_CHANGE = "CarrierNetworkChangeActive"
-        const val COL_RESOLVED_NETWORK_TYPE = "NetworkType"
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/ResolvedNetworkType.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/ResolvedNetworkType.kt
index 5562e73..cf7a313 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/ResolvedNetworkType.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/ResolvedNetworkType.kt
@@ -17,8 +17,12 @@
 package com.android.systemui.statusbar.pipeline.mobile.data.model
 
 import android.telephony.Annotation.NetworkType
+import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
 import com.android.settingslib.SignalIcon
+import com.android.settingslib.mobile.MobileMappings
 import com.android.settingslib.mobile.TelephonyIcons
+import com.android.systemui.log.table.Diffable
+import com.android.systemui.log.table.TableRowLogger
 import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
 
 /**
@@ -26,11 +30,19 @@
  * on whether or not the display info contains an override type, we may have to call different
  * methods on [MobileMappingsProxy] to generate an icon lookup key.
  */
-sealed interface ResolvedNetworkType {
+sealed interface ResolvedNetworkType : Diffable<ResolvedNetworkType> {
     val lookupKey: String
 
+    override fun logDiffs(prevVal: ResolvedNetworkType, row: TableRowLogger) {
+        if (prevVal != this) {
+            row.logChange(COL_NETWORK_TYPE, this.toString())
+        }
+    }
+
     object UnknownNetworkType : ResolvedNetworkType {
-        override val lookupKey: String = "unknown"
+        override val lookupKey: String = MobileMappings.toIconKey(NETWORK_TYPE_UNKNOWN)
+
+        override fun toString(): String = "Unknown"
     }
 
     data class DefaultNetworkType(
@@ -47,5 +59,11 @@
         override val lookupKey: String = "cwf"
 
         val iconGroupOverride: SignalIcon.MobileIconGroup = TelephonyIcons.CARRIER_MERGED_WIFI
+
+        override fun toString(): String = "CarrierMerged"
+    }
+
+    companion object {
+        private const val COL_NETWORK_TYPE = "networkType"
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt
index 8c82fba..f4e3eab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt
@@ -45,7 +45,7 @@
  * 1. Define a new `private val` wrapping the key using [BooleanCarrierConfig]
  * 2. Define a public `val` exposing the wrapped flow using [BooleanCarrierConfig.config]
  * 3. Add the new [BooleanCarrierConfig] to the list of tracked configs, so they are properly
- * updated when a new carrier config comes down
+ *    updated when a new carrier config comes down
  */
 class SystemUiCarrierConfig
 internal constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt
index bb3b9b2..efdce06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt
@@ -30,8 +30,8 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
-import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
 import java.io.PrintWriter
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt
index 6187f64..90c32dc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt
@@ -17,11 +17,12 @@
 package com.android.systemui.statusbar.pipeline.mobile.data.repository
 
 import android.telephony.SubscriptionInfo
-import android.telephony.TelephonyCallback
 import android.telephony.TelephonyManager
 import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
+import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
 import kotlinx.coroutines.flow.StateFlow
 
 /**
@@ -45,11 +46,57 @@
      */
     val tableLogBuffer: TableLogBuffer
 
+    /** True if the [android.telephony.ServiceState] says this connection is emergency calls only */
+    val isEmergencyOnly: StateFlow<Boolean>
+
+    /** True if [android.telephony.ServiceState] says we are roaming */
+    val isRoaming: StateFlow<Boolean>
+
     /**
-     * A flow that aggregates all necessary callbacks from [TelephonyCallback] into a single
-     * listener + model.
+     * See [android.telephony.ServiceState.getOperatorAlphaShort], this value is defined as the
+     * current registered operator name in short alphanumeric format. In some cases this name might
+     * be preferred over other methods of calculating the network name
      */
-    val connectionInfo: StateFlow<MobileConnectionModel>
+    val operatorAlphaShort: StateFlow<String?>
+
+    /**
+     * TODO (b/263167683): Clarify this field
+     *
+     * This check comes from [com.android.settingslib.Utils.isInService]. It is intended to be a
+     * mapping from a ServiceState to a notion of connectivity. Notably, it will consider a
+     * connection to be in-service if either the voice registration state is IN_SERVICE or the data
+     * registration state is IN_SERVICE and NOT IWLAN.
+     */
+    val isInService: StateFlow<Boolean>
+
+    /** True if [android.telephony.SignalStrength] told us that this connection is using GSM */
+    val isGsm: StateFlow<Boolean>
+
+    /**
+     * There is still specific logic in the pipeline that calls out CDMA level explicitly. This
+     * field is not completely orthogonal to [primaryLevel], because CDMA could be primary.
+     */
+    // @IntRange(from = 0, to = 4)
+    val cdmaLevel: StateFlow<Int>
+
+    /** [android.telephony.SignalStrength]'s concept of the overall signal level */
+    // @IntRange(from = 0, to = 4)
+    val primaryLevel: StateFlow<Int>
+
+    /** The current data connection state. See [DataConnectionState] */
+    val dataConnectionState: StateFlow<DataConnectionState>
+
+    /** The current data activity direction. See [DataActivityModel] */
+    val dataActivityDirection: StateFlow<DataActivityModel>
+
+    /** True if there is currently a carrier network change in process */
+    val carrierNetworkChangeActive: StateFlow<Boolean>
+
+    /**
+     * [resolvedNetworkType] is the [TelephonyDisplayInfo.getOverrideNetworkType] if it exists or
+     * [TelephonyDisplayInfo.getNetworkType]. This is used to look up the proper network type icon
+     */
+    val resolvedNetworkType: StateFlow<ResolvedNetworkType>
 
     /** The total number of levels. Used with [SignalDrawable]. */
     val numberOfLevels: StateFlow<Int>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt
new file mode 100644
index 0000000..809772e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt
@@ -0,0 +1,231 @@
+/*
+ * 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.pipeline.mobile.data.repository.demo
+
+import android.telephony.CellSignalStrength
+import android.telephony.TelephonyManager
+import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logDiffsForTable
+import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
+import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_CARRIER_NETWORK_CHANGE
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_CDMA_LEVEL
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_EMERGENCY
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_IS_GSM
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_IS_IN_SERVICE
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_OPERATOR
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_PRIMARY_LEVEL
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_ROAMING
+import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
+import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
+import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.stateIn
+
+/**
+ * Demo version of [MobileConnectionRepository]. Note that this class shares all of its flows using
+ * [SharingStarted.WhileSubscribed()] to give the same semantics as using a regular
+ * [MutableStateFlow] while still logging all of the inputs in the same manor as the production
+ * repos.
+ */
+class DemoMobileConnectionRepository(
+    override val subId: Int,
+    override val tableLogBuffer: TableLogBuffer,
+    val scope: CoroutineScope,
+) : MobileConnectionRepository {
+    private val _isEmergencyOnly = MutableStateFlow(false)
+    override val isEmergencyOnly =
+        _isEmergencyOnly
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = COL_EMERGENCY,
+                _isEmergencyOnly.value
+            )
+            .stateIn(scope, SharingStarted.WhileSubscribed(), _isEmergencyOnly.value)
+
+    private val _isRoaming = MutableStateFlow(false)
+    override val isRoaming =
+        _isRoaming
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = COL_ROAMING,
+                _isRoaming.value
+            )
+            .stateIn(scope, SharingStarted.WhileSubscribed(), _isRoaming.value)
+
+    private val _operatorAlphaShort: MutableStateFlow<String?> = MutableStateFlow(null)
+    override val operatorAlphaShort =
+        _operatorAlphaShort
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = COL_OPERATOR,
+                _operatorAlphaShort.value
+            )
+            .stateIn(scope, SharingStarted.WhileSubscribed(), _operatorAlphaShort.value)
+
+    private val _isInService = MutableStateFlow(false)
+    override val isInService =
+        _isInService
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = COL_IS_IN_SERVICE,
+                _isInService.value
+            )
+            .stateIn(scope, SharingStarted.WhileSubscribed(), _isInService.value)
+
+    private val _isGsm = MutableStateFlow(false)
+    override val isGsm =
+        _isGsm
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = COL_IS_GSM,
+                _isGsm.value
+            )
+            .stateIn(scope, SharingStarted.WhileSubscribed(), _isGsm.value)
+
+    private val _cdmaLevel = MutableStateFlow(CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
+    override val cdmaLevel =
+        _cdmaLevel
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = COL_CDMA_LEVEL,
+                _cdmaLevel.value
+            )
+            .stateIn(scope, SharingStarted.WhileSubscribed(), _cdmaLevel.value)
+
+    private val _primaryLevel = MutableStateFlow(CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
+    override val primaryLevel =
+        _primaryLevel
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = COL_PRIMARY_LEVEL,
+                _primaryLevel.value
+            )
+            .stateIn(scope, SharingStarted.WhileSubscribed(), _primaryLevel.value)
+
+    private val _dataConnectionState = MutableStateFlow(DataConnectionState.Disconnected)
+    override val dataConnectionState =
+        _dataConnectionState
+            .logDiffsForTable(tableLogBuffer, columnPrefix = "", _dataConnectionState.value)
+            .stateIn(scope, SharingStarted.WhileSubscribed(), _dataConnectionState.value)
+
+    private val _dataActivityDirection =
+        MutableStateFlow(
+            DataActivityModel(
+                hasActivityIn = false,
+                hasActivityOut = false,
+            )
+        )
+    override val dataActivityDirection =
+        _dataActivityDirection
+            .logDiffsForTable(tableLogBuffer, columnPrefix = "", _dataActivityDirection.value)
+            .stateIn(scope, SharingStarted.WhileSubscribed(), _dataActivityDirection.value)
+
+    private val _carrierNetworkChangeActive = MutableStateFlow(false)
+    override val carrierNetworkChangeActive =
+        _carrierNetworkChangeActive
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = COL_CARRIER_NETWORK_CHANGE,
+                _carrierNetworkChangeActive.value
+            )
+            .stateIn(scope, SharingStarted.WhileSubscribed(), _carrierNetworkChangeActive.value)
+
+    private val _resolvedNetworkType: MutableStateFlow<ResolvedNetworkType> =
+        MutableStateFlow(ResolvedNetworkType.UnknownNetworkType)
+    override val resolvedNetworkType =
+        _resolvedNetworkType
+            .logDiffsForTable(tableLogBuffer, columnPrefix = "", _resolvedNetworkType.value)
+            .stateIn(scope, SharingStarted.WhileSubscribed(), _resolvedNetworkType.value)
+
+    override val numberOfLevels = MutableStateFlow(MobileConnectionRepository.DEFAULT_NUM_LEVELS)
+
+    override val dataEnabled = MutableStateFlow(true)
+
+    override val cdmaRoaming = MutableStateFlow(false)
+
+    override val networkName = MutableStateFlow(NetworkNameModel.IntentDerived("demo network"))
+
+    /**
+     * Process a new demo mobile event. Note that [resolvedNetworkType] must be passed in separately
+     * from the event, due to the requirement to reverse the mobile mappings lookup in the top-level
+     * repository.
+     */
+    fun processDemoMobileEvent(
+        event: FakeNetworkEventModel.Mobile,
+        resolvedNetworkType: ResolvedNetworkType,
+    ) {
+        // This is always true here, because we split out disabled states at the data-source level
+        dataEnabled.value = true
+        networkName.value = NetworkNameModel.IntentDerived(event.name)
+
+        cdmaRoaming.value = event.roaming
+        _isRoaming.value = event.roaming
+        // TODO(b/261029387): not yet supported
+        _isEmergencyOnly.value = false
+        _operatorAlphaShort.value = event.name
+        _isInService.value = (event.level ?: 0) > 0
+        // TODO(b/261029387): not yet supported
+        _isGsm.value = false
+        _cdmaLevel.value = event.level ?: 0
+        _primaryLevel.value = event.level ?: 0
+        // TODO(b/261029387): not yet supported
+        _dataConnectionState.value = DataConnectionState.Connected
+        _dataActivityDirection.value =
+            (event.activity ?: TelephonyManager.DATA_ACTIVITY_NONE).toMobileDataActivityModel()
+        _carrierNetworkChangeActive.value = event.carrierNetworkChange
+        _resolvedNetworkType.value = resolvedNetworkType
+    }
+
+    fun processCarrierMergedEvent(event: FakeWifiEventModel.CarrierMerged) {
+        // This is always true here, because we split out disabled states at the data-source level
+        dataEnabled.value = true
+        networkName.value = NetworkNameModel.IntentDerived(CARRIER_MERGED_NAME)
+        numberOfLevels.value = event.numberOfLevels
+        cdmaRoaming.value = false
+        _primaryLevel.value = event.level
+        _cdmaLevel.value = event.level
+        _dataActivityDirection.value = event.activity.toMobileDataActivityModel()
+
+        // These fields are always the same for carrier-merged networks
+        _resolvedNetworkType.value = ResolvedNetworkType.CarrierMergedNetworkType
+        _dataConnectionState.value = DataConnectionState.Connected
+        _isRoaming.value = false
+        _isEmergencyOnly.value = false
+        _operatorAlphaShort.value = null
+        _isInService.value = true
+        _isGsm.value = false
+        _carrierNetworkChangeActive.value = false
+    }
+
+    companion object {
+        private const val CARRIER_MERGED_NAME = "Carrier Merged Network"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt
index e924832..3cafb73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt
@@ -18,30 +18,22 @@
 
 import android.content.Context
 import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
-import android.telephony.TelephonyManager.DATA_ACTIVITY_NONE
 import android.util.Log
 import com.android.settingslib.SignalIcon
 import com.android.settingslib.mobile.MobileMappings
 import com.android.settingslib.mobile.TelephonyIcons
 import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.log.table.TableLogBufferFactory
-import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
-import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel.Mobile
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel.MobileDisabled
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.CarrierMergedConnectionRepository.Companion.createCarrierMergedConnectionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Factory.Companion.MOBILE_CONNECTION_BUFFER_SIZE
-import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
 import javax.inject.Inject
@@ -183,7 +175,7 @@
     private fun createDemoMobileConnectionRepo(subId: Int): CacheContainer {
         val tableLogBuffer =
             logFactory.getOrCreate(
-                "DemoMobileConnectionLog [$subId]",
+                "DemoMobileConnectionLog[$subId]",
                 MOBILE_CONNECTION_BUFFER_SIZE,
             )
 
@@ -191,6 +183,7 @@
             DemoMobileConnectionRepository(
                 subId,
                 tableLogBuffer,
+                scope,
             )
         return CacheContainer(repo, lastMobileState = null)
     }
@@ -237,23 +230,18 @@
         }
     }
 
-    private fun processEnabledMobileState(state: Mobile) {
+    private fun processEnabledMobileState(event: Mobile) {
         // get or create the connection repo, and set its values
-        val subId = state.subId ?: DEFAULT_SUB_ID
+        val subId = event.subId ?: DEFAULT_SUB_ID
         maybeCreateSubscription(subId)
 
         val connection = getRepoForSubId(subId)
-        connectionRepoCache[subId]?.lastMobileState = state
+        connectionRepoCache[subId]?.lastMobileState = event
 
         // TODO(b/261029387): until we have a command, use the most recent subId
         defaultDataSubId.value = subId
 
-        // This is always true here, because we split out disabled states at the data-source level
-        connection.dataEnabled.value = true
-        connection.networkName.value = NetworkNameModel.IntentDerived(state.name)
-
-        connection.cdmaRoaming.value = state.roaming
-        connection.connectionInfo.value = state.toMobileConnectionModel()
+        connection.processDemoMobileEvent(event, event.dataType.toResolvedNetworkType())
     }
 
     private fun processCarrierMergedWifiState(event: FakeWifiEventModel.CarrierMerged) {
@@ -272,13 +260,7 @@
         defaultDataSubId.value = subId
 
         val connection = getRepoForSubId(subId)
-        // This is always true here, because we split out disabled states at the data-source level
-        connection.dataEnabled.value = true
-        connection.networkName.value = NetworkNameModel.IntentDerived(CARRIER_MERGED_NAME)
-        connection.numberOfLevels.value = event.numberOfLevels
-        connection.cdmaRoaming.value = false
-        connection.connectionInfo.value = event.toMobileConnectionModel()
-        Log.e("CCS", "output connection info = ${connection.connectionInfo.value}")
+        connection.processCarrierMergedEvent(event)
     }
 
     private fun maybeRemoveSubscription(subId: Int?) {
@@ -332,29 +314,6 @@
     private fun subIdsString(): String =
         _subscriptions.value.joinToString(",") { it.subscriptionId.toString() }
 
-    private fun Mobile.toMobileConnectionModel(): MobileConnectionModel {
-        return MobileConnectionModel(
-            isEmergencyOnly = false, // TODO(b/261029387): not yet supported
-            isRoaming = roaming,
-            isInService = (level ?: 0) > 0,
-            isGsm = false, // TODO(b/261029387): not yet supported
-            cdmaLevel = level ?: 0,
-            primaryLevel = level ?: 0,
-            dataConnectionState =
-                DataConnectionState.Connected, // TODO(b/261029387): not yet supported
-            dataActivityDirection = (activity ?: DATA_ACTIVITY_NONE).toMobileDataActivityModel(),
-            carrierNetworkChangeActive = carrierNetworkChange,
-            resolvedNetworkType = dataType.toResolvedNetworkType()
-        )
-    }
-
-    private fun FakeWifiEventModel.CarrierMerged.toMobileConnectionModel(): MobileConnectionModel {
-        return createCarrierMergedConnectionModel(
-            this.level,
-            activity.toMobileDataActivityModel(),
-        )
-    }
-
     private fun SignalIcon.MobileIconGroup?.toResolvedNetworkType(): ResolvedNetworkType {
         val key = mobileMappingsReverseLookup.value[this] ?: "dis"
         return DefaultNetworkType(key)
@@ -364,8 +323,6 @@
         private const val TAG = "DemoMobileConnectionsRepo"
 
         private const val DEFAULT_SUB_ID = 1
-
-        private const val CARRIER_MERGED_NAME = "Carrier Merged Network"
     }
 }
 
@@ -374,18 +331,3 @@
     /** The last received [Mobile] event. Used when switching from carrier merged back to mobile. */
     var lastMobileState: Mobile?,
 )
-
-class DemoMobileConnectionRepository(
-    override val subId: Int,
-    override val tableLogBuffer: TableLogBuffer,
-) : MobileConnectionRepository {
-    override val connectionInfo = MutableStateFlow(MobileConnectionModel())
-
-    override val numberOfLevels = MutableStateFlow(DEFAULT_NUM_LEVELS)
-
-    override val dataEnabled = MutableStateFlow(true)
-
-    override val cdmaRoaming = MutableStateFlow(false)
-
-    override val networkName = MutableStateFlow(NetworkNameModel.IntentDerived("demo network"))
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt
index 8f6a87b..94d6d0b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt
@@ -16,18 +16,17 @@
 
 package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod
 
+import android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN
 import android.telephony.TelephonyManager
 import android.util.Log
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
-import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
 import javax.inject.Inject
@@ -94,16 +93,6 @@
             }
         }
 
-    override val connectionInfo: StateFlow<MobileConnectionModel> =
-        combine(network, wifiRepository.wifiActivity) { network, activity ->
-                if (network == null) {
-                    MobileConnectionModel()
-                } else {
-                    createCarrierMergedConnectionModel(network.level, activity)
-                }
-            }
-            .stateIn(scope, SharingStarted.WhileSubscribed(), MobileConnectionModel())
-
     override val cdmaRoaming: StateFlow<Boolean> = MutableStateFlow(ROAMING).asStateFlow()
 
     override val networkName: StateFlow<NetworkNameModel> =
@@ -129,34 +118,54 @@
             }
             .stateIn(scope, SharingStarted.WhileSubscribed(), DEFAULT_NUM_LEVELS)
 
+    override val primaryLevel =
+        network
+            .map { it?.level ?: SIGNAL_STRENGTH_NONE_OR_UNKNOWN }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
+
+    override val cdmaLevel =
+        network
+            .map { it?.level ?: SIGNAL_STRENGTH_NONE_OR_UNKNOWN }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
+
+    override val dataActivityDirection = wifiRepository.wifiActivity
+
+    override val resolvedNetworkType =
+        network
+            .map {
+                if (it != null) {
+                    ResolvedNetworkType.CarrierMergedNetworkType
+                } else {
+                    ResolvedNetworkType.UnknownNetworkType
+                }
+            }
+            .stateIn(
+                scope,
+                SharingStarted.WhileSubscribed(),
+                ResolvedNetworkType.UnknownNetworkType
+            )
+
+    override val dataConnectionState =
+        network
+            .map {
+                if (it != null) {
+                    DataConnectionState.Connected
+                } else {
+                    DataConnectionState.Disconnected
+                }
+            }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), DataConnectionState.Disconnected)
+
+    override val isRoaming = MutableStateFlow(false).asStateFlow()
+    override val isEmergencyOnly = MutableStateFlow(false).asStateFlow()
+    override val operatorAlphaShort = MutableStateFlow(null).asStateFlow()
+    override val isInService = MutableStateFlow(true).asStateFlow()
+    override val isGsm = MutableStateFlow(false).asStateFlow()
+    override val carrierNetworkChangeActive = MutableStateFlow(false).asStateFlow()
+
     override val dataEnabled: StateFlow<Boolean> = wifiRepository.isWifiEnabled
 
     companion object {
-        /**
-         * Creates an instance of [MobileConnectionModel] that represents a carrier merged network
-         * with the given [level] and [activity].
-         */
-        fun createCarrierMergedConnectionModel(
-            level: Int,
-            activity: DataActivityModel,
-        ): MobileConnectionModel {
-            return MobileConnectionModel(
-                primaryLevel = level,
-                cdmaLevel = level,
-                dataActivityDirection = activity,
-                // Here and below: These values are always the same for every carrier-merged
-                // connection.
-                resolvedNetworkType = ResolvedNetworkType.CarrierMergedNetworkType,
-                dataConnectionState = DataConnectionState.Connected,
-                isRoaming = ROAMING,
-                isEmergencyOnly = false,
-                operatorAlphaShort = null,
-                isInService = true,
-                isGsm = false,
-                carrierNetworkChangeActive = false,
-            )
-        }
-
         // Carrier merged is never roaming
         private const val ROAMING = false
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt
index a39ea0a..b3737ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt
@@ -114,15 +114,147 @@
             .flatMapLatest { it.cdmaRoaming }
             .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.cdmaRoaming.value)
 
-    override val connectionInfo =
+    override val isEmergencyOnly =
         activeRepo
-            .flatMapLatest { it.connectionInfo }
+            .flatMapLatest { it.isEmergencyOnly }
             .logDiffsForTable(
                 tableLogBuffer,
                 columnPrefix = "",
-                initialValue = activeRepo.value.connectionInfo.value,
+                columnName = COL_EMERGENCY,
+                activeRepo.value.isEmergencyOnly.value
             )
-            .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.connectionInfo.value)
+            .stateIn(
+                scope,
+                SharingStarted.WhileSubscribed(),
+                activeRepo.value.isEmergencyOnly.value
+            )
+
+    override val isRoaming =
+        activeRepo
+            .flatMapLatest { it.isRoaming }
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = COL_ROAMING,
+                activeRepo.value.isRoaming.value
+            )
+            .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.isRoaming.value)
+
+    override val operatorAlphaShort =
+        activeRepo
+            .flatMapLatest { it.operatorAlphaShort }
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = COL_OPERATOR,
+                activeRepo.value.operatorAlphaShort.value
+            )
+            .stateIn(
+                scope,
+                SharingStarted.WhileSubscribed(),
+                activeRepo.value.operatorAlphaShort.value
+            )
+
+    override val isInService =
+        activeRepo
+            .flatMapLatest { it.isInService }
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = COL_IS_IN_SERVICE,
+                activeRepo.value.isInService.value
+            )
+            .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.isInService.value)
+
+    override val isGsm =
+        activeRepo
+            .flatMapLatest { it.isGsm }
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = COL_IS_GSM,
+                activeRepo.value.isGsm.value
+            )
+            .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.isGsm.value)
+
+    override val cdmaLevel =
+        activeRepo
+            .flatMapLatest { it.cdmaLevel }
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = COL_CDMA_LEVEL,
+                activeRepo.value.cdmaLevel.value
+            )
+            .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.cdmaLevel.value)
+
+    override val primaryLevel =
+        activeRepo
+            .flatMapLatest { it.primaryLevel }
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = COL_PRIMARY_LEVEL,
+                activeRepo.value.primaryLevel.value
+            )
+            .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.primaryLevel.value)
+
+    override val dataConnectionState =
+        activeRepo
+            .flatMapLatest { it.dataConnectionState }
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                activeRepo.value.dataConnectionState.value
+            )
+            .stateIn(
+                scope,
+                SharingStarted.WhileSubscribed(),
+                activeRepo.value.dataConnectionState.value
+            )
+
+    override val dataActivityDirection =
+        activeRepo
+            .flatMapLatest { it.dataActivityDirection }
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                activeRepo.value.dataActivityDirection.value
+            )
+            .stateIn(
+                scope,
+                SharingStarted.WhileSubscribed(),
+                activeRepo.value.dataActivityDirection.value
+            )
+
+    override val carrierNetworkChangeActive =
+        activeRepo
+            .flatMapLatest { it.carrierNetworkChangeActive }
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = COL_CARRIER_NETWORK_CHANGE,
+                activeRepo.value.carrierNetworkChangeActive.value
+            )
+            .stateIn(
+                scope,
+                SharingStarted.WhileSubscribed(),
+                activeRepo.value.carrierNetworkChangeActive.value
+            )
+
+    override val resolvedNetworkType =
+        activeRepo
+            .flatMapLatest { it.resolvedNetworkType }
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                activeRepo.value.resolvedNetworkType.value
+            )
+            .stateIn(
+                scope,
+                SharingStarted.WhileSubscribed(),
+                activeRepo.value.resolvedNetworkType.value
+            )
 
     override val dataEnabled =
         activeRepo
@@ -187,4 +319,15 @@
             fun tableBufferLogName(subId: Int): String = "MobileConnectionLog[$subId]"
         }
     }
+
+    companion object {
+        const val COL_EMERGENCY = "emergencyOnly"
+        const val COL_ROAMING = "roaming"
+        const val COL_OPERATOR = "operatorName"
+        const val COL_IS_IN_SERVICE = "isInService"
+        const val COL_IS_GSM = "isGsm"
+        const val COL_CDMA_LEVEL = "cdmaLevel"
+        const val COL_PRIMARY_LEVEL = "primaryLevel"
+        const val COL_CARRIER_NETWORK_CHANGE = "carrierNetworkChangeActive"
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
index 96b96f1..f866d65 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
@@ -18,7 +18,7 @@
 
 import android.content.Context
 import android.content.IntentFilter
-import android.telephony.CellSignalStrength
+import android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN
 import android.telephony.CellSignalStrengthCdma
 import android.telephony.ServiceState
 import android.telephony.SignalStrength
@@ -27,16 +27,17 @@
 import android.telephony.TelephonyDisplayInfo
 import android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE
 import android.telephony.TelephonyManager
-import android.telephony.TelephonyManager.ERI_OFF
+import android.telephony.TelephonyManager.ERI_FLASH
+import android.telephony.TelephonyManager.ERI_ON
 import android.telephony.TelephonyManager.EXTRA_SUBSCRIPTION_ID
 import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
 import com.android.settingslib.Utils
 import com.android.systemui.broadcast.BroadcastDispatcher
-import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
+import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
+import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState.Disconnected
 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.OverrideNetworkType
@@ -47,8 +48,8 @@
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.CarrierConfigRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
-import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
 import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
+import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
 import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
@@ -57,16 +58,14 @@
 import kotlinx.coroutines.asExecutor
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableSharedFlow
-import kotlinx.coroutines.flow.SharedFlow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.callbackFlow
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.mapLatest
 import kotlinx.coroutines.flow.mapNotNull
 import kotlinx.coroutines.flow.scan
-import kotlinx.coroutines.flow.shareIn
 import kotlinx.coroutines.flow.stateIn
 
 /**
@@ -98,8 +97,6 @@
         }
     }
 
-    private val telephonyCallbackEvent = MutableSharedFlow<Unit>(extraBufferCapacity = 1)
-
     /**
      * This flow defines the single shared connection to system_server via TelephonyCallback. Any
      * new callback should be added to this listener and funneled through callbackEvents via a data
@@ -107,9 +104,15 @@
      *
      * The reason we need to do this is because TelephonyManager limits the number of registered
      * listeners per-process, so we don't want to create a new listener for every callback.
+     *
+     * A note on the design for back pressure here: We use the [coalesce] operator here to change
+     * the backpressure strategy to store exactly the last callback event of _each type_ here, as
+     * opposed to the default strategy which is to drop the oldest event (regardless of type). This
+     * means that we should never miss any single event as long as the flow has been started.
      */
-    private val callbackEvents: SharedFlow<CallbackEvent> =
-        conflatedCallbackFlow {
+    private val callbackEvents: StateFlow<TelephonyCallbackState> = run {
+        val initial = TelephonyCallbackState()
+        callbackFlow {
                 val callback =
                     object :
                         TelephonyCallback(),
@@ -163,86 +166,103 @@
                 telephonyManager.registerTelephonyCallback(bgDispatcher.asExecutor(), callback)
                 awaitClose { telephonyManager.unregisterTelephonyCallback(callback) }
             }
-            .shareIn(scope, SharingStarted.WhileSubscribed())
-
-    private fun updateConnectionState(
-        prevState: MobileConnectionModel,
-        callbackEvent: CallbackEvent,
-    ): MobileConnectionModel =
-        when (callbackEvent) {
-            is CallbackEvent.OnServiceStateChanged -> {
-                val serviceState = callbackEvent.serviceState
-                prevState.copy(
-                    isEmergencyOnly = serviceState.isEmergencyOnly,
-                    isRoaming = serviceState.roaming,
-                    operatorAlphaShort = serviceState.operatorAlphaShort,
-                    isInService = Utils.isInService(serviceState),
-                )
-            }
-            is CallbackEvent.OnSignalStrengthChanged -> {
-                val signalStrength = callbackEvent.signalStrength
-                val cdmaLevel =
-                    signalStrength.getCellSignalStrengths(CellSignalStrengthCdma::class.java).let {
-                        strengths ->
-                        if (!strengths.isEmpty()) {
-                            strengths[0].level
-                        } else {
-                            CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN
-                        }
-                    }
-
-                val primaryLevel = signalStrength.level
-
-                prevState.copy(
-                    cdmaLevel = cdmaLevel,
-                    primaryLevel = primaryLevel,
-                    isGsm = signalStrength.isGsm,
-                )
-            }
-            is CallbackEvent.OnDataConnectionStateChanged -> {
-                prevState.copy(dataConnectionState = callbackEvent.dataState.toDataConnectionType())
-            }
-            is CallbackEvent.OnDataActivity -> {
-                prevState.copy(
-                    dataActivityDirection = callbackEvent.direction.toMobileDataActivityModel()
-                )
-            }
-            is CallbackEvent.OnCarrierNetworkChange -> {
-                prevState.copy(carrierNetworkChangeActive = callbackEvent.active)
-            }
-            is CallbackEvent.OnDisplayInfoChanged -> {
-                val telephonyDisplayInfo = callbackEvent.telephonyDisplayInfo
-                val networkType =
-                    if (telephonyDisplayInfo.networkType == NETWORK_TYPE_UNKNOWN) {
-                        UnknownNetworkType
-                    } else if (
-                        telephonyDisplayInfo.overrideNetworkType == OVERRIDE_NETWORK_TYPE_NONE
-                    ) {
-                        DefaultNetworkType(
-                            mobileMappingsProxy.toIconKey(telephonyDisplayInfo.networkType)
-                        )
-                    } else {
-                        OverrideNetworkType(
-                            mobileMappingsProxy.toIconKeyOverride(
-                                telephonyDisplayInfo.overrideNetworkType
-                            )
-                        )
-                    }
-                prevState.copy(resolvedNetworkType = networkType)
-            }
-            is CallbackEvent.OnDataEnabledChanged -> {
-                // Not part of this object, handled in a separate flow
-                prevState
-            }
-        }
-
-    override val connectionInfo = run {
-        val initial = MobileConnectionModel()
-        callbackEvents
-            .scan(initial, ::updateConnectionState)
-            .stateIn(scope, SharingStarted.WhileSubscribed(), initial)
+            .scan(initial = initial) { state, event -> state.applyEvent(event) }
+            .stateIn(scope = scope, started = SharingStarted.WhileSubscribed(), initial)
     }
 
+    override val isEmergencyOnly =
+        callbackEvents
+            .mapNotNull { it.onServiceStateChanged }
+            .map { it.serviceState.isEmergencyOnly }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+
+    override val isRoaming =
+        callbackEvents
+            .mapNotNull { it.onServiceStateChanged }
+            .map { it.serviceState.roaming }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+
+    override val operatorAlphaShort =
+        callbackEvents
+            .mapNotNull { it.onServiceStateChanged }
+            .map { it.serviceState.operatorAlphaShort }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), null)
+
+    override val isInService =
+        callbackEvents
+            .mapNotNull { it.onServiceStateChanged }
+            .map { Utils.isInService(it.serviceState) }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+
+    override val isGsm =
+        callbackEvents
+            .mapNotNull { it.onSignalStrengthChanged }
+            .map { it.signalStrength.isGsm }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+
+    override val cdmaLevel =
+        callbackEvents
+            .mapNotNull { it.onSignalStrengthChanged }
+            .map {
+                it.signalStrength.getCellSignalStrengths(CellSignalStrengthCdma::class.java).let {
+                    strengths ->
+                    if (strengths.isNotEmpty()) {
+                        strengths[0].level
+                    } else {
+                        SIGNAL_STRENGTH_NONE_OR_UNKNOWN
+                    }
+                }
+            }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
+
+    override val primaryLevel =
+        callbackEvents
+            .mapNotNull { it.onSignalStrengthChanged }
+            .map { it.signalStrength.level }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
+
+    override val dataConnectionState =
+        callbackEvents
+            .mapNotNull { it.onDataConnectionStateChanged }
+            .map { it.dataState.toDataConnectionType() }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), Disconnected)
+
+    override val dataActivityDirection =
+        callbackEvents
+            .mapNotNull { it.onDataActivity }
+            .map { it.direction.toMobileDataActivityModel() }
+            .stateIn(
+                scope,
+                SharingStarted.WhileSubscribed(),
+                DataActivityModel(hasActivityIn = false, hasActivityOut = false)
+            )
+
+    override val carrierNetworkChangeActive =
+        callbackEvents
+            .mapNotNull { it.onCarrierNetworkChange }
+            .map { it.active }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+
+    override val resolvedNetworkType =
+        callbackEvents
+            .mapNotNull { it.onDisplayInfoChanged }
+            .map {
+                if (it.telephonyDisplayInfo.overrideNetworkType != OVERRIDE_NETWORK_TYPE_NONE) {
+                    OverrideNetworkType(
+                        mobileMappingsProxy.toIconKeyOverride(
+                            it.telephonyDisplayInfo.overrideNetworkType
+                        )
+                    )
+                } else if (it.telephonyDisplayInfo.networkType != NETWORK_TYPE_UNKNOWN) {
+                    DefaultNetworkType(
+                        mobileMappingsProxy.toIconKey(it.telephonyDisplayInfo.networkType)
+                    )
+                } else {
+                    UnknownNetworkType
+                }
+            }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), UnknownNetworkType)
+
     override val numberOfLevels =
         systemUiCarrierConfig.shouldInflateSignalStrength
             .map { shouldInflate ->
@@ -263,7 +283,10 @@
 
     override val cdmaRoaming: StateFlow<Boolean> =
         telephonyPollingEvent
-            .mapLatest { telephonyManager.cdmaEnhancedRoamingIndicatorDisplayNumber != ERI_OFF }
+            .mapLatest {
+                val cdmaEri = telephonyManager.cdmaEnhancedRoamingIndicatorDisplayNumber
+                cdmaEri == ERI_ON || cdmaEri == ERI_FLASH
+            }
             .stateIn(scope, SharingStarted.WhileSubscribed(), false)
 
     override val networkName: StateFlow<NetworkNameModel> =
@@ -281,7 +304,8 @@
     override val dataEnabled = run {
         val initial = telephonyManager.isDataConnectionAllowed
         callbackEvents
-            .mapNotNull { (it as? CallbackEvent.OnDataEnabledChanged)?.enabled }
+            .mapNotNull { it.onDataEnabledChanged }
+            .map { it.enabled }
             .stateIn(scope, SharingStarted.WhileSubscribed(), initial)
     }
 
@@ -325,12 +349,41 @@
  * Wrap every [TelephonyCallback] we care about in a data class so we can accept them in a single
  * shared flow and then split them back out into other flows.
  */
-private sealed interface CallbackEvent {
+sealed interface CallbackEvent {
+    data class OnCarrierNetworkChange(val active: Boolean) : CallbackEvent
+    data class OnDataActivity(val direction: Int) : CallbackEvent
+    data class OnDataConnectionStateChanged(val dataState: Int) : CallbackEvent
+    data class OnDataEnabledChanged(val enabled: Boolean) : CallbackEvent
+    data class OnDisplayInfoChanged(val telephonyDisplayInfo: TelephonyDisplayInfo) : CallbackEvent
     data class OnServiceStateChanged(val serviceState: ServiceState) : CallbackEvent
     data class OnSignalStrengthChanged(val signalStrength: SignalStrength) : CallbackEvent
-    data class OnDataConnectionStateChanged(val dataState: Int) : CallbackEvent
-    data class OnDataActivity(val direction: Int) : CallbackEvent
-    data class OnCarrierNetworkChange(val active: Boolean) : CallbackEvent
-    data class OnDisplayInfoChanged(val telephonyDisplayInfo: TelephonyDisplayInfo) : CallbackEvent
-    data class OnDataEnabledChanged(val enabled: Boolean) : CallbackEvent
+}
+
+/**
+ * A simple box type for 1-to-1 mapping of [CallbackEvent] to the batched event. Used in conjunction
+ * with [scan] to make sure we don't drop important callbacks due to late subscribers
+ */
+data class TelephonyCallbackState(
+    val onDataActivity: CallbackEvent.OnDataActivity? = null,
+    val onCarrierNetworkChange: CallbackEvent.OnCarrierNetworkChange? = null,
+    val onDataConnectionStateChanged: CallbackEvent.OnDataConnectionStateChanged? = null,
+    val onDataEnabledChanged: CallbackEvent.OnDataEnabledChanged? = null,
+    val onDisplayInfoChanged: CallbackEvent.OnDisplayInfoChanged? = null,
+    val onServiceStateChanged: CallbackEvent.OnServiceStateChanged? = null,
+    val onSignalStrengthChanged: CallbackEvent.OnSignalStrengthChanged? = null,
+) {
+    fun applyEvent(event: CallbackEvent): TelephonyCallbackState {
+        return when (event) {
+            is CallbackEvent.OnCarrierNetworkChange -> copy(onCarrierNetworkChange = event)
+            is CallbackEvent.OnDataActivity -> copy(onDataActivity = event)
+            is CallbackEvent.OnDataConnectionStateChanged ->
+                copy(onDataConnectionStateChanged = event)
+            is CallbackEvent.OnDataEnabledChanged -> copy(onDataEnabledChanged = event)
+            is CallbackEvent.OnDisplayInfoChanged -> copy(onDisplayInfoChanged = event)
+            is CallbackEvent.OnServiceStateChanged -> {
+                copy(onServiceStateChanged = event)
+            }
+            is CallbackEvent.OnSignalStrengthChanged -> copy(onSignalStrengthChanged = event)
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
index b3d5b1e..b7da3f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
@@ -45,11 +45,11 @@
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.log.table.logDiffsForTable
 import com.android.systemui.statusbar.pipeline.dagger.MobileSummaryLog
+import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
 import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
-import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
 import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
@@ -266,6 +266,7 @@
                 val callback =
                     object : NetworkCallback(FLAG_INCLUDE_LOCATION_INFO) {
                         override fun onLost(network: Network) {
+                            logger.logOnLost(network, isDefaultNetworkCallback = true)
                             // Send a disconnected model when lost. Maybe should create a sealed
                             // type or null here?
                             trySend(MobileConnectivityModel())
@@ -275,6 +276,11 @@
                             network: Network,
                             caps: NetworkCapabilities
                         ) {
+                            logger.logOnCapabilitiesChanged(
+                                network,
+                                caps,
+                                isDefaultNetworkCallback = true,
+                            )
                             trySend(
                                 MobileConnectivityModel(
                                     isConnected = caps.hasTransport(TRANSPORT_CELLULAR),
@@ -353,8 +359,8 @@
      * True if the checked subId is in the list of current subs or the active mobile data subId
      *
      * @param checkedSubs the list to validate [subId] against. To invalidate the cache, pass in the
-     * new subscription list. Otherwise use [subscriptions.value] to validate a subId against the
-     * current known subscriptions
+     *   new subscription list. Otherwise use [subscriptions.value] to validate a subId against the
+     *   current known subscriptions
      */
     private fun checkSub(subId: Int, checkedSubs: List<SubscriptionModel>): Boolean {
         if (activeMobileDataSubscriptionId.value == subId) return true
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
index 7b0f952..7df6764 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
@@ -34,6 +34,7 @@
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.mapLatest
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.stateIn
@@ -92,7 +93,8 @@
      * 1. The default network name, if one is configured
      * 2. A derived name based off of the intent [ACTION_SERVICE_PROVIDERS_UPDATED]
      * 3. Or, in the case where the repository sends us the default network name, we check for an
-     * override in [connectionInfo.operatorAlphaShort], a value that is derived from [ServiceState]
+     *    override in [connectionInfo.operatorAlphaShort], a value that is derived from
+     *    [ServiceState]
      */
     val networkName: StateFlow<NetworkNameModel>
 
@@ -132,11 +134,9 @@
     override val isForceHidden: Flow<Boolean>,
     connectionRepository: MobileConnectionRepository,
 ) : MobileIconInteractor {
-    private val connectionInfo = connectionRepository.connectionInfo
-
     override val tableLogBuffer: TableLogBuffer = connectionRepository.tableLogBuffer
 
-    override val activity = connectionInfo.mapLatest { it.dataActivityDirection }
+    override val activity = connectionRepository.dataActivityDirection
 
     override val isConnected: Flow<Boolean> = defaultMobileConnectivity.mapLatest { it.isConnected }
 
@@ -154,11 +154,11 @@
     override val isDefaultDataEnabled = defaultSubscriptionHasDataEnabled
 
     override val networkName =
-        combine(connectionInfo, connectionRepository.networkName) { connection, networkName ->
-                if (
-                    networkName is NetworkNameModel.Default && connection.operatorAlphaShort != null
-                ) {
-                    NetworkNameModel.IntentDerived(connection.operatorAlphaShort)
+        combine(connectionRepository.operatorAlphaShort, connectionRepository.networkName) {
+                operatorAlphaShort,
+                networkName ->
+                if (networkName is NetworkNameModel.Default && operatorAlphaShort != null) {
+                    NetworkNameModel.IntentDerived(operatorAlphaShort)
                 } else {
                     networkName
                 }
@@ -172,19 +172,19 @@
     /** Observable for the current RAT indicator icon ([MobileIconGroup]) */
     override val networkTypeIconGroup: StateFlow<MobileIconGroup> =
         combine(
-                connectionInfo,
+                connectionRepository.resolvedNetworkType,
                 defaultMobileIconMapping,
                 defaultMobileIconGroup,
                 isDefault,
-            ) { info, mapping, defaultGroup, isDefault ->
+            ) { resolvedNetworkType, mapping, defaultGroup, isDefault ->
                 if (!isDefault) {
                     return@combine NOT_DEFAULT_DATA
                 }
 
-                when (info.resolvedNetworkType) {
+                when (resolvedNetworkType) {
                     is ResolvedNetworkType.CarrierMergedNetworkType ->
-                        info.resolvedNetworkType.iconGroupOverride
-                    else -> mapping[info.resolvedNetworkType.lookupKey] ?: defaultGroup
+                        resolvedNetworkType.iconGroupOverride
+                    else -> mapping[resolvedNetworkType.lookupKey] ?: defaultGroup
                 }
             }
             .distinctUntilChanged()
@@ -199,17 +199,19 @@
             }
             .stateIn(scope, SharingStarted.WhileSubscribed(), defaultMobileIconGroup.value)
 
-    override val isEmergencyOnly: StateFlow<Boolean> =
-        connectionInfo
-            .mapLatest { it.isEmergencyOnly }
-            .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+    override val isEmergencyOnly = connectionRepository.isEmergencyOnly
 
     override val isRoaming: StateFlow<Boolean> =
-        combine(connectionInfo, connectionRepository.cdmaRoaming) { connection, cdmaRoaming ->
-                if (connection.carrierNetworkChangeActive) {
+        combine(
+                connectionRepository.carrierNetworkChangeActive,
+                connectionRepository.isGsm,
+                connectionRepository.isRoaming,
+                connectionRepository.cdmaRoaming,
+            ) { carrierNetworkChangeActive, isGsm, isRoaming, cdmaRoaming ->
+                if (carrierNetworkChangeActive) {
                     false
-                } else if (connection.isGsm) {
-                    connection.isRoaming
+                } else if (isGsm) {
+                    isRoaming
                 } else {
                     cdmaRoaming
                 }
@@ -217,12 +219,17 @@
             .stateIn(scope, SharingStarted.WhileSubscribed(), false)
 
     override val level: StateFlow<Int> =
-        combine(connectionInfo, alwaysUseCdmaLevel) { connection, alwaysUseCdmaLevel ->
+        combine(
+                connectionRepository.isGsm,
+                connectionRepository.primaryLevel,
+                connectionRepository.cdmaLevel,
+                alwaysUseCdmaLevel,
+            ) { isGsm, primaryLevel, cdmaLevel, alwaysUseCdmaLevel ->
                 when {
                     // GSM connections should never use the CDMA level
-                    connection.isGsm -> connection.primaryLevel
-                    alwaysUseCdmaLevel -> connection.cdmaLevel
-                    else -> connection.primaryLevel
+                    isGsm -> primaryLevel
+                    alwaysUseCdmaLevel -> cdmaLevel
+                    else -> primaryLevel
                 }
             }
             .stateIn(scope, SharingStarted.WhileSubscribed(), 0)
@@ -235,12 +242,9 @@
         )
 
     override val isDataConnected: StateFlow<Boolean> =
-        connectionInfo
-            .mapLatest { connection -> connection.dataConnectionState == Connected }
+        connectionRepository.dataConnectionState
+            .map { it == Connected }
             .stateIn(scope, SharingStarted.WhileSubscribed(), false)
 
-    override val isInService =
-        connectionRepository.connectionInfo
-            .mapLatest { it.isInService }
-            .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+    override val isInService = connectionRepository.isInService
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt
index da63ab1..075e6ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt
@@ -22,7 +22,6 @@
 import com.android.systemui.statusbar.phone.StatusBarIconController
 import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
-import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel
 import java.io.PrintWriter
 import javax.inject.Inject
@@ -55,17 +54,14 @@
     interactor: MobileIconsInteractor,
     private val iconController: StatusBarIconController,
     private val iconsViewModelFactory: MobileIconsViewModel.Factory,
-    private val logger: MobileInputLogger,
+    private val logger: MobileViewLogger,
     @Application private val scope: CoroutineScope,
     private val statusBarPipelineFlags: StatusBarPipelineFlags,
 ) : CoreStartable {
     private val mobileSubIds: Flow<List<Int>> =
-        interactor.filteredSubscriptions
-            .mapLatest { subscriptions ->
-                subscriptions.map { subscriptionModel -> subscriptionModel.subscriptionId }
-            }
-            .distinctUntilChanged()
-            .onEach { logger.logUiAdapterSubIdsUpdated(it) }
+        interactor.filteredSubscriptions.mapLatest { subscriptions ->
+            subscriptions.map { subscriptionModel -> subscriptionModel.subscriptionId }
+        }
 
     /**
      * We expose the list of tracked subscriptions as a flow of a list of ints, where each int is
@@ -75,7 +71,10 @@
      * NOTE: this should go away as the view presenter learns more about this data pipeline
      */
     private val mobileSubIdsState: StateFlow<List<Int>> =
-        mobileSubIds.stateIn(scope, SharingStarted.WhileSubscribed(), listOf())
+        mobileSubIds
+            .distinctUntilChanged()
+            .onEach { logger.logUiAdapterSubIdsUpdated(it) }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), listOf())
 
     /** In order to keep the logs tame, we will reuse the same top-level mobile icons view model */
     val mobileIconsViewModel = iconsViewModelFactory.create(mobileSubIdsState)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLogger.kt
new file mode 100644
index 0000000..90dff23
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLogger.kt
@@ -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.systemui.statusbar.pipeline.mobile.ui
+
+import android.view.View
+import com.android.systemui.Dumpable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.statusbar.pipeline.dagger.MobileViewLog
+import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.LocationBasedMobileViewModel
+import java.io.PrintWriter
+import javax.inject.Inject
+
+/** Logs for changes with the new mobile views. */
+@SysUISingleton
+class MobileViewLogger
+@Inject
+constructor(
+    @MobileViewLog private val buffer: LogBuffer,
+    dumpManager: DumpManager,
+) : Dumpable {
+    init {
+        dumpManager.registerNormalDumpable(this)
+    }
+
+    private val collectionStatuses = mutableMapOf<String, Boolean>()
+
+    fun logUiAdapterSubIdsUpdated(subs: List<Int>) {
+        buffer.log(
+            TAG,
+            LogLevel.INFO,
+            { str1 = subs.toString() },
+            { "Sub IDs in MobileUiAdapter updated internally: $str1" },
+        )
+    }
+
+    fun logUiAdapterSubIdsSentToIconController(subs: List<Int>) {
+        buffer.log(
+            TAG,
+            LogLevel.INFO,
+            { str1 = subs.toString() },
+            { "Sub IDs in MobileUiAdapter being sent to icon controller: $str1" },
+        )
+    }
+
+    fun logNewViewBinding(view: View, viewModel: LocationBasedMobileViewModel) {
+        buffer.log(
+            TAG,
+            LogLevel.INFO,
+            {
+                str1 = view.getIdForLogging()
+                str2 = viewModel.getIdForLogging()
+                str3 = viewModel.locationName
+            },
+            { "New view binding. viewId=$str1, viewModelId=$str2, viewModelLocation=$str3" },
+        )
+    }
+
+    fun logCollectionStarted(view: View, viewModel: LocationBasedMobileViewModel) {
+        collectionStatuses[view.getIdForLogging()] = true
+        buffer.log(
+            TAG,
+            LogLevel.INFO,
+            {
+                str1 = view.getIdForLogging()
+                str2 = viewModel.getIdForLogging()
+                str3 = viewModel.locationName
+            },
+            { "Collection started. viewId=$str1, viewModelId=$str2, viewModelLocation=$str3" },
+        )
+    }
+
+    fun logCollectionStopped(view: View, viewModel: LocationBasedMobileViewModel) {
+        collectionStatuses[view.getIdForLogging()] = false
+        buffer.log(
+            TAG,
+            LogLevel.INFO,
+            {
+                str1 = view.getIdForLogging()
+                str2 = viewModel.getIdForLogging()
+                str3 = viewModel.locationName
+            },
+            { "Collection stopped. viewId=$str1, viewModelId=$str2, viewModelLocation=$str3" },
+        )
+    }
+
+    override fun dump(pw: PrintWriter, args: Array<out String>) {
+        pw.println("Collection statuses per view:---")
+        collectionStatuses.forEach { viewId, isCollecting ->
+            pw.println("viewId=$viewId, isCollecting=$isCollecting")
+        }
+    }
+
+    companion object {
+        fun Any.getIdForLogging(): String {
+            // The identityHashCode is guaranteed to be constant for the lifetime of the object.
+            return Integer.toHexString(System.identityHashCode(this))
+        }
+    }
+}
+
+private const val TAG = "MobileViewLogger"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/VerboseMobileViewLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/VerboseMobileViewLogger.kt
new file mode 100644
index 0000000..f67bc8f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/VerboseMobileViewLogger.kt
@@ -0,0 +1,76 @@
+/*
+ * 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.pipeline.mobile.ui
+
+import android.view.View
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.statusbar.pipeline.dagger.VerboseMobileViewLog
+import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger.Companion.getIdForLogging
+import com.android.systemui.statusbar.pipeline.mobile.ui.model.SignalIconModel
+import javax.inject.Inject
+
+/**
+ * Logs for **verbose** changes with the new mobile views.
+ *
+ * This is a hopefully temporary log until we resolve some open bugs (b/267236367, b/269565345,
+ * b/270300839).
+ */
+@SysUISingleton
+class VerboseMobileViewLogger
+@Inject
+constructor(
+    @VerboseMobileViewLog private val buffer: LogBuffer,
+) {
+    fun logBinderReceivedSignalIcon(parentView: View, subId: Int, icon: SignalIconModel) {
+        buffer.log(
+            TAG,
+            LogLevel.VERBOSE,
+            {
+                str1 = parentView.getIdForLogging()
+                int1 = subId
+                int2 = icon.level
+                bool1 = icon.showExclamationMark
+            },
+            {
+                "Binder[subId=$int1, viewId=$str1] received new signal icon: " +
+                    "level=$int2 showExclamation=$bool1"
+            },
+        )
+    }
+
+    fun logBinderReceivedNetworkTypeIcon(parentView: View, subId: Int, icon: Icon.Resource?) {
+        buffer.log(
+            TAG,
+            LogLevel.VERBOSE,
+            {
+                str1 = parentView.getIdForLogging()
+                int1 = subId
+                bool1 = icon != null
+                int2 = icon?.res ?: -1
+            },
+            {
+                "Binder[subId=$int1, viewId=$str1] received new network type icon: " +
+                    if (bool1) "resId=$int2" else "null"
+            },
+        )
+    }
+}
+
+private const val TAG = "VerboseMobileViewLogger"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconBinder.kt
index db585e6..5b7d45b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconBinder.kt
@@ -36,8 +36,10 @@
 import com.android.systemui.statusbar.StatusBarIconView.STATE_DOT
 import com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN
 import com.android.systemui.statusbar.StatusBarIconView.STATE_ICON
+import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger
 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.LocationBasedMobileViewModel
 import com.android.systemui.statusbar.pipeline.shared.ui.binder.ModernStatusBarViewBinding
+import kotlinx.coroutines.awaitCancellation
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.launch
@@ -48,6 +50,7 @@
     fun bind(
         view: ViewGroup,
         viewModel: LocationBasedMobileViewModel,
+        logger: MobileViewLogger,
     ): ModernStatusBarViewBinding {
         val mobileGroupView = view.requireViewById<ViewGroup>(R.id.mobile_group)
         val activityContainer = view.requireViewById<View>(R.id.inout_container)
@@ -70,8 +73,13 @@
         val iconTint: MutableStateFlow<Int> = MutableStateFlow(viewModel.defaultColor)
         val decorTint: MutableStateFlow<Int> = MutableStateFlow(viewModel.defaultColor)
 
+        var isCollecting: Boolean = false
+
         view.repeatWhenAttached {
             repeatOnLifecycle(Lifecycle.State.STARTED) {
+                logger.logCollectionStarted(view, viewModel)
+                isCollecting = true
+
                 launch {
                     visibilityState.collect { state ->
                         when (state) {
@@ -96,6 +104,11 @@
                 // Set the icon for the triangle
                 launch {
                     viewModel.icon.distinctUntilChanged().collect { icon ->
+                        viewModel.verboseLogger?.logBinderReceivedSignalIcon(
+                            view,
+                            viewModel.subscriptionId,
+                            icon,
+                        )
                         mobileDrawable.level =
                             SignalDrawable.getState(
                                 icon.level,
@@ -114,6 +127,11 @@
                 // Set the network type icon
                 launch {
                     viewModel.networkTypeIcon.distinctUntilChanged().collect { dataTypeId ->
+                        viewModel.verboseLogger?.logBinderReceivedNetworkTypeIcon(
+                            view,
+                            viewModel.subscriptionId,
+                            dataTypeId,
+                        )
                         dataTypeId?.let { IconViewBinder.bind(dataTypeId, networkTypeView) }
                         networkTypeView.visibility = if (dataTypeId != null) VISIBLE else GONE
                     }
@@ -150,6 +168,13 @@
                 }
 
                 launch { decorTint.collect { tint -> dotView.setDecorColor(tint) } }
+
+                try {
+                    awaitCancellation()
+                } finally {
+                    isCollecting = false
+                    logger.logCollectionStopped(view, viewModel)
+                }
             }
         }
 
@@ -175,6 +200,10 @@
                 }
                 decorTint.value = newTint
             }
+
+            override fun isCollecting(): Boolean {
+                return isCollecting
+            }
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileView.kt
index ed9a188..4144293d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileView.kt
@@ -20,6 +20,8 @@
 import android.util.AttributeSet
 import android.view.LayoutInflater
 import com.android.systemui.R
+import com.android.systemui.statusbar.StatusBarIconView.getVisibleStateString
+import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger
 import com.android.systemui.statusbar.pipeline.mobile.ui.binder.MobileIconBinder
 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.LocationBasedMobileViewModel
 import com.android.systemui.statusbar.pipeline.shared.ui.view.ModernStatusBarView
@@ -31,6 +33,15 @@
 
     var subId: Int = -1
 
+    override fun toString(): String {
+        return "ModernStatusBarMobileView(" +
+            "slot='$slot', " +
+            "subId=$subId, " +
+            "isCollecting=${binding.isCollecting()}, " +
+            "visibleState=${getVisibleStateString(visibleState)}); " +
+            "viewString=${super.toString()}"
+    }
+
     companion object {
 
         /**
@@ -40,6 +51,7 @@
         @JvmStatic
         fun constructAndBind(
             context: Context,
+            logger: MobileViewLogger,
             slot: String,
             viewModel: LocationBasedMobileViewModel,
         ): ModernStatusBarMobileView {
@@ -48,7 +60,8 @@
                     as ModernStatusBarMobileView)
                 .also {
                     it.subId = viewModel.subscriptionId
-                    it.initView(slot) { MobileIconBinder.bind(it, viewModel) }
+                    it.initView(slot) { MobileIconBinder.bind(it, viewModel, logger) }
+                    logger.logNewViewBinding(it, viewModel)
                 }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileViewModel.kt
index 24cd930..f775940 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileViewModel.kt
@@ -19,18 +19,23 @@
 import android.graphics.Color
 import com.android.systemui.statusbar.phone.StatusBarLocation
 import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
+import com.android.systemui.statusbar.pipeline.mobile.ui.VerboseMobileViewLogger
 
 /**
  * A view model for an individual mobile icon that embeds the notion of a [StatusBarLocation]. This
  * allows the mobile icon to change some view parameters at different locations
  *
  * @param commonImpl for convenience, this class wraps a base interface that can provides all of the
- * common implementations between locations. See [MobileIconViewModel]
+ *   common implementations between locations. See [MobileIconViewModel]
+ * @property locationName the name of the location of this VM, used for logging.
+ * @property verboseLogger an optional logger to log extremely verbose view updates.
  */
 abstract class LocationBasedMobileViewModel(
     val commonImpl: MobileIconViewModelCommon,
     statusBarPipelineFlags: StatusBarPipelineFlags,
     debugTint: Int,
+    val locationName: String,
+    val verboseLogger: VerboseMobileViewLogger?,
 ) : MobileIconViewModelCommon by commonImpl {
     val useDebugColoring: Boolean = statusBarPipelineFlags.useDebugColoring()
 
@@ -45,11 +50,16 @@
         fun viewModelForLocation(
             commonImpl: MobileIconViewModelCommon,
             statusBarPipelineFlags: StatusBarPipelineFlags,
+            verboseMobileViewLogger: VerboseMobileViewLogger,
             loc: StatusBarLocation,
         ): LocationBasedMobileViewModel =
             when (loc) {
                 StatusBarLocation.HOME ->
-                    HomeMobileIconViewModel(commonImpl, statusBarPipelineFlags)
+                    HomeMobileIconViewModel(
+                        commonImpl,
+                        statusBarPipelineFlags,
+                        verboseMobileViewLogger,
+                    )
                 StatusBarLocation.KEYGUARD ->
                     KeyguardMobileIconViewModel(commonImpl, statusBarPipelineFlags)
                 StatusBarLocation.QS -> QsMobileIconViewModel(commonImpl, statusBarPipelineFlags)
@@ -60,20 +70,41 @@
 class HomeMobileIconViewModel(
     commonImpl: MobileIconViewModelCommon,
     statusBarPipelineFlags: StatusBarPipelineFlags,
+    verboseMobileViewLogger: VerboseMobileViewLogger,
 ) :
     MobileIconViewModelCommon,
-    LocationBasedMobileViewModel(commonImpl, statusBarPipelineFlags, debugTint = Color.CYAN)
+    LocationBasedMobileViewModel(
+        commonImpl,
+        statusBarPipelineFlags,
+        debugTint = Color.CYAN,
+        locationName = "Home",
+        verboseMobileViewLogger,
+    )
 
 class QsMobileIconViewModel(
     commonImpl: MobileIconViewModelCommon,
     statusBarPipelineFlags: StatusBarPipelineFlags,
 ) :
     MobileIconViewModelCommon,
-    LocationBasedMobileViewModel(commonImpl, statusBarPipelineFlags, debugTint = Color.GREEN)
+    LocationBasedMobileViewModel(
+        commonImpl,
+        statusBarPipelineFlags,
+        debugTint = Color.GREEN,
+        locationName = "QS",
+        // Only do verbose logging for the Home location.
+        verboseLogger = null,
+    )
 
 class KeyguardMobileIconViewModel(
     commonImpl: MobileIconViewModelCommon,
     statusBarPipelineFlags: StatusBarPipelineFlags,
 ) :
     MobileIconViewModelCommon,
-    LocationBasedMobileViewModel(commonImpl, statusBarPipelineFlags, debugTint = Color.MAGENTA)
+    LocationBasedMobileViewModel(
+        commonImpl,
+        statusBarPipelineFlags,
+        debugTint = Color.MAGENTA,
+        locationName = "Keyguard",
+        // Only do verbose logging for the Home location.
+        verboseLogger = null,
+    )
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt
index 0496278..dbb534b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt
@@ -49,7 +49,7 @@
     val contentDescription: Flow<ContentDescription>
     val roaming: Flow<Boolean>
     /** The RAT icon (LTE, 3G, 5G, etc) to be displayed. Null if we shouldn't show anything */
-    val networkTypeIcon: Flow<Icon?>
+    val networkTypeIcon: Flow<Icon.Resource?>
     val activityInVisible: Flow<Boolean>
     val activityOutVisible: Flow<Boolean>
     val activityContainerVisible: Flow<Boolean>
@@ -161,7 +161,7 @@
             )
             .stateIn(scope, SharingStarted.WhileSubscribed(), false)
 
-    override val networkTypeIcon: Flow<Icon?> =
+    override val networkTypeIcon: Flow<Icon.Resource?> =
         combine(
                 iconInteractor.networkTypeIconGroup,
                 showNetworkTypeIcon,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt
index 8cb52af..2b90065 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt
@@ -23,6 +23,8 @@
 import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
 import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
+import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger
+import com.android.systemui.statusbar.pipeline.mobile.ui.VerboseMobileViewLogger
 import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
 import javax.inject.Inject
@@ -39,6 +41,8 @@
 @Inject
 constructor(
     val subscriptionIdsFlow: StateFlow<List<Int>>,
+    val logger: MobileViewLogger,
+    private val verboseLogger: VerboseMobileViewLogger,
     private val interactor: MobileIconsInteractor,
     private val airplaneModeInteractor: AirplaneModeInteractor,
     private val constants: ConnectivityConstants,
@@ -66,6 +70,7 @@
         return LocationBasedMobileViewModel.viewModelForLocation(
             common,
             statusBarPipelineFlags,
+            verboseLogger,
             location,
         )
     }
@@ -79,6 +84,8 @@
     class Factory
     @Inject
     constructor(
+        private val logger: MobileViewLogger,
+        private val verboseLogger: VerboseMobileViewLogger,
         private val interactor: MobileIconsInteractor,
         private val airplaneModeInteractor: AirplaneModeInteractor,
         private val constants: ConnectivityConstants,
@@ -88,6 +95,8 @@
         fun create(subscriptionIdsFlow: StateFlow<List<Int>>): MobileIconsViewModel {
             return MobileIconsViewModel(
                 subscriptionIdsFlow,
+                logger,
+                verboseLogger,
                 interactor,
                 airplaneModeInteractor,
                 constants,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/LoggerHelper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/LoggerHelper.kt
index 6f29e33..a96e8ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/LoggerHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/LoggerHelper.kt
@@ -38,11 +38,24 @@
                 int1 = network.getNetId()
                 str1 = networkCapabilities.toString()
             },
-            { "onCapabilitiesChanged[default=$bool1]: net=$int1 capabilities=$str1" }
+            { "on${if (bool1) "Default" else ""}CapabilitiesChanged: net=$int1 capabilities=$str1" }
         )
     }
 
-    fun logOnLost(buffer: LogBuffer, tag: String, network: Network) {
-        buffer.log(tag, LogLevel.INFO, { int1 = network.getNetId() }, { "onLost: net=$int1" })
+    fun logOnLost(
+        buffer: LogBuffer,
+        tag: String,
+        network: Network,
+        isDefaultNetworkCallback: Boolean,
+    ) {
+        buffer.log(
+            tag,
+            LogLevel.INFO,
+            {
+                int1 = network.getNetId()
+                bool1 = isDefaultNetworkCallback
+            },
+            { "on${if (bool1) "Default" else ""}Lost: net=$int1" }
+        )
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/ModernStatusBarViewBinding.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/ModernStatusBarViewBinding.kt
index f67876b..81f8683 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/ModernStatusBarViewBinding.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/ModernStatusBarViewBinding.kt
@@ -37,4 +37,7 @@
 
     /** Notifies that the decor tint has been updated (used only for the dot). */
     fun onDecorTintChanged(newTint: Int)
+
+    /** Returns true if the binding between the view and view-model is currently collecting. */
+    fun isCollecting(): Boolean
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt
index b1e2812..1a13404 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt
@@ -36,7 +36,7 @@
     BaseStatusBarFrameLayout(context, attrs) {
 
     private lateinit var slot: String
-    private lateinit var binding: ModernStatusBarViewBinding
+    internal lateinit var binding: ModernStatusBarViewBinding
 
     @StatusBarIconView.VisibleState
     private var iconVisibleState: Int = STATE_HIDDEN
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt
index e0e0ed7..b129617 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt
@@ -41,7 +41,6 @@
  * or the [WifiRepositoryImpl]'s prod implementation, based on the current demo mode value. In this
  * way, downstream clients can all consist of real implementations and not care about which
  * repository is responsible for the data. Graphically:
- *
  * ```
  * RealRepository
  *                 │
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
index ee58160..b5e7b7a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
@@ -128,6 +128,7 @@
                         }
 
                         override fun onLost(network: Network) {
+                            logger.logOnLost(network, isDefaultNetworkCallback = true)
                             // The system no longer has a default network, so wifi is definitely not
                             // default.
                             trySend(false)
@@ -179,7 +180,7 @@
                         }
 
                         override fun onLost(network: Network) {
-                            logger.logOnLost(network)
+                            logger.logOnLost(network, isDefaultNetworkCallback = false)
 
                             wifiNetworkChangeEvents.tryEmit(Unit)
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiInputLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiInputLogger.kt
index a32e475..bb0b166 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiInputLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiInputLogger.kt
@@ -48,8 +48,8 @@
         )
     }
 
-    fun logOnLost(network: Network) {
-        LoggerHelper.logOnLost(buffer, TAG, network)
+    fun logOnLost(network: Network, isDefaultNetworkCallback: Boolean) {
+        LoggerHelper.logOnLost(buffer, TAG, network, isDefaultNetworkCallback)
     }
 
     fun logIntent(intentName: String) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt
index 2aff12c..9e8c814 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt
@@ -34,6 +34,7 @@
 import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon
 import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel
 import kotlinx.coroutines.InternalCoroutinesApi
+import kotlinx.coroutines.awaitCancellation
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.flow.distinctUntilChanged
@@ -74,8 +75,12 @@
         val iconTint: MutableStateFlow<Int> = MutableStateFlow(viewModel.defaultColor)
         val decorTint: MutableStateFlow<Int> = MutableStateFlow(viewModel.defaultColor)
 
+        var isCollecting: Boolean = false
+
         view.repeatWhenAttached {
             repeatOnLifecycle(Lifecycle.State.STARTED) {
+                isCollecting = true
+
                 launch {
                     visibilityState.collect { visibilityState ->
                         groupView.isVisible = visibilityState == STATE_ICON
@@ -127,6 +132,12 @@
                         airplaneSpacer.isVisible = visible
                     }
                 }
+
+                try {
+                    awaitCancellation()
+                } finally {
+                    isCollecting = false
+                }
             }
         }
 
@@ -152,6 +163,10 @@
                 }
                 decorTint.value = newTint
             }
+
+            override fun isCollecting(): Boolean {
+                return isCollecting
+            }
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt
index 7a73486..f23e102 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt
@@ -21,6 +21,7 @@
 import android.util.AttributeSet
 import android.view.LayoutInflater
 import com.android.systemui.R
+import com.android.systemui.statusbar.StatusBarIconView
 import com.android.systemui.statusbar.pipeline.shared.ui.view.ModernStatusBarView
 import com.android.systemui.statusbar.pipeline.wifi.ui.binder.WifiViewBinder
 import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel
@@ -33,6 +34,15 @@
     context: Context,
     attrs: AttributeSet?,
 ) : ModernStatusBarView(context, attrs) {
+
+    override fun toString(): String {
+        return "ModernStatusBarWifiView(" +
+            "slot='$slot', " +
+            "isCollecting=${binding.isCollecting()}, " +
+            "visibleState=${StatusBarIconView.getVisibleStateString(visibleState)}); " +
+            "viewString=${super.toString()}"
+    }
+
     companion object {
         /**
          * Inflates a new instance of [ModernStatusBarWifiView], binds it to a view model, and
@@ -45,12 +55,9 @@
             slot: String,
             wifiViewModel: LocationBasedWifiViewModel,
         ): ModernStatusBarWifiView {
-            return (
-                LayoutInflater.from(context).inflate(R.layout.new_status_bar_wifi_group, null)
-                    as ModernStatusBarWifiView
-                ).also {
-                    it.initView(slot) { WifiViewBinder.bind(it, wifiViewModel) }
-                }
+            return (LayoutInflater.from(context).inflate(R.layout.new_status_bar_wifi_group, null)
+                    as ModernStatusBarWifiView)
+                .also { it.initView(slot) { WifiViewBinder.bind(it, wifiViewModel) } }
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
index 1057231..4b24e7a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
@@ -124,7 +124,8 @@
                     isDefault -> icon
                     wifiConstants.alwaysShowIconIfEnabled -> icon
                     !connectivityConstants.hasDataCapabilities -> icon
-                    wifiNetwork is WifiNetworkModel.Active && wifiNetwork.isValidated -> icon
+                    // See b/272509965: Even if we have an active and validated wifi network, we
+                    // don't want to show the icon if wifi isn't the default network.
                     else -> WifiIcon.Hidden
                 }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java
index 3944c8c..0d09fc1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java
@@ -21,7 +21,8 @@
 /**
  * Controller to cache in process the state of the device provisioning.
  * <p>
- * This controller keeps track of the values of device provisioning and user setup complete
+ * This controller keeps track of the values of device provisioning, user setup complete, and
+ * whether Factory Reset Protection is active.
  */
 public interface DeviceProvisionedController extends CallbackController<DeviceProvisionedListener> {
 
@@ -49,6 +50,9 @@
      */
     boolean isCurrentUserSetup();
 
+    /** Returns true when Factory Reset Protection is locking the device. */
+    boolean isFrpActive();
+
     /**
      * Interface to provide calls when the values tracked change
      */
@@ -69,5 +73,10 @@
          * Call when some user changes from not provisioned to provisioned
          */
         default void onUserSetupChanged() { }
+
+        /**
+         * Called when the state of FRP changes.
+         */
+        default void onFrpActiveChanged() {}
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.kt
index a6b7d9c5..32c64f4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.kt
@@ -60,9 +60,11 @@
     }
 
     private val deviceProvisionedUri = globalSettings.getUriFor(Settings.Global.DEVICE_PROVISIONED)
+    private val frpActiveUri = secureSettings.getUriFor(Settings.Secure.SECURE_FRP_MODE)
     private val userSetupUri = secureSettings.getUriFor(Settings.Secure.USER_SETUP_COMPLETE)
 
     private val deviceProvisioned = AtomicBoolean(false)
+    private val frpActive = AtomicBoolean(false)
     @GuardedBy("lock")
     private val userSetupComplete = SparseBooleanArray()
     @GuardedBy("lock")
@@ -89,11 +91,15 @@
             userId: Int
         ) {
             val updateDeviceProvisioned = deviceProvisionedUri in uris
+            val updateFrp = frpActiveUri in uris
             val updateUser = if (userSetupUri in uris) userId else NO_USERS
-            updateValues(updateDeviceProvisioned, updateUser)
+            updateValues(updateDeviceProvisioned, updateFrp, updateUser)
             if (updateDeviceProvisioned) {
                 onDeviceProvisionedChanged()
             }
+            if (updateFrp) {
+                onFrpActiveChanged()
+            }
             if (updateUser != NO_USERS) {
                 onUserSetupChanged()
             }
@@ -103,7 +109,7 @@
     private val userChangedCallback = object : UserTracker.Callback {
         @WorkerThread
         override fun onUserChanged(newUser: Int, userContext: Context) {
-            updateValues(updateDeviceProvisioned = false, updateUser = newUser)
+            updateValues(updateDeviceProvisioned = false, updateFrp = false, updateUser = newUser)
             onUserSwitched()
         }
 
@@ -125,19 +131,27 @@
         updateValues()
         userTracker.addCallback(userChangedCallback, backgroundExecutor)
         globalSettings.registerContentObserver(deviceProvisionedUri, observer)
+        globalSettings.registerContentObserver(frpActiveUri, observer)
         secureSettings.registerContentObserverForUser(userSetupUri, observer, UserHandle.USER_ALL)
     }
 
     @WorkerThread
-    private fun updateValues(updateDeviceProvisioned: Boolean = true, updateUser: Int = ALL_USERS) {
+    private fun updateValues(
+        updateDeviceProvisioned: Boolean = true,
+        updateFrp: Boolean = true,
+        updateUser: Int = ALL_USERS
+    ) {
         if (updateDeviceProvisioned) {
             deviceProvisioned
                     .set(globalSettings.getInt(Settings.Global.DEVICE_PROVISIONED, 0) != 0)
         }
+        if (updateFrp) {
+            frpActive.set(globalSettings.getInt(Settings.Secure.SECURE_FRP_MODE, 0) != 0)
+        }
         synchronized(lock) {
             if (updateUser == ALL_USERS) {
-                val N = userSetupComplete.size()
-                for (i in 0 until N) {
+                val n = userSetupComplete.size()
+                for (i in 0 until n) {
                     val user = userSetupComplete.keyAt(i)
                     val value = secureSettings
                             .getIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 0, user) != 0
@@ -172,6 +186,10 @@
         return deviceProvisioned.get()
     }
 
+    override fun isFrpActive(): Boolean {
+        return frpActive.get()
+    }
+
     override fun isUserSetup(user: Int): Boolean {
         val index = synchronized(lock) {
             userSetupComplete.indexOfKey(user)
@@ -196,7 +214,13 @@
 
     override fun onDeviceProvisionedChanged() {
         dispatchChange(
-                DeviceProvisionedController.DeviceProvisionedListener::onDeviceProvisionedChanged
+            DeviceProvisionedController.DeviceProvisionedListener::onDeviceProvisionedChanged
+        )
+    }
+
+    override fun onFrpActiveChanged() {
+        dispatchChange(
+            DeviceProvisionedController.DeviceProvisionedListener::onFrpActiveChanged
         )
     }
 
@@ -221,6 +245,7 @@
 
     override fun dump(pw: PrintWriter, args: Array<out String>) {
         pw.println("Device provisioned: ${deviceProvisioned.get()}")
+        pw.println("Factory Reset Protection active: ${frpActive.get()}")
         synchronized(lock) {
             pw.println("User setup complete: $userSetupComplete")
             pw.println("Listeners: $listeners")
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingController.java
index 7acdaff..01fabcc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingController.java
@@ -22,13 +22,18 @@
 import android.annotation.Nullable;
 import android.hardware.devicestate.DeviceStateManager;
 import android.os.Trace;
-import android.util.Log;
+import android.util.IndentingPrintWriter;
+
+import androidx.annotation.NonNull;
 
 import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager;
+import com.android.systemui.Dumpable;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.util.wrapper.RotationPolicyWrapper;
 
+import java.io.PrintWriter;
 import java.util.concurrent.Executor;
 
 import javax.inject.Inject;
@@ -39,19 +44,19 @@
  */
 @SysUISingleton
 public final class DeviceStateRotationLockSettingController
-        implements Listenable, RotationLockController.RotationLockControllerCallback {
-
-    private static final String TAG = "DSRotateLockSettingCon";
+        implements Listenable, RotationLockController.RotationLockControllerCallback, Dumpable {
 
     private final RotationPolicyWrapper mRotationPolicyWrapper;
     private final DeviceStateManager mDeviceStateManager;
     private final Executor mMainExecutor;
     private final DeviceStateRotationLockSettingsManager mDeviceStateRotationLockSettingsManager;
+    private final DeviceStateRotationLockSettingControllerLogger mLogger;
 
     // On registration for DeviceStateCallback, we will receive a callback with the current state
     // and this will be initialized.
     private int mDeviceState = -1;
-    @Nullable private DeviceStateManager.DeviceStateCallback mDeviceStateCallback;
+    @Nullable
+    private DeviceStateManager.DeviceStateCallback mDeviceStateCallback;
     private DeviceStateRotationLockSettingsManager.DeviceStateRotationLockSettingsListener
             mDeviceStateRotationLockSettingsListener;
 
@@ -60,21 +65,27 @@
             RotationPolicyWrapper rotationPolicyWrapper,
             DeviceStateManager deviceStateManager,
             @Main Executor executor,
-            DeviceStateRotationLockSettingsManager deviceStateRotationLockSettingsManager) {
+            DeviceStateRotationLockSettingsManager deviceStateRotationLockSettingsManager,
+            DeviceStateRotationLockSettingControllerLogger logger,
+            DumpManager dumpManager) {
         mRotationPolicyWrapper = rotationPolicyWrapper;
         mDeviceStateManager = deviceStateManager;
         mMainExecutor = executor;
         mDeviceStateRotationLockSettingsManager = deviceStateRotationLockSettingsManager;
+        mLogger = logger;
+        dumpManager.registerDumpable(this);
     }
 
     @Override
     public void setListening(boolean listening) {
+        mLogger.logListeningChange(listening);
         if (listening) {
             // Note that this is called once with the initial state of the device, even if there
             // is no user action.
             mDeviceStateCallback = this::updateDeviceState;
             mDeviceStateManager.registerCallback(mMainExecutor, mDeviceStateCallback);
-            mDeviceStateRotationLockSettingsListener = () -> readPersistedSetting(mDeviceState);
+            mDeviceStateRotationLockSettingsListener = () ->
+                    readPersistedSetting("deviceStateRotationLockChange", mDeviceState);
             mDeviceStateRotationLockSettingsManager.registerListener(
                     mDeviceStateRotationLockSettingsListener);
         } else {
@@ -89,35 +100,28 @@
     }
 
     @Override
-    public void onRotationLockStateChanged(boolean rotationLocked, boolean affordanceVisible) {
-        if (mDeviceState == -1) {
-            Log.wtf(TAG, "Device state was not initialized.");
+    public void onRotationLockStateChanged(boolean newRotationLocked, boolean affordanceVisible) {
+        int deviceState = mDeviceState;
+        boolean currentRotationLocked = mDeviceStateRotationLockSettingsManager
+                .isRotationLocked(deviceState);
+        mLogger.logRotationLockStateChanged(deviceState, newRotationLocked, currentRotationLocked);
+        if (deviceState == -1) {
             return;
         }
-
-        if (rotationLocked
-                == mDeviceStateRotationLockSettingsManager.isRotationLocked(mDeviceState)) {
-            Log.v(TAG, "Rotation lock same as the current setting, no need to update.");
+        if (newRotationLocked == currentRotationLocked) {
             return;
         }
-
-        saveNewRotationLockSetting(rotationLocked);
+        saveNewRotationLockSetting(newRotationLocked);
     }
 
     private void saveNewRotationLockSetting(boolean isRotationLocked) {
-        Log.v(
-                TAG,
-                "saveNewRotationLockSetting [state="
-                        + mDeviceState
-                        + "] [isRotationLocked="
-                        + isRotationLocked
-                        + "]");
-
-        mDeviceStateRotationLockSettingsManager.updateSetting(mDeviceState, isRotationLocked);
+        int deviceState = mDeviceState;
+        mLogger.logSaveNewRotationLockSetting(isRotationLocked, deviceState);
+        mDeviceStateRotationLockSettingsManager.updateSetting(deviceState, isRotationLocked);
     }
 
     private void updateDeviceState(int state) {
-        Log.v(TAG, "updateDeviceState [state=" + state + "]");
+        mLogger.logUpdateDeviceState(mDeviceState, state);
         if (Trace.isEnabled()) {
             Trace.traceBegin(
                     Trace.TRACE_TAG_APP, "updateDeviceState [state=" + state + "]");
@@ -127,22 +131,26 @@
                 return;
             }
 
-            readPersistedSetting(state);
+            readPersistedSetting("updateDeviceState", state);
         } finally {
             Trace.endSection();
         }
     }
 
-    private void readPersistedSetting(int state) {
+    private void readPersistedSetting(String caller, int state) {
         int rotationLockSetting =
                 mDeviceStateRotationLockSettingsManager.getRotationLockSetting(state);
+        boolean shouldBeLocked = rotationLockSetting == DEVICE_STATE_ROTATION_LOCK_LOCKED;
+        boolean isLocked = mRotationPolicyWrapper.isRotationLocked();
+
+        mLogger.readPersistedSetting(caller, state, rotationLockSetting, shouldBeLocked, isLocked);
+
         if (rotationLockSetting == DEVICE_STATE_ROTATION_LOCK_IGNORED) {
             // This should not happen. Device states that have an ignored setting, should also
             // specify a fallback device state which is not ignored.
             // We won't handle this device state. The same rotation lock setting as before should
             // apply and any changes to the rotation lock setting will be written for the previous
             // valid device state.
-            Log.w(TAG, "Missing fallback. Ignoring new device state: " + state);
             return;
         }
 
@@ -150,9 +158,18 @@
         mDeviceState = state;
 
         // Update the rotation policy, if needed, for this new device state
-        boolean newRotationLockSetting = rotationLockSetting == DEVICE_STATE_ROTATION_LOCK_LOCKED;
-        if (newRotationLockSetting != mRotationPolicyWrapper.isRotationLocked()) {
-            mRotationPolicyWrapper.setRotationLock(newRotationLockSetting);
+        if (shouldBeLocked != isLocked) {
+            mRotationPolicyWrapper.setRotationLock(shouldBeLocked);
         }
     }
+
+    @Override
+    public void dump(@NonNull PrintWriter printWriter, @NonNull String[] args) {
+        IndentingPrintWriter pw = new IndentingPrintWriter(printWriter);
+        mDeviceStateRotationLockSettingsManager.dump(pw);
+        pw.println("DeviceStateRotationLockSettingController");
+        pw.increaseIndent();
+        pw.println("mDeviceState: " + mDeviceState);
+        pw.decreaseIndent();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerLogger.kt
new file mode 100644
index 0000000..aa502bc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerLogger.kt
@@ -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.systemui.statusbar.policy
+
+import android.content.Context
+import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_IGNORED
+import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_LOCKED
+import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_UNLOCKED
+import com.android.internal.R
+import com.android.systemui.log.dagger.DeviceStateAutoRotationLog
+import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.plugins.log.LogLevel.VERBOSE
+import javax.inject.Inject
+
+class DeviceStateRotationLockSettingControllerLogger
+@Inject
+constructor(@DeviceStateAutoRotationLog private val logBuffer: LogBuffer, context: Context) {
+
+    private val foldedStates = context.resources.getIntArray(R.array.config_foldedDeviceStates)
+    private val halfFoldedStates =
+        context.resources.getIntArray(R.array.config_halfFoldedDeviceStates)
+    private val unfoldedStates = context.resources.getIntArray(R.array.config_openDeviceStates)
+
+    fun logListeningChange(listening: Boolean) {
+        logBuffer.log(TAG, VERBOSE, { bool1 = listening }, { "setListening: $bool1" })
+    }
+
+    fun logRotationLockStateChanged(
+        state: Int,
+        newRotationLocked: Boolean,
+        currentRotationLocked: Boolean
+    ) {
+        logBuffer.log(
+            TAG,
+            VERBOSE,
+            {
+                int1 = state
+                bool1 = newRotationLocked
+                bool2 = currentRotationLocked
+            },
+            {
+                "onRotationLockStateChanged: " +
+                    "state=$int1 [${int1.toDevicePostureString()}], " +
+                    "newRotationLocked=$bool1, " +
+                    "currentRotationLocked=$bool2"
+            }
+        )
+    }
+
+    fun logSaveNewRotationLockSetting(isRotationLocked: Boolean, state: Int) {
+        logBuffer.log(
+            TAG,
+            VERBOSE,
+            {
+                bool1 = isRotationLocked
+                int1 = state
+            },
+            { "saveNewRotationLockSetting: isRotationLocked=$bool1, state=$int1" }
+        )
+    }
+
+    fun logUpdateDeviceState(currentState: Int, newState: Int) {
+        logBuffer.log(
+            TAG,
+            VERBOSE,
+            {
+                int1 = currentState
+                int2 = newState
+            },
+            {
+                "updateDeviceState: " +
+                    "current=$int1 [${int1.toDevicePostureString()}], " +
+                    "new=$int2 [${int2.toDevicePostureString()}]"
+            }
+        )
+    }
+
+    fun readPersistedSetting(
+        caller: String,
+        state: Int,
+        rotationLockSetting: Int,
+        shouldBeLocked: Boolean,
+        isLocked: Boolean
+    ) {
+        logBuffer.log(
+            TAG,
+            VERBOSE,
+            {
+                str1 = caller
+                int1 = state
+                int2 = rotationLockSetting
+                bool1 = shouldBeLocked
+                bool2 = isLocked
+            },
+            {
+                "readPersistedSetting: " +
+                    "caller=$str1, " +
+                    "state=$int1 [${int1.toDevicePostureString()}], " +
+                    "rotationLockSettingForState: ${int2.toRotationLockSettingString()}, " +
+                    "shouldBeLocked=$bool1, " +
+                    "isLocked=$bool2"
+            }
+        )
+    }
+
+    private fun Int.toDevicePostureString(): String {
+        return when (this) {
+            in foldedStates -> "Folded"
+            in unfoldedStates -> "Unfolded"
+            in halfFoldedStates -> "Half-Folded"
+            -1 -> "Uninitialized"
+            else -> "Unknown"
+        }
+    }
+}
+
+private fun Int.toRotationLockSettingString(): String {
+    return when (this) {
+        DEVICE_STATE_ROTATION_LOCK_IGNORED -> "IGNORED"
+        DEVICE_STATE_ROTATION_LOCK_LOCKED -> "LOCKED"
+        DEVICE_STATE_ROTATION_LOCK_UNLOCKED -> "UNLOCKED"
+        else -> "Unknown"
+    }
+}
+
+private const val TAG = "DSRotateLockSettingCon"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt
index bdb656b..1e223b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt
@@ -146,7 +146,7 @@
      *
      * @param guestUserId id of the guest user to remove
      * @param targetUserId id of the user to switch to after guest is removed. If
-     * `UserHandle.USER_NULL`, then switch immediately to the newly created guest user.
+     *   `UserHandle.USER_NULL`, then switch immediately to the newly created guest user.
      */
     fun removeGuestUser(guestUserId: Int, targetUserId: Int) {
         userInteractor.removeGuestUser(
@@ -160,9 +160,9 @@
      *
      * @param guestUserId user id of the guest user to exit
      * @param targetUserId user id of the guest user to exit, set to UserHandle#USER_NULL when
-     * target user id is not known
+     *   target user id is not known
      * @param forceRemoveGuestOnExit true: remove guest before switching user, false: remove guest
-     * only if its ephemeral, else keep guest
+     *   only if its ephemeral, else keep guest
      */
     fun exitGuestUser(guestUserId: Int, targetUserId: Int, forceRemoveGuestOnExit: Boolean) {
         userInteractor.exitGuestUser(guestUserId, targetUserId, forceRemoveGuestOnExit)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java
index 853de7b..bcf3b0c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java
@@ -16,9 +16,9 @@
 
 package com.android.systemui.statusbar.window;
 
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
-import static android.view.InsetsState.ITYPE_TOP_MANDATORY_GESTURES;
-import static android.view.InsetsState.ITYPE_TOP_TAPPABLE_ELEMENT;
+import static android.view.WindowInsets.Type.mandatorySystemGestures;
+import static android.view.WindowInsets.Type.statusBars;
+import static android.view.WindowInsets.Type.tappableElement;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
@@ -85,6 +85,7 @@
     private final ViewGroup mLaunchAnimationContainer;
     private WindowManager.LayoutParams mLp;
     private final WindowManager.LayoutParams mLpChanged;
+    private final Binder mInsetsSourceOwner = new Binder();
 
     @Inject
     public StatusBarWindowController(
@@ -231,16 +232,16 @@
         lp.packageName = mContext.getPackageName();
         lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
         final InsetsFrameProvider gestureInsetsProvider =
-                new InsetsFrameProvider(ITYPE_TOP_MANDATORY_GESTURES);
+                new InsetsFrameProvider(mInsetsSourceOwner, 0, mandatorySystemGestures());
         final int safeTouchRegionHeight = mContext.getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.display_cutout_touchable_region_size);
         if (safeTouchRegionHeight > 0) {
-            gestureInsetsProvider.minimalInsetsSizeInDisplayCutoutSafe =
-                    Insets.of(0, safeTouchRegionHeight, 0, 0);
+            gestureInsetsProvider.setMinimalInsetsSizeInDisplayCutoutSafe(
+                    Insets.of(0, safeTouchRegionHeight, 0, 0));
         }
         lp.providedInsets = new InsetsFrameProvider[] {
-                new InsetsFrameProvider(ITYPE_STATUS_BAR),
-                new InsetsFrameProvider(ITYPE_TOP_TAPPABLE_ELEMENT),
+                new InsetsFrameProvider(mInsetsSourceOwner, 0, statusBars()),
+                new InsetsFrameProvider(mInsetsSourceOwner, 0, tappableElement()),
                 gestureInsetsProvider
         };
         return lp;
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/OWNERS b/packages/SystemUI/src/com/android/systemui/stylus/OWNERS
index 7ccb316..0ec996b 100644
--- a/packages/SystemUI/src/com/android/systemui/stylus/OWNERS
+++ b/packages/SystemUI/src/com/android/systemui/stylus/OWNERS
@@ -5,4 +5,6 @@
 madym@google.com
 mgalhardo@google.com
 petrcermak@google.com
+stevenckng@google.com
+tkachenkoi@google.com
 vanjan@google.com
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt b/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt
index 462504e..9952cfd 100644
--- a/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt
@@ -22,6 +22,7 @@
 import android.hardware.BatteryState
 import android.hardware.input.InputManager
 import android.hardware.input.InputSettings
+import android.os.Build
 import android.os.Handler
 import android.util.ArrayMap
 import android.util.Log
@@ -61,8 +62,6 @@
     BluetoothAdapter.OnMetadataChangedListener {
 
     private val stylusCallbacks: CopyOnWriteArrayList<StylusCallback> = CopyOnWriteArrayList()
-    private val stylusBatteryCallbacks: CopyOnWriteArrayList<StylusBatteryCallback> =
-        CopyOnWriteArrayList()
 
     // This map should only be accessed on the handler
     private val inputDeviceAddressMap: MutableMap<Int, String?> = ArrayMap()
@@ -82,6 +81,8 @@
     fun startListener() {
         handler.post {
             if (hasStarted) return@post
+            logDebug { "Listener has started." }
+
             hasStarted = true
             isInUsiSession =
                 inputManager.hasInputDevice {
@@ -103,19 +104,15 @@
         stylusCallbacks.remove(callback)
     }
 
-    fun registerBatteryCallback(callback: StylusBatteryCallback) {
-        stylusBatteryCallbacks.add(callback)
-    }
-
-    fun unregisterBatteryCallback(callback: StylusBatteryCallback) {
-        stylusBatteryCallbacks.remove(callback)
-    }
-
     override fun onInputDeviceAdded(deviceId: Int) {
         if (!hasStarted) return
 
         val device: InputDevice = inputManager.getInputDevice(deviceId) ?: return
         if (!device.supportsSource(InputDevice.SOURCE_STYLUS)) return
+        logDebug {
+            "Stylus InputDevice added: $deviceId ${device.name}, " +
+                "External: ${device.isExternal}"
+        }
 
         if (!device.isExternal) {
             registerBatteryListener(deviceId)
@@ -137,6 +134,7 @@
 
         val device: InputDevice = inputManager.getInputDevice(deviceId) ?: return
         if (!device.supportsSource(InputDevice.SOURCE_STYLUS)) return
+        logDebug { "Stylus InputDevice changed: $deviceId ${device.name}" }
 
         val currAddress: String? = device.bluetoothAddress
         val prevAddress: String? = inputDeviceAddressMap[deviceId]
@@ -157,6 +155,8 @@
         if (!hasStarted) return
 
         if (!inputDeviceAddressMap.contains(deviceId)) return
+        logDebug { "Stylus InputDevice removed: $deviceId" }
+
         unregisterBatteryListener(deviceId)
 
         val btAddress: String? = inputDeviceAddressMap[deviceId]
@@ -180,7 +180,12 @@
 
             val isCharging = String(value) == "true"
 
-            executeStylusBatteryCallbacks { cb ->
+            logDebug {
+                "Charging state metadata changed for device $inputDeviceId " +
+                    "${device.address}: $isCharging"
+            }
+
+            executeStylusCallbacks { cb ->
                 cb.onStylusBluetoothChargingStateChanged(inputDeviceId, device, isCharging)
             }
         }
@@ -194,13 +199,10 @@
         handler.post {
             if (!hasStarted) return@post
 
-            if (DEBUG) {
-                Log.d(
-                    TAG,
-                    "onBatteryStateChanged for $deviceId. " +
-                        "batteryState present: ${batteryState.isPresent}, " +
-                        "capacity: ${batteryState.capacity}"
-                )
+            logDebug {
+                "Battery state changed for $deviceId. " +
+                    "batteryState present: ${batteryState.isPresent}, " +
+                    "capacity: ${batteryState.capacity}"
             }
 
             val batteryStateValid = isBatteryStateValid(batteryState)
@@ -209,14 +211,14 @@
                 onStylusUsed()
             }
 
-            executeStylusBatteryCallbacks { cb ->
+            executeStylusCallbacks { cb ->
                 cb.onStylusUsiBatteryStateChanged(deviceId, eventTimeMillis, batteryState)
             }
         }
     }
 
     private fun onStylusBluetoothConnected(deviceId: Int, btAddress: String) {
-        trackAndLogBluetoothSession(deviceId, true)
+        trackAndLogBluetoothSession(deviceId, btAddress, true)
         val device: BluetoothDevice = bluetoothAdapter?.getRemoteDevice(btAddress) ?: return
         try {
             bluetoothAdapter.addOnMetadataChangedListener(device, executor, this)
@@ -226,7 +228,7 @@
     }
 
     private fun onStylusBluetoothDisconnected(deviceId: Int, btAddress: String) {
-        trackAndLogBluetoothSession(deviceId, false)
+        trackAndLogBluetoothSession(deviceId, btAddress, false)
         val device: BluetoothDevice = bluetoothAdapter?.getRemoteDevice(btAddress) ?: return
         try {
             bluetoothAdapter.removeOnMetadataChangedListener(device, this)
@@ -245,6 +247,7 @@
         if (!featureFlags.isEnabled(Flags.TRACK_STYLUS_EVER_USED)) return
         if (InputSettings.isStylusEverUsed(context)) return
 
+        logDebug { "Stylus used for the first time." }
         InputSettings.setStylusEverUsed(context, true)
         executeStylusCallbacks { cb -> cb.onStylusFirstUsed() }
     }
@@ -259,12 +262,7 @@
         // TODO(b/268618918) handle cases where an invalid battery callback from a previous stylus
         //  is sent after the actual valid callback
         if (batteryStateValid && usiSessionId == null) {
-            if (DEBUG) {
-                Log.d(
-                    TAG,
-                    "USI battery newly present, entering new USI session. Device ID: $deviceId"
-                )
-            }
+            logDebug { "USI battery newly present, entering new USI session: $deviceId" }
             usiSessionId = instanceIdSequence.newInstanceId()
             uiEventLogger.logWithInstanceId(
                 StylusUiEvent.USI_STYLUS_BATTERY_PRESENCE_FIRST_DETECTED,
@@ -273,9 +271,7 @@
                 usiSessionId
             )
         } else if (!batteryStateValid && usiSessionId != null) {
-            if (DEBUG) {
-                Log.d(TAG, "USI battery newly absent, exiting USI session Device ID: $deviceId")
-            }
+            logDebug { "USI battery newly absent, exiting USI session: $deviceId" }
             uiEventLogger.logWithInstanceId(
                 StylusUiEvent.USI_STYLUS_BATTERY_PRESENCE_REMOVED,
                 0,
@@ -286,8 +282,17 @@
         }
     }
 
-    private fun trackAndLogBluetoothSession(deviceId: Int, bluetoothConnected: Boolean) {
-        if (bluetoothConnected) {
+    private fun trackAndLogBluetoothSession(
+        deviceId: Int,
+        btAddress: String,
+        btConnected: Boolean
+    ) {
+        logDebug {
+            "Bluetooth stylus ${if (btConnected) "connected" else "disconnected"}:" +
+                " $deviceId $btAddress"
+        }
+
+        if (btConnected) {
             inputDeviceBtSessionIdMap[deviceId] = instanceIdSequence.newInstanceId()
             uiEventLogger.logWithInstanceId(
                 StylusUiEvent.BLUETOOTH_STYLUS_CONNECTED,
@@ -314,10 +319,6 @@
         stylusCallbacks.forEach(run)
     }
 
-    private fun executeStylusBatteryCallbacks(run: (cb: StylusBatteryCallback) -> Unit) {
-        stylusBatteryCallbacks.forEach(run)
-    }
-
     private fun registerBatteryListener(deviceId: Int) {
         try {
             inputManager.addInputDeviceBatteryListener(deviceId, executor, this)
@@ -363,13 +364,6 @@
         fun onStylusBluetoothConnected(deviceId: Int, btAddress: String) {}
         fun onStylusBluetoothDisconnected(deviceId: Int, btAddress: String) {}
         fun onStylusFirstUsed() {}
-    }
-
-    /**
-     * Callback interface to receive stylus battery events from the StylusManager. All callbacks are
-     * runs on the same background handler.
-     */
-    interface StylusBatteryCallback {
         fun onStylusBluetoothChargingStateChanged(
             inputDeviceId: Int,
             btDevice: BluetoothDevice,
@@ -383,7 +377,12 @@
     }
 
     companion object {
-        private val TAG = StylusManager::class.simpleName.orEmpty()
-        private val DEBUG = false
+        val TAG = StylusManager::class.simpleName.orEmpty()
+    }
+}
+
+private inline fun logDebug(message: () -> String) {
+    if (Build.IS_DEBUGGABLE) {
+        Log.d(StylusManager.TAG, message())
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerStartable.kt b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerStartable.kt
index 27cafb1..3667392 100644
--- a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerStartable.kt
@@ -37,7 +37,7 @@
     private val inputManager: InputManager,
     private val stylusUsiPowerUi: StylusUsiPowerUI,
     private val featureFlags: FeatureFlags,
-) : CoreStartable, StylusManager.StylusCallback, StylusManager.StylusBatteryCallback {
+) : CoreStartable, StylusManager.StylusCallback {
 
     override fun onStylusAdded(deviceId: Int) {
         // On some devices, the addition of a new internal stylus indicates the use of a
@@ -74,7 +74,6 @@
 
         stylusUsiPowerUi.init()
         stylusManager.registerCallback(this)
-        stylusManager.registerBatteryCallback(this)
         stylusManager.startListener()
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
index ec0a6e7..21b0efa 100644
--- a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
+++ b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
@@ -26,6 +26,7 @@
 import android.content.IntentFilter
 import android.hardware.BatteryState
 import android.hardware.input.InputManager
+import android.os.Build
 import android.os.Bundle
 import android.os.Handler
 import android.os.UserHandle
@@ -109,6 +110,10 @@
 
             inputDeviceId = deviceId
             batteryCapacity = batteryState.capacity
+            logDebug {
+                "Updating notification battery state to $batteryCapacity " +
+                    "for InputDevice $deviceId."
+            }
             refresh()
         }
     }
@@ -125,12 +130,14 @@
         handler.post updateSuppressed@{
             if (suppressed == suppress) return@updateSuppressed
 
+            logDebug { "Updating notification suppression to $suppress." }
             suppressed = suppress
             refresh()
         }
     }
 
     private fun hideNotification() {
+        logDebug { "Cancelling USI low battery notification." }
         instanceId = null
         notificationManager.cancel(USI_NOTIFICATION_ID)
     }
@@ -153,6 +160,7 @@
                 .setAutoCancel(true)
                 .build()
 
+        logDebug { "Show or update USI low battery notification at $batteryCapacity." }
         logUiEvent(StylusUiEvent.STYLUS_LOW_BATTERY_NOTIFICATION_SHOWN)
         notificationManager.notify(USI_NOTIFICATION_ID, notification)
     }
@@ -180,10 +188,12 @@
             override fun onReceive(context: Context, intent: Intent) {
                 when (intent.action) {
                     ACTION_DISMISSED_LOW_BATTERY -> {
+                        logDebug { "USI low battery notification dismissed." }
                         logUiEvent(StylusUiEvent.STYLUS_LOW_BATTERY_NOTIFICATION_DISMISSED)
                         updateSuppression(true)
                     }
                     ACTION_CLICKED_LOW_BATTERY -> {
+                        logDebug { "USI low battery notification clicked." }
                         logUiEvent(StylusUiEvent.STYLUS_LOW_BATTERY_NOTIFICATION_CLICKED)
                         updateSuppression(true)
                         if (inputDeviceId == null) return
@@ -233,6 +243,8 @@
     }
 
     companion object {
+        val TAG = StylusUsiPowerUI::class.simpleName.orEmpty()
+
         // Low battery threshold matches CrOS, see:
         // https://source.chromium.org/chromium/chromium/src/+/main:ash/system/power/peripheral_battery_notifier.cc;l=41
         private const val LOW_BATTERY_THRESHOLD = 0.16f
@@ -251,3 +263,9 @@
         @VisibleForTesting const val KEY_SETTINGS_FRAGMENT_ARGS = ":settings:show_fragment_args"
     }
 }
+
+private inline fun logDebug(message: () -> String) {
+    if (Build.IS_DEBUGGABLE) {
+        Log.d(StylusUsiPowerUI.TAG, message())
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/telephony/ui/activity/SwitchToManagedProfileForCallActivity.kt b/packages/SystemUI/src/com/android/systemui/telephony/ui/activity/SwitchToManagedProfileForCallActivity.kt
index e092f01..8e2b05c 100644
--- a/packages/SystemUI/src/com/android/systemui/telephony/ui/activity/SwitchToManagedProfileForCallActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/telephony/ui/activity/SwitchToManagedProfileForCallActivity.kt
@@ -66,7 +66,7 @@
     private fun switchToManagedProfile() {
         try {
             applicationContext.startActivityAsUser(
-                Intent(Intent.ACTION_DIAL, phoneNumber),
+                Intent(Intent.ACTION_CALL, phoneNumber),
                 ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle(),
                 UserHandle.of(managedProfileUserId)
             )
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt
index 1065d33..59122af 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt
@@ -274,6 +274,7 @@
             it.title = newInfo.windowTitle
         }
         newView.keepScreenOn = true
+        logger.logViewAddedToWindowManager(displayInfo.info, newView)
         windowManager.addView(newView, paramsWithTitle)
         animateViewIn(newView)
     }
@@ -286,6 +287,11 @@
         val view = checkNotNull(currentDisplayInfo.view) {
             "First item in activeViews list must have a valid view"
         }
+        logger.logViewRemovedFromWindowManager(
+            currentDisplayInfo.info,
+            view,
+            isReinflation = true,
+        )
         windowManager.removeView(view)
         inflateAndUpdateView(currentDisplayInfo)
     }
@@ -294,6 +300,10 @@
         override fun onDensityOrFontScaleChanged() {
             reinflateView()
         }
+
+        override fun onThemeChanged() {
+            reinflateView()
+        }
     }
 
     private fun addCallbacks() {
@@ -378,6 +388,7 @@
         }
         displayInfo.view = null // Need other places??
         animateViewOut(view, removalReason) {
+            logger.logViewRemovedFromWindowManager(displayInfo.info, view)
             windowManager.removeView(view)
             displayInfo.wakeLock?.release(displayInfo.info.wakeReason)
         }
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt
index 899b0c2..667e22a 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.temporarydisplay
 
+import android.view.View
 import com.android.systemui.plugins.log.LogBuffer
 import com.android.systemui.plugins.log.LogLevel
 
@@ -141,4 +142,46 @@
             { "Removal of view with id=$str2 is ignored because $str1" }
         )
     }
+
+    fun logViewAddedToWindowManager(info: T, view: View) {
+        buffer.log(
+            tag,
+            LogLevel.DEBUG,
+            {
+                str1 = info.id
+                str2 = info.windowTitle
+                str3 = view.javaClass.name
+                int1 = view.getIdForLogging()
+            },
+            {
+                "Adding view to window manager. " +
+                    "id=$str1 window=$str2 view=$str3(id=${Integer.toHexString(int1)})"
+            }
+        )
+    }
+
+    fun logViewRemovedFromWindowManager(info: T, view: View, isReinflation: Boolean = false) {
+        buffer.log(
+            tag,
+            LogLevel.DEBUG,
+            {
+                str1 = info.id
+                str2 = info.windowTitle
+                str3 = view.javaClass.name
+                int1 = view.getIdForLogging()
+                bool1 = isReinflation
+            },
+            {
+                "Removing view from window manager${if (bool1) " due to reinflation" else ""}. " +
+                    "id=$str1 window=$str2 view=$str3(id=${Integer.toHexString(int1)})"
+            }
+        )
+    }
+
+    companion object {
+        private fun View.getIdForLogging(): Int {
+            // The identityHashCode is guaranteed to be constant for the lifetime of the object.
+            return System.identityHashCode(this)
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TouchableRegionViewController.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TouchableRegionViewController.kt
index 60241a9..cf0184f 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TouchableRegionViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TouchableRegionViewController.kt
@@ -27,7 +27,7 @@
  * pass through to the window below.
  *
  * @param touchableRegionSetter a function that, given the view and an out rect, fills the rect with
- * the touchable region of this view.
+ *   the touchable region of this view.
  */
 class TouchableRegionViewController(
     view: View,
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt
index 01a81de..1612388 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt
@@ -35,7 +35,7 @@
      * Animates [innerView] and its children into view.
      *
      * @return true if the animation was successfully started and false if the animation can't be
-     * run for any reason.
+     *   run for any reason.
      *
      * See [ViewHierarchyAnimator.animateAddition].
      */
@@ -55,7 +55,7 @@
      * Animates [innerView] and its children out of view.
      *
      * @return true if the animation was successfully started and false if the animation can't be
-     * run for any reason.
+     *   run for any reason.
      *
      * See [ViewHierarchyAnimator.animateRemoval].
      */
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt
index fe46318..125cc76 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt
@@ -28,10 +28,10 @@
  * A container for all the state needed to display a chipbar via [ChipbarCoordinator].
  *
  * @property startIcon the icon to display at the start of the chipbar (on the left in LTR locales;
- * on the right in RTL locales).
+ *   on the right in RTL locales).
  * @property text the text to display.
  * @property endItem an optional end item to display at the end of the chipbar (on the right in LTR
- * locales; on the left in RTL locales).
+ *   locales; on the left in RTL locales).
  * @property vibrationEffect an optional vibration effect when the chipbar is displayed
  * @property allowSwipeToDismiss true if users are allowed to swipe up to dismiss this chipbar.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index 2ad3558..faae8df 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -29,6 +29,7 @@
 import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_COLOR_SOURCE;
 import static com.android.systemui.theme.ThemeOverlayApplier.TIMESTAMP_FIELD;
 
+import android.app.UiModeManager;
 import android.app.WallpaperColors;
 import android.app.WallpaperManager;
 import android.app.WallpaperManager.OnColorsChangedListener;
@@ -54,7 +55,6 @@
 import android.util.Log;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
-import android.view.accessibility.AccessibilityManager;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
@@ -140,8 +140,8 @@
     private boolean mNeedsOverlayCreation;
     // Dominant color extracted from wallpaper, NOT the color used on the overlay
     protected int mMainWallpaperColor = Color.TRANSPARENT;
-    // UI contrast as reported by AccessibilityManager
-    private float mUiContrast = 0;
+    // UI contrast as reported by UiModeManager
+    private float mContrast = 0;
     // Theme variant: Vibrant, Tonal, Expressive, etc
     @VisibleForTesting
     protected Style mThemeStyle = Style.TONAL_SPOT;
@@ -158,7 +158,7 @@
     private final SparseArray<WallpaperColors> mDeferredWallpaperColors = new SparseArray<>();
     private final SparseIntArray mDeferredWallpaperColorsFlags = new SparseIntArray();
     private final WakefulnessLifecycle mWakefulnessLifecycle;
-    private final AccessibilityManager mAccessibilityManager;
+    private final UiModeManager mUiModeManager;
     private DynamicScheme mDynamicSchemeDark;
     private DynamicScheme mDynamicSchemeLight;
 
@@ -392,7 +392,7 @@
             FeatureFlags featureFlags,
             @Main Resources resources,
             WakefulnessLifecycle wakefulnessLifecycle,
-            AccessibilityManager accessibilityManager) {
+            UiModeManager uiModeManager) {
         mContext = context;
         mIsMonochromaticEnabled = featureFlags.isEnabled(Flags.MONOCHROMATIC_THEME);
         mIsMonetEnabled = featureFlags.isEnabled(Flags.MONET);
@@ -408,7 +408,7 @@
         mUserTracker = userTracker;
         mResources = resources;
         mWakefulnessLifecycle = wakefulnessLifecycle;
-        mAccessibilityManager = accessibilityManager;
+        mUiModeManager = uiModeManager;
         dumpManager.registerDumpable(TAG, this);
     }
 
@@ -445,9 +445,9 @@
                     }
                 },
                 UserHandle.USER_ALL);
-        mUiContrast = mAccessibilityManager.getUiContrast();
-        mAccessibilityManager.addUiContrastChangeListener(mMainExecutor, uiContrast -> {
-            mUiContrast = uiContrast;
+        mContrast = mUiModeManager.getContrast();
+        mUiModeManager.addContrastChangeListener(mMainExecutor, contrast -> {
+            mContrast = contrast;
             // Force reload so that we update even when the main color has not changed
             reevaluateSystemTheme(true /* forceReload */);
         });
@@ -586,9 +586,9 @@
         mSecondaryOverlay = createAccentOverlay();
 
         mDynamicSchemeDark = dynamicSchemeFromStyle(
-                mThemeStyle, color, true /* isDark */, mUiContrast);
+                mThemeStyle, color, true /* isDark */, mContrast);
         mDynamicSchemeLight = dynamicSchemeFromStyle(
-                mThemeStyle, color, false /* isDark */, mUiContrast);
+                mThemeStyle, color, false /* isDark */, mContrast);
         mDynamicOverlay = createDynamicOverlay();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/FoldStateLoggingProviderImpl.kt b/packages/SystemUI/src/com/android/systemui/unfold/FoldStateLoggingProviderImpl.kt
index 2683971..981f429 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/FoldStateLoggingProviderImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/FoldStateLoggingProviderImpl.kt
@@ -61,8 +61,6 @@
         foldStateProvider.stop()
     }
 
-    override fun onHingeAngleUpdate(angle: Float) {}
-
     override fun onFoldUpdate(@FoldUpdate update: Int) {
         val now = clock.elapsedRealtime()
         when (update) {
@@ -77,6 +75,10 @@
         }
     }
 
+    override fun onUnfoldedScreenAvailable() {
+        Log.d(TAG, "Unfolded screen available")
+    }
+
     private fun dispatchState(@LoggedFoldedStates current: Int) {
         val now = clock.elapsedRealtime()
         val previous = lastState
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java
index d5d3efd..3a7ac9c 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java
@@ -31,6 +31,9 @@
 import com.android.internal.app.AlertActivity;
 import com.android.internal.app.AlertController;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+
+import javax.inject.Inject;
 
 /**
  * If the attached USB accessory has a URL associated with it, and that URL is valid,
@@ -46,13 +49,27 @@
     private UsbAccessory mAccessory;
     private Uri mUri;
 
+    private final DeviceProvisionedController mDeviceProvisionedController;
+
+    @Inject
+    UsbAccessoryUriActivity(DeviceProvisionedController deviceProvisionedController) {
+        mDeviceProvisionedController = deviceProvisionedController;
+    }
+
     @Override
     public void onCreate(Bundle icicle) {
-       getWindow().addSystemFlags(
+        getWindow().addSystemFlags(
                 WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
-       super.onCreate(icicle);
+        super.onCreate(icicle);
 
-       Intent intent = getIntent();
+        // Don't show this dialog during Setup Wizard
+        if (!mDeviceProvisionedController.isDeviceProvisioned()) {
+            Log.e(TAG, "device not provisioned");
+            finish();
+            return;
+        }
+
+        Intent intent = getIntent();
         mAccessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
         String uriString = intent.getStringExtra("uri");
         mUri = (uriString == null ? null : Uri.parse(uriString));
diff --git a/packages/SystemUI/src/com/android/systemui/user/UserCreator.kt b/packages/SystemUI/src/com/android/systemui/user/UserCreator.kt
index 5f89d5d..9304a46 100644
--- a/packages/SystemUI/src/com/android/systemui/user/UserCreator.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/UserCreator.kt
@@ -45,7 +45,7 @@
      *
      * @param successCallback is called when the user creation is successful.
      * @param errorCallback is called when userManager.createUser returns null. (Exceptions are not
-     * handled by this class)
+     *   handled by this class)
      */
     fun createUser(
         userName: String?,
diff --git a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
index 70523bb..a0b56aa 100644
--- a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
@@ -17,11 +17,8 @@
 
 package com.android.systemui.user.data.repository
 
-import android.app.IActivityManager
-import android.app.UserSwitchObserver
 import android.content.Context
 import android.content.pm.UserInfo
-import android.os.IRemoteCallback
 import android.os.UserHandle
 import android.os.UserManager
 import android.provider.Settings
@@ -121,7 +118,6 @@
     @Background private val backgroundDispatcher: CoroutineDispatcher,
     private val globalSettings: GlobalSettings,
     private val tracker: UserTracker,
-    private val activityManager: IActivityManager,
     featureFlags: FeatureFlags,
 ) : UserRepository {
 
@@ -213,18 +209,18 @@
     private fun observeUserSwitching() {
         conflatedCallbackFlow {
                 val callback =
-                    object : UserSwitchObserver() {
-                        override fun onUserSwitching(newUserId: Int, reply: IRemoteCallback) {
+                    object : UserTracker.Callback {
+                        override fun onUserChanging(newUser: Int, userContext: Context) {
                             trySendWithFailureLogging(true, TAG, "userSwitching started")
                         }
 
-                        override fun onUserSwitchComplete(newUserId: Int) {
+                        override fun onUserChanged(newUserId: Int, userContext: Context) {
                             trySendWithFailureLogging(false, TAG, "userSwitching completed")
                         }
                     }
-                activityManager.registerUserSwitchObserver(callback, TAG)
+                tracker.addCallback(callback, mainDispatcher.asExecutor())
                 trySendWithFailureLogging(false, TAG, "initial value defaulting to false")
-                awaitClose { activityManager.unregisterUserSwitchObserver(callback) }
+                awaitClose { tracker.removeCallback(callback) }
             }
             .onEach { _isUserSwitchingInProgress.value = it }
             // TODO (b/262838215), Make this stateIn and initialize directly in field declaration
diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/GuestUserInteractor.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/GuestUserInteractor.kt
index 2f63f32..f026f0f 100644
--- a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/GuestUserInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/GuestUserInteractor.kt
@@ -313,7 +313,7 @@
      * to create a new one.
      *
      * @return The multi-user user ID of the newly created guest user, or [UserHandle.USER_NULL] if
-     * the guest couldn't be created.
+     *   the guest couldn't be created.
      */
     @UserIdInt
     private suspend fun createInBackground(): Int {
diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt
index 433642b..94dd1b3 100644
--- a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt
@@ -33,6 +33,8 @@
 import android.util.Log
 import com.android.internal.logging.UiEventLogger
 import com.android.internal.util.UserIcons
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.KeyguardUpdateMonitorCallback
 import com.android.systemui.R
 import com.android.systemui.SystemUISecondaryUserService
 import com.android.systemui.animation.Expandable
@@ -93,6 +95,7 @@
     @Application private val applicationScope: CoroutineScope,
     telephonyInteractor: TelephonyInteractor,
     broadcastDispatcher: BroadcastDispatcher,
+    keyguardUpdateMonitor: KeyguardUpdateMonitor,
     @Background private val backgroundDispatcher: CoroutineDispatcher,
     private val activityManager: ActivityManager,
     private val refreshUsersScheduler: RefreshUsersScheduler,
@@ -290,6 +293,12 @@
 
     val isSimpleUserSwitcher: Boolean
         get() = repository.isSimpleUserSwitcher()
+    val keyguardUpdateMonitorCallback =
+        object : KeyguardUpdateMonitorCallback() {
+            override fun onKeyguardGoingAway() {
+                dismissDialog()
+            }
+        }
 
     init {
         refreshUsersScheduler.refreshIfNotPaused()
@@ -320,6 +329,7 @@
                 onBroadcastReceived(intent, previousSelectedUser)
             }
             .launchIn(applicationScope)
+        keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
     }
 
     fun addCallback(callback: UserCallback) {
diff --git a/packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.java b/packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.java
index 81ae6e8..c72853e 100644
--- a/packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.java
+++ b/packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.java
@@ -115,6 +115,17 @@
     }
 
     /**
+     * Provide a Long running Executor.
+     */
+    @Provides
+    @SysUISingleton
+    @LongRunning
+    public static DelayableExecutor provideLongRunningDelayableExecutor(
+            @LongRunning Looper looper) {
+        return new ExecutorImpl(looper);
+    }
+
+    /**
      * Provide a Background-Thread Executor.
      */
     @Provides
diff --git a/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java b/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java
index 064c224..c6da55c 100644
--- a/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java
+++ b/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java
@@ -119,11 +119,11 @@
 
     /**
      * Default constructor for {@link ObservableServiceConnection}.
-     * @param context The context from which the service will be bound with.
+     * @param context       The context from which the service will be bound with.
      * @param serviceIntent The intent to  bind service with.
-     * @param executor The executor for connection callbacks to be delivered on
-     * @param transformer A {@link ServiceTransformer} for transforming the resulting service
-     *                    into a desired type.
+     * @param executor      The executor for connection callbacks to be delivered on
+     * @param transformer   A {@link ServiceTransformer} for transforming the resulting service
+     *                      into a desired type.
      */
     @Inject
     public ObservableServiceConnection(Context context, Intent serviceIntent,
@@ -143,7 +143,13 @@
      * @return {@code true} if initiating binding succeed, {@code false} otherwise.
      */
     public boolean bind() {
-        final boolean bindResult = mContext.bindService(mServiceIntent, mFlags, mExecutor, this);
+        boolean bindResult = false;
+        try {
+            bindResult = mContext.bindService(mServiceIntent, mFlags, mExecutor, this);
+        } catch (SecurityException e) {
+            Log.d(TAG, "Could not bind to service", e);
+            mContext.unbindService(this);
+        }
         mBoundCalled = true;
         if (DEBUG) {
             Log.d(TAG, "bind. bound:" + bindResult);
@@ -197,7 +203,7 @@
             Log.d(TAG, "removeCallback:" + callback);
         }
 
-        mExecutor.execute(()-> mCallbacks.removeIf(el -> el.get() == callback));
+        mExecutor.execute(() -> mCallbacks.removeIf(el-> el.get() == callback));
     }
 
     private void onDisconnected(@DisconnectReason int reason) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 94ce002..95cc12a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -1508,6 +1508,7 @@
         mHandler.removeMessages(H.SHOW);
         if (mIsAnimatingDismiss) {
             Log.d(TAG, "dismissH: isAnimatingDismiss");
+            Trace.endSection();
             return;
         }
         mIsAnimatingDismiss = true;
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
index 76a01b9..54b3030 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
@@ -41,7 +41,7 @@
 import androidx.annotation.NonNull;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.LongRunning;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.util.concurrency.DelayableExecutor;
 
@@ -71,17 +71,16 @@
     private HandlerThread mWorker;
 
     // used for most tasks (call canvas.drawBitmap, load/unload the bitmap)
-    @Background
-    private final DelayableExecutor mBackgroundExecutor;
+    @LongRunning
+    private final DelayableExecutor mLongExecutor;
 
     // wait at least this duration before unloading the bitmap
     private static final int DELAY_UNLOAD_BITMAP = 2000;
 
     @Inject
-    public ImageWallpaper(@Background DelayableExecutor backgroundExecutor,
-            UserTracker userTracker) {
+    public ImageWallpaper(@LongRunning DelayableExecutor longExecutor, UserTracker userTracker) {
         super();
-        mBackgroundExecutor = backgroundExecutor;
+        mLongExecutor = longExecutor;
         mUserTracker = userTracker;
     }
 
@@ -131,7 +130,7 @@
             setFixedSizeAllowed(true);
             setShowForAllUsers(true);
             mWallpaperLocalColorExtractor = new WallpaperLocalColorExtractor(
-                    mBackgroundExecutor,
+                    mLongExecutor,
                     new WallpaperLocalColorExtractor.WallpaperLocalColorExtractorCallback() {
                         @Override
                         public void onColorsProcessed(List<RectF> regions,
@@ -230,7 +229,7 @@
         }
 
         private void drawFrame() {
-            mBackgroundExecutor.execute(this::drawFrameSynchronized);
+            mLongExecutor.execute(this::drawFrameSynchronized);
         }
 
         private void drawFrameSynchronized() {
@@ -285,7 +284,7 @@
         }
 
         private void unloadBitmapIfNotUsed() {
-            mBackgroundExecutor.execute(this::unloadBitmapIfNotUsedSynchronized);
+            mLongExecutor.execute(this::unloadBitmapIfNotUsedSynchronized);
         }
 
         private void unloadBitmapIfNotUsedSynchronized() {
@@ -381,7 +380,7 @@
                  *   - the mini bitmap from color extractor is recomputed
                  *   - the DELAY_UNLOAD_BITMAP has passed
                  */
-                mBackgroundExecutor.executeDelayed(
+                mLongExecutor.executeDelayed(
                         this::unloadBitmapIfNotUsedSynchronized, DELAY_UNLOAD_BITMAP);
             }
             // even if the bitmap cannot be loaded, call reportEngineShown
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractor.java b/packages/SystemUI/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractor.java
index 988fd71..1e8446f 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractor.java
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractor.java
@@ -29,7 +29,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
 
-import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.LongRunning;
 import com.android.systemui.util.Assert;
 
 import java.io.FileDescriptor;
@@ -66,8 +66,8 @@
     private final List<RectF> mPendingRegions = new ArrayList<>();
     private final Set<RectF> mProcessedRegions = new ArraySet<>();
 
-    @Background
-    private final Executor mBackgroundExecutor;
+    @LongRunning
+    private final Executor mLongExecutor;
 
     private final WallpaperLocalColorExtractorCallback mWallpaperLocalColorExtractorCallback;
 
@@ -101,13 +101,13 @@
 
     /**
      * Creates a new color extractor.
-     * @param backgroundExecutor the executor on which the color extraction will be performed
+     * @param longExecutor the executor on which the color extraction will be performed
      * @param wallpaperLocalColorExtractorCallback an interface to handle the callbacks from
      *                                        the color extractor.
      */
-    public WallpaperLocalColorExtractor(@Background Executor backgroundExecutor,
+    public WallpaperLocalColorExtractor(@LongRunning Executor longExecutor,
             WallpaperLocalColorExtractorCallback wallpaperLocalColorExtractorCallback) {
-        mBackgroundExecutor = backgroundExecutor;
+        mLongExecutor = longExecutor;
         mWallpaperLocalColorExtractorCallback = wallpaperLocalColorExtractorCallback;
     }
 
@@ -117,7 +117,7 @@
      * not recomputed.
      */
     public void setDisplayDimensions(int displayWidth, int displayHeight) {
-        mBackgroundExecutor.execute(() ->
+        mLongExecutor.execute(() ->
                 setDisplayDimensionsSynchronized(displayWidth, displayHeight));
     }
 
@@ -144,7 +144,7 @@
      * @param bitmap the new wallpaper
      */
     public void onBitmapChanged(@NonNull Bitmap bitmap) {
-        mBackgroundExecutor.execute(() -> onBitmapChangedSynchronized(bitmap));
+        mLongExecutor.execute(() -> onBitmapChangedSynchronized(bitmap));
     }
 
     private void onBitmapChangedSynchronized(@NonNull Bitmap bitmap) {
@@ -167,7 +167,7 @@
      * @param pages the total number of pages of the launcher
      */
     public void onPageChanged(int pages) {
-        mBackgroundExecutor.execute(() -> onPageChangedSynchronized(pages));
+        mLongExecutor.execute(() -> onPageChangedSynchronized(pages));
     }
 
     private void onPageChangedSynchronized(int pages) {
@@ -194,7 +194,7 @@
      */
     public void addLocalColorsAreas(@NonNull List<RectF> regions) {
         if (regions.size() > 0) {
-            mBackgroundExecutor.execute(() -> addLocalColorsAreasSynchronized(regions));
+            mLongExecutor.execute(() -> addLocalColorsAreasSynchronized(regions));
         } else {
             Log.w(TAG, "Attempt to add colors with an empty list");
         }
@@ -218,7 +218,7 @@
      * @param regions The areas of interest in our wallpaper (in screen pixel coordinates)
      */
     public void removeLocalColorAreas(@NonNull List<RectF> regions) {
-        mBackgroundExecutor.execute(() -> removeLocalColorAreasSynchronized(regions));
+        mLongExecutor.execute(() -> removeLocalColorAreasSynchronized(regions));
     }
 
     private void removeLocalColorAreasSynchronized(@NonNull List<RectF> regions) {
@@ -236,7 +236,7 @@
      * Clean up the memory (in particular, the mini bitmap) used by this class.
      */
     public void cleanUp() {
-        mBackgroundExecutor.execute(this::cleanUpSynchronized);
+        mLongExecutor.execute(this::cleanUpSynchronized);
     }
 
     private void cleanUpSynchronized() {
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
index 9600fd8..08f7eae 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
@@ -25,7 +25,6 @@
 import static android.service.notification.NotificationStats.DISMISSAL_BUBBLE;
 import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL;
 
-import static com.android.systemui.flags.Flags.WM_BUBBLE_BAR;
 import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES;
 import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
 
@@ -364,7 +363,6 @@
                 });
             }
         };
-        mBubbles.setBubbleBarEnabled(featureFlags.isEnabled(WM_BUBBLE_BAR));
         mBubbles.setSysuiProxy(mSysuiProxy);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
index 082c8cc..13b3b1a 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
@@ -18,8 +18,10 @@
 
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
+import android.view.View
 import android.view.inputmethod.InputMethodManager
 import android.widget.EditText
+import android.widget.ImageView
 import androidx.test.filters.SmallTest
 import com.android.internal.util.LatencyTracker
 import com.android.internal.widget.LockPatternUtils
@@ -30,6 +32,7 @@
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
 import org.mockito.ArgumentMatchers.anyBoolean
 import org.mockito.ArgumentMatchers.anyString
 import org.mockito.Mock
@@ -37,6 +40,7 @@
 import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.`when`
+import org.mockito.Mockito.mock
 import org.mockito.MockitoAnnotations
 
 @SmallTest
@@ -76,7 +80,9 @@
     Mockito.`when`(keyguardPasswordView.findViewById<EditText>(R.id.passwordEntry))
         .thenReturn(passwordEntry)
     `when`(keyguardPasswordView.resources).thenReturn(context.resources)
-    keyguardPasswordViewController =
+    `when`(keyguardPasswordView.findViewById<ImageView>(R.id.switch_ime_button))
+        .thenReturn(mock(ImageView::class.java))
+     keyguardPasswordViewController =
         KeyguardPasswordViewController(
             keyguardPasswordView,
             keyguardUpdateMonitor,
@@ -113,6 +119,18 @@
   }
 
   @Test
+  fun onApplyWindowInsetsListener_onApplyWindowInsets() {
+      `when`(keyguardViewController.isBouncerShowing).thenReturn(false)
+      val argumentCaptor = ArgumentCaptor.forClass(View.OnApplyWindowInsetsListener::class.java)
+
+      keyguardPasswordViewController.onViewAttached()
+      verify(keyguardPasswordView).setOnApplyWindowInsetsListener(argumentCaptor.capture())
+      argumentCaptor.value.onApplyWindowInsets(keyguardPasswordView, null)
+
+      verify(keyguardPasswordView).hideKeyboard()
+  }
+
+  @Test
   fun testHideKeyboardWhenOnPause() {
     keyguardPasswordViewController.onPause()
     keyguardPasswordView.post {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
index 064bc9c..38d3a3e 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
@@ -521,6 +521,38 @@
     }
 
     @Test
+    public void testWillRunDismissFromKeyguardIsTrue() {
+        ActivityStarter.OnDismissAction action = mock(ActivityStarter.OnDismissAction.class);
+        when(action.willRunAnimationOnKeyguard()).thenReturn(true);
+        mKeyguardSecurityContainerController.setOnDismissAction(action, null /* cancelAction */);
+
+        mKeyguardSecurityContainerController.finish(false /* strongAuth */, 0 /* currentUser */);
+
+        assertThat(mKeyguardSecurityContainerController.willRunDismissFromKeyguard()).isTrue();
+    }
+
+    @Test
+    public void testWillRunDismissFromKeyguardIsFalse() {
+        ActivityStarter.OnDismissAction action = mock(ActivityStarter.OnDismissAction.class);
+        when(action.willRunAnimationOnKeyguard()).thenReturn(false);
+        mKeyguardSecurityContainerController.setOnDismissAction(action, null /* cancelAction */);
+
+        mKeyguardSecurityContainerController.finish(false /* strongAuth */, 0 /* currentUser */);
+
+        assertThat(mKeyguardSecurityContainerController.willRunDismissFromKeyguard()).isFalse();
+    }
+
+    @Test
+    public void testWillRunDismissFromKeyguardIsFalseWhenNoDismissActionSet() {
+        mKeyguardSecurityContainerController.setOnDismissAction(null /* action */,
+                null /* cancelAction */);
+
+        mKeyguardSecurityContainerController.finish(false /* strongAuth */, 0 /* currentUser */);
+
+        assertThat(mKeyguardSecurityContainerController.willRunDismissFromKeyguard()).isFalse();
+    }
+
+    @Test
     public void testOnStartingToHide() {
         mKeyguardSecurityContainerController.onStartingToHide();
         verify(mInputViewController).onStartingToHide();
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
index 1bbc199..565fc57 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
@@ -37,6 +37,7 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -160,6 +161,29 @@
     }
 
     @Test
+    public void testOnApplyWindowInsets_disappearAnimation_paddingNotSet() {
+        int paddingBottom = getContext().getResources()
+                .getDimensionPixelSize(R.dimen.keyguard_security_view_bottom_margin);
+        int imeInsetAmount = paddingBottom + 1;
+        int systemBarInsetAmount = 0;
+        initMode(MODE_DEFAULT);
+
+        Insets imeInset = Insets.of(0, 0, 0, imeInsetAmount);
+        Insets systemBarInset = Insets.of(0, 0, 0, systemBarInsetAmount);
+
+        WindowInsets insets = new WindowInsets.Builder()
+                .setInsets(ime(), imeInset)
+                .setInsetsIgnoringVisibility(systemBars(), systemBarInset)
+                .build();
+
+        ensureViewFlipperIsMocked();
+        mKeyguardSecurityContainer.startDisappearAnimation(
+                KeyguardSecurityModel.SecurityMode.Password);
+        mKeyguardSecurityContainer.onApplyWindowInsets(insets);
+        assertThat(mKeyguardSecurityContainer.getPaddingBottom()).isNotEqualTo(imeInsetAmount);
+    }
+
+    @Test
     public void testDefaultViewMode() {
         initMode(MODE_ONE_HANDED);
         initMode(MODE_DEFAULT);
@@ -239,9 +263,6 @@
         assertThat(viewFlipperConstraint.layout.bottomToBottom).isEqualTo(PARENT_ID);
         assertThat(userSwitcherConstraint.layout.topToTop).isEqualTo(PARENT_ID);
         assertThat(userSwitcherConstraint.layout.bottomToBottom).isEqualTo(PARENT_ID);
-        assertThat(userSwitcherConstraint.layout.bottomMargin).isEqualTo(
-                getContext().getResources().getDimensionPixelSize(
-                        R.dimen.bouncer_user_switcher_y_trans));
         assertThat(viewFlipperConstraint.layout.horizontalChainStyle).isEqualTo(CHAIN_SPREAD);
         assertThat(userSwitcherConstraint.layout.horizontalChainStyle).isEqualTo(CHAIN_SPREAD);
         assertThat(viewFlipperConstraint.layout.mHeight).isEqualTo(MATCH_CONSTRAINT);
@@ -376,6 +397,17 @@
         assertThat(mKeyguardSecurityContainer.getScaleY()).isEqualTo(1);
     }
 
+    @Test
+    public void testDisappearAnimationPassword() {
+        ensureViewFlipperIsMocked();
+        KeyguardPasswordView keyguardPasswordView = mock(KeyguardPasswordView.class);
+        when(mSecurityViewFlipper.getSecurityView()).thenReturn(keyguardPasswordView);
+
+        mKeyguardSecurityContainer
+                .startDisappearAnimation(KeyguardSecurityModel.SecurityMode.Password);
+        verify(keyguardPasswordView).setDisappearAnimationListener(any());
+    }
+
     private BackEvent createBackEvent(float touchX, float progress) {
         return new BackEvent(0, 0, progress, BackEvent.EDGE_LEFT);
     }
@@ -446,4 +478,12 @@
                 mUserSwitcherController, () -> {
                 }, mFalsingA11yDelegate);
     }
+
+    private void ensureViewFlipperIsMocked() {
+        mSecurityViewFlipper = mock(KeyguardSecurityViewFlipper.class);
+        KeyguardPasswordView keyguardPasswordView = mock(KeyguardPasswordView.class);
+        when(mSecurityViewFlipper.getSecurityView()).thenReturn(keyguardPasswordView);
+        mKeyguardSecurityContainer.mSecurityViewFlipper = mSecurityViewFlipper;
+    }
+
 }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 09b738f..86ba30c 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -18,9 +18,10 @@
 
 import static android.app.StatusBarManager.SESSION_KEYGUARD;
 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
-import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_TIMED;
 import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT;
 import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT_PERMANENT;
+import static android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN;
+import static android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_STARTED_WAKING_UP;
 import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON;
 import static android.telephony.SubscriptionManager.DATA_ROAMING_DISABLE;
 import static android.telephony.SubscriptionManager.NAME_SOURCE_CARRIER_ID;
@@ -30,7 +31,6 @@
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
 import static com.android.keyguard.FaceAuthApiRequestReason.NOTIFICATION_PANEL_CLICKED;
 import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_AVAILABLE;
-import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_STATE_CANCELLING;
 import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_STATE_CANCELLING_RESTARTING;
 import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT;
 import static com.android.keyguard.KeyguardUpdateMonitor.HAL_POWER_PRESS_TIMEOUT;
@@ -59,8 +59,6 @@
 import static org.mockito.Mockito.when;
 
 import android.app.Activity;
-import android.app.ActivityManager;
-import android.app.IActivityManager;
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.IStrongAuthTracker;
 import android.app.trust.TrustManager;
@@ -82,6 +80,7 @@
 import android.hardware.biometrics.ComponentInfoInternal;
 import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
 import android.hardware.biometrics.SensorProperties;
+import android.hardware.face.FaceAuthenticateOptions;
 import android.hardware.face.FaceManager;
 import android.hardware.face.FaceSensorProperties;
 import android.hardware.face.FaceSensorPropertiesInternal;
@@ -97,7 +96,6 @@
 import android.os.Bundle;
 import android.os.CancellationSignal;
 import android.os.Handler;
-import android.os.IRemoteCallback;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -156,6 +154,7 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicBoolean;
 
@@ -239,8 +238,6 @@
     @Mock
     private KeyguardUpdateMonitorLogger mKeyguardUpdateMonitorLogger;
     @Mock
-    private IActivityManager mActivityService;
-    @Mock
     private SessionTracker mSessionTracker;
     @Mock
     private UiEventLogger mUiEventLogger;
@@ -282,8 +279,6 @@
     @Before
     public void setup() throws RemoteException {
         MockitoAnnotations.initMocks(this);
-        when(mActivityService.getCurrentUser()).thenReturn(mCurrentUserInfo);
-        when(mActivityService.getCurrentUserId()).thenReturn(mCurrentUserId);
         when(mFaceManager.isHardwareDetected()).thenReturn(true);
         when(mAuthController.isFaceAuthEnrolled(anyInt())).thenReturn(true);
         when(mFaceManager.getSensorPropertiesInternal()).thenReturn(mFaceSensorProperties);
@@ -322,13 +317,11 @@
 
         mMockitoSession = ExtendedMockito.mockitoSession()
                 .spyStatic(SubscriptionManager.class)
-                .spyStatic(ActivityManager.class)
                 .startMocking();
         ExtendedMockito.doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
                 .when(SubscriptionManager::getDefaultSubscriptionId);
         KeyguardUpdateMonitor.setCurrentUser(mCurrentUserId);
         when(mUserTracker.getUserId()).thenReturn(mCurrentUserId);
-        ExtendedMockito.doReturn(mActivityService).when(ActivityManager::getService);
 
         mContext.getOrCreateTestableResources().addOverride(
                 com.android.systemui.R.integer.config_face_auth_supported_posture,
@@ -633,20 +626,48 @@
 
     @Test
     public void testOnlyDetectFingerprint_whenFingerprintUnlockNotAllowed() {
-        // Clear invocations, since previous setup (e.g. registering BiometricManager callbacks)
-        // will trigger updateBiometricListeningState();
-        clearInvocations(mFingerprintManager);
-        mKeyguardUpdateMonitor.resetBiometricListeningState();
-
-        when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
-        mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
-        mTestableLooper.processAllMessages();
+        givenDetectFingerprintWithClearingFingerprintManagerInvocations();
 
         verifyFingerprintAuthenticateNeverCalled();
         verifyFingerprintDetectCall();
     }
 
     @Test
+    public void whenDetectFingerprint_biometricDetectCallback() {
+        ArgumentCaptor<FingerprintManager.FingerprintDetectionCallback> fpDetectCallbackCaptor =
+                ArgumentCaptor.forClass(FingerprintManager.FingerprintDetectionCallback.class);
+
+        givenDetectFingerprintWithClearingFingerprintManagerInvocations();
+        verify(mFingerprintManager).detectFingerprint(
+                any(), fpDetectCallbackCaptor.capture(), any());
+        fpDetectCallbackCaptor.getValue().onFingerprintDetected(0, 0, true);
+
+        // THEN verify keyguardUpdateMonitorCallback receives a detect callback
+        // and NO authenticate callbacks
+        verify(mTestCallback).onBiometricDetected(
+                eq(0), eq(BiometricSourceType.FINGERPRINT), eq(true));
+        verify(mTestCallback, never()).onBiometricAuthenticated(
+                anyInt(), any(), anyBoolean());
+    }
+
+    @Test
+    public void whenDetectFace_biometricDetectCallback() {
+        ArgumentCaptor<FaceManager.FaceDetectionCallback> faceDetectCallbackCaptor =
+                ArgumentCaptor.forClass(FaceManager.FaceDetectionCallback.class);
+
+        givenDetectFace();
+        verify(mFaceManager).detectFace(any(), faceDetectCallbackCaptor.capture(), any());
+        faceDetectCallbackCaptor.getValue().onFaceDetected(0, 0, false);
+
+        // THEN verify keyguardUpdateMonitorCallback receives a detect callback
+        // and NO authenticate callbacks
+        verify(mTestCallback).onBiometricDetected(
+                eq(0), eq(BiometricSourceType.FACE), eq(false));
+        verify(mTestCallback, never()).onBiometricAuthenticated(
+                anyInt(), any(), anyBoolean());
+    }
+
+    @Test
     public void testUnlockingWithFaceAllowed_strongAuthTrackerUnlockingWithBiometricAllowed() {
         // GIVEN unlocking with biometric is allowed
         strongAuthNotRequired();
@@ -674,7 +695,7 @@
         strongAuthNotRequired();
 
         // WHEN fingerprint is locked out
-        fingerprintErrorLockedOut();
+        fingerprintErrorTemporaryLockedOut();
 
         // THEN unlocking with face is not allowed
         Assert.assertFalse(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
@@ -697,7 +718,7 @@
         strongAuthNotRequired();
 
         // WHEN fingerprint is locked out
-        fingerprintErrorLockedOut();
+        fingerprintErrorTemporaryLockedOut();
 
         // THEN unlocking with fingerprint is not allowed
         Assert.assertFalse(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
@@ -721,7 +742,7 @@
         Assert.assertTrue(mKeyguardUpdateMonitor.getUserHasTrust(getCurrentUser()));
 
         // WHEN fingerprint is locked out
-        fingerprintErrorLockedOut();
+        fingerprintErrorTemporaryLockedOut();
 
         // THEN user is NOT considered as "having trust" and bouncer cannot be skipped
         Assert.assertFalse(mKeyguardUpdateMonitor.getUserHasTrust(getCurrentUser()));
@@ -781,11 +802,6 @@
 
     @Test
     public void nofaceDetect_whenStrongAuthRequiredAndBypassUdfpsSupportedAndFpRunning() {
-        // GIVEN mocked keyguardUpdateMonitorCallback
-        KeyguardUpdateMonitorCallback keyguardUpdateMonitorCallback =
-                mock(KeyguardUpdateMonitorCallback.class);
-        mKeyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback);
-
         // GIVEN bypass is enabled, face detection is supported
         lockscreenBypassIsAllowed();
         supportsFaceDetection();
@@ -804,22 +820,13 @@
         verifyFaceAuthenticateNeverCalled();
 
         // THEN biometric help message sent to callback
-        verify(keyguardUpdateMonitorCallback).onBiometricHelp(
+        verify(mTestCallback).onBiometricHelp(
                 eq(BIOMETRIC_HELP_FACE_NOT_AVAILABLE), anyString(), eq(BiometricSourceType.FACE));
     }
 
     @Test
     public void faceDetect_whenStrongAuthRequiredAndBypass() {
-        // GIVEN bypass is enabled, face detection is supported and strong auth is required
-        lockscreenBypassIsAllowed();
-        supportsFaceDetection();
-        strongAuthRequiredEncrypted();
-        keyguardIsVisible();
-        // fingerprint is NOT running, UDFPS is NOT supported
-
-        // WHEN the device wakes up
-        mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
-        mTestableLooper.processAllMessages();
+        givenDetectFace();
 
         // FACE detect is triggered, not authenticate
         verifyFaceDetectCall();
@@ -836,39 +843,6 @@
     }
 
     @Test
-    public void noFaceRun_whenFpLockout() {
-        // GIVEN bypass is enabled, face detection is supported and strong auth is required
-        lockscreenBypassIsAllowed();
-        supportsFaceDetection();
-        strongAuthRequiredEncrypted();
-        keyguardIsVisible();
-        // fingerprint is NOT running, UDFPS is NOT supported
-
-        // GIVEN fp is locked out
-        when(mFingerprintManager.getLockoutModeForUser(eq(FINGERPRINT_SENSOR_ID), anyInt()))
-                .thenReturn(BIOMETRIC_LOCKOUT_TIMED);
-        mKeyguardUpdateMonitor.handleUserSwitchComplete(0);
-        assertThat(mKeyguardUpdateMonitor.isFingerprintLockedOut()).isEqualTo(true);
-
-        // WHEN the device wakes up
-        mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
-        mTestableLooper.processAllMessages();
-
-        // FACE detect is NOT triggered and face authenticate is NOT triggered
-        verifyFaceDetectNeverCalled();
-        verifyFaceAuthenticateNeverCalled();
-
-        // WHEN bouncer becomes visible
-        setKeyguardBouncerVisibility(true);
-        clearInvocations(mFaceManager);
-
-        // THEN face scanning is not run
-        mKeyguardUpdateMonitor.requestFaceAuth(FaceAuthApiRequestReason.UDFPS_POINTER_DOWN);
-        verifyFaceAuthenticateNeverCalled();
-        verifyFaceDetectNeverCalled();
-    }
-
-    @Test
     public void noFaceDetect_whenStrongAuthRequiredAndBypass_faceDetectionUnsupported() {
         // GIVEN bypass is enabled, face detection is NOT supported and strong auth is required
         lockscreenBypassIsAllowed();
@@ -1100,11 +1074,6 @@
 
     @Test
     public void testBiometricsCleared_whenUserSwitches() throws Exception {
-        final IRemoteCallback reply = new IRemoteCallback.Stub() {
-            @Override
-            public void sendResult(Bundle data) {
-            } // do nothing
-        };
         final BiometricAuthenticated dummyAuthentication =
                 new BiometricAuthenticated(true /* authenticated */, true /* strong */);
         mKeyguardUpdateMonitor.mUserFaceAuthenticated.put(0 /* user */, dummyAuthentication);
@@ -1112,18 +1081,13 @@
         assertThat(mKeyguardUpdateMonitor.mUserFingerprintAuthenticated.size()).isEqualTo(1);
         assertThat(mKeyguardUpdateMonitor.mUserFaceAuthenticated.size()).isEqualTo(1);
 
-        mKeyguardUpdateMonitor.handleUserSwitching(10 /* user */, reply);
+        mKeyguardUpdateMonitor.handleUserSwitching(10 /* user */, new CountDownLatch(0));
         assertThat(mKeyguardUpdateMonitor.mUserFingerprintAuthenticated.size()).isEqualTo(0);
         assertThat(mKeyguardUpdateMonitor.mUserFaceAuthenticated.size()).isEqualTo(0);
     }
 
     @Test
     public void testMultiUserJankMonitor_whenUserSwitches() throws Exception {
-        final IRemoteCallback reply = new IRemoteCallback.Stub() {
-            @Override
-            public void sendResult(Bundle data) {
-            } // do nothing
-        };
         mKeyguardUpdateMonitor.handleUserSwitchComplete(10 /* user */);
         verify(mInteractionJankMonitor).end(InteractionJankMonitor.CUJ_USER_SWITCH);
         verify(mLatencyTracker).onActionEnd(LatencyTracker.ACTION_USER_SWITCH);
@@ -1186,8 +1150,7 @@
         // Fingerprint should be cancelled on lockout if going to lockout state, else
         // restarted if it's not
         assertThat(mKeyguardUpdateMonitor.mFingerprintRunningState)
-                .isEqualTo(fpLocked
-                        ? BIOMETRIC_STATE_CANCELLING : BIOMETRIC_STATE_CANCELLING_RESTARTING);
+                .isEqualTo(BIOMETRIC_STATE_CANCELLING_RESTARTING);
     }
 
     @Test
@@ -1646,7 +1609,7 @@
         assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
 
         // Fingerprint is locked out.
-        fingerprintErrorLockedOut();
+        fingerprintErrorTemporaryLockedOut();
 
         assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
     }
@@ -2247,6 +2210,32 @@
     }
 
     @Test
+    public void testPostureChangeToUnsupported_stopsFaceListeningState() {
+        // GIVEN device is listening for face
+        mKeyguardUpdateMonitor.mConfigFaceAuthSupportedPosture = DEVICE_POSTURE_CLOSED;
+        deviceInPostureStateClosed();
+        mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
+        mTestableLooper.processAllMessages();
+        keyguardIsVisible();
+
+        verifyFaceAuthenticateCall();
+
+        final CancellationSignal faceCancel = spy(mKeyguardUpdateMonitor.mFaceCancelSignal);
+        mKeyguardUpdateMonitor.mFaceCancelSignal = faceCancel;
+        KeyguardUpdateMonitorCallback callback = mock(KeyguardUpdateMonitorCallback.class);
+        mKeyguardUpdateMonitor.registerCallback(callback);
+
+        // WHEN device is opened
+        deviceInPostureStateOpened();
+        mTestableLooper.processAllMessages();
+
+        // THEN face listening is stopped.
+        verify(faceCancel).cancel();
+        verify(callback).onBiometricRunningStateChanged(
+                eq(false), eq(BiometricSourceType.FACE));
+    }
+
+    @Test
     public void testShouldListenForFace_withLockedDown_returnsFalse()
             throws RemoteException {
         keyguardNotGoingAway();
@@ -2499,7 +2488,69 @@
                 eq(false));
     }
 
+    @Test
+    public void detectFingerprint_onTemporaryLockoutReset_authenticateFingerprint() {
+        ArgumentCaptor<FingerprintManager.LockoutResetCallback> fpLockoutResetCallbackCaptor =
+                ArgumentCaptor.forClass(FingerprintManager.LockoutResetCallback.class);
+        verify(mFingerprintManager).addLockoutResetCallback(fpLockoutResetCallbackCaptor.capture());
+
+        // GIVEN device is locked out
+        fingerprintErrorTemporaryLockedOut();
+
+        // GIVEN FP detection is running
+        givenDetectFingerprintWithClearingFingerprintManagerInvocations();
+        verifyFingerprintDetectCall();
+        verifyFingerprintAuthenticateNeverCalled();
+
+        // WHEN temporary lockout resets
+        fpLockoutResetCallbackCaptor.getValue().onLockoutReset(0);
+        mTestableLooper.processAllMessages();
+
+        // THEN fingerprint detect state should cancel & then restart (for authenticate call)
+        assertThat(mKeyguardUpdateMonitor.mFingerprintRunningState)
+                .isEqualTo(BIOMETRIC_STATE_CANCELLING_RESTARTING);
+    }
+
+    @Test
+    public void faceAuthenticateOptions_bouncerAuthenticateReason() {
+        // GIVEN the bouncer is fully visible
+        bouncerFullyVisible();
+
+        // WHEN authenticate is called
+        ArgumentCaptor<FaceAuthenticateOptions> captor =
+                ArgumentCaptor.forClass(FaceAuthenticateOptions.class);
+        verify(mFaceManager).authenticate(any(), any(), any(), any(), captor.capture());
+
+        // THEN the authenticate reason is attributed to the bouncer
+        assertThat(captor.getValue().getAuthenticateReason())
+                .isEqualTo(AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN);
+    }
+
+    @Test
+    public void faceAuthenticateOptions_wakingUpAuthenticateReason_powerButtonWakeReason() {
+        // GIVEN keyguard is visible
+        keyguardIsVisible();
+
+        // WHEN device wakes up from the power button
+        mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
+        mTestableLooper.processAllMessages();
+
+        // THEN face auth is triggered
+        ArgumentCaptor<FaceAuthenticateOptions> captor =
+                ArgumentCaptor.forClass(FaceAuthenticateOptions.class);
+        verify(mFaceManager).authenticate(any(), any(), any(), any(), captor.capture());
+
+        // THEN the authenticate reason is attributed to the waking
+        assertThat(captor.getValue().getAuthenticateReason())
+                .isEqualTo(AUTHENTICATE_REASON_STARTED_WAKING_UP);
+
+        // THEN the wake reason is attributed to the power button
+        assertThat(captor.getValue().getWakeReason())
+                .isEqualTo(PowerManager.WAKE_REASON_POWER_BUTTON);
+    }
+
     private void verifyFingerprintAuthenticateNeverCalled() {
+        verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), any());
         verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
                 anyInt(), anyInt());
     }
@@ -2518,11 +2569,12 @@
     }
 
     private void verifyFaceAuthenticateNeverCalled() {
+        verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), any());
         verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
     }
 
     private void verifyFaceAuthenticateCall() {
-        verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
+        verify(mFaceManager).authenticate(any(), any(), any(), any(), any());
     }
 
     private void verifyFaceDetectNeverCalled() {
@@ -2602,7 +2654,7 @@
         mKeyguardUpdateMonitor.setSwitchingUser(true);
     }
 
-    private void fingerprintErrorLockedOut() {
+    private void fingerprintErrorTemporaryLockedOut() {
         mKeyguardUpdateMonitor.mFingerprintAuthenticationCallback
                 .onAuthenticationError(FINGERPRINT_ERROR_LOCKOUT, "Fingerprint locked out");
     }
@@ -2630,7 +2682,7 @@
                 any(),
                 mAuthenticationCallbackCaptor.capture(),
                 any(),
-                anyInt());
+                any());
         mAuthenticationCallbackCaptor.getValue()
                 .onAuthenticationSucceeded(
                         new FaceManager.AuthenticationResult(null, null, mCurrentUserId, false));
@@ -2741,6 +2793,30 @@
         receiver.setPendingResult(pendingResult);
     }
 
+    private void givenDetectFingerprintWithClearingFingerprintManagerInvocations() {
+        // Clear invocations, since previous setup (e.g. registering BiometricManager callbacks)
+        // will trigger updateBiometricListeningState();
+        clearInvocations(mFingerprintManager);
+        mKeyguardUpdateMonitor.resetBiometricListeningState();
+
+        when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
+        mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
+        mTestableLooper.processAllMessages();
+    }
+
+    private void givenDetectFace() {
+        // GIVEN bypass is enabled, face detection is supported and strong auth is required
+        lockscreenBypassIsAllowed();
+        supportsFaceDetection();
+        strongAuthRequiredEncrypted();
+        keyguardIsVisible();
+        // fingerprint is NOT running, UDFPS is NOT supported
+
+        // WHEN the device wakes up
+        mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
+        mTestableLooper.processAllMessages();
+    }
+
     private Intent putPhoneInfo(Intent intent, Bundle data, Boolean simInited) {
         int subscription = simInited
                 ? 1/* mock subid=1 */ : SubscriptionManager.PLACEHOLDER_SUBSCRIPTION_ID_BASE;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
index f370ad6..33f0ae5 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
@@ -36,6 +36,7 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.settingslib.udfps.UdfpsOverlayParams;
 import com.android.systemui.doze.util.BurnInHelperKt;
 
 import org.junit.Test;
@@ -107,7 +108,7 @@
         Pair<Float, Point> udfps = setupUdfps();
 
         // WHEN udfps location changes
-        mAuthControllerCallback.onUdfpsLocationChanged();
+        mAuthControllerCallback.onUdfpsLocationChanged(new UdfpsOverlayParams());
         mDelayableExecutor.runAllReady();
 
         // THEN lock icon view location is updated with the same coordinates as auth controller vals
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/FontInterpolatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/FontInterpolatorTest.kt
index f01da2d..8a5c5b5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/FontInterpolatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/FontInterpolatorTest.kt
@@ -61,7 +61,7 @@
         val interp = FontInterpolator()
         assertSameAxes(startFont, interp.lerp(startFont, endFont, 0f))
         assertSameAxes(endFont, interp.lerp(startFont, endFont, 1f))
-        assertSameAxes("'wght' 500, 'ital' 0.5, 'GRAD' 450", interp.lerp(startFont, endFont, 0.5f))
+        assertSameAxes("'wght' 496, 'ital' 0.5, 'GRAD' 450", interp.lerp(startFont, endFont, 0.5f))
     }
 
     @Test
@@ -74,7 +74,7 @@
                 .build()
 
         val interp = FontInterpolator()
-        assertSameAxes("'wght' 250, 'ital' 0.5", interp.lerp(startFont, endFont, 0.5f))
+        assertSameAxes("'wght' 249, 'ital' 0.5", interp.lerp(startFont, endFont, 0.5f))
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index e1c7417..c068efb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -35,7 +35,6 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
@@ -930,6 +929,15 @@
         assertNotSame(firstFpLocation, mAuthController.getFingerprintSensorLocation());
     }
 
+    @Test
+    public void testCloseDialog_whenGlobalActionsMenuShown() throws Exception {
+        showDialog(new int[]{1} /* sensorIds */, false /* credentialAllowed */);
+        mAuthController.handleShowGlobalActionsMenu();
+        verify(mReceiver).onDialogDismissed(
+                eq(BiometricPrompt.DISMISSED_REASON_USER_CANCEL),
+                eq(null) /* credentialAttestation */);
+    }
+
     private void showDialog(int[] sensorIds, boolean credentialAllowed) {
         mAuthController.showAuthenticationDialog(createTestPromptInfo(),
                 mReceiver /* receiver */,
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 b765ab3..6e423593 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
@@ -17,15 +17,17 @@
 package com.android.systemui.biometrics
 
 import android.graphics.Point
-import android.hardware.biometrics.BiometricSourceType
+import android.hardware.biometrics.BiometricSourceType.FACE
+import android.hardware.biometrics.BiometricSourceType.FINGERPRINT
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper.RunWithLooper
 import androidx.test.filters.SmallTest
 import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
 import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.keyguard.KeyguardUpdateMonitorCallback
+import com.android.keyguard.logging.KeyguardLogger
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.logcatLogBuffer
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.keyguard.WakefulnessLifecycle
 import com.android.systemui.plugins.statusbar.StatusBarStateController
@@ -34,11 +36,11 @@
 import com.android.systemui.statusbar.commandline.CommandRegistry
 import com.android.systemui.statusbar.phone.BiometricUnlockController
 import com.android.systemui.statusbar.phone.CentralSurfaces
-import com.android.systemui.statusbar.phone.KeyguardBypassController
 import com.android.systemui.statusbar.policy.ConfigurationController
 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
@@ -48,15 +50,15 @@
 import org.mockito.ArgumentCaptor
 import org.mockito.ArgumentMatchers
 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)
@@ -73,7 +75,6 @@
     @Mock private lateinit var keyguardStateController: KeyguardStateController
     @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
     @Mock private lateinit var notificationShadeWindowController: NotificationShadeWindowController
-    @Mock private lateinit var bypassController: KeyguardBypassController
     @Mock private lateinit var biometricUnlockController: BiometricUnlockController
     @Mock private lateinit var udfpsControllerProvider: Provider<UdfpsController>
     @Mock private lateinit var udfpsController: UdfpsController
@@ -82,10 +83,15 @@
     @Mock private lateinit var lightRevealScrim: LightRevealScrim
     @Mock private lateinit var fpSensorProp: FingerprintSensorPropertiesInternal
 
+    @Captor
+    private lateinit var biometricModeListener:
+        ArgumentCaptor<BiometricUnlockController.BiometricModeListener>
+
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
-        staticMockSession = mockitoSession()
+        staticMockSession =
+            mockitoSession()
                 .mockStatic(RotationUtils::class.java)
                 .strictness(Strictness.LENIENT)
                 .startMocking()
@@ -94,23 +100,24 @@
         `when`(authController.udfpsProps).thenReturn(listOf(fpSensorProp))
         `when`(udfpsControllerProvider.get()).thenReturn(udfpsController)
 
-        controller = AuthRippleController(
-            mCentralSurfaces,
-            context,
-            authController,
-            configurationController,
-            keyguardUpdateMonitor,
-            keyguardStateController,
-            wakefulnessLifecycle,
-            commandRegistry,
-            notificationShadeWindowController,
-            bypassController,
-            biometricUnlockController,
-            udfpsControllerProvider,
-            statusBarStateController,
-            featureFlags,
-            rippleView
-        )
+        controller =
+            AuthRippleController(
+                mCentralSurfaces,
+                context,
+                authController,
+                configurationController,
+                keyguardUpdateMonitor,
+                keyguardStateController,
+                wakefulnessLifecycle,
+                commandRegistry,
+                notificationShadeWindowController,
+                biometricUnlockController,
+                udfpsControllerProvider,
+                statusBarStateController,
+                featureFlags,
+                KeyguardLogger(logcatLogBuffer(AuthRippleController.TAG)),
+                rippleView
+            )
         controller.init()
         `when`(mCentralSurfaces.lightRevealScrim).thenReturn(lightRevealScrim)
     }
@@ -127,16 +134,14 @@
         `when`(authController.fingerprintSensorLocation).thenReturn(fpsLocation)
         controller.onViewAttached()
         `when`(keyguardStateController.isShowing).thenReturn(true)
-        `when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
-                eq(BiometricSourceType.FINGERPRINT))).thenReturn(true)
+        `when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(eq(FINGERPRINT)))
+            .thenReturn(true)
+        `when`(biometricUnlockController.isBiometricUnlock).thenReturn(true)
+        `when`(biometricUnlockController.biometricType).thenReturn(FINGERPRINT)
 
-        // WHEN fingerprint authenticated
-        val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
-        verify(keyguardUpdateMonitor).registerCallback(captor.capture())
-        captor.value.onBiometricAuthenticated(
-            0 /* userId */,
-            BiometricSourceType.FINGERPRINT /* type */,
-            false /* isStrongBiometric */)
+        // WHEN unlocked with fingerprint
+        verify(biometricUnlockController).addBiometricModeListener(biometricModeListener.capture())
+        biometricModeListener.value.onModeChanged(/* mode= */ 0)
 
         // THEN update sensor location and show ripple
         verify(rippleView).setFingerprintSensorLocation(fpsLocation, 0f)
@@ -149,17 +154,15 @@
         val fpsLocation = Point(5, 5)
         `when`(authController.udfpsLocation).thenReturn(fpsLocation)
         controller.onViewAttached()
-        `when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
-                eq(BiometricSourceType.FINGERPRINT))).thenReturn(true)
+        `when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(eq(FINGERPRINT)))
+            .thenReturn(true)
+        `when`(biometricUnlockController.isBiometricUnlock).thenReturn(true)
+        `when`(biometricUnlockController.biometricType).thenReturn(FINGERPRINT)
 
         // WHEN keyguard is NOT showing & fingerprint authenticated
         `when`(keyguardStateController.isShowing).thenReturn(false)
-        val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
-        verify(keyguardUpdateMonitor).registerCallback(captor.capture())
-        captor.value.onBiometricAuthenticated(
-            0 /* userId */,
-            BiometricSourceType.FINGERPRINT /* type */,
-            false /* isStrongBiometric */)
+        verify(biometricUnlockController).addBiometricModeListener(biometricModeListener.capture())
+        biometricModeListener.value.onModeChanged(/* mode= */ 0)
 
         // THEN no ripple
         verify(rippleView, never()).startUnlockedRipple(any())
@@ -172,61 +175,14 @@
         `when`(authController.udfpsLocation).thenReturn(fpsLocation)
         controller.onViewAttached()
         `when`(keyguardStateController.isShowing).thenReturn(true)
+        `when`(biometricUnlockController.isBiometricUnlock).thenReturn(true)
+        `when`(biometricUnlockController.biometricType).thenReturn(FINGERPRINT)
 
         // WHEN unlocking with fingerprint is NOT allowed & fingerprint authenticated
-        `when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
-                eq(BiometricSourceType.FINGERPRINT))).thenReturn(false)
-        val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
-        verify(keyguardUpdateMonitor).registerCallback(captor.capture())
-        captor.value.onBiometricAuthenticated(
-            0 /* userId */,
-            BiometricSourceType.FINGERPRINT /* type */,
-            false /* isStrongBiometric */)
-
-        // THEN no ripple
-        verify(rippleView, never()).startUnlockedRipple(any())
-    }
-
-    @Test
-    fun testFaceTriggerBypassEnabled_Ripple() {
-        // GIVEN face auth sensor exists, keyguard is showing & unlocking with face is allowed
-        val faceLocation = Point(5, 5)
-        `when`(authController.faceSensorLocation).thenReturn(faceLocation)
-        controller.onViewAttached()
-
-        `when`(keyguardStateController.isShowing).thenReturn(true)
-        `when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
-                BiometricSourceType.FACE)).thenReturn(true)
-
-        // WHEN bypass is enabled & face authenticated
-        `when`(bypassController.canBypass()).thenReturn(true)
-        val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
-        verify(keyguardUpdateMonitor).registerCallback(captor.capture())
-        captor.value.onBiometricAuthenticated(
-            0 /* userId */,
-            BiometricSourceType.FACE /* type */,
-            false /* isStrongBiometric */)
-
-        // THEN show ripple
-        verify(rippleView).setSensorLocation(faceLocation)
-        verify(rippleView).startUnlockedRipple(any())
-    }
-
-    @Test
-    fun testFaceTriggerNonBypass_NoRipple() {
-        // GIVEN face auth sensor exists
-        val faceLocation = Point(5, 5)
-        `when`(authController.faceSensorLocation).thenReturn(faceLocation)
-        controller.onViewAttached()
-
-        // WHEN bypass isn't enabled & face authenticated
-        `when`(bypassController.canBypass()).thenReturn(false)
-        val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
-        verify(keyguardUpdateMonitor).registerCallback(captor.capture())
-        captor.value.onBiometricAuthenticated(
-            0 /* userId */,
-            BiometricSourceType.FACE /* type */,
-            false /* isStrongBiometric */)
+        `when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(eq(FINGERPRINT)))
+            .thenReturn(false)
+        verify(biometricUnlockController).addBiometricModeListener(biometricModeListener.capture())
+        biometricModeListener.value.onModeChanged(/* mode= */ 0)
 
         // THEN no ripple
         verify(rippleView, never()).startUnlockedRipple(any())
@@ -236,14 +192,12 @@
     fun testNullFaceSensorLocationDoesNothing() {
         `when`(authController.faceSensorLocation).thenReturn(null)
         controller.onViewAttached()
+        `when`(biometricUnlockController.biometricType).thenReturn(FACE)
+        `when`(biometricUnlockController.isBiometricUnlock).thenReturn(true)
 
-        val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
-        verify(keyguardUpdateMonitor).registerCallback(captor.capture())
+        verify(biometricUnlockController).addBiometricModeListener(biometricModeListener.capture())
+        biometricModeListener.value.onModeChanged(/* mode= */ 0)
 
-        captor.value.onBiometricAuthenticated(
-            0 /* userId */,
-            BiometricSourceType.FACE /* type */,
-            false /* isStrongBiometric */)
         verify(rippleView, never()).startUnlockedRipple(any())
     }
 
@@ -251,25 +205,21 @@
     fun testNullFingerprintSensorLocationDoesNothing() {
         `when`(authController.fingerprintSensorLocation).thenReturn(null)
         controller.onViewAttached()
+        `when`(biometricUnlockController.biometricType).thenReturn(FINGERPRINT)
+        `when`(biometricUnlockController.isBiometricUnlock).thenReturn(true)
 
-        val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
-        verify(keyguardUpdateMonitor).registerCallback(captor.capture())
+        verify(biometricUnlockController).addBiometricModeListener(biometricModeListener.capture())
+        biometricModeListener.value.onModeChanged(/* mode= */ 0)
 
-        captor.value.onBiometricAuthenticated(
-            0 /* userId */,
-            BiometricSourceType.FINGERPRINT /* type */,
-            false /* isStrongBiometric */)
         verify(rippleView, never()).startUnlockedRipple(any())
     }
 
     @Test
     fun registersAndDeregisters() {
         controller.onViewAttached()
-        val captor = ArgumentCaptor
-            .forClass(KeyguardStateController.Callback::class.java)
+        val captor = ArgumentCaptor.forClass(KeyguardStateController.Callback::class.java)
         verify(keyguardStateController).addCallback(captor.capture())
-        val captor2 = ArgumentCaptor
-            .forClass(WakefulnessLifecycle.Observer::class.java)
+        val captor2 = ArgumentCaptor.forClass(WakefulnessLifecycle.Observer::class.java)
         verify(wakefulnessLifecycle).addObserver(captor2.capture())
         controller.onViewDetached()
         verify(keyguardStateController).removeCallback(any())
@@ -283,17 +233,20 @@
         `when`(authController.fingerprintSensorLocation).thenReturn(fpsLocation)
         controller.onViewAttached()
         `when`(keyguardStateController.isShowing).thenReturn(true)
-        `when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
-                BiometricSourceType.FINGERPRINT)).thenReturn(true)
+        `when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(FINGERPRINT)).thenReturn(true)
         `when`(biometricUnlockController.isWakeAndUnlock).thenReturn(true)
 
-        controller.showUnlockRipple(BiometricSourceType.FINGERPRINT)
-        assertTrue("reveal didn't start on keyguardFadingAway",
-            controller.startLightRevealScrimOnKeyguardFadingAway)
+        controller.showUnlockRipple(FINGERPRINT)
+        assertTrue(
+            "reveal didn't start on keyguardFadingAway",
+            controller.startLightRevealScrimOnKeyguardFadingAway
+        )
         `when`(keyguardStateController.isKeyguardFadingAway).thenReturn(true)
         controller.onKeyguardFadingAwayChanged()
-        assertFalse("reveal triggers multiple times",
-            controller.startLightRevealScrimOnKeyguardFadingAway)
+        assertFalse(
+            "reveal triggers multiple times",
+            controller.startLightRevealScrimOnKeyguardFadingAway
+        )
     }
 
     @Test
@@ -305,23 +258,26 @@
         `when`(keyguardStateController.isShowing).thenReturn(true)
         `when`(biometricUnlockController.isWakeAndUnlock).thenReturn(true)
         `when`(authController.isUdfpsFingerDown).thenReturn(true)
-        `when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
-                eq(BiometricSourceType.FACE))).thenReturn(true)
+        `when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(eq(FACE))).thenReturn(true)
 
-        controller.showUnlockRipple(BiometricSourceType.FACE)
-        assertTrue("reveal didn't start on keyguardFadingAway",
-                controller.startLightRevealScrimOnKeyguardFadingAway)
+        controller.showUnlockRipple(FACE)
+        assertTrue(
+            "reveal didn't start on keyguardFadingAway",
+            controller.startLightRevealScrimOnKeyguardFadingAway
+        )
         `when`(keyguardStateController.isKeyguardFadingAway).thenReturn(true)
         controller.onKeyguardFadingAwayChanged()
-        assertFalse("reveal triggers multiple times",
-                controller.startLightRevealScrimOnKeyguardFadingAway)
+        assertFalse(
+            "reveal triggers multiple times",
+            controller.startLightRevealScrimOnKeyguardFadingAway
+        )
     }
 
     @Test
     fun testUpdateRippleColor() {
         controller.onViewAttached()
-        val captor = ArgumentCaptor
-            .forClass(ConfigurationController.ConfigurationListener::class.java)
+        val captor =
+            ArgumentCaptor.forClass(ConfigurationController.ConfigurationListener::class.java)
         verify(configurationController).addCallback(captor.capture())
 
         reset(rippleView)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
index 6333a68..3ec49b2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
@@ -354,7 +354,9 @@
             deviceConfig = DeviceConfig.X_ALIGNED,
             isReverseDefaultRotation = false,
             { rotation = Surface.ROTATION_0 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_90() =
@@ -362,7 +364,9 @@
             deviceConfig = DeviceConfig.X_ALIGNED,
             isReverseDefaultRotation = false,
             { rotation = Surface.ROTATION_90 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_180() =
@@ -370,7 +374,9 @@
             deviceConfig = DeviceConfig.X_ALIGNED,
             isReverseDefaultRotation = false,
             { rotation = Surface.ROTATION_180 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarCollapsedDownForXAlignedSensor_180() =
@@ -379,7 +385,9 @@
             isReverseDefaultRotation = false,
             { rotation = Surface.ROTATION_180 },
             windowInsets = insetsForSmallNavbar()
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun hidesSfpsIndicatorWhenOccludingTaskbarForXAlignedSensor_180() =
@@ -388,7 +396,9 @@
             isReverseDefaultRotation = false,
             { rotation = Surface.ROTATION_180 },
             windowInsets = insetsForLargeNavbar()
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_270() =
@@ -396,7 +406,9 @@
             deviceConfig = DeviceConfig.X_ALIGNED,
             isReverseDefaultRotation = false,
             { rotation = Surface.ROTATION_270 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_0() =
@@ -404,7 +416,9 @@
             deviceConfig = DeviceConfig.X_ALIGNED,
             isReverseDefaultRotation = true,
             { rotation = Surface.ROTATION_0 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_90() =
@@ -412,7 +426,9 @@
             deviceConfig = DeviceConfig.X_ALIGNED,
             isReverseDefaultRotation = true,
             { rotation = Surface.ROTATION_90 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarCollapsedDownForXAlignedSensor_InReverseDefaultRotation_90() =
@@ -421,7 +437,9 @@
             isReverseDefaultRotation = true,
             { rotation = Surface.ROTATION_90 },
             windowInsets = insetsForSmallNavbar()
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun hidesSfpsIndicatorWhenOccludingTaskbarForXAlignedSensor_InReverseDefaultRotation_90() =
@@ -430,7 +448,9 @@
             isReverseDefaultRotation = true,
             { rotation = Surface.ROTATION_90 },
             windowInsets = insetsForLargeNavbar()
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_180() =
@@ -438,7 +458,9 @@
             deviceConfig = DeviceConfig.X_ALIGNED,
             isReverseDefaultRotation = true,
             { rotation = Surface.ROTATION_180 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_270() =
@@ -446,7 +468,9 @@
             deviceConfig = DeviceConfig.X_ALIGNED,
             isReverseDefaultRotation = true,
             { rotation = Surface.ROTATION_270 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_0() =
@@ -454,7 +478,9 @@
             deviceConfig = DeviceConfig.Y_ALIGNED,
             isReverseDefaultRotation = false,
             { rotation = Surface.ROTATION_0 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_90() =
@@ -462,7 +488,9 @@
             deviceConfig = DeviceConfig.Y_ALIGNED,
             isReverseDefaultRotation = false,
             { rotation = Surface.ROTATION_90 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_180() =
@@ -480,7 +508,9 @@
             deviceConfig = DeviceConfig.Y_ALIGNED,
             isReverseDefaultRotation = false,
             { rotation = Surface.ROTATION_270 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarCollapsedDownForYAlignedSensor_270() =
@@ -489,7 +519,9 @@
             isReverseDefaultRotation = false,
             { rotation = Surface.ROTATION_270 },
             windowInsets = insetsForSmallNavbar()
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun hidesSfpsIndicatorWhenOccludingTaskbarForYAlignedSensor_270() =
@@ -498,7 +530,9 @@
             isReverseDefaultRotation = false,
             { rotation = Surface.ROTATION_270 },
             windowInsets = insetsForLargeNavbar()
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_0() =
@@ -506,7 +540,9 @@
             deviceConfig = DeviceConfig.Y_ALIGNED,
             isReverseDefaultRotation = true,
             { rotation = Surface.ROTATION_0 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_90() =
@@ -524,7 +560,9 @@
             deviceConfig = DeviceConfig.Y_ALIGNED,
             isReverseDefaultRotation = true,
             { rotation = Surface.ROTATION_180 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarCollapsedDownForYAlignedSensor_InReverseDefaultRotation_180() =
@@ -533,7 +571,9 @@
             isReverseDefaultRotation = true,
             { rotation = Surface.ROTATION_180 },
             windowInsets = insetsForSmallNavbar()
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun hidesSfpsIndicatorWhenOccludingTaskbarForYAlignedSensor_InReverseDefaultRotation_180() =
@@ -542,7 +582,9 @@
             isReverseDefaultRotation = true,
             { rotation = Surface.ROTATION_180 },
             windowInsets = insetsForLargeNavbar()
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_270() =
@@ -550,7 +592,9 @@
             deviceConfig = DeviceConfig.Y_ALIGNED,
             isReverseDefaultRotation = true,
             { rotation = Surface.ROTATION_270 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun verifiesSfpsIndicatorNotAddedInRearDisplayMode_0() =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index 05266f1..9a73898 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -1224,6 +1224,44 @@
     }
 
     @Test
+    public void onTouch_WithNewTouchDetection_forwardToKeyguard() throws RemoteException {
+        final NormalizedTouchData touchData = new NormalizedTouchData(0, 0f, 0f, 0f, 0f, 0f, 0L,
+                0L);
+        final TouchProcessorResult processorResultDown = new TouchProcessorResult.ProcessedTouch(
+                InteractionEvent.UNCHANGED, -1 /* pointerOnSensorId */, touchData);
+
+        // Enable new touch detection.
+        when(mFeatureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)).thenReturn(true);
+
+        // Configure UdfpsController to use FingerprintManager as opposed to AlternateTouchProvider.
+        initUdfpsController(mOpticalProps, false /* hasAlternateTouchProvider */);
+
+        // Configure UdfpsView to accept the ACTION_DOWN event
+        when(mUdfpsView.isDisplayConfigured()).thenReturn(false);
+        when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(false);
+
+        // GIVEN that the overlay is showing and a11y touch exploration NOT enabled
+        when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
+        when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(false);
+        mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId,
+                BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
+        mFgExecutor.runAllReady();
+
+        verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture());
+
+        // WHEN ACTION_DOWN is received
+        when(mSinglePointerTouchProcessor.processTouch(any(), anyInt(), any())).thenReturn(
+                processorResultDown);
+        MotionEvent downEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0);
+        mTouchListenerCaptor.getValue().onTouch(mUdfpsView, downEvent);
+        mBiometricExecutor.runAllReady();
+
+        // THEN the touch is forwarded to Keyguard
+        verify(mStatusBarKeyguardViewManager).onTouch(downEvent);
+        downEvent.recycle();
+    }
+
+    @Test
     public void onAodInterrupt_onAcquiredGood_fingerNoLongerDown() throws RemoteException {
         // GIVEN UDFPS overlay is showing
         mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
index 86fb279..786cb01 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
@@ -138,7 +138,7 @@
 
             // WHEN the bouncer expansion is VISIBLE
             val job = mController.listenForBouncerExpansion(this)
-            keyguardBouncerRepository.setPrimaryVisible(true)
+            keyguardBouncerRepository.setPrimaryShow(true)
             keyguardBouncerRepository.setPanelExpansion(KeyguardBouncerConstants.EXPANSION_VISIBLE)
             yield()
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractorTest.kt
new file mode 100644
index 0000000..87d5ae6
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractorTest.kt
@@ -0,0 +1,116 @@
+/*
+ * 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.graphics.Rect
+import android.test.suitebuilder.annotation.SmallTest
+import android.view.MotionEvent
+import android.view.Surface
+import com.android.settingslib.udfps.UdfpsOverlayParams
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.AuthController
+import com.android.systemui.coroutines.collectLastValue
+import com.google.common.truth.Truth.assertThat
+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.ArgumentCaptor
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.junit.MockitoJUnit
+
+@SmallTest
+@RunWith(JUnit4::class)
+class UdfpsOverlayInteractorTest : SysuiTestCase() {
+
+    @JvmField @Rule var mockitoRule = MockitoJUnit.rule()
+
+    private lateinit var testScope: TestScope
+
+    @Mock private lateinit var authController: AuthController
+    @Captor private lateinit var authControllerCallback: ArgumentCaptor<AuthController.Callback>
+
+    @Mock private lateinit var udfpsOverlayParams: UdfpsOverlayParams
+    @Mock private lateinit var overlayBounds: Rect
+
+    private lateinit var underTest: UdfpsOverlayInteractor
+
+    @Before
+    fun setUp() {
+        testScope = TestScope(StandardTestDispatcher())
+    }
+
+    @Test
+    fun testShouldInterceptTouch() =
+        testScope.runTest {
+            createUdpfsOverlayInteractor()
+
+            // When fingerprint enrolled and touch is within bounds
+            verify(authController).addCallback(authControllerCallback.capture())
+            authControllerCallback.value.onUdfpsLocationChanged(udfpsOverlayParams)
+            whenever(authController.isUdfpsEnrolled(anyInt())).thenReturn(true)
+            whenever(udfpsOverlayParams.overlayBounds).thenReturn(overlayBounds)
+            whenever(overlayBounds.contains(downEv.x.toInt(), downEv.y.toInt())).thenReturn(true)
+
+            runCurrent()
+
+            // Then touch should not be intercepted
+            val canInterceptTrue = underTest.canInterceptTouchInUdfpsBounds(downEv)
+            assertThat(canInterceptTrue).isFalse()
+
+            // When touch is outside of bounds
+            whenever(overlayBounds.contains(downEv.x.toInt(), downEv.y.toInt())).thenReturn(false)
+
+            // Then touch should be intercepted
+            val canInterceptFalse = underTest.canInterceptTouchInUdfpsBounds(downEv)
+            assertThat(canInterceptFalse).isTrue()
+        }
+
+    @Test
+    fun testUdfpsOverlayParamsChange() =
+        testScope.runTest {
+            createUdpfsOverlayInteractor()
+            val udfpsOverlayParams = collectLastValue(underTest.udfpsOverlayParams)
+            runCurrent()
+
+            verify(authController).addCallback(authControllerCallback.capture())
+
+            // When udfpsLocationChanges in authcontroller
+            authControllerCallback.value.onUdfpsLocationChanged(firstParams)
+
+            // Then the value in the interactor should be updated
+            assertThat(udfpsOverlayParams()).isEqualTo(firstParams)
+        }
+
+    private fun createUdpfsOverlayInteractor() {
+        underTest = UdfpsOverlayInteractor(authController, testScope.backgroundScope)
+        testScope.runCurrent()
+    }
+}
+
+private val firstParams =
+    UdfpsOverlayParams(Rect(0, 0, 10, 10), Rect(0, 0, 10, 10), 1, 1, 1f, Surface.ROTATION_0)
+private val downEv = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/BroadcastDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/BroadcastDialogTest.java
index 3503902..9d16185 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/BroadcastDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/BroadcastDialogTest.java
@@ -45,8 +45,8 @@
 public class BroadcastDialogTest extends SysuiTestCase {
 
     private static final String CURRENT_BROADCAST_APP = "Music";
-    private static final String SWITCH_APP = "Files by Google";
-    private static final String TEST_PACKAGE = "com.google.android.apps.nbu.files";
+    private static final String SWITCH_APP = "System UI";
+    private static final String TEST_PACKAGE = "com.android.systemui";
     private BroadcastDialog mBroadcastDialog;
     private View mDialogView;
     private TextView mTitle;
@@ -59,6 +59,7 @@
         MockitoAnnotations.initMocks(this);
         mBroadcastDialog = new BroadcastDialog(mContext, mock(MediaOutputDialogFactory.class),
                 CURRENT_BROADCAST_APP, TEST_PACKAGE, mock(UiEventLogger.class));
+
         mBroadcastDialog.show();
         mDialogView = mBroadcastDialog.mDialogView;
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java
index faa5db4..ab6d5b7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java
@@ -94,7 +94,9 @@
         mClassifier.onTouchEvent(appendMoveEvent(1, 16, 3));
         mClassifier.onTouchEvent(appendMoveEvent(1, 17, 300));
         mClassifier.onTouchEvent(appendMoveEvent(1, 18, 301));
-        mClassifier.onTouchEvent(appendUpEvent(1, 19, 501));
+        mClassifier.onTouchEvent(appendMoveEvent(1, 19, 501));
+        mClassifier.onTouchEvent(appendUpEvent(1, 19, 501)); //event will be dropped
+
         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isTrue();
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java
index 2edc3d3..8eadadf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java
@@ -75,16 +75,17 @@
     }
 
     @Test
-    public void test_trackMotionEvents() {
+    public void test_trackMotionEvents_dropUpEvent() {
         mDataProvider.onMotionEvent(appendDownEvent(2, 9));
         mDataProvider.onMotionEvent(appendMoveEvent(4, 7));
-        mDataProvider.onMotionEvent(appendUpEvent(6, 5));
+        mDataProvider.onMotionEvent(appendMoveEvent(6, 5));
+        mDataProvider.onMotionEvent(appendUpEvent(0, 0)); // event will be dropped
         List<MotionEvent> motionEventList = mDataProvider.getRecentMotionEvents();
 
         assertThat(motionEventList.size()).isEqualTo(3);
         assertThat(motionEventList.get(0).getActionMasked()).isEqualTo(MotionEvent.ACTION_DOWN);
         assertThat(motionEventList.get(1).getActionMasked()).isEqualTo(MotionEvent.ACTION_MOVE);
-        assertThat(motionEventList.get(2).getActionMasked()).isEqualTo(MotionEvent.ACTION_UP);
+        assertThat(motionEventList.get(2).getActionMasked()).isEqualTo(MotionEvent.ACTION_MOVE);
         assertThat(motionEventList.get(0).getEventTime()).isEqualTo(1L);
         assertThat(motionEventList.get(1).getEventTime()).isEqualTo(2L);
         assertThat(motionEventList.get(2).getEventTime()).isEqualTo(3L);
@@ -97,6 +98,28 @@
     }
 
     @Test
+    public void test_trackMotionEvents_keepUpEvent() {
+        mDataProvider.onMotionEvent(appendDownEvent(2, 9));
+        mDataProvider.onMotionEvent(appendMoveEvent(4, 7));
+        mDataProvider.onMotionEvent(appendUpEvent(0, 0, 100));
+        List<MotionEvent> motionEventList = mDataProvider.getRecentMotionEvents();
+
+        assertThat(motionEventList.size()).isEqualTo(3);
+        assertThat(motionEventList.get(0).getActionMasked()).isEqualTo(MotionEvent.ACTION_DOWN);
+        assertThat(motionEventList.get(1).getActionMasked()).isEqualTo(MotionEvent.ACTION_MOVE);
+        assertThat(motionEventList.get(2).getActionMasked()).isEqualTo(MotionEvent.ACTION_UP);
+        assertThat(motionEventList.get(0).getEventTime()).isEqualTo(1L);
+        assertThat(motionEventList.get(1).getEventTime()).isEqualTo(2L);
+        assertThat(motionEventList.get(2).getEventTime()).isEqualTo(100);
+        assertThat(motionEventList.get(0).getX()).isEqualTo(2f);
+        assertThat(motionEventList.get(1).getX()).isEqualTo(4f);
+        assertThat(motionEventList.get(2).getX()).isEqualTo(0f);
+        assertThat(motionEventList.get(0).getY()).isEqualTo(9f);
+        assertThat(motionEventList.get(1).getY()).isEqualTo(7f);
+        assertThat(motionEventList.get(2).getY()).isEqualTo(0f);
+    }
+
+    @Test
     public void test_trackRecentMotionEvents() {
         mDataProvider.onMotionEvent(appendDownEvent(2, 9, 1));
         mDataProvider.onMotionEvent(appendMoveEvent(4, 7, 800));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java
index c343c20..ae2b8bb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java
@@ -68,6 +68,15 @@
     }
 
     @Test
+    public void testPass_dropClosingUpEvent() {
+        appendMoveEvent(0, 0);
+        appendMoveEvent(0, 100);
+        appendMoveEvent(0, 200);
+        appendUpEvent(0, 180); // this event would push us over the maxDevianceY
+        assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
+    }
+
+    @Test
     public void testPass_fewTouchesHorizontal() {
         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
         appendMoveEvent(0, 0);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java
index 2099281..ffd75fb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerTest.java
@@ -35,6 +35,7 @@
 import static org.mockito.Mockito.when;
 
 import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.app.RemoteAction;
 import android.content.ClipData;
 import android.content.ClipDescription;
@@ -101,6 +102,9 @@
     private ArgumentCaptor<ClipboardOverlayView.ClipboardOverlayCallbacks> mOverlayCallbacksCaptor;
     private ClipboardOverlayView.ClipboardOverlayCallbacks mCallbacks;
 
+    @Captor
+    private ArgumentCaptor<AnimatorListenerAdapter> mAnimatorArgumentCaptor;
+
     private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
 
     @Before
@@ -446,7 +450,7 @@
         mFeatureFlags.set(CLIPBOARD_REMOTE_BEHAVIOR, true);
         when(mClipboardUtils.isRemoteCopy(any(Context.class), any(ClipData.class), anyString()))
                 .thenReturn(true);
-        when(mClipboardUtils.getAction(any(CharSequence.class), any(TextLinks.class), anyString()))
+        when(mClipboardUtils.getAction(any(TextLinks.class), anyString()))
                 .thenReturn(Optional.of(Mockito.mock(RemoteAction.class)));
         when(mClipboardOverlayView.post(any(Runnable.class))).thenAnswer(new Answer<Object>() {
             @Override
@@ -478,12 +482,16 @@
         when(mClipboardOverlayWindow.getWindowInsets()).thenReturn(
                 getImeInsets(new Rect(0, 0, 0, 1)));
         mOverlayController.setClipData(mSampleClipData, "");
+        Animator mockFadeoutAnimator = Mockito.mock(Animator.class);
+        when(mClipboardOverlayView.getMinimizedFadeoutAnimation()).thenReturn(mockFadeoutAnimator);
 
         verify(mClipboardOverlayView).setMinimized(true);
         verify(mClipboardOverlayView, never()).setMinimized(false);
         verify(mClipboardOverlayView, never()).showTextPreview(any(), anyBoolean());
 
         mCallbacks.onMinimizedViewTapped();
+        verify(mockFadeoutAnimator).addListener(mAnimatorArgumentCaptor.capture());
+        mAnimatorArgumentCaptor.getValue().onAnimationEnd(mockFadeoutAnimator);
 
         verify(mClipboardOverlayView).setMinimized(false);
         verify(mClipboardOverlayView).showTextPreview("Test Item", false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtilsTest.java b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtilsTest.java
index aea6be3..3d8f04e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtilsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtilsTest.java
@@ -21,6 +21,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.when;
 
@@ -77,6 +78,74 @@
 
     @Test
     public void test_getAction_noLinks_returnsEmptyOptional() {
+        Optional<RemoteAction> action =
+                mClipboardUtils.getAction(Mockito.mock(TextLinks.class), "abc");
+
+        assertTrue(action.isEmpty());
+    }
+
+    @Test
+    public void test_getAction_returnsFirstLink() {
+        TextLinks links = getFakeTextLinksBuilder().build();
+        RemoteAction actionA = constructRemoteAction("abc");
+        RemoteAction actionB = constructRemoteAction("def");
+        TextClassification classificationA = Mockito.mock(TextClassification.class);
+        when(classificationA.getActions()).thenReturn(Lists.newArrayList(actionA));
+        TextClassification classificationB = Mockito.mock(TextClassification.class);
+        when(classificationB.getActions()).thenReturn(Lists.newArrayList(actionB));
+        when(mTextClassifier.classifyText(anyString(), anyInt(), anyInt(), isNull())).thenReturn(
+                classificationA, classificationB);
+
+        RemoteAction result = mClipboardUtils.getAction(links, "test").orElse(null);
+
+        assertEquals(actionA, result);
+    }
+
+    @Test
+    public void test_getAction_skipsMatchingComponent() {
+        TextLinks links = getFakeTextLinksBuilder().build();
+        RemoteAction actionA = constructRemoteAction("abc");
+        RemoteAction actionB = constructRemoteAction("def");
+        TextClassification classificationA = Mockito.mock(TextClassification.class);
+        when(classificationA.getActions()).thenReturn(Lists.newArrayList(actionA));
+        TextClassification classificationB = Mockito.mock(TextClassification.class);
+        when(classificationB.getActions()).thenReturn(Lists.newArrayList(actionB));
+        when(mTextClassifier.classifyText(anyString(), anyInt(), anyInt(), isNull())).thenReturn(
+                classificationA, classificationB);
+
+        RemoteAction result = mClipboardUtils.getAction(links, "abc").orElse(null);
+
+        assertEquals(actionB, result);
+    }
+
+    @Test
+    public void test_getAction_skipsShortEntity() {
+        TextLinks.Builder textLinks = new TextLinks.Builder("test text of length 22");
+        final Map<String, Float> scores = new ArrayMap<>();
+        scores.put(TextClassifier.TYPE_EMAIL, 1f);
+        textLinks.addLink(20, 22, scores);
+        textLinks.addLink(0, 22, scores);
+
+        RemoteAction actionA = constructRemoteAction("abc");
+        RemoteAction actionB = constructRemoteAction("def");
+        TextClassification classificationA = Mockito.mock(TextClassification.class);
+        when(classificationA.getActions()).thenReturn(Lists.newArrayList(actionA));
+        TextClassification classificationB = Mockito.mock(TextClassification.class);
+        when(classificationB.getActions()).thenReturn(Lists.newArrayList(actionB));
+        when(mTextClassifier.classifyText(anyString(), eq(20), eq(22), isNull())).thenReturn(
+                classificationA);
+        when(mTextClassifier.classifyText(anyString(), eq(0), eq(22), isNull())).thenReturn(
+                classificationB);
+
+        RemoteAction result = mClipboardUtils.getAction(textLinks.build(), "test").orElse(null);
+
+        assertEquals(actionB, result);
+    }
+
+    // TODO(b/267162944): Next four tests (marked "legacy") are obsolete once
+    //  CLIPBOARD_MINIMIZED_LAYOUT flag is released and removed
+    @Test
+    public void test_getAction_noLinks_returnsEmptyOptional_legacy() {
         ClipData.Item item = new ClipData.Item("no text links");
         item.setTextLinks(Mockito.mock(TextLinks.class));
 
@@ -86,8 +155,8 @@
     }
 
     @Test
-    public void test_getAction_returnsFirstLink() {
-        when(mClipDataItem.getTextLinks()).thenReturn(getFakeTextLinks());
+    public void test_getAction_returnsFirstLink_legacy() {
+        when(mClipDataItem.getTextLinks()).thenReturn(getFakeTextLinksBuilder().build());
         when(mClipDataItem.getText()).thenReturn("");
         RemoteAction actionA = constructRemoteAction("abc");
         RemoteAction actionB = constructRemoteAction("def");
@@ -98,14 +167,14 @@
         when(mTextClassifier.classifyText(anyString(), anyInt(), anyInt(), isNull())).thenReturn(
                 classificationA, classificationB);
 
-        RemoteAction result = mClipboardUtils.getAction(mClipDataItem, "def").orElse(null);
+        RemoteAction result = mClipboardUtils.getAction(mClipDataItem, "test").orElse(null);
 
         assertEquals(actionA, result);
     }
 
     @Test
-    public void test_getAction_skipsMatchingComponent() {
-        when(mClipDataItem.getTextLinks()).thenReturn(getFakeTextLinks());
+    public void test_getAction_skipsMatchingComponent_legacy() {
+        when(mClipDataItem.getTextLinks()).thenReturn(getFakeTextLinksBuilder().build());
         when(mClipDataItem.getText()).thenReturn("");
         RemoteAction actionA = constructRemoteAction("abc");
         RemoteAction actionB = constructRemoteAction("def");
@@ -122,6 +191,33 @@
     }
 
     @Test
+    public void test_getAction_skipsShortEntity_legacy() {
+        TextLinks.Builder textLinks = new TextLinks.Builder("test text of length 22");
+        final Map<String, Float> scores = new ArrayMap<>();
+        scores.put(TextClassifier.TYPE_EMAIL, 1f);
+        textLinks.addLink(20, 22, scores);
+        textLinks.addLink(0, 22, scores);
+
+        when(mClipDataItem.getTextLinks()).thenReturn(textLinks.build());
+        when(mClipDataItem.getText()).thenReturn(textLinks.build().getText());
+
+        RemoteAction actionA = constructRemoteAction("abc");
+        RemoteAction actionB = constructRemoteAction("def");
+        TextClassification classificationA = Mockito.mock(TextClassification.class);
+        when(classificationA.getActions()).thenReturn(Lists.newArrayList(actionA));
+        TextClassification classificationB = Mockito.mock(TextClassification.class);
+        when(classificationB.getActions()).thenReturn(Lists.newArrayList(actionB));
+        when(mTextClassifier.classifyText(anyString(), eq(20), eq(22), isNull())).thenReturn(
+                classificationA);
+        when(mTextClassifier.classifyText(anyString(), eq(0), eq(22), isNull())).thenReturn(
+                classificationB);
+
+        RemoteAction result = mClipboardUtils.getAction(mClipDataItem, "test").orElse(null);
+
+        assertEquals(actionB, result);
+    }
+
+    @Test
     public void test_extra_withPackage_returnsTrue() {
         PersistableBundle b = new PersistableBundle();
         b.putBoolean(ClipDescription.EXTRA_IS_REMOTE_DEVICE, true);
@@ -184,12 +280,12 @@
         return action;
     }
 
-    private static TextLinks getFakeTextLinks() {
-        TextLinks.Builder textLinks = new TextLinks.Builder("test");
+    private static TextLinks.Builder getFakeTextLinksBuilder() {
+        TextLinks.Builder textLinks = new TextLinks.Builder("test text of length 22");
         final Map<String, Float> scores = new ArrayMap<>();
         scores.put(TextClassifier.TYPE_EMAIL, 1f);
-        textLinks.addLink(0, 0, scores);
-        textLinks.addLink(0, 0, scores);
-        return textLinks.build();
+        textLinks.addLink(0, 22, scores);
+        textLinks.addLink(0, 22, scores);
+        return textLinks;
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsViewTest.java
index eafe727..afd9be5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsViewTest.java
@@ -107,4 +107,32 @@
 
         assertThat(mSeekbar.getProgress()).isEqualTo(0);
     }
+
+    @Test
+    public void setProgressStateLabels_getExpectedStateDescriptionOnInitialization() {
+        String[] stateLabels = new String[]{"1", "2", "3", "4", "5"};
+        mIconDiscreteSliderLinearLayout.setMax(stateLabels.length);
+        mIconDiscreteSliderLinearLayout.setProgress(1);
+        mIconDiscreteSliderLinearLayout.setProgressStateLabels(stateLabels);
+
+        final int currentProgress = mSeekbar.getProgress();
+        final CharSequence stateDescription = mSeekbar.getStateDescription();
+
+        assertThat(currentProgress).isEqualTo(1);
+        assertThat(stateDescription).isEqualTo(stateLabels[currentProgress]);
+    }
+
+    @Test
+    public void setProgressStateLabels_progressChanged_getExpectedStateDescription() {
+        String[] stateLabels = new String[]{"1", "2", "3", "4", "5"};
+        mIconDiscreteSliderLinearLayout.setMax(stateLabels.length);
+        mIconDiscreteSliderLinearLayout.setProgressStateLabels(stateLabels);
+        mIconDiscreteSliderLinearLayout.setProgress(1);
+
+        final int currentProgress = mSeekbar.getProgress();
+        final CharSequence stateDescription = mSeekbar.getStateDescription();
+
+        assertThat(currentProgress).isEqualTo(1);
+        assertThat(stateDescription).isEqualTo(stateLabels[currentProgress]);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
index e35b2a3..c98d537 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
@@ -34,16 +34,15 @@
 import com.android.systemui.controls.ControlsServiceInfo
 import com.android.systemui.controls.management.ControlsListingController
 import com.android.systemui.controls.panels.AuthorizedPanelsRepository
+import com.android.systemui.controls.panels.FakeSelectedComponentRepository
 import com.android.systemui.controls.ui.ControlsUiController
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.settings.UserFileManager
 import com.android.systemui.settings.UserTracker
 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.io.File
-import java.util.Optional
-import java.util.function.Consumer
 import org.junit.After
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
@@ -59,6 +58,7 @@
 import org.mockito.Mock
 import org.mockito.Mockito
 import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.clearInvocations
 import org.mockito.Mockito.inOrder
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.never
@@ -67,8 +67,10 @@
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.verifyNoMoreInteractions
 import org.mockito.Mockito.`when`
-import org.mockito.Mockito.clearInvocations
 import org.mockito.MockitoAnnotations
+import java.io.File
+import java.util.*
+import java.util.function.Consumer
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
@@ -107,6 +109,8 @@
     private lateinit var listingCallbackCaptor:
             ArgumentCaptor<ControlsListingController.ControlsListingCallback>
 
+    private val preferredPanelRepository = FakeSelectedComponentRepository()
+
     private lateinit var delayableExecutor: FakeExecutor
     private lateinit var controller: ControlsControllerImpl
     private lateinit var canceller: DidRunRunnable
@@ -146,6 +150,7 @@
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
+        whenever(authorizedPanelsRepository.getAuthorizedPanels()).thenReturn(setOf())
         `when`(userTracker.userHandle).thenReturn(UserHandle.of(user))
 
         delayableExecutor = FakeExecutor(FakeSystemClock())
@@ -166,6 +171,7 @@
                 wrapper,
                 delayableExecutor,
                 uiController,
+                preferredPanelRepository,
                 bindingController,
                 listingController,
                 userFileManager,
@@ -219,6 +225,7 @@
                 mContext,
                 delayableExecutor,
                 uiController,
+                preferredPanelRepository,
                 bindingController,
                 listingController,
                 userFileManager,
@@ -238,6 +245,7 @@
                 mContext,
                 delayableExecutor,
                 uiController,
+                preferredPanelRepository,
                 bindingController,
                 listingController,
                 userFileManager,
@@ -945,6 +953,28 @@
         controller.bindComponentForPanel(TEST_COMPONENT)
         verify(bindingController).bindServiceForPanel(TEST_COMPONENT)
     }
+
+    @Test
+    fun testRemoveFavoriteRemovesFavorite() {
+        val componentName = ComponentName(context, "test.Cls")
+        controller.addFavorite(
+                componentName,
+                "test structure",
+                ControlInfo(
+                        controlId = "testId",
+                        controlTitle = "Test Control",
+                        controlSubtitle = "test control subtitle",
+                        deviceType = DeviceTypes.TYPE_LIGHT,
+                ),
+        )
+
+        controller.removeFavorites(componentName)
+        delayableExecutor.runAllReady()
+
+        verify(authorizedPanelsRepository)
+                .removeAuthorizedPanels(eq(setOf(componentName.packageName)))
+        assertThat(controller.getFavorites()).isEmpty()
+    }
 }
 
 private class DidRunRunnable() : Runnable {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt
index 35cd3d2..10bfc1b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt
@@ -45,6 +45,8 @@
 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
+import java.util.concurrent.Executor
 import org.junit.After
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertNull
@@ -62,7 +64,6 @@
 import org.mockito.Mockito.reset
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
-import java.util.concurrent.Executor
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
@@ -106,6 +107,7 @@
         MockitoAnnotations.initMocks(this)
 
         `when`(userTracker.userId).thenReturn(user)
+        `when`(userTracker.userHandle).thenReturn(UserHandle.of(user))
         `when`(userTracker.userContext).thenReturn(context)
         // Return disabled by default
         `when`(packageManager.getComponentEnabledSetting(any()))
@@ -564,6 +566,79 @@
         assertTrue(controller.getCurrentServices().isEmpty())
     }
 
+    @Test
+    fun testForceReloadQueriesPackageManager() {
+        val user = 10
+        `when`(userTracker.userHandle).thenReturn(UserHandle.of(user))
+
+        controller.forceReload()
+        verify(packageManager).queryIntentServicesAsUser(
+                argThat(IntentMatcherAction(ControlsProviderService.SERVICE_CONTROLS)),
+                argThat(FlagsMatcher(
+                        PackageManager.GET_META_DATA.toLong() or
+                                PackageManager.GET_SERVICES.toLong() or
+                                PackageManager.MATCH_DIRECT_BOOT_AWARE.toLong() or
+                                PackageManager.MATCH_DIRECT_BOOT_UNAWARE.toLong()
+                )),
+                eq(UserHandle.of(user))
+        )
+    }
+
+    @Test
+    fun testForceReloadUpdatesList() {
+        val resolveInfo = ResolveInfo()
+        resolveInfo.serviceInfo = ServiceInfo(componentName)
+
+        `when`(packageManager.queryIntentServicesAsUser(
+                argThat(IntentMatcherAction(ControlsProviderService.SERVICE_CONTROLS)),
+                argThat(FlagsMatcher(
+                        PackageManager.GET_META_DATA.toLong() or
+                                PackageManager.GET_SERVICES.toLong() or
+                                PackageManager.MATCH_DIRECT_BOOT_AWARE.toLong() or
+                                PackageManager.MATCH_DIRECT_BOOT_UNAWARE.toLong()
+                )),
+                any<UserHandle>()
+        )).thenReturn(listOf(resolveInfo))
+
+        controller.forceReload()
+
+        val services = controller.getCurrentServices()
+        assertThat(services.size).isEqualTo(1)
+        assertThat(services[0].serviceInfo.componentName).isEqualTo(componentName)
+    }
+
+    @Test
+    fun testForceReloadCallsListeners() {
+        controller.addCallback(mockCallback)
+        executor.runAllReady()
+
+        @Suppress("unchecked_cast")
+        val captor: ArgumentCaptor<List<ControlsServiceInfo>> =
+                ArgumentCaptor.forClass(List::class.java)
+                        as ArgumentCaptor<List<ControlsServiceInfo>>
+
+        val resolveInfo = ResolveInfo()
+        resolveInfo.serviceInfo = ServiceInfo(componentName)
+
+        `when`(packageManager.queryIntentServicesAsUser(
+                any(),
+                any<PackageManager.ResolveInfoFlags>(),
+                any<UserHandle>()
+        )).thenReturn(listOf(resolveInfo))
+
+        reset(mockCallback)
+        controller.forceReload()
+
+        verify(mockCallback).onServicesUpdated(capture(captor))
+
+        val services = captor.value
+
+        assertThat(services.size).isEqualTo(1)
+        assertThat(services[0].serviceInfo.componentName).isEqualTo(componentName)
+    }
+
+
+
     private fun ServiceInfo(
             componentName: ComponentName,
             panelActivityComponentName: ComponentName? = null
@@ -600,7 +675,7 @@
     private fun setUpQueryResult(infos: List<ActivityInfo>) {
         `when`(
                 packageManager.queryIntentActivitiesAsUser(
-                        argThat(IntentMatcher(activityName)),
+                        argThat(IntentMatcherComponent(activityName)),
                         argThat(FlagsMatcher(FLAGS)),
                         eq(UserHandle.of(user))
                 )
@@ -609,7 +684,7 @@
         })
     }
 
-    private class IntentMatcher(
+    private class IntentMatcherComponent(
             private val componentName: ComponentName
     ) : ArgumentMatcher<Intent> {
         override fun matches(argument: Intent?): Boolean {
@@ -617,6 +692,14 @@
         }
     }
 
+    private class IntentMatcherAction(
+            private val action: String
+    ) : ArgumentMatcher<Intent> {
+        override fun matches(argument: Intent?): Boolean {
+            return argument?.action == action
+        }
+    }
+
     private class FlagsMatcher(
             private val flags: Long
     ) : ArgumentMatcher<PackageManager.ResolveInfoFlags> {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImplTest.kt
index b91a3fd..272f589 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImplTest.kt
@@ -22,6 +22,8 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags
 import com.android.systemui.settings.UserFileManager
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.util.FakeSharedPreferences
@@ -40,6 +42,8 @@
 
     @Mock private lateinit var userTracker: UserTracker
 
+    private val featureFlags = FakeFeatureFlags()
+
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
@@ -48,6 +52,7 @@
             arrayOf<String>()
         )
         whenever(userTracker.userId).thenReturn(0)
+        featureFlags.set(Flags.APP_PANELS_REMOVE_APPS_ALLOWED, true)
     }
 
     @Test
@@ -115,8 +120,37 @@
         assertThat(sharedPrefs.getStringSet(KEY, null)).containsExactly(TEST_PACKAGE)
     }
 
+    @Test
+    fun testRemoveAuthorizedPackageRemovesIt() {
+        val sharedPrefs = FakeSharedPreferences()
+        val fileManager = FakeUserFileManager(mapOf(0 to sharedPrefs))
+        val repository = createRepository(fileManager)
+        repository.addAuthorizedPanels(setOf(TEST_PACKAGE))
+
+        repository.removeAuthorizedPanels(setOf(TEST_PACKAGE))
+
+        assertThat(sharedPrefs.getStringSet(KEY, null)).isEmpty()
+    }
+
+    @Test
+    fun testSetAuthorizedPackageAfterFeatureDisabled() {
+        mContext.orCreateTestableResources.addOverride(
+            R.array.config_controlsPreferredPackages,
+            arrayOf(TEST_PACKAGE)
+        )
+        val sharedPrefs = FakeSharedPreferences()
+        val fileManager = FakeUserFileManager(mapOf(0 to sharedPrefs))
+        val repository = createRepository(fileManager)
+
+        repository.removeAuthorizedPanels(setOf(TEST_PACKAGE))
+
+        featureFlags.set(Flags.APP_PANELS_REMOVE_APPS_ALLOWED, false)
+
+        assertThat(repository.getAuthorizedPanels()).isEqualTo(setOf(TEST_PACKAGE))
+    }
+
     private fun createRepository(userFileManager: UserFileManager): AuthorizedPanelsRepositoryImpl {
-        return AuthorizedPanelsRepositoryImpl(mContext, userFileManager, userTracker)
+        return AuthorizedPanelsRepositoryImpl(mContext, userFileManager, userTracker, featureFlags)
     }
 
     private class FakeUserFileManager(private val sharedPrefs: Map<Int, SharedPreferences>) :
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/panels/FakeSelectedComponentRepository.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/panels/FakeSelectedComponentRepository.kt
new file mode 100644
index 0000000..a7677cc
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/panels/FakeSelectedComponentRepository.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.controls.panels
+
+class FakeSelectedComponentRepository : SelectedComponentRepository {
+
+    private var selectedComponent: SelectedComponentRepository.SelectedComponent? = null
+    private var shouldAddDefaultPanel: Boolean = true
+
+    override fun getSelectedComponent(): SelectedComponentRepository.SelectedComponent? =
+        selectedComponent
+
+    override fun setSelectedComponent(
+        selectedComponent: SelectedComponentRepository.SelectedComponent
+    ) {
+        this.selectedComponent = selectedComponent
+    }
+
+    override fun removeSelectedComponent() {
+        selectedComponent = null
+    }
+
+    override fun shouldAddDefaultComponent(): Boolean = shouldAddDefaultPanel
+
+    override fun setShouldAddDefaultComponent(shouldAdd: Boolean) {
+        shouldAddDefaultPanel = shouldAdd
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/panels/SelectedComponentRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/panels/SelectedComponentRepositoryTest.kt
new file mode 100644
index 0000000..0c7b9cb
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/panels/SelectedComponentRepositoryTest.kt
@@ -0,0 +1,163 @@
+/*
+ * 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.controls.panels
+
+import android.content.ComponentName
+import android.content.SharedPreferences
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.settings.UserFileManager
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl
+import com.android.systemui.util.FakeSharedPreferences
+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.Mock
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class SelectedComponentRepositoryTest : SysuiTestCase() {
+
+    private companion object {
+        val COMPONENT_A =
+            SelectedComponentRepository.SelectedComponent(
+                name = "a",
+                componentName = ComponentName.unflattenFromString("pkg/.cls_a"),
+                isPanel = false,
+            )
+        val COMPONENT_B =
+            SelectedComponentRepository.SelectedComponent(
+                name = "b",
+                componentName = ComponentName.unflattenFromString("pkg/.cls_b"),
+                isPanel = false,
+            )
+    }
+
+    @Mock private lateinit var userTracker: UserTracker
+    @Mock private lateinit var userFileManager: UserFileManager
+
+    private val featureFlags = FakeFeatureFlags()
+    private val sharedPreferences: SharedPreferences = FakeSharedPreferences()
+
+    // under test
+    private lateinit var repository: SelectedComponentRepository
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        whenever(userFileManager.getSharedPreferences(any(), any(), any()))
+            .thenReturn(sharedPreferences)
+
+        repository = SelectedComponentRepositoryImpl(userFileManager, userTracker, featureFlags)
+    }
+
+    @Test
+    fun testUnsetIsNull() {
+        assertThat(repository.getSelectedComponent()).isNull()
+    }
+
+    @Test
+    fun testGetReturnsSet() {
+        repository.setSelectedComponent(COMPONENT_A)
+
+        assertThat(repository.getSelectedComponent()).isEqualTo(COMPONENT_A)
+    }
+
+    @Test
+    fun testSetOverrides() {
+        repository.setSelectedComponent(COMPONENT_A)
+        repository.setSelectedComponent(COMPONENT_B)
+
+        assertThat(repository.getSelectedComponent()).isEqualTo(COMPONENT_B)
+    }
+
+    @Test
+    fun testRemove() {
+        repository.setSelectedComponent(COMPONENT_A)
+
+        repository.removeSelectedComponent()
+
+        assertThat(repository.getSelectedComponent()).isNull()
+    }
+
+    @Test
+    fun testFeatureEnabled_shouldAddDefaultPanelDefaultsToTrue() {
+        featureFlags.set(Flags.APP_PANELS_REMOVE_APPS_ALLOWED, true)
+
+        assertThat(repository.shouldAddDefaultComponent()).isTrue()
+    }
+
+    @Test
+    fun testFeatureDisabled_shouldAddDefaultPanelDefaultsToTrue() {
+        featureFlags.set(Flags.APP_PANELS_REMOVE_APPS_ALLOWED, false)
+
+        assertThat(repository.shouldAddDefaultComponent()).isTrue()
+    }
+
+    @Test
+    fun testFeatureEnabled_shouldAddDefaultPanelChecked() {
+        featureFlags.set(Flags.APP_PANELS_REMOVE_APPS_ALLOWED, true)
+        repository.setShouldAddDefaultComponent(false)
+
+        assertThat(repository.shouldAddDefaultComponent()).isFalse()
+    }
+
+    @Test
+    fun testFeatureDisabled_shouldAlwaysAddDefaultPanelAlwaysTrue() {
+        featureFlags.set(Flags.APP_PANELS_REMOVE_APPS_ALLOWED, false)
+        repository.setShouldAddDefaultComponent(false)
+
+        assertThat(repository.shouldAddDefaultComponent()).isTrue()
+    }
+
+    @Test
+    fun testGetPreferredStructure_differentUserId() {
+        sharedPreferences.savePanel(COMPONENT_A)
+        whenever(
+                userFileManager.getSharedPreferences(
+                    DeviceControlsControllerImpl.PREFS_CONTROLS_FILE,
+                    0,
+                    1,
+                )
+            )
+            .thenReturn(FakeSharedPreferences().also { it.savePanel(COMPONENT_B) })
+
+        val previousPreferredStructure = repository.getSelectedComponent()
+        whenever(userTracker.userId).thenReturn(1)
+        val currentPreferredStructure = repository.getSelectedComponent()
+
+        assertThat(previousPreferredStructure).isEqualTo(COMPONENT_A)
+        assertThat(currentPreferredStructure).isNotEqualTo(previousPreferredStructure)
+        assertThat(currentPreferredStructure).isEqualTo(COMPONENT_B)
+    }
+
+    private fun SharedPreferences.savePanel(panel: SelectedComponentRepository.SelectedComponent) {
+        edit()
+            .putString("controls_component", panel.componentName?.flattenToString())
+            .putString("controls_structure", panel.name)
+            .putBoolean("controls_is_panel", panel.isPanel)
+            .commit()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt
index 0c9986d..590989d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt
@@ -45,6 +45,7 @@
 import org.mockito.ArgumentMatchers.anyBoolean
 import org.mockito.Mock
 import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.doAnswer
 import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.`when`
@@ -104,7 +105,9 @@
                 controlsSettingsRepository,
                 userTracker,
                 activityStarter
-            ) { context, _ -> TestableAlertDialog(context).also { dialog = it } }
+            ) { context, _ ->
+                TestableAlertDialog(context).also { dialog = it }
+            }
     }
 
     @After
@@ -232,6 +235,36 @@
     }
 
     @Test
+    fun dialogPositiveButtonWhenCalledOnCompleteSettingIsTrue() {
+        sharedPreferences.putAttempts(0)
+        secureSettings.putBool(SETTING_SHOW, true)
+        secureSettings.putBool(SETTING_ACTION, false)
+
+        doAnswer { assertThat(secureSettings.getBool(SETTING_ACTION, false)).isTrue() }
+            .`when`(completedRunnable)
+            .invoke()
+
+        underTest.maybeShowDialog(context, completedRunnable)
+        clickButton(DialogInterface.BUTTON_POSITIVE)
+
+        verify(completedRunnable).invoke()
+    }
+
+    @Test
+    fun dialogPositiveCancelKeyguardStillCallsOnComplete() {
+        `when`(activityStarter.dismissKeyguardThenExecute(any(), nullable(), anyBoolean()))
+            .thenAnswer { (it.arguments[1] as Runnable).run() }
+        sharedPreferences.putAttempts(0)
+        secureSettings.putBool(SETTING_SHOW, true)
+        secureSettings.putBool(SETTING_ACTION, false)
+
+        underTest.maybeShowDialog(context, completedRunnable)
+        clickButton(DialogInterface.BUTTON_POSITIVE)
+
+        verify(completedRunnable).invoke()
+    }
+
+    @Test
     fun dialogCancelDoesntChangeSetting() {
         sharedPreferences.putAttempts(0)
         secureSettings.putBool(SETTING_SHOW, true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/start/ControlsStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/start/ControlsStartableTest.kt
index 7ecaca6..bd7e98e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/start/ControlsStartableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/start/ControlsStartableTest.kt
@@ -23,23 +23,27 @@
 import android.content.pm.ServiceInfo
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
-import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.controls.ControlsServiceInfo
 import com.android.systemui.controls.controller.ControlsController
 import com.android.systemui.controls.dagger.ControlsComponent
 import com.android.systemui.controls.management.ControlsListingController
+import com.android.systemui.controls.panels.AuthorizedPanelsRepository
+import com.android.systemui.controls.panels.FakeSelectedComponentRepository
 import com.android.systemui.controls.ui.SelectedItem
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.time.FakeSystemClock
 import java.util.Optional
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mock
+import org.mockito.Mockito.doAnswer
+import org.mockito.Mockito.doReturn
 import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.verifyZeroInteractions
@@ -53,16 +57,16 @@
     @Mock private lateinit var controlsController: ControlsController
     @Mock private lateinit var controlsListingController: ControlsListingController
     @Mock private lateinit var userTracker: UserTracker
+    @Mock private lateinit var authorizedPanelsRepository: AuthorizedPanelsRepository
+
+    private val preferredPanelsRepository = FakeSelectedComponentRepository()
 
     private lateinit var fakeExecutor: FakeExecutor
 
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
-        context.orCreateTestableResources.addOverride(
-            R.array.config_controlsPreferredPackages,
-            arrayOf<String>()
-        )
+        whenever(authorizedPanelsRepository.getPreferredPackages()).thenReturn(setOf())
 
         fakeExecutor = FakeExecutor(FakeSystemClock())
     }
@@ -78,107 +82,102 @@
     fun testNoPreferredPackagesNoDefaultSelected_noNewSelection() {
         `when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
         val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true))
-        `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+        setUpControlsListingControls(listings)
 
         createStartable(enabled = true).start()
+        fakeExecutor.runAllReady()
 
         verify(controlsController, never()).setPreferredSelection(any())
     }
 
     @Test
     fun testPreferredPackagesNotInstalled_noNewSelection() {
-        context.orCreateTestableResources.addOverride(
-            R.array.config_controlsPreferredPackages,
-            arrayOf(TEST_PACKAGE_PANEL)
-        )
+        whenever(authorizedPanelsRepository.getPreferredPackages())
+            .thenReturn(setOf(TEST_PACKAGE_PANEL))
         `when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
-        `when`(controlsListingController.getCurrentServices()).thenReturn(emptyList())
+        setUpControlsListingControls(emptyList())
 
         createStartable(enabled = true).start()
+        fakeExecutor.runAllReady()
 
         verify(controlsController, never()).setPreferredSelection(any())
     }
 
     @Test
     fun testPreferredPackageNotPanel_noNewSelection() {
-        context.orCreateTestableResources.addOverride(
-            R.array.config_controlsPreferredPackages,
-            arrayOf(TEST_PACKAGE_PANEL)
-        )
+        whenever(authorizedPanelsRepository.getPreferredPackages())
+            .thenReturn(setOf(TEST_PACKAGE_PANEL))
         `when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
         val listings = listOf(ControlsServiceInfo(TEST_COMPONENT, "not panel", hasPanel = false))
-        `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+        setUpControlsListingControls(listings)
 
         createStartable(enabled = true).start()
+        fakeExecutor.runAllReady()
 
         verify(controlsController, never()).setPreferredSelection(any())
     }
 
     @Test
     fun testExistingSelection_noNewSelection() {
-        context.orCreateTestableResources.addOverride(
-            R.array.config_controlsPreferredPackages,
-            arrayOf(TEST_PACKAGE_PANEL)
-        )
+        whenever(authorizedPanelsRepository.getPreferredPackages())
+            .thenReturn(setOf(TEST_PACKAGE_PANEL))
         `when`(controlsController.getPreferredSelection())
             .thenReturn(mock<SelectedItem.PanelItem>())
         val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true))
-        `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+        setUpControlsListingControls(listings)
 
         createStartable(enabled = true).start()
+        fakeExecutor.runAllReady()
 
         verify(controlsController, never()).setPreferredSelection(any())
     }
 
     @Test
     fun testPanelAdded() {
-        context.orCreateTestableResources.addOverride(
-            R.array.config_controlsPreferredPackages,
-            arrayOf(TEST_PACKAGE_PANEL)
-        )
+        whenever(authorizedPanelsRepository.getPreferredPackages())
+            .thenReturn(setOf(TEST_PACKAGE_PANEL))
         `when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
         val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true))
-        `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+        setUpControlsListingControls(listings)
 
         createStartable(enabled = true).start()
+        fakeExecutor.runAllReady()
 
         verify(controlsController).setPreferredSelection(listings[0].toPanelItem())
     }
 
     @Test
     fun testMultiplePreferredOnlyOnePanel_panelAdded() {
-        context.orCreateTestableResources.addOverride(
-            R.array.config_controlsPreferredPackages,
-            arrayOf("other_package", TEST_PACKAGE_PANEL)
-        )
+        whenever(authorizedPanelsRepository.getPreferredPackages())
+            .thenReturn(setOf(TEST_PACKAGE_PANEL))
         `when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
         val listings =
             listOf(
                 ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true),
                 ControlsServiceInfo(ComponentName("other_package", "cls"), "non panel", false)
             )
-        `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+        setUpControlsListingControls(listings)
 
         createStartable(enabled = true).start()
+        fakeExecutor.runAllReady()
 
         verify(controlsController).setPreferredSelection(listings[0].toPanelItem())
     }
 
     @Test
     fun testMultiplePreferredMultiplePanels_firstPreferredAdded() {
-        context.orCreateTestableResources.addOverride(
-            R.array.config_controlsPreferredPackages,
-            arrayOf(TEST_PACKAGE_PANEL, "other_package")
-        )
+        whenever(authorizedPanelsRepository.getPreferredPackages())
+            .thenReturn(setOf(TEST_PACKAGE_PANEL))
         `when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
         val listings =
             listOf(
                 ControlsServiceInfo(ComponentName("other_package", "cls"), "panel", true),
                 ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true)
             )
-        `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+        setUpControlsListingControls(listings)
 
         createStartable(enabled = true).start()
+        fakeExecutor.runAllReady()
 
         verify(controlsController).setPreferredSelection(listings[1].toPanelItem())
     }
@@ -186,10 +185,11 @@
     @Test
     fun testPreferredSelectionIsPanel_bindOnStart() {
         val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true))
-        `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+        setUpControlsListingControls(listings)
         `when`(controlsController.getPreferredSelection()).thenReturn(listings[0].toPanelItem())
 
         createStartable(enabled = true).start()
+        fakeExecutor.runAllReady()
 
         verify(controlsController).bindComponentForPanel(TEST_COMPONENT_PANEL)
     }
@@ -197,11 +197,12 @@
     @Test
     fun testPreferredSelectionPanel_listingNoPanel_notBind() {
         val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = false))
-        `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+        setUpControlsListingControls(listings)
         `when`(controlsController.getPreferredSelection())
             .thenReturn(SelectedItem.PanelItem("panel", TEST_COMPONENT_PANEL))
 
         createStartable(enabled = true).start()
+        fakeExecutor.runAllReady()
 
         verify(controlsController, never()).bindComponentForPanel(any())
     }
@@ -209,14 +210,35 @@
     @Test
     fun testNotPanelSelection_noBind() {
         val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = false))
-        `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+        setUpControlsListingControls(listings)
         `when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
 
         createStartable(enabled = true).start()
+        fakeExecutor.runAllReady()
 
         verify(controlsController, never()).bindComponentForPanel(any())
     }
 
+    @Test
+    fun testAlreadyAddedPanel_noNewSelection() {
+        preferredPanelsRepository.setShouldAddDefaultComponent(false)
+        whenever(authorizedPanelsRepository.getPreferredPackages())
+            .thenReturn(setOf(TEST_PACKAGE_PANEL))
+        `when`(controlsController.getPreferredSelection()).thenReturn(SelectedItem.EMPTY_SELECTION)
+        val listings = listOf(ControlsServiceInfo(TEST_COMPONENT_PANEL, "panel", hasPanel = true))
+        `when`(controlsListingController.getCurrentServices()).thenReturn(listings)
+
+        createStartable(enabled = true).start()
+
+        verify(controlsController, never()).setPreferredSelection(any())
+    }
+
+    private fun setUpControlsListingControls(listings: List<ControlsServiceInfo>) {
+        doAnswer { doReturn(listings).`when`(controlsListingController).getCurrentServices() }
+            .`when`(controlsListingController)
+            .forceReload()
+    }
+
     private fun createStartable(enabled: Boolean): ControlsStartable {
         val component: ControlsComponent =
             mock() {
@@ -230,7 +252,13 @@
                     `when`(getControlsListingController()).thenReturn(Optional.empty())
                 }
             }
-        return ControlsStartable(context.resources, fakeExecutor, component, userTracker)
+        return ControlsStartable(
+            fakeExecutor,
+            component,
+            userTracker,
+            authorizedPanelsRepository,
+            preferredPanelsRepository,
+        )
     }
 
     private fun ControlsServiceInfo(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsDialogsFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsDialogsFactoryTest.kt
new file mode 100644
index 0000000..1e8cd41
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsDialogsFactoryTest.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.controls.ui
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.FakeSystemUIDialogController
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.eq
+import org.mockito.Mockito.verify
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class ControlsDialogsFactoryTest : SysuiTestCase() {
+
+    private companion object {
+        const val APP_NAME = "Test App"
+    }
+
+    private val fakeDialogController = FakeSystemUIDialogController()
+
+    private lateinit var underTest: ControlsDialogsFactory
+
+    @Before
+    fun setup() {
+        underTest = ControlsDialogsFactory { fakeDialogController.dialog }
+    }
+
+    @Test
+    fun testCreatesRemoveAppDialog() {
+        val dialog = underTest.createRemoveAppDialog(context, APP_NAME) {}
+
+        verify(dialog)
+            .setTitle(
+                eq(context.getString(R.string.controls_panel_remove_app_authorization, APP_NAME))
+            )
+        verify(dialog).setCanceledOnTouchOutside(eq(true))
+    }
+
+    @Test
+    fun testPositiveClickRemoveAppDialogWorks() {
+        var dialogResult: Boolean? = null
+        underTest.createRemoveAppDialog(context, APP_NAME) { dialogResult = it }
+
+        fakeDialogController.clickPositive()
+
+        assertThat(dialogResult).isTrue()
+    }
+
+    @Test
+    fun testNeutralClickRemoveAppDialogWorks() {
+        var dialogResult: Boolean? = null
+        underTest.createRemoveAppDialog(context, APP_NAME) { dialogResult = it }
+
+        fakeDialogController.clickNeutral()
+
+        assertThat(dialogResult).isFalse()
+    }
+
+    @Test
+    fun testCancelRemoveAppDialogWorks() {
+        var dialogResult: Boolean? = null
+        underTest.createRemoveAppDialog(context, APP_NAME) { dialogResult = it }
+
+        fakeDialogController.cancel()
+
+        assertThat(dialogResult).isFalse()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
index aa90e2a..3f61bf7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
@@ -42,16 +42,15 @@
 import com.android.systemui.controls.management.ControlsListingController
 import com.android.systemui.controls.management.ControlsProviderSelectorActivity
 import com.android.systemui.controls.panels.AuthorizedPanelsRepository
+import com.android.systemui.controls.panels.FakeSelectedComponentRepository
+import com.android.systemui.controls.panels.SelectedComponentRepository
 import com.android.systemui.controls.settings.FakeControlsSettingsRepository
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.settings.UserFileManager
 import com.android.systemui.settings.UserTracker
-import com.android.systemui.shade.ShadeController
-import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl
 import com.android.systemui.statusbar.policy.KeyguardStateController
-import com.android.systemui.util.FakeSharedPreferences
+import com.android.systemui.util.FakeSystemUIDialogController
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.argumentCaptor
@@ -63,15 +62,12 @@
 import com.android.wm.shell.TaskView
 import com.android.wm.shell.TaskViewFactory
 import com.google.common.truth.Truth.assertThat
-import dagger.Lazy
 import java.util.Optional
 import java.util.function.Consumer
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mock
-import org.mockito.Mockito.anyInt
-import org.mockito.Mockito.anyString
 import org.mockito.Mockito.clearInvocations
 import org.mockito.Mockito.never
 import org.mockito.Mockito.spy
@@ -87,24 +83,24 @@
     @Mock lateinit var controlsListingController: ControlsListingController
     @Mock lateinit var controlActionCoordinator: ControlActionCoordinator
     @Mock lateinit var activityStarter: ActivityStarter
-    @Mock lateinit var shadeController: ShadeController
     @Mock lateinit var iconCache: CustomIconCache
     @Mock lateinit var controlsMetricsLogger: ControlsMetricsLogger
     @Mock lateinit var keyguardStateController: KeyguardStateController
-    @Mock lateinit var userFileManager: UserFileManager
     @Mock lateinit var userTracker: UserTracker
     @Mock lateinit var taskViewFactory: TaskViewFactory
     @Mock lateinit var dumpManager: DumpManager
     @Mock lateinit var authorizedPanelsRepository: AuthorizedPanelsRepository
     @Mock lateinit var featureFlags: FeatureFlags
     @Mock lateinit var packageManager: PackageManager
-    val sharedPreferences = FakeSharedPreferences()
-    lateinit var controlsSettingsRepository: FakeControlsSettingsRepository
 
-    var uiExecutor = FakeExecutor(FakeSystemClock())
-    var bgExecutor = FakeExecutor(FakeSystemClock())
-    lateinit var underTest: ControlsUiControllerImpl
-    lateinit var parent: FrameLayout
+    private val preferredPanelRepository = FakeSelectedComponentRepository()
+    private val fakeDialogController = FakeSystemUIDialogController()
+    private val uiExecutor = FakeExecutor(FakeSystemClock())
+    private val bgExecutor = FakeExecutor(FakeSystemClock())
+
+    private lateinit var controlsSettingsRepository: FakeControlsSettingsRepository
+    private lateinit var parent: FrameLayout
+    private lateinit var underTest: ControlsUiControllerImpl
 
     @Before
     fun setup() {
@@ -125,104 +121,41 @@
 
         underTest =
             ControlsUiControllerImpl(
-                Lazy { controlsController },
+                { controlsController },
                 context,
                 packageManager,
                 uiExecutor,
                 bgExecutor,
-                Lazy { controlsListingController },
+                { controlsListingController },
                 controlActionCoordinator,
                 activityStarter,
                 iconCache,
                 controlsMetricsLogger,
                 keyguardStateController,
-                userFileManager,
                 userTracker,
                 Optional.of(taskViewFactory),
                 controlsSettingsRepository,
                 authorizedPanelsRepository,
+                preferredPanelRepository,
                 featureFlags,
-                dumpManager
+                ControlsDialogsFactory { fakeDialogController.dialog },
+                dumpManager,
             )
-        `when`(
-                userFileManager.getSharedPreferences(
-                    DeviceControlsControllerImpl.PREFS_CONTROLS_FILE,
-                    0,
-                    0
-                )
-            )
-            .thenReturn(sharedPreferences)
-        `when`(userFileManager.getSharedPreferences(anyString(), anyInt(), anyInt()))
-            .thenReturn(sharedPreferences)
         `when`(userTracker.userId).thenReturn(0)
         `when`(userTracker.userHandle).thenReturn(UserHandle.of(0))
     }
 
     @Test
-    fun testGetPreferredStructure() {
-        val structureInfo = mock<StructureInfo>()
-        underTest.getPreferredSelectedItem(listOf(structureInfo))
-        verify(userFileManager)
-            .getSharedPreferences(
-                fileName = DeviceControlsControllerImpl.PREFS_CONTROLS_FILE,
-                mode = 0,
-                userId = 0
-            )
-    }
-
-    @Test
-    fun testGetPreferredStructure_differentUserId() {
-        val selectedItems =
-            listOf(
-                SelectedItem.StructureItem(
-                    StructureInfo(ComponentName.unflattenFromString("pkg/.cls1"), "a", ArrayList())
-                ),
-                SelectedItem.StructureItem(
-                    StructureInfo(ComponentName.unflattenFromString("pkg/.cls2"), "b", ArrayList())
-                ),
-            )
-        val structures = selectedItems.map { it.structure }
-        sharedPreferences
-            .edit()
-            .putString("controls_component", selectedItems[0].componentName.flattenToString())
-            .putString("controls_structure", selectedItems[0].name.toString())
-            .commit()
-
-        val differentSharedPreferences = FakeSharedPreferences()
-        differentSharedPreferences
-            .edit()
-            .putString("controls_component", selectedItems[1].componentName.flattenToString())
-            .putString("controls_structure", selectedItems[1].name.toString())
-            .commit()
-
-        val previousPreferredStructure = underTest.getPreferredSelectedItem(structures)
-
-        `when`(
-                userFileManager.getSharedPreferences(
-                    DeviceControlsControllerImpl.PREFS_CONTROLS_FILE,
-                    0,
-                    1
-                )
-            )
-            .thenReturn(differentSharedPreferences)
-        `when`(userTracker.userId).thenReturn(1)
-
-        val currentPreferredStructure = underTest.getPreferredSelectedItem(structures)
-
-        assertThat(previousPreferredStructure).isEqualTo(selectedItems[0])
-        assertThat(currentPreferredStructure).isEqualTo(selectedItems[1])
-        assertThat(currentPreferredStructure).isNotEqualTo(previousPreferredStructure)
-    }
-
-    @Test
     fun testGetPreferredPanel() {
         val panel = SelectedItem.PanelItem("App name", ComponentName("pkg", "cls"))
-        sharedPreferences
-            .edit()
-            .putString("controls_component", panel.componentName.flattenToString())
-            .putString("controls_structure", panel.appName.toString())
-            .putBoolean("controls_is_panel", true)
-            .commit()
+
+        preferredPanelRepository.setSelectedComponent(
+            SelectedComponentRepository.SelectedComponent(
+                name = panel.appName.toString(),
+                componentName = panel.componentName,
+                isPanel = true,
+            )
+        )
 
         val selected = underTest.getPreferredSelectedItem(emptyList())
 
@@ -366,11 +299,9 @@
                     StructureInfo(ComponentName.unflattenFromString("pkg/.cls1"), "a", ArrayList())
                 ),
             )
-        sharedPreferences
-            .edit()
-            .putString("controls_component", selectedItems[0].componentName.flattenToString())
-            .putString("controls_structure", selectedItems[0].name.toString())
-            .commit()
+        preferredPanelRepository.setSelectedComponent(
+            SelectedComponentRepository.SelectedComponent(selectedItems[0])
+        )
 
         assertThat(underTest.resolveActivity())
             .isEqualTo(ControlsProviderSelectorActivity::class.java)
@@ -410,14 +341,42 @@
         verify(controlsListingController, never()).removeCallback(any())
     }
 
+    @Test
+    fun testRemovingAppsRemovesFavorite() {
+        val componentName = ComponentName(context, "cls")
+        whenever(controlsController.removeFavorites(eq(componentName))).thenReturn(true)
+        val panel = SelectedItem.PanelItem("App name", componentName)
+        preferredPanelRepository.setSelectedComponent(
+                SelectedComponentRepository.SelectedComponent(panel)
+        )
+        underTest.show(parent, {}, context)
+        underTest.startRemovingApp(componentName, "Test App")
+
+        fakeDialogController.clickPositive()
+
+        verify(controlsController).removeFavorites(eq(componentName))
+        assertThat(underTest.getPreferredSelectedItem(emptyList()))
+            .isEqualTo(SelectedItem.EMPTY_SELECTION)
+        assertThat(preferredPanelRepository.shouldAddDefaultComponent()).isFalse()
+        assertThat(preferredPanelRepository.getSelectedComponent()).isNull()
+    }
+
+    @Test
+    fun testHideCancelsTheRemoveAppDialog() {
+        val componentName = ComponentName(context, "cls")
+        underTest.show(parent, {}, context)
+        underTest.startRemovingApp(componentName, "Test App")
+
+        underTest.hide(parent)
+
+        verify(fakeDialogController.dialog).cancel()
+    }
+
     private fun setUpPanel(panel: SelectedItem.PanelItem): ControlsServiceInfo {
-        val activity = ComponentName("pkg", "activity")
-        sharedPreferences
-            .edit()
-            .putString("controls_component", panel.componentName.flattenToString())
-            .putString("controls_structure", panel.appName.toString())
-            .putBoolean("controls_is_panel", true)
-            .commit()
+        val activity = ComponentName(context, "activity")
+        preferredPanelRepository.setSelectedComponent(
+                SelectedComponentRepository.SelectedComponent(panel)
+        )
         return ControlsServiceInfo(panel.componentName, panel.appName, activity)
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt
index dbaf94f..483ab3b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt
@@ -37,7 +37,9 @@
                 context,
                 layoutId = 0,
                 labels.zip(ids).map { OverflowMenuAdapter.MenuItem(it.first, it.second) }
-            ) { true }
+            ) {
+                true
+            }
 
         ids.forEachIndexed { index, id -> assertThat(adapter.getItemId(index)).isEqualTo(id) }
     }
@@ -51,7 +53,9 @@
                 context,
                 layoutId = 0,
                 labels.zip(ids).map { OverflowMenuAdapter.MenuItem(it.first, it.second) }
-            ) { position -> position == 0 }
+            ) { position ->
+                position == 0
+            }
 
         assertThat(adapter.isEnabled(0)).isTrue()
         assertThat(adapter.isEnabled(1)).isFalse()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/devicepolicy/DevicePolicyManagerExtTest.kt b/packages/SystemUI/tests/src/com/android/systemui/devicepolicy/DevicePolicyManagerExtTest.kt
new file mode 100644
index 0000000..8203291
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/devicepolicy/DevicePolicyManagerExtTest.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.devicepolicy
+
+import android.app.admin.DevicePolicyManager
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FACE
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.util.mockito.eq
+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.junit.runners.JUnit4
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(JUnit4::class)
+class DevicePolicyManagerExtTest : SysuiTestCase() {
+
+    @Mock lateinit var devicePolicyManager: DevicePolicyManager
+    @Mock private lateinit var userTracker: UserTracker
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+
+        whenever(userTracker.userId).thenReturn(CURRENT_USER_ID)
+    }
+
+    // region areKeyguardShortcutsDisabled
+    @Test
+    fun areKeyguardShortcutsDisabled_noDisabledKeyguardFeature_shouldReturnFalse() {
+        whenever(devicePolicyManager.getKeyguardDisabledFeatures(eq(null), anyInt()))
+            .thenReturn(KEYGUARD_DISABLE_FEATURES_NONE)
+
+        assertThat(devicePolicyManager.areKeyguardShortcutsDisabled(userId = CURRENT_USER_ID))
+            .isFalse()
+    }
+
+    @Test
+    fun areKeyguardShortcutsDisabled_otherDisabledKeyguardFeatures_shouldReturnFalse() {
+        whenever(devicePolicyManager.getKeyguardDisabledFeatures(eq(null), anyInt()))
+            .thenReturn(KEYGUARD_DISABLE_SECURE_CAMERA or KEYGUARD_DISABLE_FACE)
+
+        assertThat(devicePolicyManager.areKeyguardShortcutsDisabled(userId = CURRENT_USER_ID))
+            .isFalse()
+    }
+
+    @Test
+    fun areKeyguardShortcutsDisabled_disabledShortcutsKeyguardFeature_shouldReturnTrue() {
+        whenever(devicePolicyManager.getKeyguardDisabledFeatures(eq(null), anyInt()))
+            .thenReturn(KEYGUARD_DISABLE_SHORTCUTS_ALL)
+
+        assertThat(devicePolicyManager.areKeyguardShortcutsDisabled(userId = CURRENT_USER_ID))
+            .isTrue()
+    }
+
+    @Test
+    fun areKeyguardShortcutsDisabled_disabledAllKeyguardFeatures_shouldReturnTrue() {
+        whenever(devicePolicyManager.getKeyguardDisabledFeatures(eq(null), anyInt()))
+            .thenReturn(KEYGUARD_DISABLE_FEATURES_ALL)
+
+        assertThat(devicePolicyManager.areKeyguardShortcutsDisabled(userId = CURRENT_USER_ID))
+            .isTrue()
+    }
+    // endregion
+
+    private companion object {
+        const val CURRENT_USER_ID = 123
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
index 6c23254..0a94706 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
@@ -1,6 +1,8 @@
 package com.android.systemui.dreams
 
+import android.animation.Animator
 import android.animation.AnimatorSet
+import android.animation.ValueAnimator
 import android.testing.AndroidTestingRunner
 import android.view.View
 import androidx.test.filters.SmallTest
@@ -10,13 +12,16 @@
 import com.android.systemui.statusbar.BlurUtils
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.mockito.argumentCaptor
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.runBlocking
+import org.junit.Assert.assertTrue
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
 import org.mockito.Mock
 import org.mockito.Mockito.anyLong
 import org.mockito.Mockito.eq
@@ -71,6 +76,19 @@
     }
 
     @Test
+    fun testExitAnimationUpdatesState() {
+        controller.startExitAnimations(animatorBuilder = { mockAnimator })
+
+        verify(stateController).setExitAnimationsRunning(true)
+
+        val captor = argumentCaptor<Animator.AnimatorListener>()
+        verify(mockAnimator).addListener(captor.capture())
+
+        captor.value.onAnimationEnd(mockAnimator)
+        verify(stateController).setExitAnimationsRunning(false)
+    }
+
+    @Test
     fun testWakeUpCallsExecutor() {
         val mockExecutor: DelayableExecutor = mock()
         val mockCallback: Runnable = mock()
@@ -87,7 +105,7 @@
     fun testWakeUpAfterStartWillCancel() {
         val mockStartAnimator: AnimatorSet = mock()
 
-        controller.startEntryAnimations(animatorBuilder = { mockStartAnimator })
+        controller.startEntryAnimations(false, animatorBuilder = { mockStartAnimator })
 
         verify(mockStartAnimator, never()).cancel()
 
@@ -100,4 +118,50 @@
         // animator.
         verify(mockStartAnimator, times(1)).cancel()
     }
+
+    @Test
+    fun testEntryAnimations_translatesUpwards() {
+        val mockStartAnimator: AnimatorSet = mock()
+
+        controller.startEntryAnimations(
+            /* downwards= */ false,
+            animatorBuilder = { mockStartAnimator }
+        )
+
+        val animatorCaptor = ArgumentCaptor.forClass(Animator::class.java)
+        verify(mockStartAnimator).playTogether(animatorCaptor.capture())
+
+        // Check if there's a ValueAnimator starting at the expected Y distance.
+        val animators: List<ValueAnimator> = animatorCaptor.allValues as List<ValueAnimator>
+        assertTrue(
+            animators.any {
+                // Call setCurrentFraction so the animated value jumps to the initial value.
+                it.setCurrentFraction(0f)
+                it.animatedValue == DREAM_IN_TRANSLATION_Y_DISTANCE.toFloat()
+            }
+        )
+    }
+
+    @Test
+    fun testEntryAnimations_translatesDownwards() {
+        val mockStartAnimator: AnimatorSet = mock()
+
+        controller.startEntryAnimations(
+            /* downwards= */ true,
+            animatorBuilder = { mockStartAnimator }
+        )
+
+        val animatorCaptor = ArgumentCaptor.forClass(Animator::class.java)
+        verify(mockStartAnimator).playTogether(animatorCaptor.capture())
+
+        // Check if there's a ValueAnimator starting at the expected Y distance.
+        val animators: List<ValueAnimator> = animatorCaptor.allValues as List<ValueAnimator>
+        assertTrue(
+            animators.any {
+                // Call setCurrentFraction so the animated value jumps to the initial value.
+                it.setCurrentFraction(0f)
+                it.animatedValue == -DREAM_IN_TRANSLATION_Y_DISTANCE.toFloat()
+            }
+        )
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
index 6b095ff..2a72e7d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
@@ -17,6 +17,7 @@
 package com.android.systemui.dreams;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyFloat;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
@@ -33,6 +34,7 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.dream.lowlight.LowLightTransitionCoordinator;
 import com.android.keyguard.BouncerPanelExpansionCalculator;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dreams.complication.ComplicationHostViewController;
@@ -65,6 +67,9 @@
     DreamOverlayStatusBarViewController mDreamOverlayStatusBarViewController;
 
     @Mock
+    LowLightTransitionCoordinator mLowLightTransitionCoordinator;
+
+    @Mock
     DreamOverlayContainerView mDreamOverlayContainerView;
 
     @Mock
@@ -109,6 +114,7 @@
                 mComplicationHostViewController,
                 mDreamOverlayContentView,
                 mDreamOverlayStatusBarViewController,
+                mLowLightTransitionCoordinator,
                 mBlurUtils,
                 mHandler,
                 mResources,
@@ -200,7 +206,7 @@
 
         mController.onViewAttached();
 
-        verify(mAnimationsController).startEntryAnimations();
+        verify(mAnimationsController).startEntryAnimations(false);
         verify(mAnimationsController, never()).cancelAnimations();
     }
 
@@ -210,11 +216,11 @@
 
         mController.onViewAttached();
 
-        verify(mAnimationsController, never()).startEntryAnimations();
+        verify(mAnimationsController, never()).startEntryAnimations(anyBoolean());
     }
 
     @Test
-    public void testSkipEntryAnimationsWhenExitingLowLight() {
+    public void testDownwardEntryAnimationsWhenExitingLowLight() {
         ArgumentCaptor<DreamOverlayStateController.Callback> callbackCaptor =
                 ArgumentCaptor.forClass(DreamOverlayStateController.Callback.class);
         when(mStateController.isLowLightActive()).thenReturn(false);
@@ -230,8 +236,14 @@
         mController.onViewAttached();
 
         // Entry animations should be started then immediately ended to skip to the end.
-        verify(mAnimationsController).startEntryAnimations();
-        verify(mAnimationsController).endAnimations();
+        verify(mAnimationsController).startEntryAnimations(true);
+    }
+
+    @Test
+    public void testStartsExitAnimationsBeforeEnteringLowLight() {
+        mController.onBeforeEnterLowLight();
+
+        verify(mAnimationsController).startExitAnimations();
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
index 9e70c27..ed73797 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
@@ -20,7 +20,9 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
@@ -63,6 +65,7 @@
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
+import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
@@ -73,6 +76,7 @@
     private static final ComponentName LOW_LIGHT_COMPONENT = new ComponentName("package",
             "lowlight");
     private static final String DREAM_COMPONENT = "package/dream";
+    private static final String WINDOW_NAME = "test";
     private final FakeSystemClock mFakeSystemClock = new FakeSystemClock();
     private final FakeExecutor mMainExecutor = new FakeExecutor(mFakeSystemClock);
 
@@ -190,7 +194,8 @@
                 mUiEventLogger,
                 mTouchInsetManager,
                 LOW_LIGHT_COMPONENT,
-                mDreamOverlayCallbackController);
+                mDreamOverlayCallbackController,
+                WINDOW_NAME);
     }
 
     public IDreamOverlayClient getClient() throws RemoteException {
@@ -293,6 +298,7 @@
         // Inform the overlay service of dream starting.
         client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
                 true /*shouldShowComplication*/);
+        mMainExecutor.runAllReady();
 
         assertThat(mService.shouldShowComplications()).isTrue();
     }
@@ -336,6 +342,48 @@
     }
 
     @Test
+    public void testImmediateEndDream() throws Exception {
+        final IDreamOverlayClient client = getClient();
+
+        // Start the dream, but don't execute any Runnables put on the executor yet. We delay
+        // executing Runnables as the timing isn't guaranteed and we want to verify that the overlay
+        // starts and finishes in the proper order even if Runnables are delayed.
+        client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
+                false /*shouldShowComplication*/);
+        // Immediately end the dream.
+        client.endDream();
+        // Run any scheduled Runnables.
+        mMainExecutor.runAllReady();
+
+        // The overlay starts then finishes.
+        InOrder inOrder = inOrder(mWindowManager);
+        inOrder.verify(mWindowManager).addView(mViewCaptor.capture(), any());
+        inOrder.verify(mWindowManager).removeView(mViewCaptor.getValue());
+    }
+
+    @Test
+    public void testEndDreamDuringStartDream() throws Exception {
+        final IDreamOverlayClient client = getClient();
+
+        // Schedule the endDream call in the middle of the startDream implementation, as any
+        // ordering is possible.
+        doAnswer(invocation -> {
+            client.endDream();
+            return null;
+        }).when(mStateController).setOverlayActive(true);
+
+        // Start the dream.
+        client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
+                false /*shouldShowComplication*/);
+        mMainExecutor.runAllReady();
+
+        // The overlay starts then finishes.
+        InOrder inOrder = inOrder(mWindowManager);
+        inOrder.verify(mWindowManager).addView(mViewCaptor.capture(), any());
+        inOrder.verify(mWindowManager).removeView(mViewCaptor.getValue());
+    }
+
+    @Test
     public void testDestroy() throws RemoteException {
         final IDreamOverlayClient client = getClient();
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationHostViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationHostViewControllerTest.java
index dcd8736..95c6897 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationHostViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationHostViewControllerTest.java
@@ -22,6 +22,8 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.os.UserHandle;
+import android.provider.Settings;
 import android.testing.AndroidTestingRunner;
 import android.view.View;
 
@@ -33,6 +35,8 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dreams.DreamOverlayStateController;
+import com.android.systemui.util.settings.FakeSettings;
+import com.android.systemui.util.settings.SecureSettings;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -88,14 +92,15 @@
     @Captor
     private ArgumentCaptor<Observer<Collection<ComplicationViewModel>>> mObserverCaptor;
 
-    @Captor
-    private ArgumentCaptor<DreamOverlayStateController.Callback> mCallbackCaptor;
-
     @Complication.Category
     static final int COMPLICATION_CATEGORY = Complication.CATEGORY_SYSTEM;
 
     private ComplicationHostViewController mController;
 
+    private SecureSettings mSecureSettings;
+
+    private static final int CURRENT_USER_ID = UserHandle.USER_SYSTEM;
+
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
@@ -108,12 +113,17 @@
         when(mViewHolder.getLayoutParams()).thenReturn(mComplicationLayoutParams);
         when(mComplicationView.getParent()).thenReturn(mComplicationHostView);
 
+        mSecureSettings = new FakeSettings();
+        mSecureSettings.putFloatForUser(
+                        Settings.Global.ANIMATOR_DURATION_SCALE, 1.0f, CURRENT_USER_ID);
+
         mController = new ComplicationHostViewController(
                 mComplicationHostView,
                 mLayoutEngine,
                 mDreamOverlayStateController,
                 mLifecycleOwner,
-                mViewModel);
+                mViewModel,
+                mSecureSettings);
 
         mController.init();
     }
@@ -176,8 +186,6 @@
 
         // Dream entry animations finished.
         when(mDreamOverlayStateController.areEntryAnimationsFinished()).thenReturn(true);
-        final DreamOverlayStateController.Callback stateCallback = captureOverlayStateCallback();
-        stateCallback.onStateChanged();
 
         // Add a complication after entry animations are finished.
         final HashSet<ComplicationViewModel> complications = new HashSet<>(
@@ -188,14 +196,26 @@
         verify(mComplicationView, never()).setVisibility(View.INVISIBLE);
     }
 
+    @Test
+    public void testAnimationsDisabled_ComplicationsNeverSetToInvisible() {
+        //Disable animations
+        mController.mIsAnimationEnabled = false;
+
+        final Observer<Collection<ComplicationViewModel>> observer =
+                captureComplicationViewModelsObserver();
+
+        // Add a complication before entry animations are finished.
+        final HashSet<ComplicationViewModel> complications = new HashSet<>(
+                Collections.singletonList(mComplicationViewModel));
+        observer.onChanged(complications);
+
+        // The complication view should not be set to invisible.
+        verify(mComplicationView, never()).setVisibility(View.INVISIBLE);
+    }
+
     private Observer<Collection<ComplicationViewModel>> captureComplicationViewModelsObserver() {
         verify(mComplicationViewModelLiveData).observe(eq(mLifecycleOwner),
                 mObserverCaptor.capture());
         return mObserverCaptor.getValue();
     }
-
-    private DreamOverlayStateController.Callback captureOverlayStateCallback() {
-        verify(mDreamOverlayStateController).addCallback(mCallbackCaptor.capture());
-        return mCallbackCaptor.getValue();
-    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java
index ef62abf..175da0b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java
@@ -33,6 +33,8 @@
 import com.android.systemui.condition.SelfExecutingMonitor;
 import com.android.systemui.dreams.DreamOverlayStateController;
 import com.android.systemui.dreams.smartspace.DreamSmartspaceController;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.BcSmartspaceDataPlugin;
 import com.android.systemui.shared.condition.Condition;
 import com.android.systemui.shared.condition.Monitor;
@@ -65,6 +67,9 @@
     @Mock
     private View mBcSmartspaceView;
 
+    @Mock
+    private FeatureFlags mFeatureFlags;
+
     private Monitor mMonitor;
 
     private final Set<Condition> mPreconditions = new HashSet<>();
@@ -73,6 +78,8 @@
     public void setup() {
         MockitoAnnotations.initMocks(this);
         mMonitor = SelfExecutingMonitor.createInstance();
+
+        when(mFeatureFlags.isEnabled(Flags.HIDE_SMARTSPACE_ON_DREAM_OVERLAY)).thenReturn(false);
     }
 
     /**
@@ -85,12 +92,22 @@
         verify(mDreamOverlayStateController, never()).addComplication(eq(mComplication));
     }
 
-    private SmartSpaceComplication.Registrant getRegistrant() {
-        return new SmartSpaceComplication.Registrant(
-                mDreamOverlayStateController,
-                mComplication,
-                mSmartspaceController,
-                mMonitor);
+    @Test
+    public void testRegistrantStart_featureEnabled_addOverlayStateCallback() {
+        final SmartSpaceComplication.Registrant registrant = getRegistrant();
+        registrant.start();
+
+        verify(mDreamOverlayStateController).addCallback(any());
+    }
+
+    @Test
+    public void testRegistrantStart_featureDisabled_doesNotAddOverlayStateCallback() {
+        when(mFeatureFlags.isEnabled(Flags.HIDE_SMARTSPACE_ON_DREAM_OVERLAY)).thenReturn(true);
+
+        final SmartSpaceComplication.Registrant registrant = getRegistrant();
+        registrant.start();
+
+        verify(mDreamOverlayStateController, never()).addCallback(any());
     }
 
     @Test
@@ -188,4 +205,13 @@
         when(mSmartspaceController.buildAndConnectView(any())).thenReturn(mBcSmartspaceView);
         assertEquals(viewHolder.getView(), viewHolder.getView());
     }
+
+    private SmartSpaceComplication.Registrant getRegistrant() {
+        return new SmartSpaceComplication.Registrant(
+                mDreamOverlayStateController,
+                mComplication,
+                mSmartspaceController,
+                mMonitor,
+                mFeatureFlags);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
index 3a168d4..d6dbd73 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
@@ -450,6 +450,15 @@
         swipeToPosition(0f, Direction.DOWN, 0);
     }
 
+    @Test
+    public void testTouchSessionOnRemovedCalledTwice() {
+        mTouchHandler.onSessionStart(mTouchSession);
+        ArgumentCaptor<DreamTouchHandler.TouchSession.Callback> onRemovedCallbackCaptor =
+                ArgumentCaptor.forClass(DreamTouchHandler.TouchSession.Callback.class);
+        verify(mTouchSession).registerCallback(onRemovedCallbackCaptor.capture());
+        onRemovedCallbackCaptor.getValue().onRemoved();
+        onRemovedCallbackCaptor.getValue().onRemoved();
+    }
 
     private void swipeToPosition(float percent, Direction direction, float velocityY) {
         Mockito.clearInvocations(mTouchSession);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/ConditionalRestarterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/ConditionalRestarterTest.kt
new file mode 100644
index 0000000..0e14591
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/ConditionalRestarterTest.kt
@@ -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.systemui.flags
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.mockito.any
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.advanceUntilIdle
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+/**
+ * Be careful with the {FeatureFlagsReleaseRestarter} in this test. It has a call to System.exit()!
+ */
+@SmallTest
+class ConditionalRestarterTest : SysuiTestCase() {
+    private lateinit var restarter: ConditionalRestarter
+
+    @Mock private lateinit var systemExitRestarter: SystemExitRestarter
+
+    val restartDelayMs = 0L
+    val dispatcher = StandardTestDispatcher()
+    val testScope = TestScope(dispatcher)
+
+    val conditionA = FakeCondition()
+    val conditionB = FakeCondition()
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+        restarter =
+            ConditionalRestarter(
+                systemExitRestarter,
+                setOf(conditionA, conditionB),
+                restartDelayMs,
+                testScope,
+                dispatcher
+            )
+    }
+
+    @Test
+    fun restart_ImmediatelySatisfied() =
+        testScope.runTest {
+            conditionA.canRestart = true
+            conditionB.canRestart = true
+            restarter.restartSystemUI("Restart for test")
+            advanceUntilIdle()
+            verify(systemExitRestarter).restartSystemUI(any())
+        }
+
+    @Test
+    fun restart_WaitsForConditionA() =
+        testScope.runTest {
+            conditionA.canRestart = false
+            conditionB.canRestart = true
+
+            restarter.restartSystemUI("Restart for test")
+            advanceUntilIdle()
+            // No restart occurs yet.
+            verify(systemExitRestarter, never()).restartSystemUI(any())
+
+            conditionA.canRestart = true
+            conditionA.retryFn?.invoke()
+            advanceUntilIdle()
+            verify(systemExitRestarter).restartSystemUI(any())
+        }
+
+    @Test
+    fun restart_WaitsForConditionB() =
+        testScope.runTest {
+            conditionA.canRestart = true
+            conditionB.canRestart = false
+
+            restarter.restartSystemUI("Restart for test")
+            advanceUntilIdle()
+            // No restart occurs yet.
+            verify(systemExitRestarter, never()).restartSystemUI(any())
+
+            conditionB.canRestart = true
+            conditionB.retryFn?.invoke()
+            advanceUntilIdle()
+            verify(systemExitRestarter).restartSystemUI(any())
+        }
+
+    @Test
+    fun restart_WaitsForAllConditions() =
+        testScope.runTest {
+            conditionA.canRestart = true
+            conditionB.canRestart = false
+
+            restarter.restartSystemUI("Restart for test")
+            advanceUntilIdle()
+            // No restart occurs yet.
+            verify(systemExitRestarter, never()).restartSystemUI(any())
+
+            // B becomes true, but A is now false
+            conditionA.canRestart = false
+            conditionB.canRestart = true
+            conditionB.retryFn?.invoke()
+            advanceUntilIdle()
+            // No restart occurs yet.
+            verify(systemExitRestarter, never()).restartSystemUI(any())
+
+            conditionA.canRestart = true
+            conditionA.retryFn?.invoke()
+            advanceUntilIdle()
+            verify(systemExitRestarter).restartSystemUI(any())
+        }
+
+    class FakeCondition : ConditionalRestarter.Condition {
+        var retryFn: (() -> Unit)? = null
+        var canRestart = false
+
+        override fun canRestartNow(retryFn: () -> Unit): Boolean {
+            this.retryFn = retryFn
+
+            return canRestart
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseRestarterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseRestarterTest.kt
deleted file mode 100644
index 6060afe..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseRestarterTest.kt
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.flags
-
-import android.test.suitebuilder.annotation.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.keyguard.WakefulnessLifecycle
-import com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP
-import com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE
-import com.android.systemui.statusbar.policy.BatteryController
-import com.android.systemui.util.concurrency.FakeExecutor
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.time.FakeSystemClock
-import com.google.common.truth.Truth.assertThat
-import org.junit.Before
-import org.junit.Test
-import org.mockito.ArgumentCaptor
-import org.mockito.Mock
-import org.mockito.Mockito.never
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when` as whenever
-import org.mockito.MockitoAnnotations
-
-/**
- * Be careful with the {FeatureFlagsReleaseRestarter} in this test. It has a call to System.exit()!
- */
-@SmallTest
-class FeatureFlagsReleaseRestarterTest : SysuiTestCase() {
-    private lateinit var restarter: FeatureFlagsReleaseRestarter
-
-    @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
-    @Mock private lateinit var batteryController: BatteryController
-    @Mock private lateinit var systemExitRestarter: SystemExitRestarter
-    private val executor = FakeExecutor(FakeSystemClock())
-
-    @Before
-    fun setup() {
-        MockitoAnnotations.initMocks(this)
-        restarter =
-            FeatureFlagsReleaseRestarter(
-                wakefulnessLifecycle,
-                batteryController,
-                executor,
-                systemExitRestarter
-            )
-    }
-
-    @Test
-    fun testRestart_ScheduledWhenReady() {
-        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
-        whenever(batteryController.isPluggedIn).thenReturn(true)
-
-        assertThat(executor.numPending()).isEqualTo(0)
-        restarter.restartSystemUI("Restart for test")
-        assertThat(executor.numPending()).isEqualTo(1)
-    }
-
-    @Test
-    fun testRestart_RestartsWhenIdle() {
-        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
-        whenever(batteryController.isPluggedIn).thenReturn(true)
-
-        restarter.restartSystemUI("Restart for test")
-        verify(systemExitRestarter, never()).restartSystemUI("Restart for test")
-        executor.advanceClockToLast()
-        executor.runAllReady()
-        verify(systemExitRestarter).restartSystemUI(any())
-    }
-
-    @Test
-    fun testRestart_NotScheduledWhenAwake() {
-        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_AWAKE)
-        whenever(batteryController.isPluggedIn).thenReturn(true)
-
-        assertThat(executor.numPending()).isEqualTo(0)
-        restarter.restartSystemUI("Restart for test")
-        assertThat(executor.numPending()).isEqualTo(0)
-    }
-
-    @Test
-    fun testRestart_NotScheduledWhenNotPluggedIn() {
-        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
-        whenever(batteryController.isPluggedIn).thenReturn(false)
-
-        assertThat(executor.numPending()).isEqualTo(0)
-        restarter.restartSystemUI("Restart for test")
-        assertThat(executor.numPending()).isEqualTo(0)
-    }
-
-    @Test
-    fun testRestart_NotDoubleSheduled() {
-        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
-        whenever(batteryController.isPluggedIn).thenReturn(true)
-
-        assertThat(executor.numPending()).isEqualTo(0)
-        restarter.restartSystemUI("Restart for test")
-        restarter.restartSystemUI("Restart for test")
-        assertThat(executor.numPending()).isEqualTo(1)
-    }
-
-    @Test
-    fun testWakefulnessLifecycle_CanRestart() {
-        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_AWAKE)
-        whenever(batteryController.isPluggedIn).thenReturn(true)
-        assertThat(executor.numPending()).isEqualTo(0)
-        restarter.restartSystemUI("Restart for test")
-
-        val captor = ArgumentCaptor.forClass(WakefulnessLifecycle.Observer::class.java)
-        verify(wakefulnessLifecycle).addObserver(captor.capture())
-
-        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
-
-        captor.value.onFinishedGoingToSleep()
-        assertThat(executor.numPending()).isEqualTo(1)
-    }
-
-    @Test
-    fun testBatteryController_CanRestart() {
-        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
-        whenever(batteryController.isPluggedIn).thenReturn(false)
-        assertThat(executor.numPending()).isEqualTo(0)
-        restarter.restartSystemUI("Restart for test")
-
-        val captor =
-            ArgumentCaptor.forClass(BatteryController.BatteryStateChangeCallback::class.java)
-        verify(batteryController).addCallback(captor.capture())
-
-        whenever(batteryController.isPluggedIn).thenReturn(true)
-
-        captor.value.onBatteryLevelChanged(0, true, true)
-        assertThat(executor.numPending()).isEqualTo(1)
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/PluggedInConditionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/PluggedInConditionTest.kt
new file mode 100644
index 0000000..647b05a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/PluggedInConditionTest.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.flags
+
+import android.test.suitebuilder.annotation.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.policy.BatteryController
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.mockito.ArgumentCaptor
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
+
+/**
+ * Be careful with the {FeatureFlagsReleaseRestarter} in this test. It has a call to System.exit()!
+ */
+@SmallTest
+class PluggedInConditionTest : SysuiTestCase() {
+    private lateinit var condition: PluggedInCondition
+
+    @Mock private lateinit var batteryController: BatteryController
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+        condition = PluggedInCondition(batteryController)
+    }
+
+    @Test
+    fun testCondition_unplugged() {
+        whenever(batteryController.isPluggedIn).thenReturn(false)
+
+        assertThat(condition.canRestartNow({})).isFalse()
+    }
+
+    @Test
+    fun testCondition_pluggedIn() {
+        whenever(batteryController.isPluggedIn).thenReturn(true)
+
+        assertThat(condition.canRestartNow({})).isTrue()
+    }
+
+    @Test
+    fun testCondition_invokesRetry() {
+        whenever(batteryController.isPluggedIn).thenReturn(false)
+        var retried = false
+        val retryFn = { retried = true }
+
+        // No restart yet, but we do register a listener now.
+        assertThat(condition.canRestartNow(retryFn)).isFalse()
+        val captor =
+            ArgumentCaptor.forClass(BatteryController.BatteryStateChangeCallback::class.java)
+        verify(batteryController).addCallback(captor.capture())
+
+        whenever(batteryController.isPluggedIn).thenReturn(true)
+
+        captor.value.onBatteryLevelChanged(0, true, true)
+        assertThat(retried).isTrue()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugRestarterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/ScreenIdleConditionTest.kt
similarity index 66%
rename from packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugRestarterTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/flags/ScreenIdleConditionTest.kt
index 686782f..f7a773e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugRestarterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/ScreenIdleConditionTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,12 +20,11 @@
 import com.android.systemui.keyguard.WakefulnessLifecycle
 import com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP
 import com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE
-import com.android.systemui.util.mockito.any
+import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Test
 import org.mockito.ArgumentCaptor
 import org.mockito.Mock
-import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.`when` as whenever
 import org.mockito.MockitoAnnotations
@@ -34,37 +33,45 @@
  * Be careful with the {FeatureFlagsReleaseRestarter} in this test. It has a call to System.exit()!
  */
 @SmallTest
-class FeatureFlagsDebugRestarterTest : SysuiTestCase() {
-    private lateinit var restarter: FeatureFlagsDebugRestarter
+class ScreenIdleConditionTest : SysuiTestCase() {
+    private lateinit var condition: ScreenIdleCondition
 
     @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
-    @Mock private lateinit var systemExitRestarter: SystemExitRestarter
 
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
-        restarter = FeatureFlagsDebugRestarter(wakefulnessLifecycle, systemExitRestarter)
+        condition = ScreenIdleCondition(wakefulnessLifecycle)
     }
 
     @Test
-    fun testRestart_ImmediateWhenAsleep() {
-        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
-        restarter.restartSystemUI("Restart for test")
-        verify(systemExitRestarter).restartSystemUI(any())
-    }
-
-    @Test
-    fun testRestart_WaitsForSceenOff() {
+    fun testCondition_awake() {
         whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_AWAKE)
 
-        restarter.restartSystemUI("Restart for test")
-        verify(systemExitRestarter, never()).restartSystemUI(any())
+        assertThat(condition.canRestartNow {}).isFalse()
+    }
 
+    @Test
+    fun testCondition_asleep() {
+        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
+
+        assertThat(condition.canRestartNow {}).isTrue()
+    }
+
+    @Test
+    fun testCondition_invokesRetry() {
+        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_AWAKE)
+        var retried = false
+        val retryFn = { retried = true }
+
+        // No restart yet, but we do register a listener now.
+        assertThat(condition.canRestartNow(retryFn)).isFalse()
         val captor = ArgumentCaptor.forClass(WakefulnessLifecycle.Observer::class.java)
         verify(wakefulnessLifecycle).addObserver(captor.capture())
 
-        captor.value.onFinishedGoingToSleep()
+        whenever(wakefulnessLifecycle.wakefulness).thenReturn(WAKEFULNESS_ASLEEP)
 
-        verify(systemExitRestarter).restartSystemUI(any())
+        captor.value.onFinishedGoingToSleep()
+        assertThat(retried).isTrue()
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractorTest.kt
new file mode 100644
index 0000000..ec94cde
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractorTest.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.keyboard.backlight.domain.interactor
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyboard.data.repository.FakeKeyboardRepository
+import com.android.systemui.keyboard.shared.model.BacklightModel
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class KeyboardBacklightInteractorTest : SysuiTestCase() {
+
+    private val keyboardRepository = FakeKeyboardRepository()
+    private lateinit var underTest: KeyboardBacklightInteractor
+
+    @Before
+    fun setUp() {
+        underTest = KeyboardBacklightInteractor(keyboardRepository)
+    }
+
+    @Test
+    fun emitsNull_whenKeyboardJustConnected() = runTest {
+        val latest by collectLastValue(underTest.backlight)
+        keyboardRepository.setKeyboardConnected(true)
+
+        assertThat(latest).isNull()
+    }
+
+    @Test
+    fun emitsBacklight_whenKeyboardConnectedAndBacklightChanged() = runTest {
+        keyboardRepository.setKeyboardConnected(true)
+        keyboardRepository.setBacklight(BacklightModel(1, 5))
+
+        assertThat(underTest.backlight.first()).isEqualTo(BacklightModel(1, 5))
+    }
+
+    @Test
+    fun emitsNull_afterKeyboardDisconnecting() = runTest {
+        val latest by collectLastValue(underTest.backlight)
+        keyboardRepository.setKeyboardConnected(true)
+        keyboardRepository.setBacklight(BacklightModel(1, 5))
+
+        keyboardRepository.setKeyboardConnected(false)
+
+        assertThat(latest).isNull()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogViewModelTest.kt
new file mode 100644
index 0000000..ec05d10
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogViewModelTest.kt
@@ -0,0 +1,102 @@
+/*
+ * 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.keyboard.backlight.ui.viewmodel
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyboard.backlight.domain.interactor.KeyboardBacklightInteractor
+import com.android.systemui.keyboard.data.repository.FakeKeyboardRepository
+import com.android.systemui.keyboard.shared.model.BacklightModel
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.test.advanceTimeBy
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class BacklightDialogViewModelTest : SysuiTestCase() {
+
+    private val keyboardRepository = FakeKeyboardRepository()
+    private lateinit var underTest: BacklightDialogViewModel
+    @Mock private lateinit var accessibilityManagerWrapper: AccessibilityManagerWrapper
+    private val timeoutMillis = 3000L
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        whenever(accessibilityManagerWrapper.getRecommendedTimeoutMillis(any(), any()))
+            .thenReturn(timeoutMillis.toInt())
+        underTest =
+            BacklightDialogViewModel(
+                KeyboardBacklightInteractor(keyboardRepository),
+                accessibilityManagerWrapper
+            )
+        keyboardRepository.setKeyboardConnected(true)
+    }
+
+    @Test
+    fun emitsViewModel_whenBacklightChanged() = runTest {
+        keyboardRepository.setBacklight(BacklightModel(1, 5))
+
+        assertThat(underTest.dialogContent.first()).isEqualTo(BacklightDialogContentViewModel(1, 5))
+    }
+
+    @Test
+    fun emitsNull_afterTimeout() = runTest {
+        val latest by collectLastValue(underTest.dialogContent)
+        keyboardRepository.setBacklight(BacklightModel(1, 5))
+
+        assertThat(latest).isEqualTo(BacklightDialogContentViewModel(1, 5))
+        advanceTimeBy(timeoutMillis + 1)
+        assertThat(latest).isNull()
+    }
+
+    @Test
+    fun emitsNull_after5secDelay_fromLastBacklightChange() = runTest {
+        val latest by collectLastValue(underTest.dialogContent)
+        keyboardRepository.setKeyboardConnected(true)
+
+        keyboardRepository.setBacklight(BacklightModel(1, 5))
+        assertThat(latest).isEqualTo(BacklightDialogContentViewModel(1, 5))
+
+        advanceTimeBy(timeoutMillis * 2 / 3)
+        // timeout yet to pass, no new emission
+        keyboardRepository.setBacklight(BacklightModel(2, 5))
+        assertThat(latest).isEqualTo(BacklightDialogContentViewModel(2, 5))
+
+        advanceTimeBy(timeoutMillis * 2 / 3)
+        // timeout refreshed because of last `setBacklight`, still content present
+        assertThat(latest).isEqualTo(BacklightDialogContentViewModel(2, 5))
+
+        advanceTimeBy(timeoutMillis * 2 / 3)
+        // finally timeout reached and null emitted
+        assertThat(latest).isNull()
+    }
+}
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 a4e5bca..1044131 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
@@ -45,6 +45,7 @@
 import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceInteractor
+import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancesMetricsLogger
 import com.android.systemui.keyguard.ui.preview.KeyguardPreviewRenderer
 import com.android.systemui.keyguard.ui.preview.KeyguardPreviewRendererFactory
 import com.android.systemui.keyguard.ui.preview.KeyguardRemotePreviewManager
@@ -91,6 +92,7 @@
     @Mock private lateinit var launchAnimator: DialogLaunchAnimator
     @Mock private lateinit var commandQueue: CommandQueue
     @Mock private lateinit var devicePolicyManager: DevicePolicyManager
+    @Mock private lateinit var logger: KeyguardQuickAffordancesMetricsLogger
 
     private lateinit var underTest: CustomizationProvider
     private lateinit var testScope: TestScope
@@ -184,11 +186,13 @@
                 featureFlags = featureFlags,
                 repository = { quickAffordanceRepository },
                 launchAnimator = launchAnimator,
+                logger = logger,
                 devicePolicyManager = devicePolicyManager,
                 backgroundDispatcher = testDispatcher,
             )
         underTest.previewManager =
             KeyguardRemotePreviewManager(
+                applicationScope = testScope.backgroundScope,
                 previewRendererFactory = previewRendererFactory,
                 mainDispatcher = testDispatcher,
                 backgroundHandler = backgroundHandler,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
index 21ad5e2..5dc04f7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
@@ -30,6 +30,7 @@
 import com.android.internal.widget.LockPatternUtils
 import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED
 import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT
+import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.biometrics.AuthController
 import com.android.systemui.coroutines.collectLastValue
@@ -38,11 +39,14 @@
 import com.android.systemui.keyguard.data.repository.BiometricType.REAR_FINGERPRINT
 import com.android.systemui.keyguard.data.repository.BiometricType.SIDE_FINGERPRINT
 import com.android.systemui.keyguard.data.repository.BiometricType.UNDER_DISPLAY_FINGERPRINT
+import com.android.systemui.keyguard.shared.model.DevicePosture
+import com.android.systemui.statusbar.policy.DevicePostureController
 import com.android.systemui.user.data.repository.FakeUserRepository
 import com.android.systemui.util.mockito.argumentCaptor
 import com.android.systemui.util.mockito.eq
 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.TestDispatcher
 import kotlinx.coroutines.test.TestScope
@@ -62,6 +66,7 @@
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
 
+@OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
 @RunWith(AndroidTestingRunner::class)
@@ -78,6 +83,7 @@
     private lateinit var biometricManagerCallback:
         ArgumentCaptor<IBiometricEnabledOnKeyguardCallback.Stub>
     private lateinit var userRepository: FakeUserRepository
+    private lateinit var devicePostureRepository: FakeDevicePostureRepository
 
     private lateinit var testDispatcher: TestDispatcher
     private lateinit var testScope: TestScope
@@ -90,6 +96,7 @@
         testDispatcher = StandardTestDispatcher()
         testScope = TestScope(testDispatcher)
         userRepository = FakeUserRepository()
+        devicePostureRepository = FakeDevicePostureRepository()
     }
 
     private suspend fun createBiometricSettingsRepository() {
@@ -108,6 +115,7 @@
                 looper = testableLooper!!.looper,
                 dumpManager = dumpManager,
                 biometricManager = biometricManager,
+                devicePostureRepository = devicePostureRepository,
             )
         testScope.runCurrent()
     }
@@ -299,6 +307,50 @@
             verify(biometricManager, times(1)).registerEnabledOnKeyguardCallback(any())
         }
 
+    @Test
+    fun faceAuthIsAlwaysSupportedIfSpecificPostureIsNotConfigured() =
+        testScope.runTest {
+            overrideResource(
+                R.integer.config_face_auth_supported_posture,
+                DevicePostureController.DEVICE_POSTURE_UNKNOWN
+            )
+
+            createBiometricSettingsRepository()
+
+            assertThat(collectLastValue(underTest.isFaceAuthSupportedInCurrentPosture)()).isTrue()
+        }
+
+    @Test
+    fun faceAuthIsSupportedOnlyWhenDevicePostureMatchesConfigValue() =
+        testScope.runTest {
+            overrideResource(
+                R.integer.config_face_auth_supported_posture,
+                DevicePostureController.DEVICE_POSTURE_FLIPPED
+            )
+
+            createBiometricSettingsRepository()
+
+            val isFaceAuthSupported =
+                collectLastValue(underTest.isFaceAuthSupportedInCurrentPosture)
+
+            assertThat(isFaceAuthSupported()).isFalse()
+
+            devicePostureRepository.setCurrentPosture(DevicePosture.CLOSED)
+            assertThat(isFaceAuthSupported()).isFalse()
+
+            devicePostureRepository.setCurrentPosture(DevicePosture.HALF_OPENED)
+            assertThat(isFaceAuthSupported()).isFalse()
+
+            devicePostureRepository.setCurrentPosture(DevicePosture.OPENED)
+            assertThat(isFaceAuthSupported()).isFalse()
+
+            devicePostureRepository.setCurrentPosture(DevicePosture.UNKNOWN)
+            assertThat(isFaceAuthSupported()).isFalse()
+
+            devicePostureRepository.setCurrentPosture(DevicePosture.FLIPPED)
+            assertThat(isFaceAuthSupported()).isTrue()
+        }
+
     private fun enrollmentChange(biometricType: BiometricType, userId: Int, enabled: Boolean) {
         authControllerCallback.value.onEnrollmentsChanged(biometricType, userId, enabled)
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt
new file mode 100644
index 0000000..bd6b7a8
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt
@@ -0,0 +1,80 @@
+/*
+ * 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.data.repository
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.shared.model.DevicePosture
+import com.android.systemui.statusbar.policy.DevicePostureController
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class DevicePostureRepositoryTest : SysuiTestCase() {
+    private lateinit var underTest: DevicePostureRepository
+    private lateinit var testScope: TestScope
+    @Mock private lateinit var devicePostureController: DevicePostureController
+    @Captor private lateinit var callback: ArgumentCaptor<DevicePostureController.Callback>
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+        testScope = TestScope()
+        underTest = DevicePostureRepositoryImpl(postureController = devicePostureController)
+    }
+
+    @Test
+    fun postureChangesArePropagated() =
+        testScope.runTest {
+            whenever(devicePostureController.devicePosture)
+                .thenReturn(DevicePostureController.DEVICE_POSTURE_FLIPPED)
+            val currentPosture = collectLastValue(underTest.currentDevicePosture)
+            assertThat(currentPosture()).isEqualTo(DevicePosture.FLIPPED)
+
+            verify(devicePostureController).addCallback(callback.capture())
+
+            callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_UNKNOWN)
+            assertThat(currentPosture()).isEqualTo(DevicePosture.UNKNOWN)
+
+            callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_CLOSED)
+            assertThat(currentPosture()).isEqualTo(DevicePosture.CLOSED)
+
+            callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_HALF_OPENED)
+            assertThat(currentPosture()).isEqualTo(DevicePosture.HALF_OPENED)
+
+            callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_OPENED)
+            assertThat(currentPosture()).isEqualTo(DevicePosture.OPENED)
+
+            callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_FLIPPED)
+            assertThat(currentPosture()).isEqualTo(DevicePosture.FLIPPED)
+        }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt
index 2eabda3..e468cc1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt
@@ -57,7 +57,7 @@
 
     @Test
     fun changingFlowValueTriggersLogging() = runBlocking {
-        underTest.setPrimaryHide(true)
-        verify(bouncerLogger).logChange("", "PrimaryBouncerHide", false)
+        underTest.setPrimaryShow(true)
+        verify(bouncerLogger).logChange("", "PrimaryBouncerShow", false)
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
index 0469e77..0e6f8d4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
@@ -219,6 +219,29 @@
         }
 
     @Test
+    fun isKeyguardUnlocked() =
+        runTest(UnconfinedTestDispatcher()) {
+            whenever(keyguardStateController.isUnlocked).thenReturn(false)
+            var latest: Boolean? = null
+            val job = underTest.isKeyguardUnlocked.onEach { latest = it }.launchIn(this)
+
+            assertThat(latest).isFalse()
+
+            val captor = argumentCaptor<KeyguardStateController.Callback>()
+            verify(keyguardStateController).addCallback(captor.capture())
+
+            whenever(keyguardStateController.isUnlocked).thenReturn(true)
+            captor.value.onUnlockedChanged()
+            assertThat(latest).isTrue()
+
+            whenever(keyguardStateController.isUnlocked).thenReturn(false)
+            captor.value.onUnlockedChanged()
+            assertThat(latest).isFalse()
+
+            job.cancel()
+        }
+
+    @Test
     fun isDozing() =
         runTest(UnconfinedTestDispatcher()) {
             var latest: Boolean? = null
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
index ae227b4..d9d4013 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
@@ -21,6 +21,7 @@
 import android.util.Log.TerribleFailure
 import android.util.Log.TerribleFailureHandler
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.animation.Interpolators
@@ -47,6 +48,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
+@FlakyTest(bugId = 270760395)
 class KeyguardTransitionRepositoryTest : SysuiTestCase() {
 
     private lateinit var underTest: KeyguardTransitionRepository
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
index d2db910..f9493d1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
@@ -62,7 +62,9 @@
             fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockModel.WAKE_AND_UNLOCK)
 
             runCurrent()
-            values.assertEffectsMatchPredicates({ it == DEFAULT_REVEAL_EFFECT },)
+            values.assertEffectsMatchPredicates(
+                { it == DEFAULT_REVEAL_EFFECT },
+            )
 
             // We got a source but still have no sensor locations, so should be sticking with
             // the default effect.
@@ -71,14 +73,18 @@
             )
 
             runCurrent()
-            values.assertEffectsMatchPredicates({ it == DEFAULT_REVEAL_EFFECT },)
+            values.assertEffectsMatchPredicates(
+                { it == DEFAULT_REVEAL_EFFECT },
+            )
 
             // We got a location for the face sensor, but we unlocked with fingerprint.
             val faceLocation = Point(250, 0)
             fakeKeyguardRepository.setFaceSensorLocation(faceLocation)
 
             runCurrent()
-            values.assertEffectsMatchPredicates({ it == DEFAULT_REVEAL_EFFECT },)
+            values.assertEffectsMatchPredicates(
+                { it == DEFAULT_REVEAL_EFFECT },
+            )
 
             // Now we have fingerprint sensor locations, and wake and unlock via fingerprint.
             val fingerprintLocation = Point(500, 500)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
index 153439e..7f30162 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
@@ -145,7 +145,7 @@
             repository.setKeyguardOccluded(true)
             assertThat(secureCameraActive()).isTrue()
 
-            bouncerRepository.setPrimaryVisible(true)
+            bouncerRepository.setPrimaryShow(true)
             assertThat(secureCameraActive()).isFalse()
         }
 
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 84ec125..46c623a 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
@@ -42,6 +42,7 @@
 import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
 import com.android.systemui.keyguard.domain.quickaffordance.FakeKeyguardQuickAffordanceRegistry
 import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition
+import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancesMetricsLogger
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.settings.FakeUserTracker
 import com.android.systemui.settings.UserFileManager
@@ -225,6 +226,7 @@
     @Mock private lateinit var launchAnimator: DialogLaunchAnimator
     @Mock private lateinit var commandQueue: CommandQueue
     @Mock private lateinit var devicePolicyManager: DevicePolicyManager
+    @Mock private lateinit var logger: KeyguardQuickAffordancesMetricsLogger
 
     private lateinit var underTest: KeyguardQuickAffordanceInteractor
     private lateinit var testScope: TestScope
@@ -331,6 +333,7 @@
                 featureFlags = featureFlags,
                 repository = { quickAffordanceRepository },
                 launchAnimator = launchAnimator,
+                logger = logger,
                 devicePolicyManager = devicePolicyManager,
                 backgroundDispatcher = testDispatcher,
             )
@@ -360,10 +363,11 @@
                     KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
                 }
 
-            underTest.onQuickAffordanceTriggered(
-                configKey = BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS,
-                expandable = expandable,
-            )
+        underTest.onQuickAffordanceTriggered(
+            configKey = BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS,
+            expandable = expandable,
+            slotId = "",
+        )
 
             if (startActivity) {
                 if (needsToUnlockFirst) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
index 62c9e5f..503e002 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
@@ -45,6 +45,7 @@
 import com.android.systemui.keyguard.shared.model.KeyguardQuickAffordancePickerRepresentation
 import com.android.systemui.keyguard.shared.quickaffordance.ActivationState
 import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition
+import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancesMetricsLogger
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.settings.UserFileManager
 import com.android.systemui.settings.UserTracker
@@ -80,6 +81,7 @@
     @Mock private lateinit var launchAnimator: DialogLaunchAnimator
     @Mock private lateinit var commandQueue: CommandQueue
     @Mock private lateinit var devicePolicyManager: DevicePolicyManager
+    @Mock private lateinit var logger: KeyguardQuickAffordancesMetricsLogger
 
     private lateinit var underTest: KeyguardQuickAffordanceInteractor
 
@@ -186,6 +188,7 @@
                 featureFlags = featureFlags,
                 repository = { quickAffordanceRepository },
                 launchAnimator = launchAnimator,
+                logger = logger,
                 devicePolicyManager = devicePolicyManager,
                 backgroundDispatcher = testDispatcher,
             )
@@ -281,6 +284,24 @@
         }
 
     @Test
+    fun `quickAffordance - hidden when quick settings is visible`() =
+        testScope.runTest {
+            repository.setQuickSettingsVisible(true)
+            quickAccessWallet.setState(
+                KeyguardQuickAffordanceConfig.LockScreenState.Visible(
+                    icon = ICON,
+                )
+            )
+
+            val collectedValue =
+                collectLastValue(
+                    underTest.quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_END)
+                )
+
+            assertThat(collectedValue()).isEqualTo(KeyguardQuickAffordanceModel.Hidden)
+        }
+
+    @Test
     fun `quickAffordance - bottom start affordance hidden while dozing`() =
         testScope.runTest {
             repository.setDozing(true)
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 ae7a928..092fdca 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
@@ -19,6 +19,8 @@
 import android.animation.ValueAnimator
 import androidx.test.filters.FlakyTest
 import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardSecurityModel
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode.PIN
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.animation.Interpolators
 import com.android.systemui.flags.FakeFeatureFlags
@@ -40,6 +42,7 @@
 import com.android.systemui.shade.data.repository.FakeShadeRepository
 import com.android.systemui.shade.data.repository.ShadeRepository
 import com.android.systemui.statusbar.CommandQueue
+import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.mockito.withArgCaptor
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.cancelChildren
@@ -51,6 +54,8 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.Mock
 import org.mockito.Mockito.reset
 import org.mockito.Mockito.verify
@@ -77,6 +82,7 @@
     // Used to verify transition requests for test output
     @Mock private lateinit var mockTransitionRepository: KeyguardTransitionRepository
     @Mock private lateinit var commandQueue: CommandQueue
+    @Mock private lateinit var keyguardSecurityModel: KeyguardSecurityModel
 
     private lateinit var fromLockscreenTransitionInteractor: FromLockscreenTransitionInteractor
     private lateinit var fromDreamingTransitionInteractor: FromDreamingTransitionInteractor
@@ -102,6 +108,8 @@
         transitionRepository = KeyguardTransitionRepositoryImpl()
         runner = KeyguardTransitionRunner(transitionRepository)
 
+        whenever(keyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(PIN)
+
         val featureFlags = FakeFeatureFlags().apply { set(Flags.FACE_AUTH_REFACTOR, true) }
         fromLockscreenTransitionInteractor =
             FromLockscreenTransitionInteractor(
@@ -173,16 +181,17 @@
                 keyguardInteractor = createKeyguardInteractor(featureFlags),
                 keyguardTransitionRepository = mockTransitionRepository,
                 keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+                keyguardSecurityModel = keyguardSecurityModel,
             )
         fromPrimaryBouncerTransitionInteractor.start()
     }
 
     @Test
-    fun `DREAMING to LOCKSCREEN - dreaming state changes first`() =
+    fun `DREAMING to LOCKSCREEN`() =
         testScope.runTest {
-            // GIVEN a device is dreaming and occluded
+            // GIVEN a device is dreaming
             keyguardRepository.setDreamingWithOverlay(true)
-            keyguardRepository.setKeyguardOccluded(true)
+            keyguardRepository.setWakefulnessModel(startingToWake())
             runCurrent()
 
             // GIVEN a prior transition has run to DREAMING
@@ -215,56 +224,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
-                }
-            // THEN a transition to BOUNCER should occur
-            assertThat(info.ownerName).isEqualTo("FromDreamingTransitionInteractor")
-            assertThat(info.from).isEqualTo(KeyguardState.DREAMING)
-            assertThat(info.to).isEqualTo(KeyguardState.LOCKSCREEN)
-            assertThat(info.animator).isNotNull()
-
-            coroutineContext.cancelChildren()
-        }
-
-    @Test
-    fun `DREAMING to LOCKSCREEN - occluded state changes first`() =
-        testScope.runTest {
-            // GIVEN a device is dreaming and occluded
-            keyguardRepository.setDreamingWithOverlay(true)
-            keyguardRepository.setKeyguardOccluded(true)
-            runCurrent()
-
-            // GIVEN a prior transition has run to DREAMING
-            runner.startTransition(
-                testScope,
-                TransitionInfo(
-                    ownerName = "",
-                    from = KeyguardState.LOCKSCREEN,
-                    to = KeyguardState.DREAMING,
-                    animator =
-                        ValueAnimator().apply {
-                            duration = 10
-                            interpolator = Interpolators.LINEAR
-                        },
-                )
-            )
-            runCurrent()
-            reset(mockTransitionRepository)
-
-            // WHEN doze is complete
-            keyguardRepository.setDozeTransitionModel(
-                DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH)
-            )
-            // AND occluded has stopped
-            keyguardRepository.setKeyguardOccluded(false)
-            advanceUntilIdle()
-            // AND then dreaming has stopped
-            keyguardRepository.setDreamingWithOverlay(false)
-            advanceUntilIdle()
-
-            val info =
-                withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to BOUNCER should occur
             assertThat(info.ownerName).isEqualTo("FromDreamingTransitionInteractor")
@@ -299,12 +259,12 @@
             runCurrent()
 
             // WHEN the primary bouncer is set to show
-            bouncerRepository.setPrimaryVisible(true)
+            bouncerRepository.setPrimaryShow(true)
             runCurrent()
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to PRIMARY_BOUNCER should occur
             assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
@@ -345,7 +305,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromOccludedTransitionInteractor")
@@ -386,7 +346,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromOccludedTransitionInteractor")
@@ -398,6 +358,50 @@
         }
 
     @Test
+    fun `LOCKSCREEN to DREAMING`() =
+        testScope.runTest {
+            // GIVEN a device that is not dreaming or dozing
+            keyguardRepository.setDreamingWithOverlay(false)
+            keyguardRepository.setWakefulnessModel(startingToWake())
+            keyguardRepository.setDozeTransitionModel(
+                DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH)
+            )
+            runCurrent()
+
+            // GIVEN a prior transition has run to LOCKSCREEN
+            runner.startTransition(
+                testScope,
+                TransitionInfo(
+                    ownerName = "",
+                    from = KeyguardState.GONE,
+                    to = KeyguardState.LOCKSCREEN,
+                    animator =
+                        ValueAnimator().apply {
+                            duration = 10
+                            interpolator = Interpolators.LINEAR
+                        },
+                )
+            )
+            reset(mockTransitionRepository)
+
+            // WHEN the device begins to dream
+            keyguardRepository.setDreamingWithOverlay(true)
+            advanceUntilIdle()
+
+            val info =
+                withArgCaptor<TransitionInfo> {
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
+                }
+            // THEN a transition to DREAMING should occur
+            assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
+            assertThat(info.from).isEqualTo(KeyguardState.LOCKSCREEN)
+            assertThat(info.to).isEqualTo(KeyguardState.DREAMING)
+            assertThat(info.animator).isNotNull()
+
+            coroutineContext.cancelChildren()
+        }
+
+    @Test
     fun `LOCKSCREEN to DOZING`() =
         testScope.runTest {
             // GIVEN a device with AOD not available
@@ -427,7 +431,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
@@ -468,7 +472,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
@@ -505,7 +509,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromDozingTransitionInteractor")
@@ -542,7 +546,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromDozingTransitionInteractor")
@@ -583,7 +587,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
@@ -624,7 +628,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to AOD should occur
             assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
@@ -661,7 +665,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to AOD should occur
             assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
@@ -677,6 +681,7 @@
         testScope.runTest {
             // GIVEN a device that is not dreaming or dozing
             keyguardRepository.setDreamingWithOverlay(false)
+            keyguardRepository.setWakefulnessModel(startingToWake())
             keyguardRepository.setDozeTransitionModel(
                 DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH)
             )
@@ -704,7 +709,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to DREAMING should occur
             assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
@@ -736,12 +741,12 @@
             reset(mockTransitionRepository)
 
             // WHEN the alternateBouncer stops showing and then the primary bouncer shows
-            bouncerRepository.setPrimaryVisible(true)
+            bouncerRepository.setPrimaryShow(true)
             runCurrent()
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to PRIMARY_BOUNCER should occur
             assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
@@ -774,7 +779,7 @@
             reset(mockTransitionRepository)
 
             // GIVEN the primary bouncer isn't showing, aod available and starting to sleep
-            bouncerRepository.setPrimaryVisible(false)
+            bouncerRepository.setPrimaryShow(false)
             keyguardRepository.setAodAvailable(true)
             keyguardRepository.setWakefulnessModel(startingToSleep())
 
@@ -784,7 +789,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to AOD should occur
             assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
@@ -818,7 +823,7 @@
 
             // GIVEN the primary bouncer isn't showing, aod not available and starting to sleep
             // to sleep
-            bouncerRepository.setPrimaryVisible(false)
+            bouncerRepository.setPrimaryShow(false)
             keyguardRepository.setAodAvailable(false)
             keyguardRepository.setWakefulnessModel(startingToSleep())
 
@@ -828,7 +833,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
@@ -861,7 +866,7 @@
             reset(mockTransitionRepository)
 
             // GIVEN the primary bouncer isn't showing and device not sleeping
-            bouncerRepository.setPrimaryVisible(false)
+            bouncerRepository.setPrimaryShow(false)
             keyguardRepository.setWakefulnessModel(startingToWake())
 
             // WHEN the alternateBouncer stops showing
@@ -870,7 +875,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to LOCKSCREEN should occur
             assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
@@ -885,7 +890,7 @@
     fun `PRIMARY_BOUNCER to AOD`() =
         testScope.runTest {
             // GIVEN a prior transition has run to PRIMARY_BOUNCER
-            bouncerRepository.setPrimaryVisible(true)
+            bouncerRepository.setPrimaryShow(true)
             runner.startTransition(
                 testScope,
                 TransitionInfo(
@@ -907,12 +912,12 @@
             keyguardRepository.setWakefulnessModel(startingToSleep())
 
             // WHEN the primaryBouncer stops showing
-            bouncerRepository.setPrimaryVisible(false)
+            bouncerRepository.setPrimaryShow(false)
             runCurrent()
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to AOD should occur
             assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor")
@@ -927,7 +932,7 @@
     fun `PRIMARY_BOUNCER to DOZING`() =
         testScope.runTest {
             // GIVEN a prior transition has run to PRIMARY_BOUNCER
-            bouncerRepository.setPrimaryVisible(true)
+            bouncerRepository.setPrimaryShow(true)
             runner.startTransition(
                 testScope,
                 TransitionInfo(
@@ -949,12 +954,12 @@
             keyguardRepository.setWakefulnessModel(startingToSleep())
 
             // WHEN the primaryBouncer stops showing
-            bouncerRepository.setPrimaryVisible(false)
+            bouncerRepository.setPrimaryShow(false)
             runCurrent()
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor")
@@ -969,7 +974,7 @@
     fun `PRIMARY_BOUNCER to LOCKSCREEN`() =
         testScope.runTest {
             // GIVEN a prior transition has run to PRIMARY_BOUNCER
-            bouncerRepository.setPrimaryVisible(true)
+            bouncerRepository.setPrimaryShow(true)
             runner.startTransition(
                 testScope,
                 TransitionInfo(
@@ -990,12 +995,12 @@
             keyguardRepository.setWakefulnessModel(startingToWake())
 
             // WHEN the alternateBouncer stops showing
-            bouncerRepository.setPrimaryVisible(false)
+            bouncerRepository.setPrimaryShow(false)
             runCurrent()
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to LOCKSCREEN should occur
             assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor")
@@ -1006,6 +1011,92 @@
             coroutineContext.cancelChildren()
         }
 
+    @Test
+    fun `OCCLUDED to GONE`() =
+        testScope.runTest {
+            // GIVEN a device on lockscreen
+            keyguardRepository.setKeyguardShowing(true)
+            runCurrent()
+
+            // GIVEN a prior transition has run to OCCLUDED
+            runner.startTransition(
+                testScope,
+                TransitionInfo(
+                    ownerName = "",
+                    from = KeyguardState.LOCKSCREEN,
+                    to = KeyguardState.OCCLUDED,
+                    animator =
+                        ValueAnimator().apply {
+                            duration = 10
+                            interpolator = Interpolators.LINEAR
+                        },
+                )
+            )
+            keyguardRepository.setKeyguardOccluded(true)
+            runCurrent()
+            reset(mockTransitionRepository)
+
+            // WHEN keyguard goes away
+            keyguardRepository.setKeyguardShowing(false)
+            // AND occlusion ends
+            keyguardRepository.setKeyguardOccluded(false)
+            runCurrent()
+
+            val info =
+                withArgCaptor<TransitionInfo> {
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
+                }
+            // THEN a transition to GONE should occur
+            assertThat(info.ownerName).isEqualTo("FromOccludedTransitionInteractor")
+            assertThat(info.from).isEqualTo(KeyguardState.OCCLUDED)
+            assertThat(info.to).isEqualTo(KeyguardState.GONE)
+            assertThat(info.animator).isNotNull()
+
+            coroutineContext.cancelChildren()
+        }
+
+    @Test
+    fun `OCCLUDED to LOCKSCREEN`() =
+        testScope.runTest {
+            // GIVEN a device on lockscreen
+            keyguardRepository.setKeyguardShowing(true)
+            runCurrent()
+
+            // GIVEN a prior transition has run to OCCLUDED
+            runner.startTransition(
+                testScope,
+                TransitionInfo(
+                    ownerName = "",
+                    from = KeyguardState.LOCKSCREEN,
+                    to = KeyguardState.OCCLUDED,
+                    animator =
+                        ValueAnimator().apply {
+                            duration = 10
+                            interpolator = Interpolators.LINEAR
+                        },
+                )
+            )
+            keyguardRepository.setKeyguardOccluded(true)
+            runCurrent()
+            reset(mockTransitionRepository)
+
+            // WHEN occlusion ends
+            keyguardRepository.setKeyguardOccluded(false)
+            runCurrent()
+
+            val info =
+                withArgCaptor<TransitionInfo> {
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
+                }
+            // THEN a transition to LOCKSCREEN should occur
+            assertThat(info.ownerName).isEqualTo("FromOccludedTransitionInteractor")
+            assertThat(info.from).isEqualTo(KeyguardState.OCCLUDED)
+            assertThat(info.to).isEqualTo(KeyguardState.LOCKSCREEN)
+            assertThat(info.animator).isNotNull()
+
+            coroutineContext.cancelChildren()
+        }
+
     private fun startingToWake() =
         WakefulnessModel(
             WakefulnessState.STARTING_TO_WAKE,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
index 6b7fd61..5ec6283 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
@@ -35,7 +35,6 @@
 import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
 import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
 import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
-import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.statusbar.phone.KeyguardBypassController
 import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -92,7 +91,7 @@
                 keyguardBypassController,
             )
         `when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
-        `when`(repository.primaryBouncerShow.value).thenReturn(null)
+        `when`(repository.primaryBouncerShow.value).thenReturn(false)
         `when`(bouncerView.delegate).thenReturn(bouncerViewDelegate)
         resources = context.orCreateTestableResources
     }
@@ -101,15 +100,13 @@
     fun testShow_isScrimmed() {
         underTest.show(true)
         verify(repository).setKeyguardAuthenticated(null)
-        verify(repository).setPrimaryHide(false)
         verify(repository).setPrimaryStartingToHide(false)
         verify(repository).setPrimaryScrimmed(true)
         verify(repository).setPanelExpansion(EXPANSION_VISIBLE)
         verify(repository).setPrimaryShowingSoon(true)
         verify(keyguardStateController).notifyPrimaryBouncerShowing(true)
         verify(mPrimaryBouncerCallbackInteractor).dispatchStartingToShow()
-        verify(repository).setPrimaryVisible(true)
-        verify(repository).setPrimaryShow(any(KeyguardBouncerModel::class.java))
+        verify(repository).setPrimaryShow(true)
         verify(repository).setPrimaryShowingSoon(false)
         verify(mPrimaryBouncerCallbackInteractor).dispatchVisibilityChanged(View.VISIBLE)
     }
@@ -132,9 +129,7 @@
         verify(falsingCollector).onBouncerHidden()
         verify(keyguardStateController).notifyPrimaryBouncerShowing(false)
         verify(repository).setPrimaryShowingSoon(false)
-        verify(repository).setPrimaryVisible(false)
-        verify(repository).setPrimaryHide(true)
-        verify(repository).setPrimaryShow(null)
+        verify(repository).setPrimaryShow(false)
         verify(mPrimaryBouncerCallbackInteractor).dispatchVisibilityChanged(View.INVISIBLE)
     }
 
@@ -160,9 +155,7 @@
         `when`(repository.panelExpansionAmount.value).thenReturn(0.5f)
         `when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
         underTest.setPanelExpansion(EXPANSION_HIDDEN)
-        verify(repository).setPrimaryVisible(false)
-        verify(repository).setPrimaryShow(null)
-        verify(repository).setPrimaryHide(true)
+        verify(repository).setPrimaryShow(false)
         verify(falsingCollector).onBouncerHidden()
         verify(mPrimaryBouncerCallbackInteractor).dispatchReset()
         verify(mPrimaryBouncerCallbackInteractor).dispatchFullyHidden()
@@ -243,11 +236,11 @@
 
     @Test
     fun testIsFullShowing() {
-        `when`(repository.primaryBouncerVisible.value).thenReturn(true)
+        `when`(repository.primaryBouncerShow.value).thenReturn(true)
         `when`(repository.panelExpansionAmount.value).thenReturn(EXPANSION_VISIBLE)
         `when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
         assertThat(underTest.isFullyShowing()).isTrue()
-        `when`(repository.primaryBouncerVisible.value).thenReturn(false)
+        `when`(repository.primaryBouncerShow.value).thenReturn(false)
         assertThat(underTest.isFullyShowing()).isFalse()
     }
 
@@ -370,7 +363,7 @@
         isUnlockingWithFpAllowed: Boolean,
         isAnimatingAway: Boolean
     ) {
-        `when`(repository.primaryBouncerVisible.value).thenReturn(isVisible)
+        `when`(repository.primaryBouncerShow.value).thenReturn(isVisible)
         resources.addOverride(R.bool.config_show_sidefps_hint_on_bouncer, sfpsEnabled)
         `when`(keyguardUpdateMonitor.isFingerprintDetectionRunning).thenReturn(fpsDetectionRunning)
         `when`(keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
index f675e79..edac468 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
@@ -77,7 +77,7 @@
     fun notInteractableWhenExpansionIsBelow90Percent() = runTest {
         val isInteractable = collectLastValue(underTest.isInteractable)
 
-        repository.setPrimaryVisible(true)
+        repository.setPrimaryShow(true)
         repository.setPanelExpansion(0.15f)
 
         assertThat(isInteractable()).isFalse()
@@ -87,7 +87,7 @@
     fun notInteractableWhenExpansionAbove90PercentButNotVisible() = runTest {
         val isInteractable = collectLastValue(underTest.isInteractable)
 
-        repository.setPrimaryVisible(false)
+        repository.setPrimaryShow(false)
         repository.setPanelExpansion(0.05f)
 
         assertThat(isInteractable()).isFalse()
@@ -97,7 +97,7 @@
     fun isInteractableWhenExpansionAbove90PercentAndVisible() = runTest {
         var isInteractable = collectLastValue(underTest.isInteractable)
 
-        repository.setPrimaryVisible(true)
+        repository.setPrimaryShow(true)
         repository.setPanelExpansion(0.09f)
 
         assertThat(isInteractable()).isTrue()
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 8bd8be5..bfc09d7 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
@@ -45,6 +45,7 @@
 import com.android.systemui.keyguard.domain.quickaffordance.FakeKeyguardQuickAffordanceRegistry
 import com.android.systemui.keyguard.shared.quickaffordance.ActivationState
 import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition
+import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancesMetricsLogger
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.settings.UserFileManager
 import com.android.systemui.settings.UserTracker
@@ -89,6 +90,7 @@
     @Mock private lateinit var launchAnimator: DialogLaunchAnimator
     @Mock private lateinit var commandQueue: CommandQueue
     @Mock private lateinit var devicePolicyManager: DevicePolicyManager
+    @Mock private lateinit var logger: KeyguardQuickAffordancesMetricsLogger
 
     private lateinit var underTest: KeyguardBottomAreaViewModel
 
@@ -208,6 +210,7 @@
                         featureFlags = featureFlags,
                         repository = { quickAffordanceRepository },
                         launchAnimator = launchAnimator,
+                        logger = logger,
                         devicePolicyManager = devicePolicyManager,
                         backgroundDispatcher = testDispatcher,
                     ),
@@ -230,6 +233,7 @@
                     icon = mock(),
                     canShowWhileLocked = false,
                     intent = Intent("action"),
+                    slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
                 )
             val configKey =
                 setUpQuickAffordanceModel(
@@ -260,6 +264,7 @@
                     icon = mock(),
                     canShowWhileLocked = false,
                     intent = Intent("action"),
+                    slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
                 )
             val configKey =
                 setUpQuickAffordanceModel(
@@ -272,6 +277,7 @@
                 testConfig =
                     TestConfig(
                         isVisible = false,
+                        slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
                     ),
                 configKey = configKey,
             )
@@ -299,6 +305,7 @@
                             icon = icon,
                             canShowWhileLocked = false,
                             intent = Intent("action"),
+                            slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
                         ),
                 )
 
@@ -308,11 +315,12 @@
                     TestConfig(
                         isVisible = true,
                         isClickable = false,
-                        isActivated = true,
+                        isActivated = false,
                         icon = icon,
                         canShowWhileLocked = false,
                         intent = Intent("action"),
                         isSelected = true,
+                        slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
                     ),
                 configKey = configKey,
             )
@@ -341,6 +349,7 @@
                         icon = icon,
                         canShowWhileLocked = false,
                         intent = Intent("action"),
+                        slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
                     ),
             )
             val configKey =
@@ -354,6 +363,7 @@
                             icon = icon,
                             canShowWhileLocked = false,
                             intent = Intent("action"),
+                            slotId = KeyguardQuickAffordancePosition.BOTTOM_END.toSlotId(),
                         ),
                 )
 
@@ -363,11 +373,12 @@
                     TestConfig(
                         isVisible = true,
                         isClickable = false,
-                        isActivated = true,
+                        isActivated = false,
                         icon = icon,
                         canShowWhileLocked = false,
                         intent = Intent("action"),
                         isDimmed = true,
+                        slotId = KeyguardQuickAffordancePosition.BOTTOM_END.toSlotId(),
                     ),
                 configKey = configKey,
             )
@@ -387,6 +398,7 @@
                     canShowWhileLocked = false,
                     intent =
                         null, // This will cause it to tell the system that the click was handled.
+                    slotId = KeyguardQuickAffordancePosition.BOTTOM_END.toSlotId(),
                 )
             val configKey =
                 setUpQuickAffordanceModel(
@@ -409,6 +421,7 @@
             val config =
                 TestConfig(
                     isVisible = false,
+                    slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
                 )
             val configKey =
                 setUpQuickAffordanceModel(
@@ -434,6 +447,7 @@
                     icon = mock(),
                     canShowWhileLocked = false,
                     intent = Intent("action"),
+                    slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
                 )
 
             setUpQuickAffordanceModel(
@@ -513,6 +527,7 @@
                         isClickable = true,
                         icon = mock(),
                         canShowWhileLocked = true,
+                        slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
                     )
             )
             assertThat(value()).isTrue()
@@ -524,6 +539,7 @@
                         isClickable = true,
                         icon = mock(),
                         canShowWhileLocked = false,
+                        slotId = KeyguardQuickAffordancePosition.BOTTOM_END.toSlotId(),
                     )
             )
             assertThat(value()).isTrue()
@@ -532,6 +548,7 @@
                 testConfig =
                     TestConfig(
                         isVisible = false,
+                        slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
                     )
             )
             assertThat(value()).isTrue()
@@ -540,6 +557,7 @@
                 testConfig =
                     TestConfig(
                         isVisible = false,
+                        slotId = KeyguardQuickAffordancePosition.BOTTOM_END.toSlotId(),
                     )
             )
             assertThat(value()).isFalse()
@@ -594,6 +612,7 @@
                     icon = mock(),
                     canShowWhileLocked = false,
                     intent = Intent("action"),
+                    slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
                 )
             val configKey =
                 setUpQuickAffordanceModel(
@@ -626,6 +645,7 @@
                     icon = mock(),
                     canShowWhileLocked = false,
                     intent = Intent("action"),
+                    slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
                 )
             val configKey =
                 setUpQuickAffordanceModel(
@@ -656,6 +676,7 @@
                     icon = mock(),
                     canShowWhileLocked = false,
                     intent = Intent("action"),
+                    slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
                 )
             val configKey =
                 setUpQuickAffordanceModel(
@@ -684,6 +705,7 @@
                     icon = mock(),
                     canShowWhileLocked = false,
                     intent = Intent("action"),
+                    slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
                 )
             val configKey =
                 setUpQuickAffordanceModel(
@@ -748,12 +770,14 @@
         assertThat(viewModel.isActivated).isEqualTo(testConfig.isActivated)
         assertThat(viewModel.isSelected).isEqualTo(testConfig.isSelected)
         assertThat(viewModel.isDimmed).isEqualTo(testConfig.isDimmed)
+        assertThat(viewModel.slotId).isEqualTo(testConfig.slotId)
         if (testConfig.isVisible) {
             assertThat(viewModel.icon).isEqualTo(testConfig.icon)
             viewModel.onClicked.invoke(
                 KeyguardQuickAffordanceViewModel.OnClickedParameters(
                     configKey = configKey,
                     expandable = expandable,
+                    slotId = viewModel.slotId,
                 )
             )
             if (testConfig.intent != null) {
@@ -775,6 +799,7 @@
         val intent: Intent? = null,
         val isSelected: Boolean = false,
         val isDimmed: Boolean = false,
+        val slotId: String = ""
     ) {
         init {
             check(!isVisible || icon != null) { "Must supply non-null icon if visible!" }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt
index 65e4c10..e66be08 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt
@@ -96,7 +96,7 @@
     fun shouldUpdateSideFps() = runTest {
         var count = 0
         val job = underTest.shouldUpdateSideFps.onEach { count++ }.launchIn(this)
-        repository.setPrimaryVisible(true)
+        repository.setPrimaryShow(true)
         // Run the tasks that are pending at this point of virtual time.
         runCurrent()
         assertThat(count).isEqualTo(1)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt
new file mode 100644
index 0000000..746f668
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt
@@ -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.systemui.keyguard.ui.viewmodel
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.ScrimAlpha
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.statusbar.SysuiStatusBarStateController
+import com.android.systemui.util.mockito.whenever
+import com.google.common.collect.Range
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class PrimaryBouncerToGoneTransitionViewModelTest : SysuiTestCase() {
+    private lateinit var underTest: PrimaryBouncerToGoneTransitionViewModel
+    private lateinit var repository: FakeKeyguardTransitionRepository
+    @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
+    @Mock private lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        repository = FakeKeyguardTransitionRepository()
+        val interactor = KeyguardTransitionInteractor(repository)
+        underTest =
+            PrimaryBouncerToGoneTransitionViewModel(
+                interactor,
+                statusBarStateController,
+                primaryBouncerInteractor
+            )
+
+        whenever(primaryBouncerInteractor.willRunDismissFromKeyguard()).thenReturn(false)
+        whenever(statusBarStateController.leaveOpenOnKeyguardHide()).thenReturn(false)
+    }
+
+    @Test
+    fun bouncerAlpha() =
+        runTest(UnconfinedTestDispatcher()) {
+            val values = mutableListOf<Float>()
+
+            val job = underTest.bouncerAlpha.onEach { values.add(it) }.launchIn(this)
+
+            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+            repository.sendTransitionStep(step(0.3f))
+            repository.sendTransitionStep(step(0.6f))
+
+            assertThat(values.size).isEqualTo(3)
+            values.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
+
+            job.cancel()
+        }
+
+    @Test
+    fun bouncerAlpha_runDimissFromKeyguard() =
+        runTest(UnconfinedTestDispatcher()) {
+            val values = mutableListOf<Float>()
+
+            val job = underTest.bouncerAlpha.onEach { values.add(it) }.launchIn(this)
+
+            whenever(primaryBouncerInteractor.willRunDismissFromKeyguard()).thenReturn(true)
+
+            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+            repository.sendTransitionStep(step(0.3f))
+            repository.sendTransitionStep(step(0.6f))
+
+            assertThat(values.size).isEqualTo(3)
+            values.forEach { assertThat(it).isEqualTo(0f) }
+
+            job.cancel()
+        }
+
+    @Test
+    fun scrimAlpha_runDimissFromKeyguard() =
+        runTest(UnconfinedTestDispatcher()) {
+            val values = mutableListOf<ScrimAlpha>()
+
+            val job = underTest.scrimAlpha.onEach { values.add(it) }.launchIn(this)
+
+            whenever(primaryBouncerInteractor.willRunDismissFromKeyguard()).thenReturn(true)
+
+            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+            repository.sendTransitionStep(step(0.3f))
+            repository.sendTransitionStep(step(0.6f))
+            repository.sendTransitionStep(step(1f))
+
+            assertThat(values.size).isEqualTo(4)
+            values.forEach { assertThat(it).isEqualTo(ScrimAlpha(notificationsAlpha = 1f)) }
+
+            job.cancel()
+        }
+
+    @Test
+    fun scrimBehindAlpha_leaveShadeOpen() =
+        runTest(UnconfinedTestDispatcher()) {
+            val values = mutableListOf<ScrimAlpha>()
+
+            val job = underTest.scrimAlpha.onEach { values.add(it) }.launchIn(this)
+
+            whenever(statusBarStateController.leaveOpenOnKeyguardHide()).thenReturn(true)
+
+            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+            repository.sendTransitionStep(step(0.3f))
+            repository.sendTransitionStep(step(0.6f))
+            repository.sendTransitionStep(step(1f))
+
+            assertThat(values.size).isEqualTo(4)
+            values.forEach {
+                assertThat(it).isEqualTo(ScrimAlpha(notificationsAlpha = 1f, behindAlpha = 1f))
+            }
+
+            job.cancel()
+        }
+
+    @Test
+    fun scrimBehindAlpha_doNotLeaveShadeOpen() =
+        runTest(UnconfinedTestDispatcher()) {
+            val values = mutableListOf<ScrimAlpha>()
+
+            val job = underTest.scrimAlpha.onEach { values.add(it) }.launchIn(this)
+
+            whenever(statusBarStateController.leaveOpenOnKeyguardHide()).thenReturn(false)
+
+            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+            repository.sendTransitionStep(step(0.3f))
+            repository.sendTransitionStep(step(0.6f))
+            repository.sendTransitionStep(step(1f))
+
+            assertThat(values.size).isEqualTo(4)
+            values.forEach { assertThat(it.notificationsAlpha).isEqualTo(0f) }
+            values.forEach { assertThat(it.frontAlpha).isEqualTo(0f) }
+            values.forEach { assertThat(it.behindAlpha).isIn(Range.closed(0f, 1f)) }
+            assertThat(values[3].behindAlpha).isEqualTo(0f)
+
+            job.cancel()
+        }
+
+    private fun step(
+        value: Float,
+        state: TransitionState = TransitionState.RUNNING
+    ): TransitionStep {
+        return TransitionStep(
+            from = KeyguardState.PRIMARY_BOUNCER,
+            to = KeyguardState.GONE,
+            value = value,
+            transitionState = state,
+            ownerName = "PrimaryBouncerToGoneTransitionViewModelTest"
+        )
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt
index c7f3fa0..fb20bac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableChangeTest.kt
@@ -121,4 +121,92 @@
         assertThat(underTest.getName()).doesNotContain("original")
         assertThat(underTest.getVal()).isEqualTo("8900")
     }
+
+    @Test
+    fun updateTo_emptyToString_isString() {
+        val underTest = TableChange(columnPrefix = "fakePrefix", columnName = "fakeName")
+
+        val new = TableChange(columnPrefix = "newPrefix", columnName = "newName")
+        new.set("newString")
+        underTest.updateTo(new)
+
+        assertThat(underTest.hasData()).isTrue()
+        assertThat(underTest.getName()).contains("newPrefix")
+        assertThat(underTest.getName()).contains("newName")
+        assertThat(underTest.getVal()).isEqualTo("newString")
+    }
+
+    @Test
+    fun updateTo_intToEmpty_isEmpty() {
+        val underTest = TableChange(columnPrefix = "fakePrefix", columnName = "fakeName")
+        underTest.set(42)
+
+        val new = TableChange(columnPrefix = "newPrefix", columnName = "newName")
+        underTest.updateTo(new)
+
+        assertThat(underTest.hasData()).isFalse()
+        assertThat(underTest.getName()).contains("newPrefix")
+        assertThat(underTest.getName()).contains("newName")
+        assertThat(underTest.getVal()).isEqualTo("null")
+    }
+
+    @Test
+    fun updateTo_stringToBool_isBool() {
+        val underTest = TableChange(columnPrefix = "fakePrefix", columnName = "fakeName")
+        underTest.set("oldString")
+
+        val new = TableChange(columnPrefix = "newPrefix", columnName = "newName")
+        new.set(true)
+        underTest.updateTo(new)
+
+        assertThat(underTest.hasData()).isTrue()
+        assertThat(underTest.getName()).contains("newPrefix")
+        assertThat(underTest.getName()).contains("newName")
+        assertThat(underTest.getVal()).isEqualTo("true")
+    }
+
+    @Test
+    fun updateTo_intToString_isString() {
+        val underTest = TableChange(columnPrefix = "fakePrefix", columnName = "fakeName")
+        underTest.set(43)
+
+        val new = TableChange(columnPrefix = "newPrefix", columnName = "newName")
+        new.set("newString")
+        underTest.updateTo(new)
+
+        assertThat(underTest.hasData()).isTrue()
+        assertThat(underTest.getName()).contains("newPrefix")
+        assertThat(underTest.getName()).contains("newName")
+        assertThat(underTest.getVal()).isEqualTo("newString")
+    }
+
+    @Test
+    fun updateTo_boolToInt_isInt() {
+        val underTest = TableChange(columnPrefix = "fakePrefix", columnName = "fakeName")
+        underTest.set(false)
+
+        val new = TableChange(columnPrefix = "newPrefix", columnName = "newName")
+        new.set(44)
+        underTest.updateTo(new)
+
+        assertThat(underTest.hasData()).isTrue()
+        assertThat(underTest.getName()).contains("newPrefix")
+        assertThat(underTest.getName()).contains("newName")
+        assertThat(underTest.getVal()).isEqualTo("44")
+    }
+
+    @Test
+    fun updateTo_boolToNewBool_isNewBool() {
+        val underTest = TableChange(columnPrefix = "fakePrefix", columnName = "fakeName")
+        underTest.set(false)
+
+        val new = TableChange(columnPrefix = "newPrefix", columnName = "newName")
+        new.set(true)
+        underTest.updateTo(new)
+
+        assertThat(underTest.hasData()).isTrue()
+        assertThat(underTest.getName()).contains("newPrefix")
+        assertThat(underTest.getName()).contains("newName")
+        assertThat(underTest.getVal()).isEqualTo("true")
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt
index 2c8d7ab..949fa1c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt
@@ -435,11 +435,236 @@
 
         assertThat(dumpedString).doesNotContain("testString[0]")
         assertThat(dumpedString).doesNotContain("testString[1]")
-        assertThat(dumpedString).doesNotContain("testString[2]")
+        // The buffer should contain [MAX_SIZE + 1] entries since we also save the most recently
+        // evicted value.
+        assertThat(dumpedString).contains("testString[2]")
         assertThat(dumpedString).contains("testString[3]")
         assertThat(dumpedString).contains("testString[${MAX_SIZE + 2}]")
     }
 
+    @Test
+    fun columnEvicted_lastKnownColumnValueInDump() {
+        systemClock.setCurrentTimeMillis(100L)
+        underTest.logChange(prefix = "", columnName = "willBeEvicted", value = "evictedValue")
+
+        // Exactly fill the buffer so that "willBeEvicted" is evicted
+        for (i in 0 until MAX_SIZE) {
+            systemClock.advanceTime(100L)
+            val dumpString = "fillString[$i]"
+            underTest.logChange(prefix = "", columnName = "fillingColumn", value = dumpString)
+        }
+
+        val dumpedString = dumpChanges()
+
+        // Expect that we'll have both the evicted column entry...
+        val evictedColumnLog =
+            TABLE_LOG_DATE_FORMAT.format(100L) +
+                SEPARATOR +
+                "willBeEvicted" +
+                SEPARATOR +
+                "evictedValue"
+        assertThat(dumpedString).contains(evictedColumnLog)
+
+        // ... *and* all of the fillingColumn entries.
+        val firstFillingColumnLog =
+            TABLE_LOG_DATE_FORMAT.format(200L) +
+                SEPARATOR +
+                "fillingColumn" +
+                SEPARATOR +
+                "fillString[0]"
+        val lastFillingColumnLog =
+            TABLE_LOG_DATE_FORMAT.format(1100L) +
+                SEPARATOR +
+                "fillingColumn" +
+                SEPARATOR +
+                "fillString[9]"
+        assertThat(dumpedString).contains(firstFillingColumnLog)
+        assertThat(dumpedString).contains(lastFillingColumnLog)
+    }
+
+    @Test
+    fun multipleColumnsEvicted_allColumnsInDump() {
+        systemClock.setCurrentTimeMillis(100L)
+        underTest.logChange(prefix = "", columnName = "willBeEvictedString", value = "evictedValue")
+        systemClock.advanceTime(100L)
+        underTest.logChange(prefix = "", columnName = "willBeEvictedInt", value = 45)
+        systemClock.advanceTime(100L)
+        underTest.logChange(prefix = "", columnName = "willBeEvictedBool", value = true)
+
+        // Exactly fill the buffer so that all the above columns will be evicted
+        for (i in 0 until MAX_SIZE) {
+            systemClock.advanceTime(100L)
+            val dumpString = "fillString[$i]"
+            underTest.logChange(prefix = "", columnName = "fillingColumn", value = dumpString)
+        }
+
+        val dumpedString = dumpChanges()
+
+        // Expect that we'll have all the evicted column entries...
+        val evictedColumnLogString =
+            TABLE_LOG_DATE_FORMAT.format(100L) +
+                SEPARATOR +
+                "willBeEvictedString" +
+                SEPARATOR +
+                "evictedValue"
+        val evictedColumnLogInt =
+            TABLE_LOG_DATE_FORMAT.format(200L) + SEPARATOR + "willBeEvictedInt" + SEPARATOR + "45"
+        val evictedColumnLogBool =
+            TABLE_LOG_DATE_FORMAT.format(300L) +
+                SEPARATOR +
+                "willBeEvictedBool" +
+                SEPARATOR +
+                "true"
+        assertThat(dumpedString).contains(evictedColumnLogString)
+        assertThat(dumpedString).contains(evictedColumnLogInt)
+        assertThat(dumpedString).contains(evictedColumnLogBool)
+
+        // ... *and* all of the fillingColumn entries.
+        val firstFillingColumnLog =
+            TABLE_LOG_DATE_FORMAT.format(400) +
+                SEPARATOR +
+                "fillingColumn" +
+                SEPARATOR +
+                "fillString[0]"
+        val lastFillingColumnLog =
+            TABLE_LOG_DATE_FORMAT.format(1300) +
+                SEPARATOR +
+                "fillingColumn" +
+                SEPARATOR +
+                "fillString[9]"
+        assertThat(dumpedString).contains(firstFillingColumnLog)
+        assertThat(dumpedString).contains(lastFillingColumnLog)
+    }
+
+    @Test
+    fun multipleColumnsEvicted_differentPrefixSameName_allColumnsInDump() {
+        systemClock.setCurrentTimeMillis(100L)
+        underTest.logChange(prefix = "prefix1", columnName = "sameName", value = "value1")
+        systemClock.advanceTime(100L)
+        underTest.logChange(prefix = "prefix2", columnName = "sameName", value = "value2")
+        systemClock.advanceTime(100L)
+        underTest.logChange(prefix = "prefix3", columnName = "sameName", value = "value3")
+
+        // Exactly fill the buffer so that all the above columns will be evicted
+        for (i in 0 until MAX_SIZE) {
+            systemClock.advanceTime(100L)
+            val dumpString = "fillString[$i]"
+            underTest.logChange(prefix = "", columnName = "fillingColumn", value = dumpString)
+        }
+
+        val dumpedString = dumpChanges()
+
+        // Expect that we'll have all the evicted column entries
+        val evictedColumn1 =
+            TABLE_LOG_DATE_FORMAT.format(100L) +
+                SEPARATOR +
+                "prefix1.sameName" +
+                SEPARATOR +
+                "value1"
+        val evictedColumn2 =
+            TABLE_LOG_DATE_FORMAT.format(200L) +
+                SEPARATOR +
+                "prefix2.sameName" +
+                SEPARATOR +
+                "value2"
+        val evictedColumn3 =
+            TABLE_LOG_DATE_FORMAT.format(300L) +
+                SEPARATOR +
+                "prefix3.sameName" +
+                SEPARATOR +
+                "value3"
+        assertThat(dumpedString).contains(evictedColumn1)
+        assertThat(dumpedString).contains(evictedColumn2)
+        assertThat(dumpedString).contains(evictedColumn3)
+    }
+
+    @Test
+    fun multipleColumnsEvicted_dumpSortedByTimestamp() {
+        systemClock.setCurrentTimeMillis(100L)
+        underTest.logChange(prefix = "", columnName = "willBeEvictedFirst", value = "evictedValue")
+        systemClock.advanceTime(100L)
+        underTest.logChange(prefix = "", columnName = "willBeEvictedSecond", value = 45)
+        systemClock.advanceTime(100L)
+        underTest.logChange(prefix = "", columnName = "willBeEvictedThird", value = true)
+
+        // Exactly fill the buffer with so that all the above columns will be evicted
+        for (i in 0 until MAX_SIZE) {
+            systemClock.advanceTime(100L)
+            val dumpString = "fillString[$i]"
+            underTest.logChange(prefix = "", columnName = "fillingColumn", value = dumpString)
+        }
+
+        val dumpedString = dumpChanges()
+
+        // Expect that we'll have all the evicted column entries in timestamp order
+        val firstEvictedLog =
+            TABLE_LOG_DATE_FORMAT.format(100L) +
+                SEPARATOR +
+                "willBeEvictedFirst" +
+                SEPARATOR +
+                "evictedValue"
+        val secondEvictedLog =
+            TABLE_LOG_DATE_FORMAT.format(200L) +
+                SEPARATOR +
+                "willBeEvictedSecond" +
+                SEPARATOR +
+                "45"
+        val thirdEvictedLog =
+            TABLE_LOG_DATE_FORMAT.format(300L) +
+                SEPARATOR +
+                "willBeEvictedThird" +
+                SEPARATOR +
+                "true"
+        assertThat(dumpedString).contains(firstEvictedLog)
+        val stringAfterFirst = dumpedString.substringAfter(firstEvictedLog)
+        assertThat(stringAfterFirst).contains(secondEvictedLog)
+        val stringAfterSecond = stringAfterFirst.substringAfter(secondEvictedLog)
+        assertThat(stringAfterSecond).contains(thirdEvictedLog)
+    }
+
+    @Test
+    fun sameColumnEvictedMultipleTimes_onlyLastEvictionInDump() {
+        systemClock.setCurrentTimeMillis(0L)
+
+        for (i in 1 until 4) {
+            systemClock.advanceTime(100L)
+            val dumpString = "evicted[$i]"
+            underTest.logChange(prefix = "", columnName = "evictedColumn", value = dumpString)
+        }
+
+        // Exactly fill the buffer so that all the entries for "evictedColumn" will be evicted.
+        for (i in 0 until MAX_SIZE) {
+            systemClock.advanceTime(100L)
+            val dumpString = "fillString[$i]"
+            underTest.logChange(prefix = "", columnName = "fillingColumn", value = dumpString)
+        }
+
+        val dumpedString = dumpChanges()
+
+        // Expect that we only have the most recent evicted column entry
+        val evictedColumnLog1 =
+            TABLE_LOG_DATE_FORMAT.format(100L) +
+                SEPARATOR +
+                "evictedColumn" +
+                SEPARATOR +
+                "evicted[1]"
+        val evictedColumnLog2 =
+            TABLE_LOG_DATE_FORMAT.format(200L) +
+                SEPARATOR +
+                "evictedColumn" +
+                SEPARATOR +
+                "evicted[2]"
+        val evictedColumnLog3 =
+            TABLE_LOG_DATE_FORMAT.format(300L) +
+                SEPARATOR +
+                "evictedColumn" +
+                SEPARATOR +
+                "evicted[3]"
+        assertThat(dumpedString).doesNotContain(evictedColumnLog1)
+        assertThat(dumpedString).doesNotContain(evictedColumnLog2)
+        assertThat(dumpedString).contains(evictedColumnLog3)
+    }
+
     private fun dumpChanges(): String {
         underTest.dump(PrintWriter(outputWriter), arrayOf())
         return outputWriter.toString()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt
index 8c54da1..d428db7b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt
@@ -139,6 +139,7 @@
     @Mock private lateinit var logger: MediaUiEventLogger
     lateinit var mediaDataManager: MediaDataManager
     lateinit var mediaNotification: StatusBarNotification
+    lateinit var remoteCastNotification: StatusBarNotification
     @Captor lateinit var mediaDataCaptor: ArgumentCaptor<MediaData>
     private val clock = FakeSystemClock()
     @Mock private lateinit var tunerService: TunerService
@@ -207,6 +208,20 @@
                 }
                 build()
             }
+        remoteCastNotification =
+            SbnBuilder().run {
+                setPkg(SYSTEM_PACKAGE_NAME)
+                modifyNotification(context).also {
+                    it.setSmallIcon(android.R.drawable.ic_media_pause)
+                    it.setStyle(
+                        MediaStyle().apply {
+                            setMediaSession(session.sessionToken)
+                            setRemotePlaybackInfo("Remote device", 0, null)
+                        }
+                    )
+                }
+                build()
+            }
         metadataBuilder =
             MediaMetadata.Builder().apply {
                 putString(MediaMetadata.METADATA_KEY_ARTIST, SESSION_ARTIST)
@@ -247,6 +262,7 @@
         whenever(mediaFlags.isExplicitIndicatorEnabled()).thenReturn(true)
         whenever(mediaFlags.isRetainingPlayersEnabled()).thenReturn(false)
         whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(false)
+        whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(false)
         whenever(logger.getNewInstanceId()).thenReturn(instanceIdSequence.newInstanceId())
         whenever(keyguardUpdateMonitor.isUserInLockdown(any())).thenReturn(false)
     }
@@ -400,33 +416,8 @@
 
     @Test
     fun testOnNotificationAdded_isRcn_markedRemote() {
-        val rcn =
-            SbnBuilder().run {
-                setPkg(SYSTEM_PACKAGE_NAME)
-                modifyNotification(context).also {
-                    it.setSmallIcon(android.R.drawable.ic_media_pause)
-                    it.setStyle(
-                        MediaStyle().apply {
-                            setMediaSession(session.sessionToken)
-                            setRemotePlaybackInfo("Remote device", 0, null)
-                        }
-                    )
-                }
-                build()
-            }
+        addNotificationAndLoad(remoteCastNotification)
 
-        mediaDataManager.onNotificationAdded(KEY, rcn)
-        assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
-        assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
-        verify(listener)
-            .onMediaDataLoaded(
-                eq(KEY),
-                eq(null),
-                capture(mediaDataCaptor),
-                eq(true),
-                eq(0),
-                eq(false)
-            )
         assertThat(mediaDataCaptor.value!!.playbackLocation)
             .isEqualTo(MediaData.PLAYBACK_CAST_REMOTE)
         verify(logger)
@@ -710,6 +701,56 @@
     }
 
     @Test
+    fun testOnNotificationRemoved_withResumption_isRemoteAndRemoteAllowed() {
+        // With the flag enabled to allow remote media to resume
+        whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(true)
+
+        // GIVEN that the manager has a notification with a resume action, but is not local
+        whenever(controller.metadata).thenReturn(metadataBuilder.build())
+        whenever(playbackInfo.playbackType)
+            .thenReturn(MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE)
+        addNotificationAndLoad()
+        val data = mediaDataCaptor.value
+        val dataRemoteWithResume =
+            data.copy(resumeAction = Runnable {}, playbackLocation = MediaData.PLAYBACK_CAST_LOCAL)
+        mediaDataManager.onMediaDataLoaded(KEY, null, dataRemoteWithResume)
+
+        // WHEN the notification is removed
+        mediaDataManager.onNotificationRemoved(KEY)
+
+        // THEN the media data is converted to a resume state
+        verify(listener)
+            .onMediaDataLoaded(
+                eq(PACKAGE_NAME),
+                eq(KEY),
+                capture(mediaDataCaptor),
+                eq(true),
+                eq(0),
+                eq(false)
+            )
+        assertThat(mediaDataCaptor.value.resumption).isTrue()
+    }
+
+    @Test
+    fun testOnNotificationRemoved_withResumption_isRcnAndRemoteAllowed() {
+        // With the flag enabled to allow remote media to resume
+        whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(true)
+
+        // GIVEN that the manager has a remote cast notification
+        addNotificationAndLoad(remoteCastNotification)
+        val data = mediaDataCaptor.value
+        assertThat(data.playbackLocation).isEqualTo(MediaData.PLAYBACK_CAST_REMOTE)
+        val dataRemoteWithResume = data.copy(resumeAction = Runnable {})
+        mediaDataManager.onMediaDataLoaded(KEY, null, dataRemoteWithResume)
+
+        // WHEN the RCN is removed
+        mediaDataManager.onNotificationRemoved(KEY)
+
+        // THEN the media data is removed
+        verify(listener).onMediaDataRemoved(eq(KEY))
+    }
+
+    @Test
     fun testOnNotificationRemoved_withResumption_tooManyPlayers() {
         // Given the maximum number of resume controls already
         val desc =
@@ -1654,22 +1695,7 @@
             )
 
         // update to remote cast
-        val rcn =
-            SbnBuilder().run {
-                setPkg(SYSTEM_PACKAGE_NAME) // System package
-                modifyNotification(context).also {
-                    it.setSmallIcon(android.R.drawable.ic_media_pause)
-                    it.setStyle(
-                        MediaStyle().apply {
-                            setMediaSession(session.sessionToken)
-                            setRemotePlaybackInfo("Remote device", 0, null)
-                        }
-                    )
-                }
-                build()
-            }
-
-        mediaDataManager.onNotificationAdded(KEY, rcn)
+        mediaDataManager.onNotificationAdded(KEY, remoteCastNotification)
         assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
         assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
         verify(logger)
@@ -2005,7 +2031,7 @@
     }
 
     @Test
-    fun testRetain_sessionPlayer_destroyedWhileActive_fullyRemoved() {
+    fun testRetain_sessionPlayer_destroyedWhileActive_noResume_fullyRemoved() {
         whenever(mediaFlags.isRetainingPlayersEnabled()).thenReturn(true)
         whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(true)
         addPlaybackStateAction()
@@ -2025,6 +2051,40 @@
     }
 
     @Test
+    fun testRetain_sessionPlayer_canResume_destroyedWhileActive_setToResume() {
+        whenever(mediaFlags.isRetainingPlayersEnabled()).thenReturn(true)
+        whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(true)
+        addPlaybackStateAction()
+
+        // When a media control using session actions and that does allow resumption is added,
+        addNotificationAndLoad()
+        val dataResumable = mediaDataCaptor.value.copy(resumeAction = Runnable {})
+        mediaDataManager.onMediaDataLoaded(KEY, null, dataResumable)
+
+        // And then the session is destroyed without timing out first
+        sessionCallbackCaptor.value.invoke(KEY)
+
+        // It is converted to a resume player
+        verify(listener)
+            .onMediaDataLoaded(
+                eq(PACKAGE_NAME),
+                eq(KEY),
+                capture(mediaDataCaptor),
+                eq(true),
+                eq(0),
+                eq(false)
+            )
+        assertThat(mediaDataCaptor.value.resumption).isTrue()
+        assertThat(mediaDataCaptor.value.active).isFalse()
+        verify(logger)
+            .logActiveConvertedToResume(
+                anyInt(),
+                eq(PACKAGE_NAME),
+                eq(mediaDataCaptor.value.instanceId)
+            )
+    }
+
+    @Test
     fun testSessionDestroyed_noNotificationKey_stillRemoved() {
         whenever(mediaFlags.isRetainingPlayersEnabled()).thenReturn(true)
         whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(true)
@@ -2038,9 +2098,14 @@
         verify(listener).onMediaDataRemoved(eq(KEY))
     }
 
-    /** Helper function to add a media notification and capture the resulting MediaData */
+    /** Helper function to add a basic media notification and capture the resulting MediaData */
     private fun addNotificationAndLoad() {
-        mediaDataManager.onNotificationAdded(KEY, mediaNotification)
+        addNotificationAndLoad(mediaNotification)
+    }
+
+    /** Helper function to add the given notification and capture the resulting MediaData */
+    private fun addNotificationAndLoad(sbn: StatusBarNotification) {
+        mediaDataManager.onNotificationAdded(KEY, sbn)
         assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
         assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
         verify(listener)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt
index 136ace1..9ab7289 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt
@@ -38,6 +38,7 @@
 import com.android.systemui.media.controls.models.player.MediaDeviceData
 import com.android.systemui.media.controls.pipeline.MediaDataManager
 import com.android.systemui.media.controls.pipeline.RESUME_MEDIA_TIMEOUT
+import com.android.systemui.media.controls.util.MediaFlags
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.tuner.TunerService
 import com.android.systemui.util.concurrency.FakeExecutor
@@ -92,6 +93,7 @@
     @Mock private lateinit var mockContext: Context
     @Mock private lateinit var pendingIntent: PendingIntent
     @Mock private lateinit var dumpManager: DumpManager
+    @Mock private lateinit var mediaFlags: MediaFlags
 
     @Captor lateinit var callbackCaptor: ArgumentCaptor<ResumeMediaBrowser.Callback>
     @Captor lateinit var actionCaptor: ArgumentCaptor<Runnable>
@@ -134,6 +136,7 @@
         whenever(mockContext.packageManager).thenReturn(context.packageManager)
         whenever(mockContext.contentResolver).thenReturn(context.contentResolver)
         whenever(mockContext.userId).thenReturn(context.userId)
+        whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(false)
 
         executor = FakeExecutor(clock)
         resumeListener =
@@ -146,7 +149,8 @@
                 tunerService,
                 resumeBrowserFactory,
                 dumpManager,
-                clock
+                clock,
+                mediaFlags,
             )
         resumeListener.setManager(mediaDataManager)
         mediaDataManager.addListener(resumeListener)
@@ -188,7 +192,8 @@
                 tunerService,
                 resumeBrowserFactory,
                 dumpManager,
-                clock
+                clock,
+                mediaFlags,
             )
         listener.setManager(mediaDataManager)
         verify(broadcastDispatcher, never())
@@ -244,6 +249,32 @@
     }
 
     @Test
+    fun testOnLoad_localCast_remoteResumeAllowed_doesCheck() {
+        // If local cast media is allowed to resume
+        whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(true)
+
+        // When media data is loaded that has not been checked yet, and is a local cast
+        val dataCast = data.copy(playbackLocation = MediaData.PLAYBACK_CAST_LOCAL)
+        resumeListener.onMediaDataLoaded(KEY, null, dataCast)
+
+        // Then we report back to the manager
+        verify(mediaDataManager).setResumeAction(KEY, null)
+    }
+
+    @Test
+    fun testOnLoad_remoteCast_remoteResumeAllowed_doesCheck() {
+        // If local cast media is allowed to resume
+        whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(true)
+
+        // When media data is loaded that has not been checked yet, and is a remote cast
+        val dataRcn = data.copy(playbackLocation = MediaData.PLAYBACK_CAST_REMOTE)
+        resumeListener.onMediaDataLoaded(KEY, null, dataRcn)
+
+        // Then we do not take action
+        verify(mediaDataManager, never()).setResumeAction(any(), any())
+    }
+
+    @Test
     fun testOnLoad_checksForResume_hasService() {
         setUpMbsWithValidResolveInfo()
 
@@ -282,6 +313,25 @@
     }
 
     @Test
+    fun testOnLoadTwice_onlyChecksOnce() {
+        // When data is first loaded,
+        setUpMbsWithValidResolveInfo()
+        resumeListener.onMediaDataLoaded(KEY, null, data)
+
+        // We notify the manager to set a null action
+        verify(mediaDataManager).setResumeAction(KEY, null)
+
+        // If we then get another update from the app before the first check completes
+        assertThat(executor.numPending()).isEqualTo(1)
+        var dataWithCheck = data.copy(hasCheckedForResume = true)
+        resumeListener.onMediaDataLoaded(KEY, null, dataWithCheck)
+
+        // We do not try to start another check
+        assertThat(executor.numPending()).isEqualTo(1)
+        verify(mediaDataManager).setResumeAction(KEY, null)
+    }
+
+    @Test
     fun testOnUserUnlock_loadsTracks() {
         // Set up mock service to successfully find valid media
         val description = MediaDescription.Builder().setTitle(TITLE).build()
@@ -361,7 +411,7 @@
                 assertThat(result.size).isEqualTo(3)
                 assertThat(result[2].toLong()).isEqualTo(currentTime)
             }
-        verify(sharedPrefsEditor, times(1)).apply()
+        verify(sharedPrefsEditor).apply()
     }
 
     @Test
@@ -389,7 +439,8 @@
                 tunerService,
                 resumeBrowserFactory,
                 dumpManager,
-                clock
+                clock,
+                mediaFlags,
             )
         resumeListener.setManager(mediaDataManager)
         mediaDataManager.addListener(resumeListener)
@@ -400,8 +451,8 @@
         resumeListener.userUnlockReceiver.onReceive(mockContext, intent)
 
         // We add its resume controls
-        verify(resumeBrowser, times(1)).findRecentMedia()
-        verify(mediaDataManager, times(1))
+        verify(resumeBrowser).findRecentMedia()
+        verify(mediaDataManager)
             .addResumptionControls(anyInt(), any(), any(), any(), any(), any(), eq(PACKAGE_NAME))
     }
 
@@ -421,7 +472,8 @@
                 tunerService,
                 resumeBrowserFactory,
                 dumpManager,
-                clock
+                clock,
+                mediaFlags,
             )
         resumeListener.setManager(mediaDataManager)
         mediaDataManager.addListener(resumeListener)
@@ -463,7 +515,8 @@
                 tunerService,
                 resumeBrowserFactory,
                 dumpManager,
-                clock
+                clock,
+                mediaFlags,
             )
         resumeListener.setManager(mediaDataManager)
         mediaDataManager.addListener(resumeListener)
@@ -482,7 +535,7 @@
                 assertThat(result.size).isEqualTo(3)
                 assertThat(result[2].toLong()).isEqualTo(currentTime)
             }
-        verify(sharedPrefsEditor, times(1)).apply()
+        verify(sharedPrefsEditor).apply()
     }
 
     @Test
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 7f57077..e0ca90e 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
@@ -18,7 +18,6 @@
 
 import android.app.PendingIntent
 import android.content.res.ColorStateList
-import android.content.res.Configuration
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import android.util.MathUtils.abs
@@ -685,46 +684,6 @@
     }
 
     @Test
-    fun testOnConfigChanged_playersAreAddedBack() {
-        mediaCarouselController.pageIndicator = pageIndicator
-
-        listener.value.onMediaDataLoaded(
-            "playing local",
-            null,
-            DATA.copy(
-                active = true,
-                isPlaying = true,
-                playbackLocation = MediaData.PLAYBACK_LOCAL,
-                resumption = false
-            )
-        )
-        listener.value.onMediaDataLoaded(
-            "paused local",
-            null,
-            DATA.copy(
-                active = true,
-                isPlaying = false,
-                playbackLocation = MediaData.PLAYBACK_LOCAL,
-                resumption = false
-            )
-        )
-        runAllReady()
-
-        val playersSize = MediaPlayerData.players().size
-
-        configListener.value.onConfigChanged(Configuration())
-        runAllReady()
-
-        verify(pageIndicator).tintList =
-            ColorStateList.valueOf(context.getColor(R.color.media_paging_indicator))
-        assertEquals(playersSize, MediaPlayerData.players().size)
-        assertEquals(
-            MediaPlayerData.getMediaPlayerIndex("playing local"),
-            mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex
-        )
-    }
-
-    @Test
     fun testOnUiModeChanged_playersAreAddedBack() {
         mediaCarouselController.pageIndicator = pageIndicator
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt
index 55a33b6..fd353af 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaControlPanelTest.kt
@@ -27,6 +27,7 @@
 import android.graphics.Bitmap
 import android.graphics.Canvas
 import android.graphics.Color
+import android.graphics.Matrix
 import android.graphics.drawable.Animatable2
 import android.graphics.drawable.AnimatedVectorDrawable
 import android.graphics.drawable.Drawable
@@ -78,6 +79,8 @@
 import com.android.systemui.media.controls.pipeline.MediaDataManager
 import com.android.systemui.media.controls.util.MediaUiEventLogger
 import com.android.systemui.media.dialog.MediaOutputDialogFactory
+import com.android.systemui.monet.ColorScheme
+import com.android.systemui.monet.Style
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.plugins.FalsingManager
 import com.android.systemui.statusbar.NotificationLockscreenUserManager
@@ -214,6 +217,7 @@
     @Mock private lateinit var recSubtitleMock2: TextView
     @Mock private lateinit var recSubtitleMock3: TextView
     @Mock private lateinit var coverItem: ImageView
+    @Mock private lateinit var matrix: Matrix
     private lateinit var coverItem1: ImageView
     private lateinit var coverItem2: ImageView
     private lateinit var coverItem3: ImageView
@@ -700,6 +704,46 @@
     }
 
     @Test
+    fun addTwoPlayerGradients_differentStates() {
+        // Setup redArtwork and its color scheme.
+        val redBmp = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888)
+        val redCanvas = Canvas(redBmp)
+        redCanvas.drawColor(Color.RED)
+        val redArt = Icon.createWithBitmap(redBmp)
+        val redWallpaperColor = player.getWallpaperColor(redArt)
+        val redColorScheme = ColorScheme(redWallpaperColor, true, Style.CONTENT)
+
+        // Setup greenArt and its color scheme.
+        val greenBmp = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888)
+        val greenCanvas = Canvas(greenBmp)
+        greenCanvas.drawColor(Color.GREEN)
+        val greenArt = Icon.createWithBitmap(greenBmp)
+        val greenWallpaperColor = player.getWallpaperColor(greenArt)
+        val greenColorScheme = ColorScheme(greenWallpaperColor, true, Style.CONTENT)
+
+        // Add gradient to both icons.
+        val redArtwork = player.addGradientToPlayerAlbum(redArt, redColorScheme, 10, 10)
+        val greenArtwork = player.addGradientToPlayerAlbum(greenArt, greenColorScheme, 10, 10)
+
+        // They should have different constant states as they have different gradient color.
+        assertThat(redArtwork.getDrawable(1).constantState)
+            .isNotEqualTo(greenArtwork.getDrawable(1).constantState)
+    }
+
+    @Test
+    fun getWallpaperColor_recycledBitmap_notCrashing() {
+        // Setup redArt icon.
+        val redBmp = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888)
+        val redArt = Icon.createWithBitmap(redBmp)
+
+        // Recycle bitmap of redArt icon.
+        redArt.bitmap.recycle()
+
+        // get wallpaperColor without illegal exception.
+        player.getWallpaperColor(redArt)
+    }
+
+    @Test
     fun bind_seekBarDisabled_hasActions_seekBarVisibilityIsSetToInvisible() {
         useRealConstraintSets()
 
@@ -2092,6 +2136,7 @@
             .thenReturn(listOf(recProgressBar1, recProgressBar2, recProgressBar3))
         whenever(recommendationViewHolder.mediaSubtitles)
             .thenReturn(listOf(recSubtitleMock1, recSubtitleMock2, recSubtitleMock3))
+        whenever(coverItem.imageMatrix).thenReturn(matrix)
 
         val bmp = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888)
         val canvas = Canvas(bmp)
@@ -2127,6 +2172,7 @@
         verify(recCardTitle).setTextColor(any<Int>())
         verify(recAppIconItem, times(3)).setImageDrawable(any(Drawable::class.java))
         verify(coverItem, times(3)).setImageDrawable(any(Drawable::class.java))
+        verify(coverItem, times(3)).imageMatrix = any()
     }
 
     @Test
@@ -2189,6 +2235,34 @@
     }
 
     @Test
+    fun addTwoRecommendationGradients_differentStates() {
+        // Setup redArtwork and its color scheme.
+        val redBmp = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888)
+        val redCanvas = Canvas(redBmp)
+        redCanvas.drawColor(Color.RED)
+        val redArt = Icon.createWithBitmap(redBmp)
+        val redWallpaperColor = player.getWallpaperColor(redArt)
+        val redColorScheme = ColorScheme(redWallpaperColor, true, Style.CONTENT)
+
+        // Setup greenArt and its color scheme.
+        val greenBmp = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888)
+        val greenCanvas = Canvas(greenBmp)
+        greenCanvas.drawColor(Color.GREEN)
+        val greenArt = Icon.createWithBitmap(greenBmp)
+        val greenWallpaperColor = player.getWallpaperColor(greenArt)
+        val greenColorScheme = ColorScheme(greenWallpaperColor, true, Style.CONTENT)
+
+        // Add gradient to both icons.
+        val redArtwork = player.addGradientToRecommendationAlbum(redArt, redColorScheme, 10, 10)
+        val greenArtwork =
+            player.addGradientToRecommendationAlbum(greenArt, greenColorScheme, 10, 10)
+
+        // They should have different constant states as they have different gradient color.
+        assertThat(redArtwork.getDrawable(1).constantState)
+            .isNotEqualTo(greenArtwork.getDrawable(1).constantState)
+    }
+
+    @Test
     fun onButtonClick_touchRippleFlagEnabled_playsTouchRipple() {
         fakeFeatureFlag.set(Flags.UMO_SURFACE_RIPPLE, true)
         val semanticActions =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt
index a579518..feb429d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt
@@ -180,6 +180,57 @@
     }
 
     @Test
+    fun testBlockedWhenConfigurationChangesAndScreenOff() {
+        // Let's set it onto QS:
+        mediaHierarchyManager.qsExpansion = 1.0f
+        verify(mediaCarouselController)
+            .onDesiredLocationChanged(
+                ArgumentMatchers.anyInt(),
+                any(MediaHostState::class.java),
+                anyBoolean(),
+                anyLong(),
+                anyLong()
+            )
+        val observer = wakefullnessObserver.value
+        assertNotNull("lifecycle observer wasn't registered", observer)
+        observer.onStartedGoingToSleep()
+        clearInvocations(mediaCarouselController)
+        configurationController.notifyConfigurationChanged()
+        verify(mediaCarouselController, times(0))
+            .onDesiredLocationChanged(
+                ArgumentMatchers.anyInt(),
+                any(MediaHostState::class.java),
+                anyBoolean(),
+                anyLong(),
+                anyLong()
+            )
+    }
+
+    @Test
+    fun testAllowedWhenConfigurationChanges() {
+        // Let's set it onto QS:
+        mediaHierarchyManager.qsExpansion = 1.0f
+        verify(mediaCarouselController)
+            .onDesiredLocationChanged(
+                ArgumentMatchers.anyInt(),
+                any(MediaHostState::class.java),
+                anyBoolean(),
+                anyLong(),
+                anyLong()
+            )
+        clearInvocations(mediaCarouselController)
+        configurationController.notifyConfigurationChanged()
+        verify(mediaCarouselController)
+            .onDesiredLocationChanged(
+                ArgumentMatchers.anyInt(),
+                any(MediaHostState::class.java),
+                anyBoolean(),
+                anyLong(),
+                anyLong()
+            )
+    }
+
+    @Test
     fun testAllowedWhenNotTurningOff() {
         // Let's set it onto QS:
         mediaHierarchyManager.qsExpansion = 1.0f
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaViewControllerTest.kt
index af91cdb..0fac3db 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaViewControllerTest.kt
@@ -16,9 +16,12 @@
 
 package com.android.systemui.media.controls.ui
 
+import android.content.res.Configuration
+import android.content.res.Configuration.ORIENTATION_LANDSCAPE
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import android.view.View
+import androidx.constraintlayout.widget.ConstraintSet
 import androidx.test.filters.SmallTest
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
@@ -58,6 +61,8 @@
     @Mock private lateinit var mediaSubTitleWidgetState: WidgetState
     @Mock private lateinit var mediaContainerWidgetState: WidgetState
     @Mock private lateinit var mediaFlags: MediaFlags
+    @Mock private lateinit var expandedLayout: ConstraintSet
+    @Mock private lateinit var collapsedLayout: ConstraintSet
 
     val delta = 0.1F
 
@@ -77,6 +82,19 @@
     }
 
     @Test
+    fun testOrientationChanged_layoutsAreLoaded() {
+        mediaViewController.expandedLayout = expandedLayout
+        mediaViewController.collapsedLayout = collapsedLayout
+
+        val newConfig = Configuration()
+        newConfig.orientation = ORIENTATION_LANDSCAPE
+        configurationController.onConfigurationChanged(newConfig)
+
+        verify(expandedLayout).load(context, R.xml.media_session_expanded)
+        verify(collapsedLayout).load(context, R.xml.media_session_collapsed)
+    }
+
+    @Test
     fun testObtainViewState_applySquishFraction_toPlayerTransitionViewState_height() {
         mediaViewController.attach(player, MediaViewController.TYPE.PLAYER)
         player.measureState =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt
index 4fc9ca7..85e8d07 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt
@@ -70,8 +70,7 @@
                 context,
                 appPackageName = null,
                 isReceiver = false,
-            ) {
-            }
+            ) {}
 
         assertThat(iconInfo.isAppIcon).isFalse()
         assertThat(iconInfo.contentDescription.loadContentDescription(context))
@@ -86,8 +85,7 @@
                 context,
                 appPackageName = null,
                 isReceiver = true,
-            ) {
-            }
+            ) {}
 
         assertThat(iconInfo.isAppIcon).isFalse()
         assertThat(iconInfo.contentDescription.loadContentDescription(context))
@@ -119,8 +117,7 @@
                 context,
                 appPackageName = "fakePackageName",
                 isReceiver = false,
-            ) {
-            }
+            ) {}
 
         assertThat(iconInfo.isAppIcon).isFalse()
         assertThat(iconInfo.contentDescription.loadContentDescription(context))
@@ -135,8 +132,7 @@
                 context,
                 appPackageName = "fakePackageName",
                 isReceiver = true,
-            ) {
-            }
+            ) {}
 
         assertThat(iconInfo.isAppIcon).isFalse()
         assertThat(iconInfo.contentDescription.loadContentDescription(context))
@@ -154,7 +150,9 @@
             context,
             appPackageName = "fakePackageName",
             isReceiver = false
-        ) { exceptionTriggered = true }
+        ) {
+            exceptionTriggered = true
+        }
 
         assertThat(exceptionTriggered).isTrue()
     }
@@ -167,7 +165,9 @@
             context,
             appPackageName = "fakePackageName",
             isReceiver = true
-        ) { exceptionTriggered = true }
+        ) {
+            exceptionTriggered = true
+        }
 
         assertThat(exceptionTriggered).isTrue()
     }
@@ -179,8 +179,7 @@
                 context,
                 PACKAGE_NAME,
                 isReceiver = false,
-            ) {
-            }
+            ) {}
 
         assertThat(iconInfo.isAppIcon).isTrue()
         assertThat(iconInfo.icon).isEqualTo(MediaTttIcon.Loaded(appIconFromPackageName))
@@ -194,8 +193,7 @@
                 context,
                 PACKAGE_NAME,
                 isReceiver = true,
-            ) {
-            }
+            ) {}
 
         assertThat(iconInfo.isAppIcon).isTrue()
         assertThat(iconInfo.icon).isEqualTo(MediaTttIcon.Loaded(appIconFromPackageName))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt
index db890f6..ca2b1da 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt
@@ -107,6 +107,7 @@
     private lateinit var fakeExecutor: FakeExecutor
     private lateinit var uiEventLoggerFake: UiEventLoggerFake
     private lateinit var uiEventLogger: MediaTttSenderUiEventLogger
+    private val defaultTimeout = context.resources.getInteger(R.integer.heads_up_notification_decay)
 
     @Before
     fun setUp() {
@@ -1356,6 +1357,92 @@
         assertThat(chipbarView.getLoadingIcon().visibility).isEqualTo(View.VISIBLE)
     }
 
+    @Test
+    fun almostClose_hasLongTimeout_eventuallyTimesOut() {
+        whenever(accessibilityManager.getRecommendedTimeoutMillis(any(), any())).thenAnswer {
+            it.arguments[0]
+        }
+
+        commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+            StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST,
+            routeInfo,
+            null,
+        )
+
+        // WHEN the default timeout has passed
+        fakeClock.advanceTime(defaultTimeout + 1L)
+
+        // THEN the view is still on-screen because it has a long timeout
+        verify(windowManager, never()).removeView(any())
+
+        // WHEN a very long amount of time has passed
+        fakeClock.advanceTime(5L * defaultTimeout)
+
+        // THEN the view does time out
+        verify(windowManager).removeView(any())
+    }
+
+    @Test
+    fun loading_hasLongTimeout_eventuallyTimesOut() {
+        whenever(accessibilityManager.getRecommendedTimeoutMillis(any(), any())).thenAnswer {
+            it.arguments[0]
+        }
+
+        commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+            StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED,
+            routeInfo,
+            null,
+        )
+
+        // WHEN the default timeout has passed
+        fakeClock.advanceTime(defaultTimeout + 1L)
+
+        // THEN the view is still on-screen because it has a long timeout
+        verify(windowManager, never()).removeView(any())
+
+        // WHEN a very long amount of time has passed
+        fakeClock.advanceTime(5L * defaultTimeout)
+
+        // THEN the view does time out
+        verify(windowManager).removeView(any())
+    }
+
+    @Test
+    fun succeeded_hasDefaultTimeout() {
+        whenever(accessibilityManager.getRecommendedTimeoutMillis(any(), any())).thenAnswer {
+            it.arguments[0]
+        }
+
+        displayReceiverTriggered()
+        commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+            StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED,
+            routeInfo,
+            null,
+        )
+
+        fakeClock.advanceTime(defaultTimeout + 1L)
+
+        verify(windowManager).removeView(any())
+    }
+
+    @Test
+    fun failed_hasDefaultTimeout() {
+        whenever(accessibilityManager.getRecommendedTimeoutMillis(any(), any())).thenAnswer {
+            it.arguments[0]
+        }
+
+        displayThisDeviceTriggered()
+        commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+            StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_FAILED,
+            routeInfo,
+            null,
+        )
+
+        fakeClock.advanceTime(defaultTimeout + 1L)
+
+        verify(windowManager).removeView(any())
+    }
+
     private fun getChipbarView(): ViewGroup {
         val viewCaptor = ArgumentCaptor.forClass(View::class.java)
         verify(windowManager).addView(viewCaptor.capture(), any())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/DynamicColorTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/DynamicColorTest.java
index 41ac3213..d364f47 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/monet/DynamicColorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/DynamicColorTest.java
@@ -18,13 +18,21 @@
 
 import static com.android.systemui.monet.utils.ArgbSubject.assertThat;
 
+import static org.junit.Assert.assertTrue;
+
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.monet.contrast.Contrast;
 import com.android.systemui.monet.dynamiccolor.DynamicColor;
+import com.android.systemui.monet.dynamiccolor.MaterialDynamicColors;
 import com.android.systemui.monet.dynamiccolor.ToneDeltaConstraint;
 import com.android.systemui.monet.dynamiccolor.TonePolarity;
 import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.scheme.DynamicScheme;
+import com.android.systemui.monet.scheme.SchemeContent;
+import com.android.systemui.monet.scheme.SchemeFidelity;
+import com.android.systemui.monet.scheme.SchemeMonochrome;
 import com.android.systemui.monet.scheme.SchemeTonalSpot;
 
 import org.junit.Test;
@@ -90,4 +98,92 @@
         final SchemeTonalSpot darkScheme = new SchemeTonalSpot(Hct.fromInt(0xff4285f4), true, 0.0);
         assertThat(dynamicColor.getArgb(darkScheme)).isSameColorAs(0x33ffffff);
     }
+
+    @Test
+    public void respectsContrast() {
+        final Hct[] seedColors =
+                new Hct[]{
+                        Hct.fromInt(0xFFFF0000),
+                        Hct.fromInt(0xFFFFFF00),
+                        Hct.fromInt(0xFF00FF00),
+                        Hct.fromInt(0xFF0000FF)
+                };
+
+        final double[] contrastLevels = {-1.0, -0.5, 0.0, 0.5, 1.0};
+
+        for (Hct seedColor : seedColors) {
+            for (double contrastLevel : contrastLevels) {
+                for (boolean isDark : new boolean[]{false, true}) {
+                    final DynamicScheme[] schemes =
+                            new DynamicScheme[]{
+                                    new SchemeContent(seedColor, isDark, contrastLevel),
+                                    new SchemeMonochrome(seedColor, isDark, contrastLevel),
+                                    new SchemeTonalSpot(seedColor, isDark, contrastLevel),
+                                    new SchemeFidelity(seedColor, isDark, contrastLevel)
+                            };
+                    for (final DynamicScheme scheme : schemes) {
+                        assertTrue(
+                                pairSatisfiesContrast(
+                                        scheme, MaterialDynamicColors.onPrimary,
+                                        MaterialDynamicColors.primary));
+                        assertTrue(
+                                pairSatisfiesContrast(
+                                        scheme,
+                                        MaterialDynamicColors.onPrimaryContainer,
+                                        MaterialDynamicColors.primaryContainer));
+                        assertTrue(
+                                pairSatisfiesContrast(
+                                        scheme, MaterialDynamicColors.onSecondary,
+                                        MaterialDynamicColors.secondary));
+                        assertTrue(
+                                pairSatisfiesContrast(
+                                        scheme,
+                                        MaterialDynamicColors.onSecondaryContainer,
+                                        MaterialDynamicColors.secondaryContainer));
+                        assertTrue(
+                                pairSatisfiesContrast(
+                                        scheme, MaterialDynamicColors.onTertiary,
+                                        MaterialDynamicColors.tertiary));
+                        assertTrue(
+                                pairSatisfiesContrast(
+                                        scheme,
+                                        MaterialDynamicColors.onTertiaryContainer,
+                                        MaterialDynamicColors.tertiaryContainer));
+                        assertTrue(
+                                pairSatisfiesContrast(
+                                        scheme, MaterialDynamicColors.onError,
+                                        MaterialDynamicColors.error));
+                        assertTrue(
+                                pairSatisfiesContrast(
+                                        scheme,
+                                        MaterialDynamicColors.onErrorContainer,
+                                        MaterialDynamicColors.errorContainer));
+                        assertTrue(
+                                pairSatisfiesContrast(
+                                        scheme, MaterialDynamicColors.onBackground,
+                                        MaterialDynamicColors.background));
+                        assertTrue(
+                                pairSatisfiesContrast(
+                                        scheme,
+                                        MaterialDynamicColors.onSurfaceVariant,
+                                        MaterialDynamicColors.surfaceVariant));
+                        assertTrue(
+                                pairSatisfiesContrast(
+                                        scheme,
+                                        MaterialDynamicColors.onSurfaceInverse,
+                                        MaterialDynamicColors.surfaceInverse));
+                    }
+                }
+            }
+        }
+    }
+
+    private boolean pairSatisfiesContrast(DynamicScheme scheme, DynamicColor fg, DynamicColor bg) {
+        double fgTone = fg.getHct(scheme).getTone();
+        double bgTone = bg.getHct(scheme).getTone();
+        // TODO(b/270915664) - Fix inconsistencies.
+        // TODO(b/270915664) - Minimum requirement should be 4.5 when not reducing contrast.
+        double minimumRequirement = 3.0;
+        return Contrast.ratioOfTones(fgTone, bgTone) >= minimumRequirement;
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/multishade/data/repository/MultiShadeRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/multishade/data/repository/MultiShadeRepositoryTest.kt
new file mode 100644
index 0000000..ceacaf9
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/multishade/data/repository/MultiShadeRepositoryTest.kt
@@ -0,0 +1,191 @@
+/*
+ * 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.multishade.data.repository
+
+import android.content.Context
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.multishade.data.model.MultiShadeInteractionModel
+import com.android.systemui.multishade.data.remoteproxy.MultiShadeInputProxy
+import com.android.systemui.multishade.shared.model.ProxiedInputModel
+import com.android.systemui.multishade.shared.model.ShadeConfig
+import com.android.systemui.multishade.shared.model.ShadeId
+import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class MultiShadeRepositoryTest : SysuiTestCase() {
+
+    private lateinit var inputProxy: MultiShadeInputProxy
+
+    @Before
+    fun setUp() {
+        inputProxy = MultiShadeInputProxy()
+    }
+
+    @Test
+    fun proxiedInput() = runTest {
+        val underTest = create()
+        val latest: ProxiedInputModel? by collectLastValue(underTest.proxiedInput)
+
+        assertWithMessage("proxiedInput should start with null").that(latest).isNull()
+
+        inputProxy.onProxiedInput(ProxiedInputModel.OnTap)
+        assertThat(latest).isEqualTo(ProxiedInputModel.OnTap)
+
+        inputProxy.onProxiedInput(ProxiedInputModel.OnDrag(0f, 100f))
+        assertThat(latest).isEqualTo(ProxiedInputModel.OnDrag(0f, 100f))
+
+        inputProxy.onProxiedInput(ProxiedInputModel.OnDrag(0f, 120f))
+        assertThat(latest).isEqualTo(ProxiedInputModel.OnDrag(0f, 120f))
+
+        inputProxy.onProxiedInput(ProxiedInputModel.OnDragEnd)
+        assertThat(latest).isEqualTo(ProxiedInputModel.OnDragEnd)
+    }
+
+    @Test
+    fun shadeConfig_dualShadeEnabled() = runTest {
+        overrideResource(R.bool.dual_shade_enabled, true)
+        val underTest = create()
+        val shadeConfig: ShadeConfig? by collectLastValue(underTest.shadeConfig)
+
+        assertThat(shadeConfig).isInstanceOf(ShadeConfig.DualShadeConfig::class.java)
+    }
+
+    @Test
+    fun shadeConfig_dualShadeNotEnabled() = runTest {
+        overrideResource(R.bool.dual_shade_enabled, false)
+        val underTest = create()
+        val shadeConfig: ShadeConfig? by collectLastValue(underTest.shadeConfig)
+
+        assertThat(shadeConfig).isInstanceOf(ShadeConfig.SingleShadeConfig::class.java)
+    }
+
+    @Test
+    fun forceCollapseAll() = runTest {
+        val underTest = create()
+        val forceCollapseAll: Boolean? by collectLastValue(underTest.forceCollapseAll)
+
+        assertWithMessage("forceCollapseAll should start as false!")
+            .that(forceCollapseAll)
+            .isFalse()
+
+        underTest.setForceCollapseAll(true)
+        assertThat(forceCollapseAll).isTrue()
+
+        underTest.setForceCollapseAll(false)
+        assertThat(forceCollapseAll).isFalse()
+    }
+
+    @Test
+    fun shadeInteraction() = runTest {
+        val underTest = create()
+        val shadeInteraction: MultiShadeInteractionModel? by
+            collectLastValue(underTest.shadeInteraction)
+
+        assertWithMessage("shadeInteraction should start as null!").that(shadeInteraction).isNull()
+
+        underTest.setShadeInteraction(
+            MultiShadeInteractionModel(shadeId = ShadeId.LEFT, isProxied = false)
+        )
+        assertThat(shadeInteraction)
+            .isEqualTo(MultiShadeInteractionModel(shadeId = ShadeId.LEFT, isProxied = false))
+
+        underTest.setShadeInteraction(
+            MultiShadeInteractionModel(shadeId = ShadeId.RIGHT, isProxied = true)
+        )
+        assertThat(shadeInteraction)
+            .isEqualTo(MultiShadeInteractionModel(shadeId = ShadeId.RIGHT, isProxied = true))
+
+        underTest.setShadeInteraction(null)
+        assertThat(shadeInteraction).isNull()
+    }
+
+    @Test
+    fun expansion() = runTest {
+        val underTest = create()
+        val leftExpansion: Float? by
+            collectLastValue(underTest.getShade(ShadeId.LEFT).map { it.expansion })
+        val rightExpansion: Float? by
+            collectLastValue(underTest.getShade(ShadeId.RIGHT).map { it.expansion })
+        val singleExpansion: Float? by
+            collectLastValue(underTest.getShade(ShadeId.SINGLE).map { it.expansion })
+
+        assertWithMessage("expansion should start as 0!").that(leftExpansion).isZero()
+        assertWithMessage("expansion should start as 0!").that(rightExpansion).isZero()
+        assertWithMessage("expansion should start as 0!").that(singleExpansion).isZero()
+
+        underTest.setExpansion(
+            shadeId = ShadeId.LEFT,
+            0.4f,
+        )
+        assertThat(leftExpansion).isEqualTo(0.4f)
+        assertThat(rightExpansion).isEqualTo(0f)
+        assertThat(singleExpansion).isEqualTo(0f)
+
+        underTest.setExpansion(
+            shadeId = ShadeId.RIGHT,
+            0.73f,
+        )
+        assertThat(leftExpansion).isEqualTo(0.4f)
+        assertThat(rightExpansion).isEqualTo(0.73f)
+        assertThat(singleExpansion).isEqualTo(0f)
+
+        underTest.setExpansion(
+            shadeId = ShadeId.LEFT,
+            0.1f,
+        )
+        underTest.setExpansion(
+            shadeId = ShadeId.SINGLE,
+            0.88f,
+        )
+        assertThat(leftExpansion).isEqualTo(0.1f)
+        assertThat(rightExpansion).isEqualTo(0.73f)
+        assertThat(singleExpansion).isEqualTo(0.88f)
+    }
+
+    private fun create(): MultiShadeRepository {
+        return create(
+            context = context,
+            inputProxy = inputProxy,
+        )
+    }
+
+    companion object {
+        fun create(
+            context: Context,
+            inputProxy: MultiShadeInputProxy,
+        ): MultiShadeRepository {
+            return MultiShadeRepository(
+                applicationContext = context,
+                inputProxy = inputProxy,
+            )
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/multishade/domain/interactor/MultiShadeInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/multishade/domain/interactor/MultiShadeInteractorTest.kt
new file mode 100644
index 0000000..415e68f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/multishade/domain/interactor/MultiShadeInteractorTest.kt
@@ -0,0 +1,301 @@
+/*
+ * 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.multishade.domain.interactor
+
+import android.content.Context
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.multishade.data.remoteproxy.MultiShadeInputProxy
+import com.android.systemui.multishade.data.repository.MultiShadeRepositoryTest
+import com.android.systemui.multishade.shared.model.ProxiedInputModel
+import com.android.systemui.multishade.shared.model.ShadeId
+import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class MultiShadeInteractorTest : SysuiTestCase() {
+
+    private lateinit var testScope: TestScope
+    private lateinit var inputProxy: MultiShadeInputProxy
+
+    @Before
+    fun setUp() {
+        testScope = TestScope()
+        inputProxy = MultiShadeInputProxy()
+    }
+
+    @Test
+    fun maxShadeExpansion() =
+        testScope.runTest {
+            val underTest = create()
+            val maxShadeExpansion: Float? by collectLastValue(underTest.maxShadeExpansion)
+            assertWithMessage("maxShadeExpansion must start with 0.0!")
+                .that(maxShadeExpansion)
+                .isEqualTo(0f)
+
+            underTest.setExpansion(shadeId = ShadeId.LEFT, expansion = 0.441f)
+            assertThat(maxShadeExpansion).isEqualTo(0.441f)
+
+            underTest.setExpansion(shadeId = ShadeId.RIGHT, expansion = 0.442f)
+            assertThat(maxShadeExpansion).isEqualTo(0.442f)
+
+            underTest.setExpansion(shadeId = ShadeId.RIGHT, expansion = 0f)
+            assertThat(maxShadeExpansion).isEqualTo(0.441f)
+
+            underTest.setExpansion(shadeId = ShadeId.LEFT, expansion = 0f)
+            assertThat(maxShadeExpansion).isEqualTo(0f)
+        }
+
+    @Test
+    fun isVisible_dualShadeConfig() =
+        testScope.runTest {
+            overrideResource(R.bool.dual_shade_enabled, true)
+            val underTest = create()
+            val isLeftShadeVisible: Boolean? by collectLastValue(underTest.isVisible(ShadeId.LEFT))
+            val isRightShadeVisible: Boolean? by
+                collectLastValue(underTest.isVisible(ShadeId.RIGHT))
+            val isSingleShadeVisible: Boolean? by
+                collectLastValue(underTest.isVisible(ShadeId.SINGLE))
+
+            assertThat(isLeftShadeVisible).isTrue()
+            assertThat(isRightShadeVisible).isTrue()
+            assertThat(isSingleShadeVisible).isFalse()
+        }
+
+    @Test
+    fun isVisible_singleShadeConfig() =
+        testScope.runTest {
+            overrideResource(R.bool.dual_shade_enabled, false)
+            val underTest = create()
+            val isLeftShadeVisible: Boolean? by collectLastValue(underTest.isVisible(ShadeId.LEFT))
+            val isRightShadeVisible: Boolean? by
+                collectLastValue(underTest.isVisible(ShadeId.RIGHT))
+            val isSingleShadeVisible: Boolean? by
+                collectLastValue(underTest.isVisible(ShadeId.SINGLE))
+
+            assertThat(isLeftShadeVisible).isFalse()
+            assertThat(isRightShadeVisible).isFalse()
+            assertThat(isSingleShadeVisible).isTrue()
+        }
+
+    @Test
+    fun isNonProxiedInputAllowed() =
+        testScope.runTest {
+            val underTest = create()
+            val isLeftShadeNonProxiedInputAllowed: Boolean? by
+                collectLastValue(underTest.isNonProxiedInputAllowed(ShadeId.LEFT))
+            assertWithMessage("isNonProxiedInputAllowed should start as true!")
+                .that(isLeftShadeNonProxiedInputAllowed)
+                .isTrue()
+
+            // Need to collect proxied input so the flows become hot as the gesture cancelation code
+            // logic sits in side the proxiedInput flow for each shade.
+            collectLastValue(underTest.proxiedInput(ShadeId.LEFT))
+            collectLastValue(underTest.proxiedInput(ShadeId.RIGHT))
+
+            // Starting a proxied interaction on the LEFT shade disallows non-proxied interaction on
+            // the
+            // same shade.
+            inputProxy.onProxiedInput(
+                ProxiedInputModel.OnDrag(xFraction = 0f, yDragAmountPx = 123f)
+            )
+            assertThat(isLeftShadeNonProxiedInputAllowed).isFalse()
+
+            // Registering the end of the proxied interaction re-allows it.
+            inputProxy.onProxiedInput(ProxiedInputModel.OnDragEnd)
+            assertThat(isLeftShadeNonProxiedInputAllowed).isTrue()
+
+            // Starting a proxied interaction on the RIGHT shade force-collapses the LEFT shade,
+            // disallowing non-proxied input on the LEFT shade.
+            inputProxy.onProxiedInput(
+                ProxiedInputModel.OnDrag(xFraction = 1f, yDragAmountPx = 123f)
+            )
+            assertThat(isLeftShadeNonProxiedInputAllowed).isFalse()
+
+            // Registering the end of the interaction on the RIGHT shade re-allows it.
+            inputProxy.onProxiedInput(ProxiedInputModel.OnDragEnd)
+            assertThat(isLeftShadeNonProxiedInputAllowed).isTrue()
+        }
+
+    @Test
+    fun isForceCollapsed_whenOtherShadeInteractionUnderway() =
+        testScope.runTest {
+            val underTest = create()
+            val isLeftShadeForceCollapsed: Boolean? by
+                collectLastValue(underTest.isForceCollapsed(ShadeId.LEFT))
+            val isRightShadeForceCollapsed: Boolean? by
+                collectLastValue(underTest.isForceCollapsed(ShadeId.RIGHT))
+            val isSingleShadeForceCollapsed: Boolean? by
+                collectLastValue(underTest.isForceCollapsed(ShadeId.SINGLE))
+
+            assertWithMessage("isForceCollapsed should start as false!")
+                .that(isLeftShadeForceCollapsed)
+                .isFalse()
+            assertWithMessage("isForceCollapsed should start as false!")
+                .that(isRightShadeForceCollapsed)
+                .isFalse()
+            assertWithMessage("isForceCollapsed should start as false!")
+                .that(isSingleShadeForceCollapsed)
+                .isFalse()
+
+            // Registering the start of an interaction on the RIGHT shade force-collapses the LEFT
+            // shade.
+            underTest.onUserInteractionStarted(ShadeId.RIGHT)
+            assertThat(isLeftShadeForceCollapsed).isTrue()
+            assertThat(isRightShadeForceCollapsed).isFalse()
+            assertThat(isSingleShadeForceCollapsed).isFalse()
+
+            // Registering the end of the interaction on the RIGHT shade re-allows it.
+            underTest.onUserInteractionEnded(ShadeId.RIGHT)
+            assertThat(isLeftShadeForceCollapsed).isFalse()
+            assertThat(isRightShadeForceCollapsed).isFalse()
+            assertThat(isSingleShadeForceCollapsed).isFalse()
+
+            // Registering the start of an interaction on the LEFT shade force-collapses the RIGHT
+            // shade.
+            underTest.onUserInteractionStarted(ShadeId.LEFT)
+            assertThat(isLeftShadeForceCollapsed).isFalse()
+            assertThat(isRightShadeForceCollapsed).isTrue()
+            assertThat(isSingleShadeForceCollapsed).isFalse()
+
+            // Registering the end of the interaction on the LEFT shade re-allows it.
+            underTest.onUserInteractionEnded(ShadeId.LEFT)
+            assertThat(isLeftShadeForceCollapsed).isFalse()
+            assertThat(isRightShadeForceCollapsed).isFalse()
+            assertThat(isSingleShadeForceCollapsed).isFalse()
+        }
+
+    @Test
+    fun collapseAll() =
+        testScope.runTest {
+            val underTest = create()
+            val isLeftShadeForceCollapsed: Boolean? by
+                collectLastValue(underTest.isForceCollapsed(ShadeId.LEFT))
+            val isRightShadeForceCollapsed: Boolean? by
+                collectLastValue(underTest.isForceCollapsed(ShadeId.RIGHT))
+            val isSingleShadeForceCollapsed: Boolean? by
+                collectLastValue(underTest.isForceCollapsed(ShadeId.SINGLE))
+
+            assertWithMessage("isForceCollapsed should start as false!")
+                .that(isLeftShadeForceCollapsed)
+                .isFalse()
+            assertWithMessage("isForceCollapsed should start as false!")
+                .that(isRightShadeForceCollapsed)
+                .isFalse()
+            assertWithMessage("isForceCollapsed should start as false!")
+                .that(isSingleShadeForceCollapsed)
+                .isFalse()
+
+            underTest.collapseAll()
+            assertThat(isLeftShadeForceCollapsed).isTrue()
+            assertThat(isRightShadeForceCollapsed).isTrue()
+            assertThat(isSingleShadeForceCollapsed).isTrue()
+
+            // Receiving proxied input on that's not a tap gesture, on the left-hand side resets the
+            // "collapse all". Note that now the RIGHT shade is force-collapsed because we're
+            // interacting with the LEFT shade.
+            inputProxy.onProxiedInput(ProxiedInputModel.OnDrag(0f, 0f))
+            assertThat(isLeftShadeForceCollapsed).isFalse()
+            assertThat(isRightShadeForceCollapsed).isTrue()
+            assertThat(isSingleShadeForceCollapsed).isFalse()
+        }
+
+    @Test
+    fun onTapOutside_collapsesAll() =
+        testScope.runTest {
+            val underTest = create()
+            val isLeftShadeForceCollapsed: Boolean? by
+                collectLastValue(underTest.isForceCollapsed(ShadeId.LEFT))
+            val isRightShadeForceCollapsed: Boolean? by
+                collectLastValue(underTest.isForceCollapsed(ShadeId.RIGHT))
+            val isSingleShadeForceCollapsed: Boolean? by
+                collectLastValue(underTest.isForceCollapsed(ShadeId.SINGLE))
+
+            assertWithMessage("isForceCollapsed should start as false!")
+                .that(isLeftShadeForceCollapsed)
+                .isFalse()
+            assertWithMessage("isForceCollapsed should start as false!")
+                .that(isRightShadeForceCollapsed)
+                .isFalse()
+            assertWithMessage("isForceCollapsed should start as false!")
+                .that(isSingleShadeForceCollapsed)
+                .isFalse()
+
+            inputProxy.onProxiedInput(ProxiedInputModel.OnTap)
+            assertThat(isLeftShadeForceCollapsed).isTrue()
+            assertThat(isRightShadeForceCollapsed).isTrue()
+            assertThat(isSingleShadeForceCollapsed).isTrue()
+        }
+
+    @Test
+    fun proxiedInput_ignoredWhileNonProxiedGestureUnderway() =
+        testScope.runTest {
+            val underTest = create()
+            val proxiedInput: ProxiedInputModel? by
+                collectLastValue(underTest.proxiedInput(ShadeId.RIGHT))
+            underTest.onUserInteractionStarted(shadeId = ShadeId.RIGHT)
+
+            inputProxy.onProxiedInput(ProxiedInputModel.OnDrag(0.9f, 100f))
+            assertThat(proxiedInput).isNull()
+
+            inputProxy.onProxiedInput(ProxiedInputModel.OnDrag(0.8f, 110f))
+            assertThat(proxiedInput).isNull()
+
+            underTest.onUserInteractionEnded(shadeId = ShadeId.RIGHT)
+
+            inputProxy.onProxiedInput(ProxiedInputModel.OnDrag(0.9f, 100f))
+            assertThat(proxiedInput).isNotNull()
+        }
+
+    private fun create(): MultiShadeInteractor {
+        return create(
+            testScope = testScope,
+            context = context,
+            inputProxy = inputProxy,
+        )
+    }
+
+    companion object {
+        fun create(
+            testScope: TestScope,
+            context: Context,
+            inputProxy: MultiShadeInputProxy,
+        ): MultiShadeInteractor {
+            return MultiShadeInteractor(
+                applicationScope = testScope.backgroundScope,
+                repository =
+                    MultiShadeRepositoryTest.create(
+                        context = context,
+                        inputProxy = inputProxy,
+                    ),
+                inputProxy = inputProxy,
+            )
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/multishade/ui/viewmodel/MultiShadeViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/multishade/ui/viewmodel/MultiShadeViewModelTest.kt
new file mode 100644
index 0000000..0484515
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/multishade/ui/viewmodel/MultiShadeViewModelTest.kt
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.multishade.ui.viewmodel
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.multishade.data.remoteproxy.MultiShadeInputProxy
+import com.android.systemui.multishade.domain.interactor.MultiShadeInteractorTest
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class MultiShadeViewModelTest : SysuiTestCase() {
+
+    private lateinit var testScope: TestScope
+    private lateinit var inputProxy: MultiShadeInputProxy
+
+    @Before
+    fun setUp() {
+        testScope = TestScope()
+        inputProxy = MultiShadeInputProxy()
+    }
+
+    @Test
+    fun scrim_whenDualShadeCollapsed() =
+        testScope.runTest {
+            val alpha = 0.5f
+            overrideResource(R.dimen.dual_shade_scrim_alpha, alpha)
+            overrideResource(R.bool.dual_shade_enabled, true)
+
+            val underTest = create()
+            val scrimAlpha: Float? by collectLastValue(underTest.scrimAlpha)
+            val isScrimEnabled: Boolean? by collectLastValue(underTest.isScrimEnabled)
+
+            assertThat(scrimAlpha).isZero()
+            assertThat(isScrimEnabled).isFalse()
+        }
+
+    @Test
+    fun scrim_whenDualShadeExpanded() =
+        testScope.runTest {
+            val alpha = 0.5f
+            overrideResource(R.dimen.dual_shade_scrim_alpha, alpha)
+            overrideResource(R.bool.dual_shade_enabled, true)
+            val underTest = create()
+            val scrimAlpha: Float? by collectLastValue(underTest.scrimAlpha)
+            val isScrimEnabled: Boolean? by collectLastValue(underTest.isScrimEnabled)
+            assertThat(scrimAlpha).isZero()
+            assertThat(isScrimEnabled).isFalse()
+
+            underTest.leftShade.onExpansionChanged(0.5f)
+            assertThat(scrimAlpha).isEqualTo(alpha * 0.5f)
+            assertThat(isScrimEnabled).isTrue()
+
+            underTest.rightShade.onExpansionChanged(1f)
+            assertThat(scrimAlpha).isEqualTo(alpha * 1f)
+            assertThat(isScrimEnabled).isTrue()
+        }
+
+    @Test
+    fun scrim_whenSingleShadeCollapsed() =
+        testScope.runTest {
+            val alpha = 0.5f
+            overrideResource(R.dimen.dual_shade_scrim_alpha, alpha)
+            overrideResource(R.bool.dual_shade_enabled, false)
+
+            val underTest = create()
+            val scrimAlpha: Float? by collectLastValue(underTest.scrimAlpha)
+            val isScrimEnabled: Boolean? by collectLastValue(underTest.isScrimEnabled)
+
+            assertThat(scrimAlpha).isZero()
+            assertThat(isScrimEnabled).isFalse()
+        }
+
+    @Test
+    fun scrim_whenSingleShadeExpanded() =
+        testScope.runTest {
+            val alpha = 0.5f
+            overrideResource(R.dimen.dual_shade_scrim_alpha, alpha)
+            overrideResource(R.bool.dual_shade_enabled, false)
+            val underTest = create()
+            val scrimAlpha: Float? by collectLastValue(underTest.scrimAlpha)
+            val isScrimEnabled: Boolean? by collectLastValue(underTest.isScrimEnabled)
+
+            underTest.singleShade.onExpansionChanged(0.95f)
+
+            assertThat(scrimAlpha).isZero()
+            assertThat(isScrimEnabled).isFalse()
+        }
+
+    private fun create(): MultiShadeViewModel {
+        return MultiShadeViewModel(
+            viewModelScope = testScope.backgroundScope,
+            interactor =
+                MultiShadeInteractorTest.create(
+                    testScope = testScope,
+                    context = context,
+                    inputProxy = inputProxy,
+                ),
+        )
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/multishade/ui/viewmodel/ShadeViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/multishade/ui/viewmodel/ShadeViewModelTest.kt
new file mode 100644
index 0000000..e32aac5
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/multishade/ui/viewmodel/ShadeViewModelTest.kt
@@ -0,0 +1,226 @@
+/*
+ * 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.multishade.ui.viewmodel
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.multishade.data.remoteproxy.MultiShadeInputProxy
+import com.android.systemui.multishade.domain.interactor.MultiShadeInteractor
+import com.android.systemui.multishade.domain.interactor.MultiShadeInteractorTest
+import com.android.systemui.multishade.shared.model.ProxiedInputModel
+import com.android.systemui.multishade.shared.model.ShadeId
+import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class ShadeViewModelTest : SysuiTestCase() {
+
+    private lateinit var testScope: TestScope
+    private lateinit var inputProxy: MultiShadeInputProxy
+    private var interactor: MultiShadeInteractor? = null
+
+    @Before
+    fun setUp() {
+        testScope = TestScope()
+        inputProxy = MultiShadeInputProxy()
+    }
+
+    @Test
+    fun isVisible_dualShadeConfig() =
+        testScope.runTest {
+            overrideResource(R.bool.dual_shade_enabled, true)
+            val isLeftShadeVisible: Boolean? by collectLastValue(create(ShadeId.LEFT).isVisible)
+            val isRightShadeVisible: Boolean? by collectLastValue(create(ShadeId.RIGHT).isVisible)
+            val isSingleShadeVisible: Boolean? by collectLastValue(create(ShadeId.SINGLE).isVisible)
+
+            assertThat(isLeftShadeVisible).isTrue()
+            assertThat(isRightShadeVisible).isTrue()
+            assertThat(isSingleShadeVisible).isFalse()
+        }
+
+    @Test
+    fun isVisible_singleShadeConfig() =
+        testScope.runTest {
+            overrideResource(R.bool.dual_shade_enabled, false)
+            val isLeftShadeVisible: Boolean? by collectLastValue(create(ShadeId.LEFT).isVisible)
+            val isRightShadeVisible: Boolean? by collectLastValue(create(ShadeId.RIGHT).isVisible)
+            val isSingleShadeVisible: Boolean? by collectLastValue(create(ShadeId.SINGLE).isVisible)
+
+            assertThat(isLeftShadeVisible).isFalse()
+            assertThat(isRightShadeVisible).isFalse()
+            assertThat(isSingleShadeVisible).isTrue()
+        }
+
+    @Test
+    fun isSwipingEnabled() =
+        testScope.runTest {
+            val underTest = create(ShadeId.LEFT)
+            val isSwipingEnabled: Boolean? by collectLastValue(underTest.isSwipingEnabled)
+            assertWithMessage("isSwipingEnabled should start as true!")
+                .that(isSwipingEnabled)
+                .isTrue()
+
+            // Need to collect proxied input so the flows become hot as the gesture cancelation code
+            // logic sits in side the proxiedInput flow for each shade.
+            collectLastValue(underTest.proxiedInput)
+            collectLastValue(create(ShadeId.RIGHT).proxiedInput)
+
+            // Starting a proxied interaction on the LEFT shade disallows non-proxied interaction on
+            // the
+            // same shade.
+            inputProxy.onProxiedInput(
+                ProxiedInputModel.OnDrag(xFraction = 0f, yDragAmountPx = 123f)
+            )
+            assertThat(isSwipingEnabled).isFalse()
+
+            // Registering the end of the proxied interaction re-allows it.
+            inputProxy.onProxiedInput(ProxiedInputModel.OnDragEnd)
+            assertThat(isSwipingEnabled).isTrue()
+
+            // Starting a proxied interaction on the RIGHT shade force-collapses the LEFT shade,
+            // disallowing non-proxied input on the LEFT shade.
+            inputProxy.onProxiedInput(
+                ProxiedInputModel.OnDrag(xFraction = 1f, yDragAmountPx = 123f)
+            )
+            assertThat(isSwipingEnabled).isFalse()
+
+            // Registering the end of the interaction on the RIGHT shade re-allows it.
+            inputProxy.onProxiedInput(ProxiedInputModel.OnDragEnd)
+            assertThat(isSwipingEnabled).isTrue()
+        }
+
+    @Test
+    fun isForceCollapsed_whenOtherShadeInteractionUnderway() =
+        testScope.runTest {
+            val leftShade = create(ShadeId.LEFT)
+            val rightShade = create(ShadeId.RIGHT)
+            val isLeftShadeForceCollapsed: Boolean? by collectLastValue(leftShade.isForceCollapsed)
+            val isRightShadeForceCollapsed: Boolean? by
+                collectLastValue(rightShade.isForceCollapsed)
+            val isSingleShadeForceCollapsed: Boolean? by
+                collectLastValue(create(ShadeId.SINGLE).isForceCollapsed)
+
+            assertWithMessage("isForceCollapsed should start as false!")
+                .that(isLeftShadeForceCollapsed)
+                .isFalse()
+            assertWithMessage("isForceCollapsed should start as false!")
+                .that(isRightShadeForceCollapsed)
+                .isFalse()
+            assertWithMessage("isForceCollapsed should start as false!")
+                .that(isSingleShadeForceCollapsed)
+                .isFalse()
+
+            // Registering the start of an interaction on the RIGHT shade force-collapses the LEFT
+            // shade.
+            rightShade.onDragStarted()
+            assertThat(isLeftShadeForceCollapsed).isTrue()
+            assertThat(isRightShadeForceCollapsed).isFalse()
+            assertThat(isSingleShadeForceCollapsed).isFalse()
+
+            // Registering the end of the interaction on the RIGHT shade re-allows it.
+            rightShade.onDragEnded()
+            assertThat(isLeftShadeForceCollapsed).isFalse()
+            assertThat(isRightShadeForceCollapsed).isFalse()
+            assertThat(isSingleShadeForceCollapsed).isFalse()
+
+            // Registering the start of an interaction on the LEFT shade force-collapses the RIGHT
+            // shade.
+            leftShade.onDragStarted()
+            assertThat(isLeftShadeForceCollapsed).isFalse()
+            assertThat(isRightShadeForceCollapsed).isTrue()
+            assertThat(isSingleShadeForceCollapsed).isFalse()
+
+            // Registering the end of the interaction on the LEFT shade re-allows it.
+            leftShade.onDragEnded()
+            assertThat(isLeftShadeForceCollapsed).isFalse()
+            assertThat(isRightShadeForceCollapsed).isFalse()
+            assertThat(isSingleShadeForceCollapsed).isFalse()
+        }
+
+    @Test
+    fun onTapOutside_collapsesAll() =
+        testScope.runTest {
+            val isLeftShadeForceCollapsed: Boolean? by
+                collectLastValue(create(ShadeId.LEFT).isForceCollapsed)
+            val isRightShadeForceCollapsed: Boolean? by
+                collectLastValue(create(ShadeId.RIGHT).isForceCollapsed)
+            val isSingleShadeForceCollapsed: Boolean? by
+                collectLastValue(create(ShadeId.SINGLE).isForceCollapsed)
+
+            assertWithMessage("isForceCollapsed should start as false!")
+                .that(isLeftShadeForceCollapsed)
+                .isFalse()
+            assertWithMessage("isForceCollapsed should start as false!")
+                .that(isRightShadeForceCollapsed)
+                .isFalse()
+            assertWithMessage("isForceCollapsed should start as false!")
+                .that(isSingleShadeForceCollapsed)
+                .isFalse()
+
+            inputProxy.onProxiedInput(ProxiedInputModel.OnTap)
+            assertThat(isLeftShadeForceCollapsed).isTrue()
+            assertThat(isRightShadeForceCollapsed).isTrue()
+            assertThat(isSingleShadeForceCollapsed).isTrue()
+        }
+
+    @Test
+    fun proxiedInput_ignoredWhileNonProxiedGestureUnderway() =
+        testScope.runTest {
+            val underTest = create(ShadeId.RIGHT)
+            val proxiedInput: ProxiedInputModel? by collectLastValue(underTest.proxiedInput)
+            underTest.onDragStarted()
+
+            inputProxy.onProxiedInput(ProxiedInputModel.OnDrag(0.9f, 100f))
+            assertThat(proxiedInput).isNull()
+
+            inputProxy.onProxiedInput(ProxiedInputModel.OnDrag(0.8f, 110f))
+            assertThat(proxiedInput).isNull()
+
+            underTest.onDragEnded()
+
+            inputProxy.onProxiedInput(ProxiedInputModel.OnDrag(0.9f, 100f))
+            assertThat(proxiedInput).isNotNull()
+        }
+
+    private fun create(
+        shadeId: ShadeId,
+    ): ShadeViewModel {
+        return ShadeViewModel(
+            viewModelScope = testScope.backgroundScope,
+            shadeId = shadeId,
+            interactor = interactor
+                    ?: MultiShadeInteractorTest.create(
+                            testScope = testScope,
+                            context = context,
+                            inputProxy = inputProxy,
+                        )
+                        .also { interactor = it },
+        )
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java
index ce6a98c..9b8605d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java
@@ -35,6 +35,7 @@
 import static org.mockito.Mockito.when;
 
 import android.content.ComponentName;
+import android.view.IWindowManager;
 import android.view.accessibility.AccessibilityManager;
 
 import androidx.test.filters.SmallTest;
@@ -46,7 +47,9 @@
 import com.android.systemui.accessibility.SystemActions;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
 import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.settings.DisplayTracker;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.phone.CentralSurfaces;
@@ -101,6 +104,14 @@
     NavBarHelper.NavbarTaskbarStateUpdater mNavbarTaskbarStateUpdater;
     @Mock
     CommandQueue mCommandQueue;
+    @Mock
+    IWindowManager mWm;
+    @Mock
+    DisplayTracker mDisplayTracker;
+    @Mock
+    EdgeBackGestureHandler mEdgeBackGestureHandler;
+    @Mock
+    EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory;
     private AccessibilityManager.AccessibilityServicesStateChangeListener
             mAccessibilityServicesStateChangeListener;
 
@@ -114,6 +125,8 @@
         when(mAssistManagerLazy.get()).thenReturn(mAssistManager);
         when(mAssistManager.getAssistInfoForUser(anyInt())).thenReturn(mAssistantComponent);
         when(mUserTracker.getUserId()).thenReturn(1);
+        when(mDisplayTracker.getDefaultDisplayId()).thenReturn(0);
+        when(mEdgeBackGestureHandlerFactory.create(any())).thenReturn(mEdgeBackGestureHandler);
 
         doAnswer((invocation) -> mAccessibilityServicesStateChangeListener =
                 invocation.getArgument(0)).when(
@@ -122,36 +135,70 @@
                 mAccessibilityButtonModeObserver, mAccessibilityButtonTargetObserver,
                 mSystemActions, mOverviewProxyService, mAssistManagerLazy,
                 () -> Optional.of(mock(CentralSurfaces.class)), mock(KeyguardStateController.class),
-                mNavigationModeController, mUserTracker, mDumpManager, mCommandQueue);
+                mNavigationModeController, mEdgeBackGestureHandlerFactory, mWm, mUserTracker,
+                mDisplayTracker, mDumpManager, mCommandQueue);
 
     }
 
     @Test
     public void registerListenersInCtor() {
-        verify(mAccessibilityButtonModeObserver, times(1)).addListener(mNavBarHelper);
         verify(mNavigationModeController, times(1)).addListener(mNavBarHelper);
         verify(mOverviewProxyService, times(1)).addCallback(mNavBarHelper);
+        verify(mCommandQueue, times(1)).addCallback(any());
     }
 
     @Test
-    public void registerAssistantContentObserver() {
-        mNavBarHelper.init();
+    public void testSetupBarsRegistersListeners() throws Exception {
+        mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
+        verify(mAccessibilityButtonModeObserver, times(1)).addListener(mNavBarHelper);
+        verify(mAccessibilityButtonTargetObserver, times(1)).addListener(mNavBarHelper);
+        verify(mAccessibilityManager, times(1)).addAccessibilityServicesStateChangeListener(
+                mNavBarHelper);
         verify(mAssistManager, times(1)).getAssistInfoForUser(anyInt());
+        verify(mWm, times(1)).watchRotation(any(), anyInt());
+        verify(mWm, times(1)).registerWallpaperVisibilityListener(any(), anyInt());
+        verify(mEdgeBackGestureHandler, times(1)).onNavBarAttached();
+    }
+
+    @Test
+    public void testCleanupBarsUnregistersListeners() throws Exception {
+        mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
+        mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
+        verify(mAccessibilityButtonModeObserver, times(1)).removeListener(mNavBarHelper);
+        verify(mAccessibilityButtonTargetObserver, times(1)).removeListener(mNavBarHelper);
+        verify(mAccessibilityManager, times(1)).removeAccessibilityServicesStateChangeListener(
+                mNavBarHelper);
+        verify(mWm, times(1)).removeRotationWatcher(any());
+        verify(mWm, times(1)).unregisterWallpaperVisibilityListener(any(), anyInt());
+        verify(mEdgeBackGestureHandler, times(1)).onNavBarDetached();
+    }
+
+    @Test
+    public void replacingBarsHint() {
+        mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
+        mNavBarHelper.setTogglingNavbarTaskbar(true);
+        mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
+        mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
+        mNavBarHelper.setTogglingNavbarTaskbar(false);
+        // Use any state in cleanup to verify it was not called
+        verify(mAccessibilityButtonModeObserver, times(0)).removeListener(mNavBarHelper);
     }
 
     @Test
     public void callbacksFiredWhenRegistering() {
-        mNavBarHelper.init();
         mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
         verify(mNavbarTaskbarStateUpdater, times(1))
                 .updateAccessibilityServicesState();
         verify(mNavbarTaskbarStateUpdater, times(1))
                 .updateAssistantAvailable(anyBoolean(), anyBoolean());
+        verify(mNavbarTaskbarStateUpdater, times(1))
+                .updateRotationWatcherState(anyInt());
+        verify(mNavbarTaskbarStateUpdater, times(1))
+                .updateWallpaperVisibility(anyBoolean(), anyInt());
     }
 
     @Test
     public void assistantCallbacksFiredAfterConnecting() {
-        mNavBarHelper.init();
         // 1st set of callbacks get called when registering
         mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
 
@@ -172,7 +219,6 @@
 
     @Test
     public void a11yCallbacksFiredAfterModeChange() {
-        mNavBarHelper.init();
         // 1st set of callbacks get called when registering
         mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
 
@@ -185,7 +231,6 @@
 
     @Test
     public void assistantCallbacksFiredAfterNavModeChange() {
-        mNavBarHelper.init();
         // 1st set of callbacks get called when registering
         mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
 
@@ -198,7 +243,6 @@
 
     @Test
     public void removeListenerNoCallbacksFired() {
-        mNavBarHelper.init();
         // 1st set of callbacks get called when registering
         mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
 
@@ -220,7 +264,7 @@
         when(mAccessibilityManager.getAccessibilityShortcutTargets(
                 AccessibilityManager.ACCESSIBILITY_BUTTON)).thenReturn(createFakeShortcutTargets());
 
-        mNavBarHelper.init();
+        mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
 
         assertThat(mNavBarHelper.getA11yButtonState()).isEqualTo(
                 ACCESSIBILITY_BUTTON_CLICKABLE_STATE);
@@ -230,13 +274,15 @@
     public void initAccessibilityStateWithFloatingMenuModeAndTargets_disableClickableState() {
         when(mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode()).thenReturn(
                 ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU);
-        mNavBarHelper.init();
+
+        mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
 
         assertThat(mNavBarHelper.getA11yButtonState()).isEqualTo(/* disable_clickable_state */ 0);
     }
 
     @Test
     public void onA11yServicesStateChangedWithMultipleServices_a11yButtonClickableState() {
+        mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
         when(mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode()).thenReturn(
                 ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR);
 
@@ -250,14 +296,7 @@
     }
 
     @Test
-    public void registerCommandQueueCallbacks() {
-        mNavBarHelper.init();
-        verify(mCommandQueue, times(1)).addCallback(any());
-    }
-
-    @Test
     public void saveMostRecentSysuiState() {
-        mNavBarHelper.init();
         mNavBarHelper.setWindowState(DISPLAY_ID, WINDOW, STATE_ID);
         NavBarHelper.CurrentSysuiState state1 = mNavBarHelper.getCurrentSysuiState();
 
@@ -274,7 +313,6 @@
 
     @Test
     public void ignoreNonNavbarSysuiState() {
-        mNavBarHelper.init();
         mNavBarHelper.setWindowState(DISPLAY_ID, WINDOW, STATE_ID);
         NavBarHelper.CurrentSysuiState state1 = mNavBarHelper.getCurrentSysuiState();
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
index 764ddc4..f062ec7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
@@ -58,6 +58,7 @@
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.Display;
 import android.view.DisplayInfo;
+import android.view.IWindowManager;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewRootImpl;
@@ -87,6 +88,7 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.recents.Recents;
+import com.android.systemui.settings.DisplayTracker;
 import com.android.systemui.settings.FakeDisplayTracker;
 import com.android.systemui.settings.UserContextProvider;
 import com.android.systemui.settings.UserTracker;
@@ -172,8 +174,6 @@
     private UiEventLogger mUiEventLogger;
     @Mock
     private ViewTreeObserver mViewTreeObserver;
-    @Mock
-    EdgeBackGestureHandler mEdgeBackGestureHandler;
     NavBarHelper mNavBarHelper;
     @Mock
     private LightBarController mLightBarController;
@@ -205,6 +205,10 @@
     private Resources mResources;
     @Mock
     private ViewRootImpl mViewRootImpl;
+    @Mock
+    private EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory;
+    @Mock
+    private EdgeBackGestureHandler mEdgeBackGestureHandler;
     private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
     private DeviceConfigProxyFake mDeviceConfigProxyFake = new DeviceConfigProxyFake();
     private TaskStackChangeListeners mTaskStackChangeListeners =
@@ -234,6 +238,7 @@
                 .thenReturn(mContext);
         when(mNavigationBarView.getResources()).thenReturn(mResources);
         when(mNavigationBarView.getViewRootImpl()).thenReturn(mViewRootImpl);
+        when(mEdgeBackGestureHandlerFactory.create(any())).thenReturn(mEdgeBackGestureHandler);
         setupSysuiDependency();
         // This class inflates views that call Dependency.get, thus these injections are still
         // necessary.
@@ -250,7 +255,9 @@
                     mSystemActions, mOverviewProxyService,
                     () -> mock(AssistManager.class), () -> Optional.of(mCentralSurfaces),
                     mKeyguardStateController, mock(NavigationModeController.class),
-                    mock(UserTracker.class), mock(DumpManager.class), mock(CommandQueue.class)));
+                    mEdgeBackGestureHandlerFactory, mock(IWindowManager.class),
+                    mock(UserTracker.class), mock(DisplayTracker.class), mock(DumpManager.class),
+                    mock(CommandQueue.class)));
             mNavigationBar = createNavBar(mContext);
             mExternalDisplayNavigationBar = createNavBar(mSysuiTestableContextExternal);
         });
@@ -492,7 +499,6 @@
                 mDeadZone,
                 mDeviceConfigProxyFake,
                 mNavigationBarTransitions,
-                mEdgeBackGestureHandler,
                 Optional.of(mock(BackAnimation.class)),
                 mUserContextProvider,
                 mWakefulnessLifecycle,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java
index 54e6509..fb08bf5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java
@@ -27,7 +27,6 @@
 import android.content.Context;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper.RunWithLooper;
-import android.view.IWindowManager;
 
 import androidx.test.filters.SmallTest;
 
@@ -60,8 +59,6 @@
     EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory;
     @Mock
     EdgeBackGestureHandler mEdgeBackGestureHandler;
-    @Mock
-    IWindowManager mIWindowManager;
 
     private NavigationBarTransitions mTransitions;
     private FakeDisplayTracker mDisplayTracker = new FakeDisplayTracker(mContext);
@@ -88,7 +85,7 @@
         when(navBar.getCurrentView()).thenReturn(navBar);
         when(navBar.findViewById(anyInt())).thenReturn(navBar);
         mTransitions = new NavigationBarTransitions(
-                navBar, mIWindowManager, mLightBarTransitionsFactory, mDisplayTracker);
+                navBar, mLightBarTransitionsFactory, mDisplayTracker);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
index 1c9336a..8d01e80d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
@@ -38,8 +38,6 @@
     private lateinit var mTaskStackChangeListeners: TaskStackChangeListeners
     private lateinit var mTaskbarDelegate: TaskbarDelegate
     @Mock
-    lateinit var mEdgeBackGestureHandlerFactory : EdgeBackGestureHandler.Factory
-    @Mock
     lateinit var mEdgeBackGestureHandler : EdgeBackGestureHandler
     @Mock
     lateinit var mLightBarControllerFactory : LightBarTransitionsController.Factory
@@ -73,13 +71,13 @@
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
-        `when`(mEdgeBackGestureHandlerFactory.create(context)).thenReturn(mEdgeBackGestureHandler)
+        `when`(mNavBarHelper.edgeBackGestureHandler).thenReturn(mEdgeBackGestureHandler)
         `when`(mLightBarControllerFactory.create(any())).thenReturn(mLightBarTransitionController)
         `when`(mNavBarHelper.currentSysuiState).thenReturn(mCurrentSysUiState)
         `when`(mSysUiState.setFlag(anyInt(), anyBoolean())).thenReturn(mSysUiState)
         mTaskStackChangeListeners = TaskStackChangeListeners.getTestInstance()
-        mTaskbarDelegate = TaskbarDelegate(context, mEdgeBackGestureHandlerFactory,
-                mLightBarControllerFactory, mStatusBarKeyguardViewManager)
+        mTaskbarDelegate = TaskbarDelegate(context, mLightBarControllerFactory,
+            mStatusBarKeyguardViewManager)
         mTaskbarDelegate.setDependencies(mCommandQueue, mOverviewProxyService, mNavBarHelper,
         mNavigationModeController, mSysUiState, mDumpManager, mAutoHideController,
                 mLightBarController, mOptionalPip, mBackAnimation, mTaskStackChangeListeners)
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 0f0b7d7..3f940d6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
@@ -16,16 +16,22 @@
 package com.android.systemui.notetask
 
 import android.app.KeyguardManager
+import android.app.admin.DevicePolicyManager
 import android.content.ComponentName
 import android.content.Context
 import android.content.Intent
+import android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK
+import android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT
+import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
 import android.content.pm.PackageManager
+import android.os.UserHandle
 import android.os.UserManager
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import androidx.test.runner.AndroidJUnit4
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.notetask.NoteTaskController.Companion.INTENT_EXTRA_USE_STYLUS_MODE
 import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
+import com.android.systemui.settings.FakeUserTracker
+import com.android.systemui.settings.UserTracker
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.argumentCaptor
 import com.android.systemui.util.mockito.capture
@@ -38,6 +44,7 @@
 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.verify
 import org.mockito.Mockito.verifyZeroInteractions
@@ -55,6 +62,8 @@
     @Mock lateinit var keyguardManager: KeyguardManager
     @Mock lateinit var userManager: UserManager
     @Mock lateinit var eventLogger: NoteTaskEventLogger
+    @Mock private lateinit var devicePolicyManager: DevicePolicyManager
+    private val userTracker: UserTracker = FakeUserTracker()
 
     private val noteTaskInfo = NoteTaskInfo(packageName = NOTES_PACKAGE_NAME, uid = NOTES_UID)
 
@@ -63,30 +72,37 @@
         MockitoAnnotations.initMocks(this)
 
         whenever(context.packageManager).thenReturn(packageManager)
-        whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(noteTaskInfo)
+        whenever(resolver.resolveInfo(any(), any())).thenReturn(noteTaskInfo)
         whenever(userManager.isUserUnlocked).thenReturn(true)
+        whenever(
+                devicePolicyManager.getKeyguardDisabledFeatures(
+                    /* admin= */ eq(null),
+                    /* userHandle= */ anyInt()
+                )
+            )
+            .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE)
     }
 
     private fun createNoteTaskController(
         isEnabled: Boolean = true,
         bubbles: Bubbles? = this.bubbles,
-        keyguardManager: KeyguardManager? = this.keyguardManager,
-        userManager: UserManager? = this.userManager,
     ): NoteTaskController =
         NoteTaskController(
             context = context,
             resolver = resolver,
             eventLogger = eventLogger,
             optionalBubbles = Optional.ofNullable(bubbles),
-            optionalUserManager = Optional.ofNullable(userManager),
-            optionalKeyguardManager = Optional.ofNullable(keyguardManager),
+            userManager = userManager,
+            keyguardManager = keyguardManager,
             isEnabled = isEnabled,
+            devicePolicyManager = devicePolicyManager,
+            userTracker = userTracker,
         )
 
     // region onBubbleExpandChanged
     @Test
     fun onBubbleExpandChanged_expanding_logNoteTaskOpened() {
-        val expectedInfo = noteTaskInfo.copy(isKeyguardLocked = false, isInMultiWindowMode = false)
+        val expectedInfo = noteTaskInfo.copy(isKeyguardLocked = false)
 
         createNoteTaskController()
             .apply { infoReference.set(expectedInfo) }
@@ -101,7 +117,7 @@
 
     @Test
     fun onBubbleExpandChanged_collapsing_logNoteTaskClosed() {
-        val expectedInfo = noteTaskInfo.copy(isKeyguardLocked = false, isInMultiWindowMode = false)
+        val expectedInfo = noteTaskInfo.copy(isKeyguardLocked = false)
 
         createNoteTaskController()
             .apply { infoReference.set(expectedInfo) }
@@ -116,7 +132,7 @@
 
     @Test
     fun onBubbleExpandChanged_expandingAndKeyguardLocked_doNothing() {
-        val expectedInfo = noteTaskInfo.copy(isKeyguardLocked = true, isInMultiWindowMode = false)
+        val expectedInfo = noteTaskInfo.copy(isKeyguardLocked = true)
 
         createNoteTaskController()
             .apply { infoReference.set(expectedInfo) }
@@ -130,35 +146,7 @@
 
     @Test
     fun onBubbleExpandChanged_notExpandingAndKeyguardLocked_doNothing() {
-        val expectedInfo = noteTaskInfo.copy(isKeyguardLocked = true, isInMultiWindowMode = false)
-
-        createNoteTaskController()
-            .apply { infoReference.set(expectedInfo) }
-            .onBubbleExpandChanged(
-                isExpanding = false,
-                key = Bubble.KEY_APP_BUBBLE,
-            )
-
-        verifyZeroInteractions(context, bubbles, keyguardManager, userManager, eventLogger)
-    }
-
-    @Test
-    fun onBubbleExpandChanged_expandingAndInMultiWindowMode_doNothing() {
-        val expectedInfo = noteTaskInfo.copy(isKeyguardLocked = false, isInMultiWindowMode = true)
-
-        createNoteTaskController()
-            .apply { infoReference.set(expectedInfo) }
-            .onBubbleExpandChanged(
-                isExpanding = true,
-                key = Bubble.KEY_APP_BUBBLE,
-            )
-
-        verifyZeroInteractions(context, bubbles, keyguardManager, userManager)
-    }
-
-    @Test
-    fun onBubbleExpandChanged_notExpandingAndInMultiWindowMode_doNothing() {
-        val expectedInfo = noteTaskInfo.copy(isKeyguardLocked = false, isInMultiWindowMode = true)
+        val expectedInfo = noteTaskInfo.copy(isKeyguardLocked = true)
 
         createNoteTaskController()
             .apply { infoReference.set(expectedInfo) }
@@ -199,26 +187,30 @@
         val expectedInfo =
             noteTaskInfo.copy(
                 entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
-                isInMultiWindowMode = false,
                 isKeyguardLocked = true,
             )
         whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
-        whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
+        whenever(resolver.resolveInfo(any(), any())).thenReturn(expectedInfo)
 
         createNoteTaskController()
             .showNoteTask(
                 entryPoint = expectedInfo.entryPoint!!,
-                isInMultiWindowMode = expectedInfo.isInMultiWindowMode,
             )
 
         val intentCaptor = argumentCaptor<Intent>()
-        verify(context).startActivity(capture(intentCaptor))
+        val userCaptor = argumentCaptor<UserHandle>()
+        verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))
         intentCaptor.value.let { intent ->
-            assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
+            assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
             assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
-            assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
-            assertThat(intent.getBooleanExtra(INTENT_EXTRA_USE_STYLUS_MODE, false)).isTrue()
+            assertThat(intent.flags and FLAG_ACTIVITY_NEW_TASK).isEqualTo(FLAG_ACTIVITY_NEW_TASK)
+            assertThat(intent.flags and FLAG_ACTIVITY_MULTIPLE_TASK)
+                .isEqualTo(FLAG_ACTIVITY_MULTIPLE_TASK)
+            assertThat(intent.flags and FLAG_ACTIVITY_NEW_DOCUMENT)
+                .isEqualTo(FLAG_ACTIVITY_NEW_DOCUMENT)
+            assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
         }
+        assertThat(userCaptor.value).isEqualTo(userTracker.userHandle)
         verify(eventLogger).logNoteTaskOpened(expectedInfo)
         verifyZeroInteractions(bubbles)
     }
@@ -228,87 +220,33 @@
         val expectedInfo =
             noteTaskInfo.copy(
                 entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
-                isInMultiWindowMode = false,
                 isKeyguardLocked = false,
             )
-        whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
+        whenever(resolver.resolveInfo(any(), any())).thenReturn(expectedInfo)
         whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
 
         createNoteTaskController()
             .showNoteTask(
                 entryPoint = expectedInfo.entryPoint!!,
-                isInMultiWindowMode = expectedInfo.isInMultiWindowMode,
             )
 
         verifyZeroInteractions(context)
         val intentCaptor = argumentCaptor<Intent>()
         verify(bubbles).showOrHideAppBubble(capture(intentCaptor))
         intentCaptor.value.let { intent ->
-            assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
+            assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
             assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
-            assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
-            assertThat(intent.getBooleanExtra(INTENT_EXTRA_USE_STYLUS_MODE, false)).isTrue()
+            assertThat(intent.flags).isEqualTo(FLAG_ACTIVITY_NEW_TASK)
+            assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
         }
         verifyZeroInteractions(eventLogger)
     }
 
     @Test
-    fun showNoteTask_isInMultiWindowMode_shouldStartActivityAndLogUiEvent() {
-        val expectedInfo =
-            noteTaskInfo.copy(
-                entryPoint = NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT,
-                isInMultiWindowMode = true,
-                isKeyguardLocked = false,
-            )
-        whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
-        whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
-
-        createNoteTaskController()
-            .showNoteTask(
-                entryPoint = expectedInfo.entryPoint!!,
-                isInMultiWindowMode = expectedInfo.isInMultiWindowMode,
-            )
-
-        val intentCaptor = argumentCaptor<Intent>()
-        verify(context).startActivity(capture(intentCaptor))
-        intentCaptor.value.let { intent ->
-            assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
-            assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
-            assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
-            assertThat(intent.getBooleanExtra(INTENT_EXTRA_USE_STYLUS_MODE, false)).isTrue()
-        }
-        verify(eventLogger).logNoteTaskOpened(expectedInfo)
-        verifyZeroInteractions(bubbles)
-    }
-
-    @Test
     fun showNoteTask_bubblesIsNull_shouldDoNothing() {
         createNoteTaskController(bubbles = null)
             .showNoteTask(
                 entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
-                isInMultiWindowMode = false,
-            )
-
-        verifyZeroInteractions(context, bubbles, eventLogger)
-    }
-
-    @Test
-    fun showNoteTask_keyguardManagerIsNull_shouldDoNothing() {
-        createNoteTaskController(keyguardManager = null)
-            .showNoteTask(
-                entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
-                isInMultiWindowMode = false,
-            )
-
-        verifyZeroInteractions(context, bubbles, eventLogger)
-    }
-
-    @Test
-    fun showNoteTask_userManagerIsNull_shouldDoNothing() {
-        createNoteTaskController(userManager = null)
-            .showNoteTask(
-                entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
-                isInMultiWindowMode = false,
             )
 
         verifyZeroInteractions(context, bubbles, eventLogger)
@@ -316,12 +254,11 @@
 
     @Test
     fun showNoteTask_intentResolverReturnsNull_shouldDoNothing() {
-        whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(null)
+        whenever(resolver.resolveInfo(any(), any())).thenReturn(null)
 
         createNoteTaskController()
             .showNoteTask(
                 entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
-                isInMultiWindowMode = false,
             )
 
         verifyZeroInteractions(context, bubbles, eventLogger)
@@ -332,7 +269,6 @@
         createNoteTaskController(isEnabled = false)
             .showNoteTask(
                 entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
-                isInMultiWindowMode = false,
             )
 
         verifyZeroInteractions(context, bubbles, eventLogger)
@@ -345,7 +281,6 @@
         createNoteTaskController()
             .showNoteTask(
                 entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
-                isInMultiWindowMode = false,
             )
 
         verifyZeroInteractions(context, bubbles, eventLogger)
@@ -384,6 +319,86 @@
     }
     // endregion
 
+    // region keyguard policy
+    @Test
+    fun showNoteTask_keyguardLocked_keyguardDisableShortcutsAll_shouldDoNothing() {
+        whenever(keyguardManager.isKeyguardLocked).thenReturn(true)
+        whenever(
+                devicePolicyManager.getKeyguardDisabledFeatures(
+                    /* admin= */ eq(null),
+                    /* userHandle= */ anyInt()
+                )
+            )
+            .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL)
+
+        createNoteTaskController().showNoteTask(entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE)
+
+        verifyZeroInteractions(context, bubbles, eventLogger)
+    }
+
+    @Test
+    fun showNoteTask_keyguardLocked_keyguardDisableFeaturesAll_shouldDoNothing() {
+        whenever(keyguardManager.isKeyguardLocked).thenReturn(true)
+        whenever(
+                devicePolicyManager.getKeyguardDisabledFeatures(
+                    /* admin= */ eq(null),
+                    /* userHandle= */ anyInt()
+                )
+            )
+            .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL)
+
+        createNoteTaskController().showNoteTask(entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE)
+
+        verifyZeroInteractions(context, bubbles, eventLogger)
+    }
+
+    @Test
+    fun showNoteTask_keyguardUnlocked_keyguardDisableShortcutsAll_shouldStartBubble() {
+        whenever(keyguardManager.isKeyguardLocked).thenReturn(false)
+        whenever(
+                devicePolicyManager.getKeyguardDisabledFeatures(
+                    /* admin= */ eq(null),
+                    /* userHandle= */ anyInt()
+                )
+            )
+            .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL)
+
+        createNoteTaskController().showNoteTask(entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE)
+
+        val intentCaptor = argumentCaptor<Intent>()
+        verify(bubbles).showOrHideAppBubble(capture(intentCaptor))
+        intentCaptor.value.let { intent ->
+            assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
+            assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
+            assertThat(intent.flags).isEqualTo(FLAG_ACTIVITY_NEW_TASK)
+            assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
+        }
+    }
+
+    @Test
+    fun showNoteTask_keyguardUnlocked_keyguardDisableFeaturesAll_shouldStartBubble() {
+        whenever(keyguardManager.isKeyguardLocked).thenReturn(false)
+        whenever(
+                devicePolicyManager.getKeyguardDisabledFeatures(
+                    /* admin= */ eq(null),
+                    /* userHandle= */ anyInt()
+                )
+            )
+            .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL)
+
+        createNoteTaskController().showNoteTask(entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE)
+
+        val intentCaptor = argumentCaptor<Intent>()
+        verify(bubbles).showOrHideAppBubble(capture(intentCaptor))
+        intentCaptor.value.let { intent ->
+            assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
+            assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
+            assertThat(intent.flags).isEqualTo(FLAG_ACTIVITY_NEW_TASK)
+            assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
+        }
+    }
+    // endregion
+
     private companion object {
         const val NOTES_PACKAGE_NAME = "com.android.note.app"
         const val NOTES_UID = 123456
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt
index d6495d8..0c945df 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt
@@ -22,6 +22,8 @@
 import android.test.suitebuilder.annotation.SmallTest
 import androidx.test.runner.AndroidJUnit4
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.settings.FakeUserTracker
+import com.android.systemui.settings.UserTracker
 import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
@@ -44,21 +46,23 @@
 
     @Mock lateinit var packageManager: PackageManager
     @Mock lateinit var roleManager: RoleManager
+    private val userTracker: UserTracker = FakeUserTracker()
 
     private lateinit var underTest: NoteTaskInfoResolver
 
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
-        underTest = NoteTaskInfoResolver(context, roleManager, packageManager)
+        underTest = NoteTaskInfoResolver(roleManager, packageManager, userTracker)
     }
 
     @Test
     fun resolveInfo_shouldReturnInfo() {
         val packageName = "com.android.note.app"
         val uid = 123456
-        whenever(roleManager.getRoleHoldersAsUser(NoteTaskInfoResolver.ROLE_NOTES, context.user))
-            .then { listOf(packageName) }
+        whenever(roleManager.getRoleHoldersAsUser(RoleManager.ROLE_NOTES, context.user)).then {
+            listOf(packageName)
+        }
         whenever(
                 packageManager.getApplicationInfoAsUser(
                     eq(packageName),
@@ -78,8 +82,9 @@
     @Test
     fun resolveInfo_packageManagerThrowsException_shouldReturnInfoWithZeroUid() {
         val packageName = "com.android.note.app"
-        whenever(roleManager.getRoleHoldersAsUser(NoteTaskInfoResolver.ROLE_NOTES, context.user))
-            .then { listOf(packageName) }
+        whenever(roleManager.getRoleHoldersAsUser(RoleManager.ROLE_NOTES, context.user)).then {
+            listOf(packageName)
+        }
         whenever(
                 packageManager.getApplicationInfoAsUser(
                     eq(packageName),
@@ -98,8 +103,9 @@
 
     @Test
     fun resolveInfo_noRoleHolderIsSet_shouldReturnNull() {
-        whenever(roleManager.getRoleHoldersAsUser(eq(NoteTaskInfoResolver.ROLE_NOTES), any()))
-            .then { listOf<String>() }
+        whenever(roleManager.getRoleHoldersAsUser(eq(RoleManager.ROLE_NOTES), any())).then {
+            emptyList<String>()
+        }
 
         val actual = underTest.resolveInfo()
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt
index 7e975b6..91cd6ae 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt
@@ -31,41 +31,19 @@
         NoteTaskInfo(packageName = NOTES_PACKAGE_NAME, uid = NOTES_UID)
 
     @Test
-    fun launchMode_notInMultiWindowModeAndKeyguardUnlocked_launchModeAppBubble() {
-        val underTest =
-            createNoteTaskInfo()
-                .copy(
-                    isKeyguardLocked = false,
-                    isInMultiWindowMode = false,
-                )
+    fun launchMode_keyguardLocked_launchModeActivity() {
+        val underTest = createNoteTaskInfo().copy(isKeyguardLocked = true)
+
+        assertThat(underTest.launchMode).isEqualTo(NoteTaskLaunchMode.Activity)
+    }
+
+    @Test
+    fun launchMode_keyguardUnlocked_launchModeActivity() {
+        val underTest = createNoteTaskInfo().copy(isKeyguardLocked = false)
 
         assertThat(underTest.launchMode).isEqualTo(NoteTaskLaunchMode.AppBubble)
     }
 
-    @Test
-    fun launchMode_inMultiWindowMode_launchModeActivity() {
-        val underTest =
-            createNoteTaskInfo()
-                .copy(
-                    isKeyguardLocked = false,
-                    isInMultiWindowMode = true,
-                )
-
-        assertThat(underTest.launchMode).isEqualTo(NoteTaskLaunchMode.Activity)
-    }
-
-    @Test
-    fun launchMode_keyguardLocked_launchModeActivity() {
-        val underTest =
-            createNoteTaskInfo()
-                .copy(
-                    isKeyguardLocked = true,
-                    isInMultiWindowMode = false,
-                )
-
-        assertThat(underTest.launchMode).isEqualTo(NoteTaskLaunchMode.Activity)
-    }
-
     private companion object {
         const val NOTES_PACKAGE_NAME = "com.android.note.app"
         const val NOTES_UID = 123456
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt
index a8eab50..46e0278 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt
@@ -103,9 +103,7 @@
     // region handleSystemKey
     @Test
     fun handleSystemKey_receiveValidSystemKey_shouldShowNoteTask() {
-        createNoteTaskInitializer()
-            .callbacks
-            .handleSystemKey(NoteTaskController.NOTE_TASK_KEY_EVENT)
+        createNoteTaskInitializer().callbacks.handleSystemKey(KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL)
 
         verify(noteTaskController).showNoteTask(entryPoint = NoteTaskEntryPoint.TAIL_BUTTON)
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/OWNERS b/packages/SystemUI/tests/src/com/android/systemui/notetask/OWNERS
index 7ccb316..0ec996b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/OWNERS
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/OWNERS
@@ -5,4 +5,6 @@
 madym@google.com
 mgalhardo@google.com
 petrcermak@google.com
+stevenckng@google.com
+tkachenkoi@google.com
 vanjan@google.com
\ No newline at end of file
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 e57d0d9..d44012f 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
@@ -18,75 +18,139 @@
 
 package com.android.systemui.notetask.quickaffordance
 
+import android.hardware.input.InputSettings
 import android.test.suitebuilder.annotation.SmallTest
-import androidx.test.runner.AndroidJUnit4
+import android.testing.AndroidTestingRunner
+import com.android.dx.mockito.inline.extended.ExtendedMockito
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.common.shared.model.ContentDescription
 import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.LockScreenState
+import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
 import com.android.systemui.notetask.NoteTaskController
 import com.android.systemui.notetask.NoteTaskEntryPoint
+import com.android.systemui.stylus.StylusManager
+import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.test.runTest
+import org.junit.After
 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.MockitoAnnotations
+import org.mockito.MockitoSession
+import org.mockito.quality.Strictness
 
-/**
- * Tests for [NoteTaskQuickAffordanceConfig].
- *
- * Build/Install/Run:
- * - atest SystemUITests:NoteTaskQuickAffordanceConfigTest
- */
+/** atest SystemUITests:NoteTaskQuickAffordanceConfigTest */
 @SmallTest
-@RunWith(AndroidJUnit4::class)
+@RunWith(AndroidTestingRunner::class)
 internal class NoteTaskQuickAffordanceConfigTest : SysuiTestCase() {
 
-    @Mock lateinit var noteTaskController: NoteTaskController
+    @Mock lateinit var controller: NoteTaskController
+    @Mock lateinit var stylusManager: StylusManager
+    @Mock lateinit var repository: KeyguardQuickAffordanceRepository
+
+    private lateinit var mockitoSession: MockitoSession
 
     @Before
     fun setUp() {
-        MockitoAnnotations.initMocks(this)
+        mockitoSession =
+            ExtendedMockito.mockitoSession()
+                .initMocks(this)
+                .mockStatic(InputSettings::class.java)
+                .strictness(Strictness.LENIENT)
+                .startMocking()
+
+        whenever(InputSettings.isStylusEverUsed(mContext)).then { true }
+        whenever(repository.selections).then {
+            val map = mapOf("" to listOf(createUnderTest()))
+            MutableStateFlow(map)
+        }
     }
 
-    private fun createUnderTest(isEnabled: Boolean) =
+    @After
+    fun tearDown() {
+        mockitoSession.finishMocking()
+    }
+
+    private fun createUnderTest(isEnabled: Boolean = true): KeyguardQuickAffordanceConfig =
         NoteTaskQuickAffordanceConfig(
             context = context,
-            noteTaskController = noteTaskController,
+            controller = controller,
+            stylusManager = stylusManager,
+            lazyRepository = { repository },
             isEnabled = isEnabled,
         )
 
+    private fun createLockScreenStateVisible(): LockScreenState =
+        LockScreenState.Visible(
+            icon =
+                Icon.Resource(
+                    res = R.drawable.ic_note_task_shortcut_keyguard,
+                    contentDescription =
+                        ContentDescription.Resource(R.string.note_task_button_label),
+                )
+        )
+
+    @Test
+    fun lockScreenState_stylusUsed_noCustomShortcutSelected_shouldEmitVisible() = runTest {
+        val underTest = createUnderTest()
+
+        val actual by collectLastValue(underTest.lockScreenState)
+
+        assertThat(actual).isEqualTo(createLockScreenStateVisible())
+    }
+
+    @Test
+    fun lockScreenState_noStylusEverUsed_noCustomShortcutSelected_shouldEmitVisible() = runTest {
+        whenever(InputSettings.isStylusEverUsed(mContext)).then { false }
+        val underTest = createUnderTest()
+
+        val actual by collectLastValue(underTest.lockScreenState)
+
+        assertThat(actual).isEqualTo(createLockScreenStateVisible())
+    }
+
+    @Test
+    fun lockScreenState_stylusUsed_customShortcutSelected_shouldEmitVisible() = runTest {
+        whenever(repository.selections).then {
+            val map = mapOf<String, List<KeyguardQuickAffordanceConfig>>()
+            MutableStateFlow(map)
+        }
+        val underTest = createUnderTest()
+
+        val actual by collectLastValue(underTest.lockScreenState)
+
+        assertThat(actual).isEqualTo(createLockScreenStateVisible())
+    }
+
+    @Test
+    fun lockScreenState_noIsStylusEverUsed_noCustomShortcutSelected_shouldEmitHidden() = runTest {
+        whenever(InputSettings.isStylusEverUsed(mContext)).then { false }
+        whenever(repository.selections).then {
+            val map = mapOf<String, List<KeyguardQuickAffordanceConfig>>()
+            MutableStateFlow(map)
+        }
+        val underTest = createUnderTest()
+
+        val actual by collectLastValue(underTest.lockScreenState)
+
+        assertThat(actual).isEqualTo(LockScreenState.Hidden)
+    }
+
     @Test
     fun lockScreenState_isNotEnabled_shouldEmitHidden() = runTest {
         val underTest = createUnderTest(isEnabled = false)
 
-        val actual = collectLastValue(underTest.lockScreenState)
+        val actual by collectLastValue(underTest.lockScreenState)
 
-        assertThat(actual()).isEqualTo(LockScreenState.Hidden)
-    }
-
-    @Test
-    fun lockScreenState_isEnabled_shouldEmitVisible() = runTest {
-        val stringResult = "Notetaking"
-        val underTest = createUnderTest(isEnabled = true)
-
-        val actual = collectLastValue(underTest.lockScreenState)
-
-        val expected =
-            LockScreenState.Visible(
-                icon =
-                    Icon.Resource(
-                        res = R.drawable.ic_note_task_shortcut_keyguard,
-                        contentDescription = ContentDescription.Loaded(stringResult),
-                    )
-            )
-        assertThat(actual()).isEqualTo(expected)
+        assertThat(actual).isEqualTo(LockScreenState.Hidden)
     }
 
     @Test
@@ -95,6 +159,6 @@
 
         underTest.onTriggered(expandable = null)
 
-        verify(noteTaskController).showNoteTask(entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE)
+        verify(controller).showNoteTask(entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE)
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index 89606bf..0ab0e2b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -52,6 +52,8 @@
 import com.android.systemui.SysuiBaseFragmentTest;
 import com.android.systemui.animation.ShadeInterpolation;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.media.controls.ui.MediaHost;
 import com.android.systemui.qs.customize.QSCustomizerController;
 import com.android.systemui.qs.dagger.QSFragmentComponent;
@@ -60,6 +62,7 @@
 import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.settings.FakeDisplayTracker;
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -103,6 +106,8 @@
     @Mock private QSSquishinessController mSquishinessController;
     @Mock private FooterActionsViewModel mFooterActionsViewModel;
     @Mock private FooterActionsViewModel.Factory mFooterActionsViewModelFactory;
+    @Mock private LargeScreenShadeInterpolator mLargeScreenShadeInterpolator;
+    @Mock private FeatureFlags mFeatureFlags;
     private View mQsFragmentView;
 
     public QSFragmentTest() {
@@ -148,8 +153,9 @@
     }
 
     @Test
-    public void transitionToFullShade_setsAlphaUsingShadeInterpolator() {
+    public void transitionToFullShade_smallScreen_alphaAlways1() {
         QSFragment fragment = resumeAndGetFragment();
+        setIsSmallScreen();
         setStatusBarCurrentAndUpcomingState(StatusBarState.SHADE);
         boolean isTransitioningToFullShade = true;
         float transitionProgress = 0.5f;
@@ -158,6 +164,43 @@
         fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress,
                 squishinessFraction);
 
+        assertThat(mQsFragmentView.getAlpha()).isEqualTo(1f);
+    }
+
+    @Test
+    public void transitionToFullShade_largeScreen_flagEnabled_alphaLargeScreenShadeInterpolator() {
+        when(mFeatureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
+                .thenReturn(true);
+        QSFragment fragment = resumeAndGetFragment();
+        setIsLargeScreen();
+        setStatusBarCurrentAndUpcomingState(StatusBarState.SHADE);
+        boolean isTransitioningToFullShade = true;
+        float transitionProgress = 0.5f;
+        float squishinessFraction = 0.5f;
+        when(mLargeScreenShadeInterpolator.getQsAlpha(transitionProgress)).thenReturn(123f);
+
+        fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress,
+                squishinessFraction);
+
+        assertThat(mQsFragmentView.getAlpha())
+                .isEqualTo(123f);
+    }
+
+    @Test
+    public void transitionToFullShade_largeScreen_flagDisabled_alphaStandardInterpolator() {
+        when(mFeatureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
+                .thenReturn(false);
+        QSFragment fragment = resumeAndGetFragment();
+        setIsLargeScreen();
+        setStatusBarCurrentAndUpcomingState(StatusBarState.SHADE);
+        boolean isTransitioningToFullShade = true;
+        float transitionProgress = 0.5f;
+        float squishinessFraction = 0.5f;
+        when(mLargeScreenShadeInterpolator.getQsAlpha(transitionProgress)).thenReturn(123f);
+
+        fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress,
+                squishinessFraction);
+
         assertThat(mQsFragmentView.getAlpha())
                 .isEqualTo(ShadeInterpolation.getContentAlpha(transitionProgress));
     }
@@ -514,7 +557,9 @@
                 mock(DumpManager.class),
                 mock(QSLogger.class),
                 mock(FooterActionsController.class),
-                mFooterActionsViewModelFactory);
+                mFooterActionsViewModelFactory,
+                mLargeScreenShadeInterpolator,
+                mFeatureFlags);
     }
 
     private void setUpOther() {
@@ -622,4 +667,12 @@
             return null;
         }).when(view).getLocationOnScreen(any(int[].class));
     }
+
+    private void setIsLargeScreen() {
+        getFragment().setIsNotificationPanelFullWidth(false);
+    }
+
+    private void setIsSmallScreen() {
+        getFragment().setIsNotificationPanelFullWidth(true);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
index d6dfc85..ac106ef 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
@@ -57,6 +57,7 @@
 import org.mockito.ArgumentMatchers.anyString
 import org.mockito.Mock
 import org.mockito.Mockito.`when`
+import org.mockito.Mockito.clearInvocations
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.never
 import org.mockito.Mockito.reset
@@ -351,4 +352,44 @@
             .startPendingIntentDismissingKeyguard(
                 eq(pi), nullable(), nullable<ActivityLaunchAnimator.Controller>())
     }
+
+    @Test
+    fun testActiveTileListensOnceAfterCreated() {
+        `when`(tileServiceManager.isActiveTile).thenReturn(true)
+
+        val tile = CustomTile.create(customTileBuilder, TILE_SPEC, mContext)
+        tile.initialize()
+        tile.postStale()
+        testableLooper.processAllMessages()
+
+        verify(tileServiceManager).setBindRequested(true)
+        verify(tileService).onStartListening()
+    }
+
+    @Test
+    fun testActiveTileDoesntListenAfterFirstTime() {
+        `when`(tileServiceManager.isActiveTile).thenReturn(true)
+
+        val tile = CustomTile.create(customTileBuilder, TILE_SPEC, mContext)
+        tile.initialize()
+        // Make sure we have an icon in the tile because we don't have a default icon
+        // This should not be overridden by the retrieved tile that has null icon.
+        tile.qsTile.icon = mock(Icon::class.java)
+        `when`(tile.qsTile.icon.loadDrawable(any(Context::class.java)))
+                .thenReturn(mock(Drawable::class.java))
+
+        tile.postStale()
+        testableLooper.processAllMessages()
+
+        // postStale will set it to not listening after it's done
+        verify(tileService).onStopListening()
+
+        clearInvocations(tileServiceManager, tileService)
+
+        tile.setListening(Any(), true)
+        testableLooper.processAllMessages()
+
+        verify(tileServiceManager, never()).setBindRequested(true)
+        verify(tileService, never()).onStartListening()
+    }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt
index 030c59f..5e0190b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt
@@ -38,6 +38,7 @@
 import com.android.systemui.util.settings.GlobalSettings
 import com.google.common.truth.Truth.assertThat
 import dagger.Lazy
+import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -94,6 +95,12 @@
             mUserTracker)
     }
 
+    @After
+    fun tearDown() {
+        mTile.destroy()
+        mTestableLooper.processAllMessages()
+    }
+
     @Test
     fun testIcon_whenDisabled_showsOffState() {
         val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt
index b4a66297..f1e3e8a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt
@@ -21,6 +21,7 @@
 import com.android.systemui.util.mockito.capture
 import com.android.systemui.util.mockito.eq
 import com.google.common.truth.Truth.assertThat
+import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -88,6 +89,12 @@
         testableLooper.processAllMessages()
     }
 
+    @After
+    fun tearDown() {
+        tile.destroy()
+        testableLooper.processAllMessages()
+    }
+
     @Test
     fun testAvailable() {
         assertThat(tile.isAvailable).isTrue()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
index 95e7ad9f..a5c0004 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
@@ -37,6 +37,7 @@
 import com.android.systemui.util.settings.FakeSettings
 import com.android.systemui.util.settings.SecureSettings
 import com.google.common.truth.Truth.assertThat
+import org.junit.After
 import org.junit.Assert.assertEquals
 import org.junit.Before
 import org.junit.Test
@@ -103,6 +104,12 @@
         testableLooper.processAllMessages()
     }
 
+    @After
+    fun tearDown() {
+        tile.destroy()
+        testableLooper.processAllMessages()
+    }
+
     @Test
     fun testSettingWithCorrectUser() {
         assertEquals(USER, tile.mSetting.currentUser)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt
index bf172f1..75fd000 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt
@@ -22,6 +22,7 @@
 import com.android.systemui.qs.tileimpl.QSTileImpl
 import com.android.systemui.statusbar.policy.BluetoothController
 import com.google.common.truth.Truth.assertThat
+import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -79,6 +80,12 @@
         testableLooper.processAllMessages()
     }
 
+    @After
+    fun tearDown() {
+        tile.destroy()
+        testableLooper.processAllMessages()
+    }
+
     @Test
     fun testRestrictionChecked() {
         tile.refreshState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt
index cfbb82f..4193854 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt
@@ -35,6 +35,7 @@
 import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.google.common.truth.Truth.assertThat
+import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -90,6 +91,12 @@
                 keyguardStateController)
     }
 
+    @After
+    fun tearDown() {
+        tile.destroy()
+        testableLooper.processAllMessages()
+    }
+
     @Test
     fun testIcon_whenCameraAccessEnabled_isOnState() {
         val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
index 18f891c..64fd09d5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
@@ -53,6 +53,7 @@
 import com.android.systemui.statusbar.policy.HotspotController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -141,6 +142,12 @@
         mHotspotCallback = hotspotCallbackArgumentCaptor.getValue();
     }
 
+    @After
+    public void tearDown() {
+        mCastTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     // -------------------------------------------------
     // All these tests for enabled/disabled wifi have hotspot not enabled
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java
index fdb63ca..13c30e9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java
@@ -43,6 +43,7 @@
 import com.android.systemui.util.settings.FakeSettings;
 import com.android.systemui.util.settings.SecureSettings;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -101,6 +102,12 @@
         mTestableLooper.processAllMessages();
     }
 
+    @After
+    public void tearDown() {
+        mTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     @Test
     public void longClick_expectedAction() {
         final ArgumentCaptor<Intent> IntentCaptor = ArgumentCaptor.forClass(Intent.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java
index 60c1a33..ff27e02 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java
@@ -46,6 +46,7 @@
 import com.android.systemui.util.settings.FakeSettings;
 import com.android.systemui.util.settings.SecureSettings;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -106,6 +107,12 @@
         mTestableLooper.processAllMessages();
     }
 
+    @After
+    public void tearDown() {
+        mTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     @Test
     public void longClick_expectedAction() {
         final ArgumentCaptor<Intent> IntentCaptor = ArgumentCaptor.forClass(Intent.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt
index ce62f2d..b048643 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt
@@ -34,6 +34,7 @@
 import com.android.systemui.qs.tileimpl.QSTileImpl
 import com.android.systemui.statusbar.policy.DataSaverController
 import com.google.common.truth.Truth.assertThat
+import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -84,6 +85,12 @@
             )
     }
 
+    @After
+    fun tearDown() {
+        tile.destroy()
+        testableLooper.processAllMessages()
+    }
+
     @Test
     fun testIcon_whenDataSaverEnabled_isOnState() {
         val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
index e0b3125..b51c378 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
@@ -67,6 +67,7 @@
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.verifyZeroInteractions
 import java.util.Optional
+import org.junit.After
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
@@ -129,6 +130,12 @@
         tile = createTile()
     }
 
+    @After
+    fun tearDown() {
+        tile.destroy()
+        testableLooper.processAllMessages()
+    }
+
     private fun setupControlsComponent() {
         `when`(controlsComponent.getControlsController()).thenAnswer {
             if (featureEnabled) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
index ce5edb1..6c0904e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
@@ -136,7 +136,8 @@
 
     @After
     fun tearDown() {
-        tile.handleSetListening(false)
+        tile.destroy()
+        testableLooper.processAllMessages()
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java
index 71d8aa4..7d41aa6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java
@@ -54,6 +54,7 @@
 import com.android.systemui.util.settings.FakeSettings;
 import com.android.systemui.util.settings.SecureSettings;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -112,6 +113,12 @@
         mTile.initialize();
     }
 
+    @After
+    public void tearDown() {
+        mTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     @Test
     public void testNotAvailable() throws RemoteException {
         // Should not be available if screensaver is disabled
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt
index c7aba1a..692a644 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt
@@ -18,6 +18,7 @@
 import com.android.systemui.qs.tileimpl.QSTileImpl
 import com.android.systemui.statusbar.policy.FlashlightController
 import com.google.common.truth.Truth
+import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -71,6 +72,12 @@
             )
     }
 
+    @After
+    fun tearDown() {
+        tile.destroy()
+        testableLooper.processAllMessages()
+    }
+
     @Test
     fun testIcon_whenFlashlightEnabled_isOnState() {
         Mockito.`when`(flashlightController.isAvailable).thenReturn(true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt
index 9d62cfd..bd99cd4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt
@@ -38,6 +38,7 @@
 import com.android.systemui.util.mockito.nullable
 import com.android.systemui.util.settings.FakeSettings
 import com.google.common.truth.Truth.assertThat
+import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -89,6 +90,12 @@
         testableLooper.processAllMessages()
     }
 
+    @After
+    fun tearDown() {
+        fontScalingTile.destroy()
+        testableLooper.processAllMessages()
+    }
+
     @Test
     fun isAvailable_whenFlagIsFalse_returnsFalse() {
         featureFlags.set(Flags.ENABLE_FONT_SCALING_TILE, false)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java
index 4a2ac96..959e750 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java
@@ -43,6 +43,7 @@
 import com.android.systemui.statusbar.policy.DataSaverController;
 import com.android.systemui.statusbar.policy.HotspotController;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -94,6 +95,12 @@
         mTestableLooper.processAllMessages();
     }
 
+    @After
+    public void tearDown() {
+        mTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     @Test
     public void handleUpdateState_wifiTetheringIsAllowed_stateIsNotUnavailable() {
         MockitoSession mockitoSession = ExtendedMockito.mockitoSession()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java
index abd9094..adfd7f7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java
@@ -43,6 +43,7 @@
 import com.android.systemui.statusbar.connectivity.NetworkController;
 import com.android.systemui.statusbar.connectivity.WifiIndicators;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -91,6 +92,12 @@
         mTestableLooper.processAllMessages();
     }
 
+    @After
+    public void tearDown() {
+        mTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     @Test
     public void setConnectivityStatus_defaultNetworkNotExists_updateTile() {
         mTile.mSignalCallback.setConnectivityStatus(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
index 08d10fd..33921c7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
@@ -35,6 +35,7 @@
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.statusbar.policy.LocationController
 import com.google.common.truth.Truth.assertThat
+import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -88,6 +89,12 @@
             keyguardStateController)
     }
 
+    @After
+    fun tearDown() {
+        tile.destroy()
+        testableLooper.processAllMessages()
+    }
+
     @Test
     fun testIcon_whenDisabled_isOffState() {
         val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt
index 1ab601c..e2f64b2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt
@@ -35,6 +35,7 @@
 import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.google.common.truth.Truth.assertThat
+import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -90,6 +91,12 @@
                 keyguardStateController)
     }
 
+    @After
+    fun tearDown() {
+        tile.destroy()
+        testableLooper.processAllMessages()
+    }
+
     @Test
     fun testIcon_whenMicrophoneAccessEnabled_isOnState() {
         val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java
index 9638a45..c7dae83 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java
@@ -39,6 +39,7 @@
 import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.logging.QSLogger;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -97,6 +98,12 @@
         mTestableLooper.processAllMessages();
     }
 
+    @After
+    public void tearDown() {
+        mNfcTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     @Test
     public void testIsAvailable_stockWithoutNfc_returnsFalse() {
         when(mMockContext.getString(R.string.quick_settings_tiles_stock)).thenReturn(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt
index 188c3a3..04af69c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt
@@ -37,6 +37,7 @@
 import com.android.systemui.qs.tileimpl.QSTileImpl
 import com.android.systemui.statusbar.policy.LocationController
 import com.google.common.truth.Truth
+import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -49,32 +50,23 @@
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
 @SmallTest
 class NightDisplayTileTest : SysuiTestCase() {
-    @Mock
-    private lateinit var mHost: QSHost
+    @Mock private lateinit var mHost: QSHost
 
-    @Mock
-    private lateinit var mMetricsLogger: MetricsLogger
+    @Mock private lateinit var mMetricsLogger: MetricsLogger
 
-    @Mock
-    private lateinit var mStatusBarStateController: StatusBarStateController
+    @Mock private lateinit var mStatusBarStateController: StatusBarStateController
 
-    @Mock
-    private lateinit var mActivityStarter: ActivityStarter
+    @Mock private lateinit var mActivityStarter: ActivityStarter
 
-    @Mock
-    private lateinit var mQsLogger: QSLogger
+    @Mock private lateinit var mQsLogger: QSLogger
 
-    @Mock
-    private lateinit var mLocationController: LocationController
+    @Mock private lateinit var mLocationController: LocationController
 
-    @Mock
-    private lateinit var mColorDisplayManager: ColorDisplayManager
+    @Mock private lateinit var mColorDisplayManager: ColorDisplayManager
 
-    @Mock
-    private lateinit var mNightDisplayListenerBuilder: NightDisplayListenerModule.Builder
+    @Mock private lateinit var mNightDisplayListenerBuilder: NightDisplayListenerModule.Builder
 
-    @Mock
-    private lateinit var mNightDisplayListener: NightDisplayListener
+    @Mock private lateinit var mNightDisplayListener: NightDisplayListener
 
     private lateinit var mTestableLooper: TestableLooper
     private lateinit var mTile: NightDisplayTile
@@ -88,24 +80,30 @@
         whenever(mHost.context).thenReturn(mContext)
         whenever(mHost.uiEventLogger).thenReturn(mUiEventLogger)
         whenever(mHost.userContext).thenReturn(mContext)
-        whenever(mNightDisplayListenerBuilder.setUser(anyInt())).thenReturn(
-            mNightDisplayListenerBuilder
-        )
+        whenever(mNightDisplayListenerBuilder.setUser(anyInt()))
+            .thenReturn(mNightDisplayListenerBuilder)
         whenever(mNightDisplayListenerBuilder.build()).thenReturn(mNightDisplayListener)
 
-        mTile = NightDisplayTile(
-            mHost,
-            mTestableLooper.looper,
-            Handler(mTestableLooper.looper),
-            FalsingManagerFake(),
-            mMetricsLogger,
-            mStatusBarStateController,
-            mActivityStarter,
-            mQsLogger,
-            mLocationController,
-            mColorDisplayManager,
-            mNightDisplayListenerBuilder
-        )
+        mTile =
+            NightDisplayTile(
+                mHost,
+                mTestableLooper.looper,
+                Handler(mTestableLooper.looper),
+                FalsingManagerFake(),
+                mMetricsLogger,
+                mStatusBarStateController,
+                mActivityStarter,
+                mQsLogger,
+                mLocationController,
+                mColorDisplayManager,
+                mNightDisplayListenerBuilder
+            )
+    }
+
+    @After
+    fun tearDown() {
+        mTile.destroy()
+        mTestableLooper.processAllMessages()
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java
index 3344a17..652c138 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java
@@ -37,6 +37,7 @@
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.util.settings.SecureSettings;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -91,6 +92,12 @@
         mTile.initialize();
     }
 
+    @After
+    public void tearDown() {
+        mTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     @Test
     public void testIsAvailable_unsupportOneHandedProperty_shouldReturnsFalse() {
         when(mTile.isSupportOneHandedMode()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java
index 24287ea..3125d45 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java
@@ -43,6 +43,7 @@
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -91,6 +92,12 @@
         mTestableLooper.processAllMessages();
     }
 
+    @After
+    public void tearDown() {
+        mTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     @Test
     public void testNewTile() {
         assertFalse(mTile.newTileState().handlesLongClick);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
index 4722c8d..596df78 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
@@ -73,6 +73,7 @@
 import com.android.systemui.util.settings.SecureSettings;
 import com.android.systemui.wallet.controller.QuickAccessWalletController;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -161,6 +162,12 @@
         mTestableLooper.processAllMessages();
     }
 
+    @After
+    public void tearDown() {
+        mTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     @Test
     public void testNewTile() {
         assertFalse(mTile.newTileState().handlesLongClick);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
index 99e5564..7913628 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
@@ -44,8 +44,8 @@
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.settings.UserTracker;
 
+import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -54,7 +54,6 @@
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
 @SmallTest
-@Ignore("b/269171747")
 public class ReduceBrightColorsTileTest extends SysuiTestCase {
     @Mock
     private QSHost mHost;
@@ -99,6 +98,12 @@
         mTestableLooper.processAllMessages();
     }
 
+    @After
+    public void tearDown() {
+        mTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     @Test
     public void testNotActive() {
         when(mReduceBrightColorsController.isReduceBrightColorsActivated()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java
index c7eb2f1..5b94cfe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java
@@ -48,6 +48,7 @@
 import com.android.systemui.util.settings.FakeSettings;
 import com.android.systemui.util.wrapper.RotationPolicyWrapper;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -139,6 +140,12 @@
         mTestableLooper.processAllMessages();
     }
 
+    @After
+    public void tearDown() {
+        mLockTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     @Test
     public void testSecondaryString_cameraRotateOn_returnsFaceBased() {
         assertEquals(mContext.getString(R.string.rotation_lock_camera_rotation_on),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
index 21acc08..5aef758 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
@@ -50,6 +50,7 @@
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -114,6 +115,12 @@
         mTestableLooper.processAllMessages();
     }
 
+    @After
+    public void tearDown() {
+        mTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     // Test that the tile is inactive and labeled correctly when the controller is neither starting
     // or recording, and that clicking on the tile in this state brings up the record prompt
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt
index 3d9f650..b556571 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt
@@ -39,6 +39,7 @@
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.statusbar.policy.LocationController
 import com.google.common.truth.Truth.assertThat
+import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -98,6 +99,12 @@
             )
     }
 
+    @After
+    fun tearDown() {
+        tile.destroy()
+        testableLooper.processAllMessages()
+    }
+
     @Test
     fun testIcon_whenNightModeOn_isOnState() {
         val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
new file mode 100644
index 0000000..eb7b481
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
@@ -0,0 +1,186 @@
+/*
+ * 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.recents
+
+import android.content.ComponentName
+import android.content.pm.PackageManager
+import android.content.pm.ResolveInfo
+import android.testing.AndroidTestingRunner
+import android.testing.TestableContext
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.internal.app.AssistUtils
+import com.android.internal.logging.UiEventLogger
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.keyguard.KeyguardUnlockAnimationController
+import com.android.systemui.keyguard.ScreenLifecycle
+import com.android.systemui.model.SysUiState
+import com.android.systemui.navigationbar.NavigationBarController
+import com.android.systemui.navigationbar.NavigationModeController
+import com.android.systemui.recents.OverviewProxyService.ACTION_QUICKSTEP
+import com.android.systemui.settings.FakeDisplayTracker
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.shared.recents.IOverviewProxy
+import com.android.systemui.shared.system.QuickStepContract.SCREEN_STATE_OFF
+import com.android.systemui.shared.system.QuickStepContract.SCREEN_STATE_ON
+import com.android.systemui.shared.system.QuickStepContract.SCREEN_STATE_TURNING_OFF
+import com.android.systemui.shared.system.QuickStepContract.SCREEN_STATE_TURNING_ON
+import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_STATE_MASK
+import com.android.systemui.statusbar.CommandQueue
+import com.android.systemui.statusbar.NotificationShadeWindowController
+import com.android.systemui.statusbar.phone.CentralSurfaces
+import com.android.systemui.unfold.progress.UnfoldTransitionProgressForwarder
+import com.android.systemui.util.mockito.whenever
+import com.android.wm.shell.sysui.ShellInterface
+import com.google.common.util.concurrent.MoreExecutors
+import dagger.Lazy
+import java.util.Optional
+import java.util.concurrent.Executor
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers
+import org.mockito.Mock
+import org.mockito.Mockito.any
+import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.intThat
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+class OverviewProxyServiceTest : SysuiTestCase() {
+
+    @Main private val executor: Executor = MoreExecutors.directExecutor()
+
+    private lateinit var subject: OverviewProxyService
+    private val dumpManager = DumpManager()
+    private val displayTracker = FakeDisplayTracker(mContext)
+    private val sysUiState = SysUiState(displayTracker)
+    private val screenLifecycle = ScreenLifecycle(dumpManager)
+
+    @Mock private lateinit var overviewProxy: IOverviewProxy.Stub
+    @Mock private lateinit var packageManager: PackageManager
+
+    // The following mocks belong to not-yet-tested parts of OverviewProxyService.
+    @Mock private lateinit var commandQueue: CommandQueue
+    @Mock private lateinit var shellInterface: ShellInterface
+    @Mock private lateinit var navBarController: NavigationBarController
+    @Mock private lateinit var centralSurfaces: CentralSurfaces
+    @Mock private lateinit var navModeController: NavigationModeController
+    @Mock private lateinit var statusBarWinController: NotificationShadeWindowController
+    @Mock private lateinit var userTracker: UserTracker
+    @Mock private lateinit var uiEventLogger: UiEventLogger
+    @Mock private lateinit var sysuiUnlockAnimationController: KeyguardUnlockAnimationController
+    @Mock private lateinit var assistUtils: AssistUtils
+    @Mock
+    private lateinit var unfoldTransitionProgressForwarder:
+        Optional<UnfoldTransitionProgressForwarder>
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+
+        val serviceComponent = ComponentName("test_package", "service_provider")
+        context.addMockService(serviceComponent, overviewProxy)
+        context.addMockServiceResolver(
+            TestableContext.MockServiceResolver {
+                if (it.action == ACTION_QUICKSTEP) serviceComponent else null
+            }
+        )
+        whenever(overviewProxy.queryLocalInterface(ArgumentMatchers.anyString()))
+            .thenReturn(overviewProxy)
+        whenever(overviewProxy.asBinder()).thenReturn(overviewProxy)
+
+        // packageManager.resolveServiceAsUser has to return non-null for
+        // OverviewProxyService#isEnabled to become true.
+        context.setMockPackageManager(packageManager)
+        whenever(packageManager.resolveServiceAsUser(any(), anyInt(), anyInt()))
+            .thenReturn(mock(ResolveInfo::class.java))
+
+        subject =
+            OverviewProxyService(
+                context,
+                executor,
+                commandQueue,
+                shellInterface,
+                Lazy { navBarController },
+                Lazy { Optional.of(centralSurfaces) },
+                navModeController,
+                statusBarWinController,
+                sysUiState,
+                userTracker,
+                screenLifecycle,
+                uiEventLogger,
+                displayTracker,
+                sysuiUnlockAnimationController,
+                assistUtils,
+                dumpManager,
+                unfoldTransitionProgressForwarder
+            )
+    }
+
+    @After
+    fun tearDown() {
+        subject.shutdownForTest()
+    }
+
+    @Test
+    fun `ScreenLifecycle - screenTurnedOn triggers SysUI state flag changes `() {
+        screenLifecycle.dispatchScreenTurnedOn()
+
+        verify(overviewProxy)
+            .onSystemUiStateChanged(
+                intThat { it and SYSUI_STATE_SCREEN_STATE_MASK == SCREEN_STATE_ON }
+            )
+    }
+
+    @Test
+    fun `ScreenLifecycle - screenTurningOn triggers SysUI state flag changes `() {
+        screenLifecycle.dispatchScreenTurningOn()
+
+        verify(overviewProxy)
+            .onSystemUiStateChanged(
+                intThat { it and SYSUI_STATE_SCREEN_STATE_MASK == SCREEN_STATE_TURNING_ON }
+            )
+    }
+
+    @Test
+    fun `ScreenLifecycle - screenTurnedOff triggers SysUI state flag changes `() {
+        screenLifecycle.dispatchScreenTurnedOff()
+
+        verify(overviewProxy)
+            .onSystemUiStateChanged(
+                intThat { it and SYSUI_STATE_SCREEN_STATE_MASK == SCREEN_STATE_OFF }
+            )
+    }
+
+    @Test
+    fun `ScreenLifecycle - screenTurningOff triggers SysUI state flag changes `() {
+        screenLifecycle.dispatchScreenTurningOff()
+
+        verify(overviewProxy)
+            .onSystemUiStateChanged(
+                intThat { it and SYSUI_STATE_SCREEN_STATE_MASK == SCREEN_STATE_TURNING_OFF }
+            )
+    }
+}
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 515e1ee..3c08d58 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
@@ -18,14 +18,14 @@
 
 import static android.app.Activity.RESULT_OK;
 
-import static com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_FOR_NOTE_ACCEPTED;
-import static com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_FOR_NOTE_CANCELLED;
+import static com.android.systemui.screenshot.appclips.AppClipsEvent.SCREENSHOT_FOR_NOTE_ACCEPTED;
+import static com.android.systemui.screenshot.appclips.AppClipsEvent.SCREENSHOT_FOR_NOTE_CANCELLED;
 
 import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -34,36 +34,35 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.ApplicationInfoFlags;
 import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.ResultReceiver;
+import android.os.UserHandle;
 import android.testing.AndroidTestingRunner;
 import android.widget.ImageView;
 
-import androidx.lifecycle.MutableLiveData;
 import androidx.test.rule.ActivityTestRule;
 import androidx.test.runner.intercepting.SingleActivityFactory;
 
 import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.screenshot.AppClipsActivity;
-import com.android.systemui.screenshot.AppClipsTrampolineActivity;
-import com.android.systemui.screenshot.AppClipsViewModel;
+import com.android.systemui.screenshot.ImageExporter;
 import com.android.systemui.settings.UserTracker;
 
+import com.google.common.util.concurrent.Futures;
+
 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;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.UUID;
+import java.util.concurrent.Executor;
 import java.util.function.BiConsumer;
 
 @RunWith(AndroidTestingRunner.class)
@@ -78,18 +77,16 @@
     private static final String TEST_CALLING_PACKAGE = "test-calling-package";
 
     @Mock
-    private AppClipsViewModel.Factory mViewModelFactory;
+    private AppClipsCrossProcessHelper mAppClipsCrossProcessHelper;
+    @Mock
+    private ImageExporter mImageExporter;
     @Mock
     private PackageManager mPackageManager;
     @Mock
     private UserTracker mUserTracker;
     @Mock
     private UiEventLogger mUiEventLogger;
-    @Mock
-    private AppClipsViewModel mViewModel;
 
-    private MutableLiveData<Bitmap> mScreenshotLiveData;
-    private MutableLiveData<Uri> mResultLiveData;
     private AppClipsActivity mActivity;
 
     // Using the deprecated ActivityTestRule and SingleActivityFactory to help with injecting mocks.
@@ -97,8 +94,11 @@
             new SingleActivityFactory<>(AppClipsActivityTestable.class) {
                 @Override
                 protected AppClipsActivityTestable create(Intent unUsed) {
-                    return new AppClipsActivityTestable(mViewModelFactory, mPackageManager,
-                            mUserTracker, mUiEventLogger);
+                    return new AppClipsActivityTestable(
+                            new AppClipsViewModel.Factory(mAppClipsCrossProcessHelper,
+                                    mImageExporter, getContext().getMainExecutor(),
+                                    directExecutor()), mPackageManager, mUserTracker,
+                            mUiEventLogger);
                 }
             };
 
@@ -110,29 +110,17 @@
     public void setUp() throws PackageManager.NameNotFoundException {
         MockitoAnnotations.initMocks(this);
 
-        mScreenshotLiveData = new MutableLiveData<>();
-        mResultLiveData = new MutableLiveData<>();
-        MutableLiveData<Integer> errorLiveData = new MutableLiveData<>();
-
-        when(mViewModelFactory.create(any(Class.class))).thenReturn(mViewModel);
-        when(mViewModel.getScreenshot()).thenReturn(mScreenshotLiveData);
-        when(mViewModel.getResultLiveData()).thenReturn(mResultLiveData);
-        when(mViewModel.getErrorLiveData()).thenReturn(errorLiveData);
         when(mUserTracker.getUserId()).thenReturn(TEST_USER_ID);
-
         ApplicationInfo applicationInfo = new ApplicationInfo();
         applicationInfo.uid = TEST_UID;
         when(mPackageManager.getApplicationInfoAsUser(eq(TEST_CALLING_PACKAGE),
                 any(ApplicationInfoFlags.class), eq(TEST_USER_ID))).thenReturn(applicationInfo);
 
-        doAnswer(invocation -> {
-            runOnMainThread(() -> mScreenshotLiveData.setValue(TEST_BITMAP));
-            return null;
-        }).when(mViewModel).performScreenshot();
-        doAnswer(invocation -> {
-            runOnMainThread(() -> mResultLiveData.setValue(TEST_URI));
-            return null;
-        }).when(mViewModel).saveScreenshotThenFinish(any(Drawable.class), any(Rect.class));
+        when(mAppClipsCrossProcessHelper.takeScreenshot()).thenReturn(TEST_BITMAP);
+        ImageExporter.Result result = new ImageExporter.Result();
+        result.uri = TEST_URI;
+        when(mImageExporter.export(any(Executor.class), any(UUID.class), any(Bitmap.class),
+                any(UserHandle.class))).thenReturn(Futures.immediateFuture(result));
     }
 
     @After
@@ -140,7 +128,6 @@
         mActivityRule.finishActivity();
     }
 
-    @Ignore("b/269403503")
     @Test
     public void appClipsLaunched_screenshotDisplayed() {
         launchActivity();
@@ -148,7 +135,6 @@
         assertThat(((ImageView) mActivity.findViewById(R.id.preview)).getDrawable()).isNotNull();
     }
 
-    @Ignore("b/269403503")
     @Test
     public void screenshotDisplayed_userConsented_screenshotExportedSuccessfully() {
         ResultReceiver resultReceiver = createResultReceiver((resultCode, data) -> {
@@ -168,7 +154,6 @@
         verify(mUiEventLogger).log(SCREENSHOT_FOR_NOTE_ACCEPTED, TEST_UID, TEST_CALLING_PACKAGE);
     }
 
-    @Ignore("b/269403503")
     @Test
     public void screenshotDisplayed_userDeclined() {
         ResultReceiver resultReceiver = createResultReceiver((resultCode, data) -> {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivityTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivityTest.java
index e40c49b..ad06dcc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivityTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivityTest.java
@@ -25,7 +25,8 @@
 import static android.content.Intent.EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE;
 
 import static com.android.systemui.flags.Flags.SCREENSHOT_APP_CLIPS;
-import static com.android.systemui.screenshot.AppClipsTrampolineActivity.EXTRA_SCREENSHOT_URI;
+import static com.android.systemui.screenshot.appclips.AppClipsEvent.SCREENSHOT_FOR_NOTE_TRIGGERED;
+import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.EXTRA_SCREENSHOT_URI;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -59,8 +60,6 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.notetask.NoteTaskController;
-import com.android.systemui.screenshot.AppClipsTrampolineActivity;
-import com.android.systemui.screenshot.ScreenshotEvent;
 import com.android.systemui.settings.UserTracker;
 import com.android.wm.shell.bubbles.Bubbles;
 
@@ -262,8 +261,7 @@
         mActivityRule.launchActivity(mActivityIntent);
         waitForIdleSync();
 
-        verify(mUiEventLogger).log(ScreenshotEvent.SCREENSHOT_FOR_NOTE_TRIGGERED, TEST_UID,
-                TEST_CALLING_PACKAGE);
+        verify(mUiEventLogger).log(SCREENSHOT_FOR_NOTE_TRIGGERED, TEST_UID, TEST_CALLING_PACKAGE);
     }
 
     private void mockToSatisfyAllPrerequisites() throws NameNotFoundException {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsViewModelTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsViewModelTest.java
index d5af7ce1..e7c3c05 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsViewModelTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsViewModelTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.screenshot;
+package com.android.systemui.screenshot.appclips;
 
 import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_FAILED;
 
@@ -36,7 +36,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.screenshot.appclips.AppClipsCrossProcessHelper;
+import com.android.systemui.screenshot.ImageExporter;
 
 import com.google.common.util.concurrent.Futures;
 
@@ -46,7 +46,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.time.ZonedDateTime;
 import java.util.UUID;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
@@ -62,7 +61,7 @@
     @Mock private AppClipsCrossProcessHelper mAppClipsCrossProcessHelper;
     @Mock private ImageExporter mImageExporter;
 
-    private com.android.systemui.screenshot.AppClipsViewModel mViewModel;
+    private AppClipsViewModel mViewModel;
 
     @Before
     public void setUp() {
@@ -99,8 +98,8 @@
 
     @Test
     public void saveScreenshot_throwsError_shouldUpdateErrorWithFailed() {
-        when(mImageExporter.export(any(Executor.class), any(UUID.class), eq(null), any(
-                ZonedDateTime.class), any(UserHandle.class))).thenReturn(
+        when(mImageExporter.export(any(Executor.class), any(UUID.class), eq(null),
+                any(UserHandle.class))).thenReturn(
                 Futures.immediateFailedFuture(new ExecutionException(new Throwable())));
 
         mViewModel.saveScreenshotThenFinish(FAKE_DRAWABLE, FAKE_RECT);
@@ -113,9 +112,9 @@
 
     @Test
     public void saveScreenshot_failsSilently_shouldUpdateErrorWithFailed() {
-        when(mImageExporter.export(any(Executor.class), any(UUID.class), eq(null), any(
-                ZonedDateTime.class), any(UserHandle.class))).thenReturn(
-                Futures.immediateFuture(new ImageExporter.Result()));
+        when(mImageExporter.export(any(Executor.class), any(UUID.class), eq(null),
+                any(UserHandle.class))).thenReturn(
+                        Futures.immediateFuture(new ImageExporter.Result()));
 
         mViewModel.saveScreenshotThenFinish(FAKE_DRAWABLE, FAKE_RECT);
         waitForIdleSync();
@@ -129,9 +128,8 @@
     public void saveScreenshot_succeeds_shouldUpdateResultWithUri() {
         ImageExporter.Result result = new ImageExporter.Result();
         result.uri = FAKE_URI;
-        when(mImageExporter.export(any(Executor.class), any(UUID.class), eq(null), any(
-                ZonedDateTime.class), any(UserHandle.class))).thenReturn(
-                Futures.immediateFuture(result));
+        when(mImageExporter.export(any(Executor.class), any(UUID.class), eq(null),
+                any(UserHandle.class))).thenReturn(Futures.immediateFuture(result));
 
         mViewModel.saveScreenshotThenFinish(FAKE_DRAWABLE, FAKE_RECT);
         waitForIdleSync();
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 52b0b6a..99cf8d0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -22,8 +22,6 @@
 
 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.anyInt;
@@ -35,6 +33,8 @@
 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;
@@ -536,12 +536,10 @@
                 mQsController,
                 mFragmentService,
                 mContentResolver,
-                mRecordingController,
                 mShadeHeaderController,
                 mScreenOffAnimationController,
                 mLockscreenGestureLogger,
                 mShadeExpansionStateManager,
-                mNotificationRemoteInputManager,
                 mSysUIUnfoldComponent,
                 mSysUiState,
                 () -> mKeyguardBottomAreaViewController,
@@ -551,6 +549,7 @@
                 mNotificationStackSizeCalculator,
                 mUnlockedScreenOffAnimationController,
                 mShadeTransitionController,
+                mInteractionJankMonitor,
                 systemClock,
                 mKeyguardBottomAreaViewModel,
                 mKeyguardBottomAreaInteractor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
index abcde3d..9a2e415 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -37,6 +37,7 @@
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -78,6 +79,25 @@
         DejankUtils.setImmediate(true);
     }
 
+    /**
+     * When the Back gesture starts (progress 0%), the scrim will stay at 100% scale (1.0f).
+     */
+    @Test
+    public void testBackGesture_min_scrimAtMaxScale() {
+        mNotificationPanelViewController.onBackProgressed(0.0f);
+        verify(mScrimController).applyBackScaling(1.0f);
+    }
+
+    /**
+     * When the Back gesture is at max (progress 100%), the scrim will be scaled to its minimum.
+     */
+    @Test
+    public void testBackGesture_max_scrimAtMinScale() {
+        mNotificationPanelViewController.onBackProgressed(1.0f);
+        verify(mScrimController).applyBackScaling(
+                NotificationPanelViewController.SHADE_BACK_ANIM_MIN_SCALE);
+    }
+
     @Test
     public void onNotificationHeightChangeWhileOnKeyguardWillComputeMaxKeyguardNotifications() {
         mStatusBarStateController.setState(KEYGUARD);
@@ -921,6 +941,38 @@
 
     }
 
+    @Test
+    public void onSplitShadeChanged_duringShadeExpansion_resetsOverScrollState() {
+        // There was a bug where there was left-over overscroll state after going from split shade
+        // to single shade.
+        // Since on single shade we don't set overscroll values on QS nor Scrim, those values that
+        // were there from split shade were never reset.
+        // To prevent this, we will reset all overscroll state.
+        enableSplitShade(true);
+        reset(mQsController, mScrimController, mNotificationStackScrollLayoutController);
+
+        mNotificationPanelViewController.setOverExpansion(123);
+        verify(mQsController).setOverScrollAmount(123);
+        verify(mScrimController).setNotificationsOverScrollAmount(123);
+        verify(mNotificationStackScrollLayoutController).setOverExpansion(123);
+
+        enableSplitShade(false);
+        verify(mQsController).setOverScrollAmount(0);
+        verify(mScrimController).setNotificationsOverScrollAmount(0);
+        verify(mNotificationStackScrollLayoutController).setOverExpansion(0);
+    }
+
+    @Test
+    public void onSplitShadeChanged_alwaysResetsOverScrollState() {
+        enableSplitShade(true);
+        enableSplitShade(false);
+
+        verify(mQsController, times(2)).setOverScrollAmount(0);
+        verify(mScrimController, times(2)).setNotificationsOverScrollAmount(0);
+        verify(mNotificationStackScrollLayoutController, times(2)).setOverExpansion(0);
+        verify(mNotificationStackScrollLayoutController, times(2)).setOverScrollAmount(0);
+    }
+
     /**
      * When shade is flinging to close and this fling is not intercepted,
      * {@link AmbientState#setIsClosing(boolean)} should be called before
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
index 0a401b0..51492eb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -26,6 +26,7 @@
 import com.android.keyguard.dagger.KeyguardBouncerComponent
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor
 import com.android.systemui.classifier.FalsingCollectorFake
 import com.android.systemui.dock.DockManager
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController
@@ -33,6 +34,7 @@
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.TransitionStep
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
+import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel
 import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler
 import com.android.systemui.statusbar.LockscreenShadeTransitionController
 import com.android.systemui.statusbar.NotificationInsetsController
@@ -65,48 +67,33 @@
 @RunWith(AndroidTestingRunner::class)
 @RunWithLooper(setAsMainLooper = true)
 class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
-    @Mock
-    private lateinit var view: NotificationShadeWindowView
-    @Mock
-    private lateinit var sysuiStatusBarStateController: SysuiStatusBarStateController
-    @Mock
-    private lateinit var centralSurfaces: CentralSurfaces
-    @Mock
-    private lateinit var dockManager: DockManager
-    @Mock
-    private lateinit var notificationPanelViewController: NotificationPanelViewController
-    @Mock
-    private lateinit var notificationShadeDepthController: NotificationShadeDepthController
-    @Mock
-    private lateinit var notificationShadeWindowController: NotificationShadeWindowController
-    @Mock
-    private lateinit var keyguardUnlockAnimationController: KeyguardUnlockAnimationController
-    @Mock
-    private lateinit var ambientState: AmbientState
-    @Mock
-    private lateinit var keyguardBouncerViewModel: KeyguardBouncerViewModel
-    @Mock
-    private lateinit var stackScrollLayoutController: NotificationStackScrollLayoutController
-    @Mock
-    private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
-    @Mock
-    private lateinit var statusBarWindowStateController: StatusBarWindowStateController
+    @Mock private lateinit var view: NotificationShadeWindowView
+    @Mock private lateinit var sysuiStatusBarStateController: SysuiStatusBarStateController
+    @Mock private lateinit var centralSurfaces: CentralSurfaces
+    @Mock private lateinit var dockManager: DockManager
+    @Mock private lateinit var notificationPanelViewController: NotificationPanelViewController
+    @Mock private lateinit var notificationShadeDepthController: NotificationShadeDepthController
+    @Mock private lateinit var notificationShadeWindowController: NotificationShadeWindowController
+    @Mock private lateinit var keyguardUnlockAnimationController: KeyguardUnlockAnimationController
+    @Mock private lateinit var ambientState: AmbientState
+    @Mock private lateinit var keyguardBouncerViewModel: KeyguardBouncerViewModel
+    @Mock private lateinit var stackScrollLayoutController: NotificationStackScrollLayoutController
+    @Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
+    @Mock private lateinit var statusBarWindowStateController: StatusBarWindowStateController
     @Mock
     private lateinit var lockscreenShadeTransitionController: LockscreenShadeTransitionController
-    @Mock
-    private lateinit var lockIconViewController: LockIconViewController
-    @Mock
-    private lateinit var phoneStatusBarViewController: PhoneStatusBarViewController
-    @Mock
-    private lateinit var pulsingGestureListener: PulsingGestureListener
-    @Mock
-    private lateinit var notificationInsetsController: NotificationInsetsController
-    @Mock
-    private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
+    @Mock private lateinit var lockIconViewController: LockIconViewController
+    @Mock private lateinit var phoneStatusBarViewController: PhoneStatusBarViewController
+    @Mock private lateinit var pulsingGestureListener: PulsingGestureListener
+    @Mock private lateinit var notificationInsetsController: NotificationInsetsController
+    @Mock private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
+    @Mock private lateinit var udfpsOverlayInteractor: UdfpsOverlayInteractor
     @Mock lateinit var keyguardBouncerComponentFactory: KeyguardBouncerComponent.Factory
     @Mock lateinit var keyguardBouncerComponent: KeyguardBouncerComponent
     @Mock lateinit var keyguardSecurityContainerController: KeyguardSecurityContainerController
     @Mock lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
+    @Mock
+    lateinit var primaryBouncerToGoneTransitionViewModel: PrimaryBouncerToGoneTransitionViewModel
 
     private lateinit var interactionEventHandlerCaptor: ArgumentCaptor<InteractionEventHandler>
     private lateinit var interactionEventHandler: InteractionEventHandler
@@ -118,43 +105,45 @@
         MockitoAnnotations.initMocks(this)
         whenever(view.bottom).thenReturn(VIEW_BOTTOM)
         whenever(view.findViewById<ViewGroup>(R.id.keyguard_bouncer_container))
-                .thenReturn(mock(ViewGroup::class.java))
+            .thenReturn(mock(ViewGroup::class.java))
         whenever(keyguardBouncerComponentFactory.create(any(ViewGroup::class.java)))
-                .thenReturn(keyguardBouncerComponent)
+            .thenReturn(keyguardBouncerComponent)
         whenever(keyguardBouncerComponent.securityContainerController)
-                .thenReturn(keyguardSecurityContainerController)
+            .thenReturn(keyguardSecurityContainerController)
         whenever(keyguardTransitionInteractor.lockscreenToDreamingTransition)
-                .thenReturn(emptyFlow<TransitionStep>())
-        underTest = NotificationShadeWindowViewController(
-            lockscreenShadeTransitionController,
-            FalsingCollectorFake(),
-            sysuiStatusBarStateController,
-            dockManager,
-            notificationShadeDepthController,
-            view,
-            notificationPanelViewController,
-            ShadeExpansionStateManager(),
-            stackScrollLayoutController,
-            statusBarKeyguardViewManager,
-            statusBarWindowStateController,
-            lockIconViewController,
-            centralSurfaces,
-            notificationShadeWindowController,
-            keyguardUnlockAnimationController,
-            notificationInsetsController,
-            ambientState,
-            pulsingGestureListener,
-            keyguardBouncerViewModel,
-            keyguardBouncerComponentFactory,
-            alternateBouncerInteractor,
-            keyguardTransitionInteractor,
-        )
+            .thenReturn(emptyFlow<TransitionStep>())
+        underTest =
+            NotificationShadeWindowViewController(
+                lockscreenShadeTransitionController,
+                FalsingCollectorFake(),
+                sysuiStatusBarStateController,
+                dockManager,
+                notificationShadeDepthController,
+                view,
+                notificationPanelViewController,
+                ShadeExpansionStateManager(),
+                stackScrollLayoutController,
+                statusBarKeyguardViewManager,
+                statusBarWindowStateController,
+                lockIconViewController,
+                centralSurfaces,
+                notificationShadeWindowController,
+                keyguardUnlockAnimationController,
+                notificationInsetsController,
+                ambientState,
+                pulsingGestureListener,
+                keyguardBouncerViewModel,
+                keyguardBouncerComponentFactory,
+                alternateBouncerInteractor,
+                udfpsOverlayInteractor,
+                keyguardTransitionInteractor,
+                primaryBouncerToGoneTransitionViewModel,
+            )
         underTest.setupExpandedStatusBar()
 
-        interactionEventHandlerCaptor =
-            ArgumentCaptor.forClass(InteractionEventHandler::class.java)
+        interactionEventHandlerCaptor = ArgumentCaptor.forClass(InteractionEventHandler::class.java)
         verify(view).setInteractionEventHandler(interactionEventHandlerCaptor.capture())
-            interactionEventHandler = interactionEventHandlerCaptor.value
+        interactionEventHandler = interactionEventHandlerCaptor.value
     }
 
     // Note: So far, these tests only cover interactions with the status bar view controller. More
@@ -184,14 +173,11 @@
     @Test
     fun handleDispatchTouchEvent_downTouchBelowViewThenAnotherTouch_sendsTouchToSb() {
         underTest.setStatusBarViewController(phoneStatusBarViewController)
-        val downEvBelow = MotionEvent.obtain(
-            0L, 0L, MotionEvent.ACTION_DOWN, 0f, VIEW_BOTTOM + 4f, 0
-        )
+        val downEvBelow =
+            MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, VIEW_BOTTOM + 4f, 0)
         interactionEventHandler.handleDispatchTouchEvent(downEvBelow)
 
-        val nextEvent = MotionEvent.obtain(
-            0L, 0L, MotionEvent.ACTION_MOVE, 0f, VIEW_BOTTOM + 5f, 0
-        )
+        val nextEvent = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, VIEW_BOTTOM + 5f, 0)
         whenever(phoneStatusBarViewController.sendTouchToView(nextEvent)).thenReturn(true)
 
         val returnVal = interactionEventHandler.handleDispatchTouchEvent(nextEvent)
@@ -282,6 +268,17 @@
     }
 
     @Test
+    fun shouldInterceptTouchEvent_downEventAlternateBouncer_ignoreIfInUdfpsOverlay() {
+        // Down event within udfpsOverlay bounds while alternateBouncer is showing
+        whenever(udfpsOverlayInteractor.canInterceptTouchInUdfpsBounds(downEv)).thenReturn(false)
+        whenever(alternateBouncerInteractor.isVisibleState()).thenReturn(true)
+
+        // Then touch should not be intercepted
+        val shouldIntercept = interactionEventHandler.shouldInterceptTouchEvent(downEv)
+        assertThat(shouldIntercept).isFalse()
+    }
+
+    @Test
     fun testGetBouncerContainer() {
         Mockito.clearInvocations(view)
         underTest.bouncerContainer
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
index 5d71979..2f528a8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
@@ -40,12 +40,14 @@
 import com.android.keyguard.dagger.KeyguardBouncerComponent;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor;
 import com.android.systemui.classifier.FalsingCollectorFake;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
 import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
 import com.android.systemui.statusbar.DragDownHelper;
 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
 import com.android.systemui.statusbar.NotificationInsetsController;
@@ -100,7 +102,9 @@
     @Mock private KeyguardSecurityContainerController mKeyguardSecurityContainerController;
     @Mock private NotificationInsetsController mNotificationInsetsController;
     @Mock private AlternateBouncerInteractor mAlternateBouncerInteractor;
+    @Mock private UdfpsOverlayInteractor mUdfpsOverlayInteractor;
     @Mock private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
+    @Mock private PrimaryBouncerToGoneTransitionViewModel mPrimaryBouncerToGoneTransitionViewModel;
 
     @Captor private ArgumentCaptor<NotificationShadeWindowView.InteractionEventHandler>
             mInteractionEventHandlerCaptor;
@@ -150,7 +154,9 @@
                 mKeyguardBouncerViewModel,
                 mKeyguardBouncerComponentFactory,
                 mAlternateBouncerInteractor,
-                mKeyguardTransitionInteractor
+                mUdfpsOverlayInteractor,
+                mKeyguardTransitionInteractor,
+                mPrimaryBouncerToGoneTransitionViewModel
         );
         mController.setupExpandedStatusBar();
         mController.setDragDownHelper(mDragDownHelper);
@@ -174,6 +180,7 @@
         // WHEN showing alt auth, not dozing, drag down helper doesn't want to intercept
         when(mStatusBarStateController.isDozing()).thenReturn(false);
         when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
+        when(mUdfpsOverlayInteractor.canInterceptTouchInUdfpsBounds(any())).thenReturn(true);
         when(mDragDownHelper.onInterceptTouchEvent(any())).thenReturn(false);
 
         // THEN we should intercept touch
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java
index e3a3678..15b8423 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java
@@ -32,6 +32,7 @@
 import static org.mockito.ArgumentMatchers.anyFloat;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
@@ -77,7 +78,6 @@
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.notification.stack.AmbientState;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
 import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
@@ -91,9 +91,12 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.List;
+
 import dagger.Lazy;
 
 @SmallTest
@@ -101,12 +104,14 @@
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
 public class QuickSettingsControllerTest extends SysuiTestCase {
 
-    private static final int SPLIT_SHADE_FULL_TRANSITION_DISTANCE = 400;
     private static final float QS_FRAME_START_X = 0f;
     private static final int QS_FRAME_WIDTH = 1000;
     private static final int QS_FRAME_TOP = 0;
     private static final int QS_FRAME_BOTTOM = 1000;
-
+    private static final int DEFAULT_HEIGHT = 1000;
+    // In split shade min = max
+    private static final int DEFAULT_MIN_HEIGHT_SPLIT_SHADE = DEFAULT_HEIGHT;
+    private static final int DEFAULT_MIN_HEIGHT = 300;
 
     private QuickSettingsController mQsController;
 
@@ -115,7 +120,6 @@
     @Mock private KeyguardStatusBarView mKeyguardStatusBar;
     @Mock private QS mQs;
     @Mock private QSFragment mQSFragment;
-
     @Mock private Lazy<NotificationPanelViewController> mPanelViewControllerLazy;
     @Mock private NotificationPanelViewController mNotificationPanelViewController;
     @Mock private NotificationPanelView mPanelView;
@@ -147,10 +151,7 @@
     @Mock private FeatureFlags mFeatureFlags;
     @Mock private InteractionJankMonitor mInteractionJankMonitor;
     @Mock private ShadeLogger mShadeLogger;
-
     @Mock private DumpManager mDumpManager;
-
-    @Mock private HeadsUpManagerPhone mHeadsUpManager;
     @Mock private UiEventLogger mUiEventLogger;
 
     private SysuiStatusBarStateController mStatusBarStateController;
@@ -173,6 +174,8 @@
         KeyguardStatusView keyguardStatusView = new KeyguardStatusView(mContext);
         keyguardStatusView.setId(R.id.keyguard_status_view);
 
+        when(mResources.getDimensionPixelSize(
+                R.dimen.lockscreen_shade_qs_transition_distance)).thenReturn(DEFAULT_HEIGHT);
         when(mPanelView.getResources()).thenReturn(mResources);
         when(mPanelView.getContext()).thenReturn(getContext());
         when(mPanelView.findViewById(R.id.keyguard_header)).thenReturn(mKeyguardStatusBar);
@@ -529,6 +532,88 @@
         assertThat(mQsController.isOpenQsEvent(event)).isTrue();
     }
 
+    @Test
+    public void shadeClosed_onLockscreen_inSplitShade_setsQsNotVisible() {
+        mQsController.setQs(mQs);
+        enableSplitShade(true);
+        lockScreen();
+
+        closeLockedQS();
+
+        assertQsVisible(false);
+    }
+
+    @Test
+    public void shadeOpened_onLockscreen_inSplitShade_setsQsVisible() {
+        mQsController.setQs(mQs);
+        enableSplitShade(true);
+        lockScreen();
+
+        openLockedQS();
+
+        assertQsVisible(true);
+    }
+
+    @Test
+    public void shadeClosed_onLockscreen_inSingleShade_setsQsNotVisible() {
+        mQsController.setQs(mQs);
+        enableSplitShade(false);
+        lockScreen();
+
+        closeLockedQS();
+
+        verify(mQs).setQsVisible(false);
+    }
+
+    @Test
+    public void shadeOpened_onLockscreen_inSingleShade_setsQsVisible() {
+        mQsController.setQs(mQs);
+        enableSplitShade(false);
+        lockScreen();
+
+        openLockedQS();
+
+        verify(mQs).setQsVisible(true);
+    }
+
+    private void lockScreen() {
+        mQsController.setBarState(KEYGUARD);
+    }
+
+    private void openLockedQS() {
+        when(mLockscreenShadeTransitionController.getQSDragProgress())
+                .thenReturn((float) DEFAULT_HEIGHT);
+        mLockscreenShadeTransitionCallback.setTransitionToFullShadeAmount(
+                /* pxAmount= */ DEFAULT_HEIGHT,
+                /* animate=*/ false,
+                /* delay= */ 0
+        );
+    }
+
+    private void closeLockedQS() {
+        when(mLockscreenShadeTransitionController.getQSDragProgress()).thenReturn(0f);
+        mLockscreenShadeTransitionCallback.setTransitionToFullShadeAmount(
+                /* pxAmount= */ 0,
+                /* animate=*/ false,
+                /* delay= */ 0
+        );
+    }
+
+    private void setSplitShadeHeightProperties() {
+        // In split shade, min = max
+        when(mQs.getQsMinExpansionHeight()).thenReturn(DEFAULT_MIN_HEIGHT_SPLIT_SHADE);
+        when(mQs.getDesiredHeight()).thenReturn(DEFAULT_HEIGHT);
+        mQsController.updateMinHeight();
+        mQsController.onHeightChanged();
+    }
+
+    private void setDefaultHeightProperties() {
+        when(mQs.getQsMinExpansionHeight()).thenReturn(DEFAULT_MIN_HEIGHT);
+        when(mQs.getDesiredHeight()).thenReturn(DEFAULT_HEIGHT);
+        mQsController.updateMinHeight();
+        mQsController.onHeightChanged();
+    }
+
     private static MotionEvent createMotionEvent(int x, int y, int action) {
         return MotionEvent.obtain(0, 0, action, x, y, 0);
     }
@@ -549,6 +634,11 @@
     private void enableSplitShade(boolean enabled) {
         when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(enabled);
         mQsController.updateResources();
+        if (enabled) {
+            setSplitShadeHeightProperties();
+        } else {
+            setDefaultHeightProperties();
+        }
     }
 
     private void setIsFullWidth(boolean fullWidth) {
@@ -561,5 +651,11 @@
         mQsController.handleShadeLayoutChanged(oldMaxHeight);
     }
 
-
+    private void assertQsVisible(boolean visible) {
+        ArgumentCaptor<Boolean> visibilityCaptor = ArgumentCaptor.forClass(Boolean.class);
+        verify(mQs, atLeastOnce()).setQsVisible(visibilityCaptor.capture());
+        List<Boolean> allVisibilities = visibilityCaptor.getAllValues();
+        boolean lastVisibility = allVisibilities.get(allVisibilities.size() - 1);
+        assertThat(lastVisibility).isEqualTo(visible);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/LargeScreenShadeInterpolatorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/LargeScreenShadeInterpolatorImplTest.kt
new file mode 100644
index 0000000..8309342
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/LargeScreenShadeInterpolatorImplTest.kt
@@ -0,0 +1,144 @@
+package com.android.systemui.shade.transition
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.policy.FakeConfigurationController
+import com.google.common.truth.Expect
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class LargeScreenShadeInterpolatorImplTest : SysuiTestCase() {
+    @get:Rule val expect: Expect = Expect.create()
+
+    private val portraitShadeInterpolator = LargeScreenPortraitShadeInterpolator()
+    private val splitShadeInterpolator = SplitShadeInterpolator()
+    private val configurationController = FakeConfigurationController()
+    private val impl =
+        LargeScreenShadeInterpolatorImpl(
+            configurationController,
+            context,
+            splitShadeInterpolator,
+            portraitShadeInterpolator
+        )
+
+    @Test
+    fun getBehindScrimAlpha_inSplitShade_usesSplitShadeValue() {
+        setSplitShadeEnabled(true)
+
+        assertInterpolation(
+            actual = { fraction -> impl.getBehindScrimAlpha(fraction) },
+            expected = { fraction -> splitShadeInterpolator.getBehindScrimAlpha(fraction) }
+        )
+    }
+
+    @Test
+    fun getBehindScrimAlpha_inPortraitShade_usesPortraitShadeValue() {
+        setSplitShadeEnabled(false)
+
+        assertInterpolation(
+            actual = { fraction -> impl.getBehindScrimAlpha(fraction) },
+            expected = { fraction -> portraitShadeInterpolator.getBehindScrimAlpha(fraction) }
+        )
+    }
+
+    @Test
+    fun getNotificationScrimAlpha_inSplitShade_usesSplitShadeValue() {
+        setSplitShadeEnabled(true)
+
+        assertInterpolation(
+            actual = { fraction -> impl.getNotificationScrimAlpha(fraction) },
+            expected = { fraction -> splitShadeInterpolator.getNotificationScrimAlpha(fraction) }
+        )
+    }
+    @Test
+    fun getNotificationScrimAlpha_inPortraitShade_usesPortraitShadeValue() {
+        setSplitShadeEnabled(false)
+
+        assertInterpolation(
+            actual = { fraction -> impl.getNotificationScrimAlpha(fraction) },
+            expected = { fraction -> portraitShadeInterpolator.getNotificationScrimAlpha(fraction) }
+        )
+    }
+
+    @Test
+    fun getNotificationContentAlpha_inSplitShade_usesSplitShadeValue() {
+        setSplitShadeEnabled(true)
+
+        assertInterpolation(
+            actual = { fraction -> impl.getNotificationContentAlpha(fraction) },
+            expected = { fraction -> splitShadeInterpolator.getNotificationContentAlpha(fraction) }
+        )
+    }
+
+    @Test
+    fun getNotificationContentAlpha_inPortraitShade_usesPortraitShadeValue() {
+        setSplitShadeEnabled(false)
+
+        assertInterpolation(
+            actual = { fraction -> impl.getNotificationContentAlpha(fraction) },
+            expected = { fraction ->
+                portraitShadeInterpolator.getNotificationContentAlpha(fraction)
+            }
+        )
+    }
+
+    @Test
+    fun getNotificationFooterAlpha_inSplitShade_usesSplitShadeValue() {
+        setSplitShadeEnabled(true)
+
+        assertInterpolation(
+            actual = { fraction -> impl.getNotificationFooterAlpha(fraction) },
+            expected = { fraction -> splitShadeInterpolator.getNotificationFooterAlpha(fraction) }
+        )
+    }
+    @Test
+    fun getNotificationFooterAlpha_inPortraitShade_usesPortraitShadeValue() {
+        setSplitShadeEnabled(false)
+
+        assertInterpolation(
+            actual = { fraction -> impl.getNotificationFooterAlpha(fraction) },
+            expected = { fraction ->
+                portraitShadeInterpolator.getNotificationFooterAlpha(fraction)
+            }
+        )
+    }
+
+    @Test
+    fun getQsAlpha_inSplitShade_usesSplitShadeValue() {
+        setSplitShadeEnabled(true)
+
+        assertInterpolation(
+            actual = { fraction -> impl.getQsAlpha(fraction) },
+            expected = { fraction -> splitShadeInterpolator.getQsAlpha(fraction) }
+        )
+    }
+    @Test
+    fun getQsAlpha_inPortraitShade_usesPortraitShadeValue() {
+        setSplitShadeEnabled(false)
+
+        assertInterpolation(
+            actual = { fraction -> impl.getQsAlpha(fraction) },
+            expected = { fraction -> portraitShadeInterpolator.getQsAlpha(fraction) }
+        )
+    }
+
+    private fun setSplitShadeEnabled(enabled: Boolean) {
+        overrideResource(R.bool.config_use_split_notification_shade, enabled)
+        configurationController.notifyConfigurationChanged()
+    }
+
+    private fun assertInterpolation(
+        actual: (fraction: Float) -> Float,
+        expected: (fraction: Float) -> Float
+    ) {
+        for (i in 0..10) {
+            val fraction = i / 10f
+            expect.that(actual(fraction)).isEqualTo(expected(fraction))
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/LinearLargeScreenShadeInterpolator.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/LinearLargeScreenShadeInterpolator.kt
new file mode 100644
index 0000000..d24bcdc
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/LinearLargeScreenShadeInterpolator.kt
@@ -0,0 +1,25 @@
+/*
+ * 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.shade.transition
+
+class LinearLargeScreenShadeInterpolator : LargeScreenShadeInterpolator {
+    override fun getBehindScrimAlpha(fraction: Float) = fraction
+    override fun getNotificationScrimAlpha(fraction: Float) = fraction
+    override fun getNotificationContentAlpha(fraction: Float) = fraction
+    override fun getNotificationFooterAlpha(fraction: Float) = fraction
+    override fun getQsAlpha(fraction: Float) = fraction
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt
index 84f8656..cbf5485 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt
@@ -5,6 +5,8 @@
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
 import com.android.systemui.shade.STATE_CLOSED
 import com.android.systemui.shade.STATE_OPEN
 import com.android.systemui.shade.STATE_OPENING
@@ -30,6 +32,7 @@
     @Mock private lateinit var dumpManager: DumpManager
     @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
     @Mock private lateinit var headsUpManager: HeadsUpManager
+    @Mock private lateinit var featureFlags: FeatureFlags
     private val configurationController = FakeConfigurationController()
 
     private lateinit var controller: ScrimShadeTransitionController
@@ -45,7 +48,8 @@
                 scrimController,
                 context.resources,
                 statusBarStateController,
-                headsUpManager)
+                headsUpManager,
+                featureFlags)
 
         controller.onPanelStateChanged(STATE_OPENING)
     }
@@ -107,6 +111,19 @@
     }
 
     @Test
+    fun onPanelExpansionChanged_inSplitShade_flagTrue_setsFractionEqualToEventFraction() {
+        whenever(featureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
+                .thenReturn(true)
+        whenever(statusBarStateController.currentOrUpcomingState)
+            .thenReturn(StatusBarState.SHADE)
+        setSplitShadeEnabled(true)
+
+        controller.onPanelExpansionChanged(EXPANSION_EVENT)
+
+        verify(scrimController).setRawPanelExpansionFraction(EXPANSION_EVENT.fraction)
+    }
+
+    @Test
     fun onPanelExpansionChanged_inSplitShade_onKeyguard_setsFractionEqualToEventFraction() {
         whenever(statusBarStateController.currentOrUpcomingState)
             .thenReturn(StatusBarState.KEYGUARD)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
index 7a74b12..56fc0c7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
@@ -36,21 +36,26 @@
 
     private val progressProvider = TestUnfoldTransitionProvider()
 
-    @Mock private lateinit var parent: ViewGroup
+    @Mock
+    private lateinit var parent: ViewGroup
+
+    @Mock
+    private lateinit var shouldBeAnimated: () -> Boolean
 
     private lateinit var animator: UnfoldConstantTranslateAnimator
 
-    private val viewsIdToRegister =
-        setOf(
-            ViewIdToTranslate(START_VIEW_ID, Direction.START),
-            ViewIdToTranslate(END_VIEW_ID, Direction.END))
+    private val viewsIdToRegister
+        get() =
+            setOf(
+                    ViewIdToTranslate(START_VIEW_ID, Direction.START, shouldBeAnimated),
+                    ViewIdToTranslate(END_VIEW_ID, Direction.END, shouldBeAnimated)
+            )
 
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
-
-        animator =
-            UnfoldConstantTranslateAnimator(viewsIdToRegister, progressProvider)
+        whenever(shouldBeAnimated.invoke()).thenReturn(true)
+        animator = UnfoldConstantTranslateAnimator(viewsIdToRegister, progressProvider)
 
         animator.init(parent, MAX_TRANSLATION)
     }
@@ -96,6 +101,20 @@
         moveAndValidate(listOf(leftView to START, rightView to END), View.LAYOUT_DIRECTION_LTR)
     }
 
+    @Test
+    fun onTransition_completeStartedTranslation() {
+        // GIVEN
+        val leftView = View(context)
+        whenever(parent.findViewById<View>(START_VIEW_ID)).thenReturn(leftView)
+        // To start animation, shouldBeAnimated should return true.
+        // There is a possibility for shouldBeAnimated to return false during the animation.
+        whenever(shouldBeAnimated.invoke()).thenReturn(true).thenReturn(false)
+
+        // shouldBeAnimated state may change during the animation.
+        // However, started animation should be completed.
+        moveAndValidate(listOf(leftView to START), View.LAYOUT_DIRECTION_LTR)
+    }
+
     private fun moveAndValidate(list: List<Pair<View, Int>>, layoutDirection: Int) {
         // Compare values as ints because -0f != 0f
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt
index cc45cf88..2eca78a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt
@@ -57,7 +57,18 @@
         clockView.measure(50, 50)
 
         verify(mockTextAnimator).glyphFilter = any()
-        verify(mockTextAnimator).setTextStyle(300, -1.0f, 200, false, 350L, null, 0L, null)
+        verify(mockTextAnimator)
+            .setTextStyle(
+                weight = 300,
+                textSize = -1.0f,
+                color = 200,
+                strokeWidth = -1F,
+                animate = false,
+                duration = 350L,
+                interpolator = null,
+                delay = 0L,
+                onAnimationEnd = null
+            )
         verifyNoMoreInteractions(mockTextAnimator)
     }
 
@@ -68,8 +79,30 @@
         clockView.animateAppearOnLockscreen()
 
         verify(mockTextAnimator, times(2)).glyphFilter = any()
-        verify(mockTextAnimator).setTextStyle(100, -1.0f, 200, false, 0L, null, 0L, null)
-        verify(mockTextAnimator).setTextStyle(300, -1.0f, 200, true, 350L, null, 0L, null)
+        verify(mockTextAnimator)
+            .setTextStyle(
+                weight = 100,
+                textSize = -1.0f,
+                color = 200,
+                strokeWidth = -1F,
+                animate = false,
+                duration = 0L,
+                interpolator = null,
+                delay = 0L,
+                onAnimationEnd = null
+            )
+        verify(mockTextAnimator)
+            .setTextStyle(
+                weight = 300,
+                textSize = -1.0f,
+                color = 200,
+                strokeWidth = -1F,
+                animate = true,
+                duration = 350L,
+                interpolator = null,
+                delay = 0L,
+                onAnimationEnd = null
+            )
         verifyNoMoreInteractions(mockTextAnimator)
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
index 26eff61..1fdb364 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
@@ -35,7 +35,6 @@
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.test.StandardTestDispatcher
 import kotlinx.coroutines.test.TestScope
-import org.json.JSONException
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
@@ -271,10 +270,14 @@
 
     @Test
     fun jsonDeserialization_gotExpectedObject() {
-        val expected = ClockSettings("ID", null).apply { _applied_timestamp = 500 }
+        val expected = ClockSettings("ID", null).apply {
+            metadata.put("appliedTimestamp", 500)
+        }
         val actual = ClockSettings.deserialize("""{
             "clockId":"ID",
-            "_applied_timestamp":500
+            "metadata": {
+                "appliedTimestamp":500
+            }
         }""")
         assertEquals(expected, actual)
     }
@@ -291,29 +294,32 @@
         val expected = ClockSettings("ID", null)
         val actual = ClockSettings.deserialize("""{
             "clockId":"ID",
-            "_applied_timestamp":null
+            "metadata":null
         }""")
         assertEquals(expected, actual)
     }
 
-    @Test(expected = JSONException::class)
-    fun jsonDeserialization_noId_threwException() {
-        val expected = ClockSettings(null, null).apply { _applied_timestamp = 500 }
-        val actual = ClockSettings.deserialize("{\"_applied_timestamp\":500}")
+    @Test
+    fun jsonDeserialization_noId_deserializedEmpty() {
+        val expected = ClockSettings(null, null).apply {
+            metadata.put("appliedTimestamp", 500)
+        }
+        val actual = ClockSettings.deserialize("{\"metadata\":{\"appliedTimestamp\":500}}")
         assertEquals(expected, actual)
     }
 
     @Test
     fun jsonSerialization_gotExpectedString() {
-        val expected = "{\"clockId\":\"ID\",\"_applied_timestamp\":500}"
-        val actual = ClockSettings.serialize(ClockSettings("ID", null)
-            .apply { _applied_timestamp = 500 })
+        val expected = "{\"clockId\":\"ID\",\"metadata\":{\"appliedTimestamp\":500}}"
+        val actual = ClockSettings.serialize(ClockSettings("ID", null).apply {
+            metadata.put("appliedTimestamp", 500)
+        })
         assertEquals(expected, actual)
     }
 
     @Test
     fun jsonSerialization_noTimestamp_gotExpectedString() {
-        val expected = "{\"clockId\":\"ID\"}"
+        val expected = "{\"clockId\":\"ID\",\"metadata\":{}}"
         val actual = ClockSettings.serialize(ClockSettings("ID", null))
         assertEquals(expected, actual)
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
index cd2efc0..7fa27f3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
@@ -26,6 +26,7 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.plugins.ClockSettings
 import com.android.systemui.shared.clocks.DefaultClockController.Companion.DOZE_COLOR
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.eq
@@ -40,7 +41,6 @@
 import org.junit.runner.RunWith
 import org.mockito.ArgumentMatchers.anyBoolean
 import org.mockito.ArgumentMatchers.anyFloat
-import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.ArgumentMatchers.notNull
 import org.mockito.Mock
 import org.mockito.Mockito.never
@@ -97,13 +97,14 @@
     @Test
     fun defaultClock_initialize() {
         val clock = provider.createClock(DEFAULT_CLOCK_ID)
-        verify(mockSmallClockView).setColors(Color.MAGENTA, Color.MAGENTA)
-        verify(mockLargeClockView).setColors(Color.MAGENTA, Color.MAGENTA)
+        verify(mockSmallClockView).setColors(DOZE_COLOR, Color.MAGENTA)
+        verify(mockLargeClockView).setColors(DOZE_COLOR, Color.MAGENTA)
 
         clock.initialize(resources, 0f, 0f)
 
-        verify(mockSmallClockView).setColors(eq(DOZE_COLOR), anyInt())
-        verify(mockLargeClockView).setColors(eq(DOZE_COLOR), anyInt())
+        val expectedColor = 0
+        verify(mockSmallClockView).setColors(DOZE_COLOR, expectedColor)
+        verify(mockLargeClockView).setColors(DOZE_COLOR, expectedColor)
         verify(mockSmallClockView).onTimeZoneChanged(notNull())
         verify(mockLargeClockView).onTimeZoneChanged(notNull())
         verify(mockSmallClockView).refreshTime()
@@ -159,15 +160,31 @@
 
     @Test
     fun defaultClock_events_onColorPaletteChanged() {
+        val expectedColor = 0
         val clock = provider.createClock(DEFAULT_CLOCK_ID)
 
-        verify(mockSmallClockView).setColors(Color.MAGENTA, Color.MAGENTA)
-        verify(mockLargeClockView).setColors(Color.MAGENTA, Color.MAGENTA)
+        verify(mockSmallClockView).setColors(DOZE_COLOR, Color.MAGENTA)
+        verify(mockLargeClockView).setColors(DOZE_COLOR, Color.MAGENTA)
 
         clock.events.onColorPaletteChanged(resources)
 
-        verify(mockSmallClockView).setColors(eq(DOZE_COLOR), anyInt())
-        verify(mockLargeClockView).setColors(eq(DOZE_COLOR), anyInt())
+        verify(mockSmallClockView).setColors(DOZE_COLOR, expectedColor)
+        verify(mockLargeClockView).setColors(DOZE_COLOR, expectedColor)
+    }
+
+    @Test
+    fun defaultClock_events_onSeedColorChanged() {
+        val initSeedColor = 10
+        val newSeedColor = 20
+        val clock = provider.createClock(ClockSettings(DEFAULT_CLOCK_ID, initSeedColor))
+
+        verify(mockSmallClockView).setColors(DOZE_COLOR, initSeedColor)
+        verify(mockLargeClockView).setColors(DOZE_COLOR, initSeedColor)
+
+        clock.events.onSeedColorChanged(newSeedColor)
+
+        verify(mockSmallClockView).setColors(DOZE_COLOR, newSeedColor)
+        verify(mockLargeClockView).setColors(DOZE_COLOR, newSeedColor)
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java
index 4478039..0e2a3ac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java
@@ -49,6 +49,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.wm.shell.util.TransitionUtil;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -120,7 +121,7 @@
         change.setTaskInfo(createTaskInfo(1 /* taskId */, ACTIVITY_TYPE_HOME));
         change.setEndAbsBounds(endBounds);
         change.setEndRelOffset(0, 0);
-        RemoteAnimationTarget wrapped = RemoteAnimationTargetCompat.newTarget(
+        RemoteAnimationTarget wrapped = TransitionUtil.newTarget(
                 change, 0 /* order */, tinfo, mock(SurfaceControl.Transaction.class), null);
         assertEquals(ACTIVITY_TYPE_HOME, wrapped.windowConfiguration.getActivityType());
         assertEquals(new Rect(0, 0, 100, 140), wrapped.localBounds);
@@ -133,7 +134,7 @@
 
         TransitionInfoBuilder(@WindowManager.TransitionType int type) {
             mInfo = new TransitionInfo(type, 0 /* flags */);
-            mInfo.setRootLeash(createMockSurface(true /* valid */), 0, 0);
+            mInfo.addRootLeash(0, createMockSurface(true /* valid */), 0, 0);
         }
 
         TransitionInfoBuilder addChange(@WindowManager.TransitionType int mode,
@@ -143,6 +144,7 @@
             change.setMode(mode);
             change.setFlags(flags);
             change.setTaskInfo(taskInfo);
+            change.setDisplayId(0, 0);
             mInfo.addChange(change);
             return this;
         }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt
index a280510..58b44ae 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt
@@ -24,6 +24,7 @@
 import android.testing.TestableLooper
 import android.view.View
 import android.view.ViewGroup
+import android.widget.FrameLayout
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dreams.smartspace.DreamSmartspaceController
@@ -46,6 +47,7 @@
 import org.mockito.Mockito
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.`when`
+import org.mockito.Mockito.anyInt
 import org.mockito.MockitoAnnotations
 import org.mockito.Spy
 
@@ -69,12 +71,21 @@
     private lateinit var viewComponent: SmartspaceViewComponent
 
     @Mock
+    private lateinit var weatherViewComponent: SmartspaceViewComponent
+
+    @Spy
+    private var weatherSmartspaceView: SmartspaceView = TestView(context)
+
+    @Mock
     private lateinit var targetFilter: SmartspaceTargetFilter
 
     @Mock
     private lateinit var plugin: BcSmartspaceDataPlugin
 
     @Mock
+    private lateinit var weatherPlugin: BcSmartspaceDataPlugin
+
+    @Mock
     private lateinit var precondition: SmartspacePrecondition
 
     @Spy
@@ -88,6 +99,9 @@
 
     private lateinit var controller: DreamSmartspaceController
 
+    // 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 DreamSmartspaceController
@@ -121,13 +135,17 @@
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
-        `when`(viewComponentFactory.create(any(), eq(plugin), any()))
+        `when`(viewComponentFactory.create(any(), eq(plugin), any(), eq(null)))
                 .thenReturn(viewComponent)
         `when`(viewComponent.getView()).thenReturn(smartspaceView)
+        `when`(viewComponentFactory.create(any(), eq(weatherPlugin), any(), any()))
+            .thenReturn(weatherViewComponent)
+        `when`(weatherViewComponent.getView()).thenReturn(weatherSmartspaceView)
         `when`(smartspaceManager.createSmartspaceSession(any())).thenReturn(session)
 
         controller = DreamSmartspaceController(context, smartspaceManager, execution, uiExecutor,
-                viewComponentFactory, precondition, Optional.of(targetFilter), Optional.of(plugin))
+                viewComponentFactory, precondition, Optional.of(targetFilter), Optional.of(plugin),
+        Optional.of(weatherPlugin))
     }
 
     /**
@@ -168,11 +186,11 @@
         `when`(precondition.conditionsMet()).thenReturn(true)
         controller.buildAndConnectView(Mockito.mock(ViewGroup::class.java))
 
-        var stateChangeListener = withArgCaptor<View.OnAttachStateChangeListener> {
-            verify(viewComponentFactory).create(any(), eq(plugin), capture())
+        val stateChangeListener = withArgCaptor<View.OnAttachStateChangeListener> {
+            verify(viewComponentFactory).create(any(), eq(plugin), capture(), eq(null))
         }
 
-        var mockView = Mockito.mock(TestView::class.java)
+        val mockView = Mockito.mock(TestView::class.java)
         `when`(precondition.conditionsMet()).thenReturn(true)
         stateChangeListener.onViewAttachedToWindow(mockView)
 
@@ -183,4 +201,74 @@
 
         verify(session).close()
     }
+
+    /**
+     * Ensures session is created when weather smartspace view is created and attached.
+     */
+    @Test
+    fun testConnectOnWeatherViewCreate() {
+        `when`(precondition.conditionsMet()).thenReturn(true)
+
+        val customView = Mockito.mock(TestView::class.java)
+        val weatherView = controller.buildAndConnectWeatherView(fakeParent, customView)
+        val weatherSmartspaceView = weatherView as SmartspaceView
+        fakeParent.addView(weatherView)
+
+        // Then weather view is created with custom view and the default weatherPlugin.getView
+        // should not be called
+        verify(viewComponentFactory).create(eq(fakeParent), eq(weatherPlugin), any(),
+            eq(customView))
+        verify(weatherPlugin, Mockito.never()).getView(fakeParent)
+
+        // And then session is created
+        controller.stateChangeListener.onViewAttachedToWindow(weatherView)
+        verify(smartspaceManager).createSmartspaceSession(any())
+        verify(weatherSmartspaceView).setPrimaryTextColor(anyInt())
+        verify(weatherSmartspaceView).setDozeAmount(0f)
+    }
+
+    /**
+     * Ensures weather plugin registers target listener when it is added from the controller.
+     */
+    @Test
+    fun testAddListenerInController_registersListenerForWeatherPlugin() {
+        val customView = Mockito.mock(TestView::class.java)
+        `when`(precondition.conditionsMet()).thenReturn(true)
+
+        // Given a session is created
+        val weatherView = controller.buildAndConnectWeatherView(fakeParent, customView)
+        controller.stateChangeListener.onViewAttachedToWindow(weatherView)
+        verify(smartspaceManager).createSmartspaceSession(any())
+
+        // When a listener is added
+        controller.addListenerForWeatherPlugin(listener)
+
+        // Then the listener is registered to the weather plugin only
+        verify(weatherPlugin).registerListener(listener)
+        verify(plugin, Mockito.never()).registerListener(any())
+    }
+
+    /**
+     * 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)
+
+        // Given a session is created
+        val customView = Mockito.mock(TestView::class.java)
+        val weatherView = controller.buildAndConnectWeatherView(fakeParent, customView)
+        controller.stateChangeListener.onViewAttachedToWindow(weatherView)
+        verify(smartspaceManager).createSmartspaceSession(any())
+
+        // When view is detached
+        controller.stateChangeListener.onViewDetachedFromWindow(weatherView)
+        // Then the session is closed
+        verify(session).close()
+
+        // And the listener receives an empty list of targets and unregisters the notifier
+        verify(weatherPlugin).onTargetsAvailable(emptyList())
+        verify(weatherPlugin).registerSmartspaceEventNotifier(null)
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index 3b4cc7c..251aced 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -1042,24 +1042,6 @@
     }
 
     @Test
-    public void onRefreshBatteryInfo_pluggedWithOverheat_presentChargingLimited() {
-        createController();
-        BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_DISCHARGING,
-                80 /* level */, BatteryManager.BATTERY_PLUGGED_AC,
-                BatteryManager.BATTERY_HEALTH_OVERHEAT, 0 /* maxChargingWattage */,
-                true /* present */);
-
-        mController.getKeyguardCallback().onRefreshBatteryInfo(status);
-        mController.setVisible(true);
-
-        verifyIndicationMessage(
-                INDICATION_TYPE_BATTERY,
-                mContext.getString(
-                        R.string.keyguard_plugged_in_charging_limited,
-                        NumberFormat.getPercentInstance().format(80 / 100f)));
-    }
-
-    @Test
     public void onRefreshBatteryInfo_fullChargedWithOverheat_presentChargingLimited() {
         createController();
         BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
index d99cdd51..ab615f9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -211,16 +211,6 @@
     }
 
     @Test
-    fun testTriggeringBouncerWhenPrivateNotificationsArentAllowed() {
-        whenever(lockScreenUserManager.userAllowsPrivateNotificationsInPublic(anyInt())).thenReturn(
-                false)
-        transitionController.goToLockedShade(null)
-        verify(statusbarStateController, never()).setState(anyInt())
-        verify(statusbarStateController).setLeaveOpenOnKeyguardHide(true)
-        verify(mCentralSurfaces).showBouncerWithDimissAndCancelIfKeyguard(anyObject(), anyObject())
-    }
-
-    @Test
     fun testTriggeringBouncerNoNotificationsOnLockscreen() {
         whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(false)
         transitionController.goToLockedShade(null)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt
new file mode 100644
index 0000000..7a67796
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.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.statusbar.notification
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.plugins.log.LogcatEchoTracker
+import com.android.systemui.statusbar.StatusBarState
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class NotificationWakeUpCoordinatorLoggerTest : SysuiTestCase() {
+
+    private val logBufferCounter = LogBufferCounter()
+    private lateinit var logger: NotificationWakeUpCoordinatorLogger
+
+    private fun verifyDidLog(times: Int) {
+        logBufferCounter.verifyDidLog(times)
+    }
+
+    @Before
+    fun setup() {
+        logger = NotificationWakeUpCoordinatorLogger(logBufferCounter.logBuffer)
+    }
+
+    @Test
+    fun setDozeAmountWillThrottleFractionalUpdates() {
+        logger.logSetDozeAmount(0f, 0f, "source1", StatusBarState.SHADE, changed = false)
+        verifyDidLog(1)
+        logger.logSetDozeAmount(0.1f, 0.1f, "source1", StatusBarState.SHADE, changed = true)
+        verifyDidLog(1)
+        logger.logSetDozeAmount(0.2f, 0.2f, "source1", StatusBarState.SHADE, changed = true)
+        logger.logSetDozeAmount(0.3f, 0.3f, "source1", StatusBarState.SHADE, changed = true)
+        logger.logSetDozeAmount(0.4f, 0.4f, "source1", StatusBarState.SHADE, changed = true)
+        logger.logSetDozeAmount(0.5f, 0.5f, "source1", StatusBarState.SHADE, changed = true)
+        verifyDidLog(0)
+        logger.logSetDozeAmount(1f, 1f, "source1", StatusBarState.SHADE, changed = true)
+        verifyDidLog(1)
+    }
+
+    @Test
+    fun setDozeAmountWillIncludeFractionalUpdatesWhenStateChanges() {
+        logger.logSetDozeAmount(0f, 0f, "source1", StatusBarState.SHADE, changed = false)
+        verifyDidLog(1)
+        logger.logSetDozeAmount(0.1f, 0.1f, "source1", StatusBarState.SHADE, changed = true)
+        verifyDidLog(1)
+        logger.logSetDozeAmount(0.2f, 0.2f, "source1", StatusBarState.SHADE, changed = true)
+        logger.logSetDozeAmount(0.3f, 0.3f, "source1", StatusBarState.SHADE, changed = true)
+        logger.logSetDozeAmount(0.4f, 0.4f, "source1", StatusBarState.SHADE, changed = true)
+        logger.logSetDozeAmount(0.5f, 0.5f, "source1", StatusBarState.SHADE, changed = true)
+        verifyDidLog(0)
+        logger.logSetDozeAmount(0.5f, 0.5f, "source1", StatusBarState.KEYGUARD, changed = false)
+        verifyDidLog(1)
+    }
+
+    @Test
+    fun setDozeAmountWillIncludeFractionalUpdatesWhenSourceChanges() {
+        logger.logSetDozeAmount(0f, 0f, "source1", StatusBarState.SHADE, changed = false)
+        verifyDidLog(1)
+        logger.logSetDozeAmount(0.1f, 0.1f, "source1", StatusBarState.SHADE, changed = true)
+        verifyDidLog(1)
+        logger.logSetDozeAmount(0.2f, 0.2f, "source1", StatusBarState.SHADE, changed = true)
+        logger.logSetDozeAmount(0.3f, 0.3f, "source1", StatusBarState.SHADE, changed = true)
+        logger.logSetDozeAmount(0.4f, 0.4f, "source1", StatusBarState.SHADE, changed = true)
+        logger.logSetDozeAmount(0.5f, 0.5f, "source1", StatusBarState.SHADE, changed = true)
+        verifyDidLog(0)
+        logger.logSetDozeAmount(0.5f, 0.5f, "source2", StatusBarState.SHADE, changed = false)
+        verifyDidLog(1)
+    }
+
+    class LogBufferCounter {
+        val recentLogs = mutableListOf<Pair<String, LogLevel>>()
+        val tracker =
+            object : LogcatEchoTracker {
+                override val logInBackgroundThread: Boolean = false
+                override fun isBufferLoggable(bufferName: String, level: LogLevel): Boolean = false
+                override fun isTagLoggable(tagName: String, level: LogLevel): Boolean {
+                    recentLogs.add(tagName to level)
+                    return true
+                }
+            }
+        val logBuffer =
+            LogBuffer(name = "test", maxSize = 1, logcatEchoTracker = tracker, systrace = false)
+
+        fun verifyDidLog(times: Int) {
+            assertThat(recentLogs).hasSize(times)
+            recentLogs.clear()
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt
new file mode 100644
index 0000000..95591a4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
+import com.android.systemui.statusbar.phone.DozeParameters
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.phone.ScreenOffAnimationController
+import com.android.systemui.statusbar.policy.HeadsUpManager
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.mockito.withArgCaptor
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.anyFloat
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.verify
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class NotificationWakeUpCoordinatorTest : SysuiTestCase() {
+
+    private val dumpManager: DumpManager = mock()
+    private val headsUpManager: HeadsUpManager = mock()
+    private val statusBarStateController: StatusBarStateController = mock()
+    private val bypassController: KeyguardBypassController = mock()
+    private val dozeParameters: DozeParameters = mock()
+    private val screenOffAnimationController: ScreenOffAnimationController = mock()
+    private val logger: NotificationWakeUpCoordinatorLogger = mock()
+    private val stackScrollerController: NotificationStackScrollLayoutController = mock()
+
+    private lateinit var notificationWakeUpCoordinator: NotificationWakeUpCoordinator
+    private lateinit var statusBarStateCallback: StatusBarStateController.StateListener
+    private lateinit var bypassChangeCallback: KeyguardBypassController.OnBypassStateChangedListener
+
+    private var bypassEnabled: Boolean = false
+    private var statusBarState: Int = StatusBarState.KEYGUARD
+    private var dozeAmount: Float = 0f
+
+    private fun setBypassEnabled(enabled: Boolean) {
+        bypassEnabled = enabled
+        bypassChangeCallback.onBypassStateChanged(enabled)
+    }
+
+    private fun setStatusBarState(state: Int) {
+        statusBarState = state
+        statusBarStateCallback.onStateChanged(state)
+    }
+
+    private fun setDozeAmount(dozeAmount: Float) {
+        this.dozeAmount = dozeAmount
+        statusBarStateCallback.onDozeAmountChanged(dozeAmount, dozeAmount)
+    }
+
+    @Before
+    fun setup() {
+        whenever(bypassController.bypassEnabled).then { bypassEnabled }
+        whenever(statusBarStateController.state).then { statusBarState }
+        notificationWakeUpCoordinator =
+            NotificationWakeUpCoordinator(
+                dumpManager,
+                headsUpManager,
+                statusBarStateController,
+                bypassController,
+                dozeParameters,
+                screenOffAnimationController,
+                logger,
+            )
+        statusBarStateCallback = withArgCaptor {
+            verify(statusBarStateController).addCallback(capture())
+        }
+        bypassChangeCallback = withArgCaptor {
+            verify(bypassController).registerOnBypassStateChangedListener(capture())
+        }
+        notificationWakeUpCoordinator.setStackScroller(stackScrollerController)
+    }
+
+    @Test
+    fun setDozeToOneWillFullyHideNotifications() {
+        setDozeAmount(1f)
+        verifyStackScrollerDozeAndHideAmount(dozeAmount = 1f, hideAmount = 1f)
+        assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isTrue()
+    }
+
+    @Test
+    fun setDozeToZeroWillFullyShowNotifications() {
+        setDozeAmount(0f)
+        verifyStackScrollerDozeAndHideAmount(dozeAmount = 0f, hideAmount = 0f)
+        assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
+    }
+
+    @Test
+    fun setDozeToOneThenZeroWillFullyShowNotifications() {
+        setDozeToOneWillFullyHideNotifications()
+        clearInvocations(stackScrollerController)
+        setDozeToZeroWillFullyShowNotifications()
+    }
+
+    @Test
+    fun setDozeToHalfWillHalfShowNotifications() {
+        setDozeAmount(0.5f)
+        verifyStackScrollerDozeAndHideAmount(dozeAmount = 0.5f, hideAmount = 0.5f)
+        assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
+    }
+
+    @Test
+    fun setDozeToZeroWithBypassWillFullyHideNotifications() {
+        bypassEnabled = true
+        setDozeAmount(0f)
+        verifyStackScrollerDozeAndHideAmount(dozeAmount = 01f, hideAmount = 1f)
+        assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isTrue()
+    }
+
+    @Test
+    fun disablingBypassWillShowNotifications() {
+        setDozeToZeroWithBypassWillFullyHideNotifications()
+        clearInvocations(stackScrollerController)
+        setBypassEnabled(false)
+        verifyStackScrollerDozeAndHideAmount(dozeAmount = 0f, hideAmount = 0f)
+        assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
+    }
+
+    @Test
+    fun switchingToShadeWithBypassEnabledWillShowNotifications() {
+        setDozeToZeroWithBypassWillFullyHideNotifications()
+        clearInvocations(stackScrollerController)
+        setStatusBarState(StatusBarState.SHADE)
+        verifyStackScrollerDozeAndHideAmount(dozeAmount = 0f, hideAmount = 0f)
+        assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
+        assertThat(notificationWakeUpCoordinator.statusBarState).isEqualTo(StatusBarState.SHADE)
+    }
+
+    private fun verifyStackScrollerDozeAndHideAmount(dozeAmount: Float, hideAmount: Float) {
+        // First verify that we did in-fact receive the correct values
+        verify(stackScrollerController).setDozeAmount(dozeAmount)
+        verify(stackScrollerController).setHideAmount(hideAmount, hideAmount)
+        // Now verify that there was just this ONE call to each of these methods
+        verify(stackScrollerController).setDozeAmount(anyFloat())
+        verify(stackScrollerController).setHideAmount(anyFloat(), anyFloat())
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupWhenCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupWhenCoordinatorTest.kt
new file mode 100644
index 0000000..eac0e29
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupWhenCoordinatorTest.kt
@@ -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.systemui.statusbar.notification.collection.coordinator
+
+import android.app.Notification
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.SbnBuilder
+import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderGroupListener
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener
+import com.android.systemui.statusbar.notification.collection.render.NotifGroupController
+import com.android.systemui.util.concurrency.DelayableExecutor
+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.util.mockito.withArgCaptor
+import com.android.systemui.util.time.SystemClock
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.InjectMocks
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations.initMocks
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+class GroupWhenCoordinatorTest : SysuiTestCase() {
+
+    private lateinit var beforeFinalizeFilterListener: OnBeforeFinalizeFilterListener
+    private lateinit var afterRenderGroupListener: OnAfterRenderGroupListener
+
+    @Mock private lateinit var pipeline: NotifPipeline
+
+    @Mock private lateinit var delayableExecutor: DelayableExecutor
+
+    @Mock private lateinit var groupController: NotifGroupController
+
+    @Mock private lateinit var systemClock: SystemClock
+
+    @InjectMocks private lateinit var coordinator: GroupWhenCoordinator
+
+    @Before
+    fun setUp() {
+        initMocks(this)
+        whenever(systemClock.currentTimeMillis()).thenReturn(NOW)
+        coordinator.attach(pipeline)
+
+        beforeFinalizeFilterListener = withArgCaptor {
+            verify(pipeline).addOnBeforeFinalizeFilterListener(capture())
+        }
+        afterRenderGroupListener = withArgCaptor {
+            verify(pipeline).addOnAfterRenderGroupListener(capture())
+        }
+    }
+
+    @Test
+    fun setNotificationGroupWhen_setClosestTimeByNow_whenAllNotificationsAreBeforeNow() {
+        // GIVEN
+        val summaryEntry = buildNotificationEntry(0, NOW)
+        val childEntry1 = buildNotificationEntry(1, NOW - 10L)
+        val childEntry2 = buildNotificationEntry(2, NOW - 100L)
+        val groupEntry =
+            GroupEntryBuilder()
+                .setSummary(summaryEntry)
+                .setChildren(listOf(childEntry1, childEntry2))
+                .build()
+        // WHEN
+        beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(groupEntry))
+        afterRenderGroupListener.onAfterRenderGroup(groupEntry, groupController)
+
+        // THEN
+        verify(groupController).setNotificationGroupWhen(eq(NOW - 10L))
+    }
+
+    @Test
+    fun setNotificationGroupWhen_setClosestTimeByNow_whenAllNotificationsAreAfterNow() {
+        // GIVEN
+        val summaryEntry = buildNotificationEntry(0, NOW)
+        val childEntry1 = buildNotificationEntry(1, NOW + 10L)
+        val childEntry2 = buildNotificationEntry(2, NOW + 100L)
+
+        val groupEntry =
+            GroupEntryBuilder()
+                .setSummary(summaryEntry)
+                .setChildren(listOf(childEntry1, childEntry2))
+                .build()
+
+        // WHEN
+        beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(groupEntry))
+        afterRenderGroupListener.onAfterRenderGroup(groupEntry, groupController)
+
+        // THEN
+        verify(groupController).setNotificationGroupWhen(eq(NOW + 10L))
+    }
+
+    @Test
+    fun setNotificationGroupWhen_setClosestFutureTimeByNow_whenThereAreBothBeforeAndAfterNow() {
+        // GIVEN
+        val summaryEntry = buildNotificationEntry(0, NOW)
+        val childEntry1 = buildNotificationEntry(1, NOW + 100L)
+        val childEntry2 = buildNotificationEntry(2, NOW + 10L)
+        val childEntry3 = buildNotificationEntry(3, NOW - 100L)
+        val childEntry4 = buildNotificationEntry(4, NOW - 9L)
+
+        val groupEntry =
+            GroupEntryBuilder()
+                .setSummary(summaryEntry)
+                .setChildren(listOf(childEntry1, childEntry2, childEntry3, childEntry4))
+                .build()
+
+        // WHEN
+        beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(groupEntry))
+        afterRenderGroupListener.onAfterRenderGroup(groupEntry, groupController)
+
+        // THEN
+        verify(groupController).setNotificationGroupWhen(eq(NOW + 10L))
+    }
+
+    @Test
+    fun setNotificationGroupWhen_filterInvalidNotificationTimes() {
+        // GIVEN
+        val summaryEntry = buildNotificationEntry(0, NOW)
+        val childEntry1 = buildNotificationEntry(1, NOW + 100L)
+        val childEntry2 = buildNotificationEntry(2, -20000L)
+        val childEntry3 = buildNotificationEntry(4, 0)
+
+        val groupEntry =
+            GroupEntryBuilder()
+                .setSummary(summaryEntry)
+                .setChildren(listOf(childEntry1, childEntry2, childEntry3))
+                .build()
+
+        // WHEN
+        beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(groupEntry))
+        afterRenderGroupListener.onAfterRenderGroup(groupEntry, groupController)
+
+        // THEN
+        verify(groupController).setNotificationGroupWhen(eq(NOW + 100))
+    }
+
+    @Test
+    fun setNotificationGroupWhen_setSummaryTimeWhenAllNotificationTimesAreInvalid() {
+        // GIVEN
+        val summaryEntry = buildNotificationEntry(0, NOW)
+        val childEntry1 = buildNotificationEntry(1, 0)
+        val childEntry2 = buildNotificationEntry(2, -1)
+
+        val groupEntry =
+            GroupEntryBuilder()
+                .setSummary(summaryEntry)
+                .setChildren(listOf(childEntry1, childEntry2))
+                .build()
+
+        // WHEN
+        beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(groupEntry))
+        afterRenderGroupListener.onAfterRenderGroup(groupEntry, groupController)
+
+        // THEN
+        verify(groupController, never()).setNotificationGroupWhen(NOW)
+    }
+
+    @Test
+    fun setNotificationGroupWhen_schedulePipelineInvalidationWhenAnyNotificationIsInTheFuture() {
+        // GIVEN
+        val summaryEntry = buildNotificationEntry(0, NOW)
+        val childEntry1 = buildNotificationEntry(1, NOW + 1000L)
+        val childEntry2 = buildNotificationEntry(2, NOW + 2000L)
+        val childEntry3 = buildNotificationEntry(3, NOW - 100L)
+
+        val groupEntry =
+            GroupEntryBuilder()
+                .setSummary(summaryEntry)
+                .setChildren(listOf(childEntry1, childEntry2, childEntry3))
+                .build()
+
+        // WHEN
+        beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(groupEntry))
+        afterRenderGroupListener.onAfterRenderGroup(groupEntry, groupController)
+
+        // THEN
+        verify(delayableExecutor).executeDelayed(any(), eq(1000))
+    }
+
+    @Test
+    fun setNotificationGroupWhen_cancelPrevPipelineInvalidation() {
+        // GIVEN
+        val summaryEntry = buildNotificationEntry(0, NOW)
+        val childEntry1 = buildNotificationEntry(1, NOW + 1L)
+        val prevInvalidation = mock<Runnable>()
+        whenever(delayableExecutor.executeDelayed(any(), any())).thenReturn(prevInvalidation)
+
+        val groupEntry =
+            GroupEntryBuilder().setSummary(summaryEntry).setChildren(listOf(childEntry1)).build()
+
+        // WHEN
+        beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(groupEntry))
+        afterRenderGroupListener.onAfterRenderGroup(groupEntry, groupController)
+
+        beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(groupEntry))
+
+        // THEN
+        verify(prevInvalidation).run()
+    }
+
+    private fun buildNotificationEntry(id: Int, timeMillis: Long): NotificationEntry {
+        val notification = Notification.Builder(mContext).setWhen(timeMillis).build()
+        val sbn = SbnBuilder().setNotification(notification).build()
+        return NotificationEntryBuilder().setId(id).setSbn(sbn).build()
+    }
+
+    private companion object {
+        private const val NOW = 1000L
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
index cb4f119..4bb14a1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
@@ -22,6 +22,7 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.logcatLogBuffer
+import com.android.systemui.flags.Flags
 import com.android.systemui.statusbar.NotificationRemoteInputManager
 import com.android.systemui.statusbar.notification.NotifPipelineFlags
 import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder
@@ -58,6 +59,7 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.ArgumentMatchers.anyString
+import org.mockito.BDDMockito.clearInvocations
 import org.mockito.BDDMockito.given
 import org.mockito.Mockito.never
 import org.mockito.Mockito.times
@@ -166,6 +168,12 @@
         mGroupChild1 = mHelper.createChildNotification(GROUP_ALERT_ALL, 1, "child", 350)
         mGroupChild2 = mHelper.createChildNotification(GROUP_ALERT_ALL, 2, "child", 250)
         mGroupChild3 = mHelper.createChildNotification(GROUP_ALERT_ALL, 3, "child", 150)
+
+        // Set the default FSI decision
+        setShouldFullScreen(any(), FullScreenIntentDecision.NO_FULL_SCREEN_INTENT)
+
+        // Run tests with default feature flag state
+        whenever(mFlags.fsiOnDNDUpdate()).thenReturn(Flags.FSI_ON_DND_UPDATE.default)
     }
 
     @Test
@@ -810,6 +818,39 @@
     }
 
     @Test
+    fun onEntryAdded_whenLaunchingFSI_doesLogDecision() {
+        // GIVEN A new notification can FSI
+        setShouldFullScreen(mEntry, FullScreenIntentDecision.FSI_DEVICE_NOT_INTERACTIVE)
+        mCollectionListener.onEntryAdded(mEntry)
+
+        verify(mLaunchFullScreenIntentProvider).launchFullScreenIntent(mEntry)
+        verify(mNotificationInterruptStateProvider).logFullScreenIntentDecision(
+                mEntry, FullScreenIntentDecision.FSI_DEVICE_NOT_INTERACTIVE)
+    }
+
+    @Test
+    fun onEntryAdded_whenNotLaunchingFSI_doesLogDecision() {
+        // GIVEN A new notification can't FSI
+        setShouldFullScreen(mEntry, FullScreenIntentDecision.NO_FULL_SCREEN_INTENT)
+        mCollectionListener.onEntryAdded(mEntry)
+
+        verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(any())
+        verify(mNotificationInterruptStateProvider).logFullScreenIntentDecision(
+                mEntry, FullScreenIntentDecision.NO_FULL_SCREEN_INTENT)
+    }
+
+    @Test
+    fun onEntryAdded_whenNotLaunchingFSIBecauseOfDnd_doesLogDecision() {
+        // GIVEN A new notification can't FSI because of DND
+        setShouldFullScreen(mEntry, FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND)
+        mCollectionListener.onEntryAdded(mEntry)
+
+        verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(any())
+        verify(mNotificationInterruptStateProvider).logFullScreenIntentDecision(
+                mEntry, FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND)
+    }
+
+    @Test
     fun testOnRankingApplied_noFSIOnUpdateWhenFlagOff() {
         // Ensure the feature flag is off
         whenever(mFlags.fsiOnDNDUpdate()).thenReturn(false)
@@ -818,13 +859,22 @@
         setShouldFullScreen(mEntry, FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND)
         mCollectionListener.onEntryAdded(mEntry)
 
+        // Verify that this causes a log
+        verify(mNotificationInterruptStateProvider).logFullScreenIntentDecision(
+                mEntry, FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND)
+        clearInvocations(mNotificationInterruptStateProvider)
+
         // and it is then updated to allow full screen
         setShouldFullScreen(mEntry, FullScreenIntentDecision.FSI_DEVICE_NOT_INTERACTIVE)
         whenever(mNotifPipeline.allNotifs).thenReturn(listOf(mEntry))
         mCollectionListener.onRankingApplied()
 
         // THEN it should not full screen because the feature is off
-        verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(mEntry)
+        verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(any())
+
+        // VERIFY that no additional logging happens either
+        verify(mNotificationInterruptStateProvider, never())
+                .logFullScreenIntentDecision(any(), any())
     }
 
     @Test
@@ -836,8 +886,11 @@
         setShouldFullScreen(mEntry, FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND)
         mCollectionListener.onEntryAdded(mEntry)
 
-        // at this point, it should not have full screened
-        verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(mEntry)
+        // at this point, it should not have full screened, but should have logged
+        verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(any())
+        verify(mNotificationInterruptStateProvider).logFullScreenIntentDecision(mEntry,
+                FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND)
+        clearInvocations(mNotificationInterruptStateProvider)
 
         // and it is then updated to allow full screen AND HUN
         setShouldFullScreen(mEntry, FullScreenIntentDecision.FSI_DEVICE_NOT_INTERACTIVE)
@@ -847,10 +900,110 @@
         mBeforeTransformGroupsListener.onBeforeTransformGroups(listOf(mEntry))
         mBeforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(mEntry))
 
-        // THEN it should full screen but it should NOT HUN
+        // THEN it should full screen and log but it should NOT HUN
         verify(mLaunchFullScreenIntentProvider).launchFullScreenIntent(mEntry)
         verify(mHeadsUpViewBinder, never()).bindHeadsUpView(any(), any())
         verify(mHeadsUpManager, never()).showNotification(any())
+        verify(mNotificationInterruptStateProvider).logFullScreenIntentDecision(mEntry,
+                FullScreenIntentDecision.FSI_DEVICE_NOT_INTERACTIVE)
+        clearInvocations(mNotificationInterruptStateProvider)
+
+        // WHEN ranking updates again and the pipeline reruns
+        clearInvocations(mLaunchFullScreenIntentProvider)
+        mCollectionListener.onRankingApplied()
+        mBeforeTransformGroupsListener.onBeforeTransformGroups(listOf(mEntry))
+        mBeforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(mEntry))
+
+        // VERIFY that the FSI does not launch again or log
+        verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(any())
+        verify(mNotificationInterruptStateProvider, never())
+                .logFullScreenIntentDecision(any(), any())
+    }
+
+    @Test
+    fun testOnRankingApplied_withOnlyDndSuppressionAllowsFsiLater() {
+        // Turn on the feature
+        whenever(mFlags.fsiOnDNDUpdate()).thenReturn(true)
+
+        // GIVEN that mEntry was previously suppressed from full-screen only by DND
+        setShouldFullScreen(mEntry, FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND)
+        mCollectionListener.onEntryAdded(mEntry)
+
+        // at this point, it should not have full screened, but should have logged
+        verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(any())
+        verify(mNotificationInterruptStateProvider).logFullScreenIntentDecision(mEntry,
+                FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND)
+        clearInvocations(mNotificationInterruptStateProvider)
+
+        // ranking is applied with only DND blocking FSI
+        setShouldFullScreen(mEntry, FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND)
+        mCollectionListener.onRankingApplied()
+        mBeforeTransformGroupsListener.onBeforeTransformGroups(listOf(mEntry))
+        mBeforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(mEntry))
+
+        // THEN it should still not yet full screen or HUN
+        verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(any())
+        verify(mHeadsUpViewBinder, never()).bindHeadsUpView(any(), any())
+        verify(mHeadsUpManager, never()).showNotification(any())
+
+        // Same decision as before; is not logged
+        verify(mNotificationInterruptStateProvider, never())
+                .logFullScreenIntentDecision(any(), any())
+        clearInvocations(mNotificationInterruptStateProvider)
+
+        // and it is then updated to allow full screen AND HUN
+        setShouldFullScreen(mEntry, FullScreenIntentDecision.FSI_DEVICE_NOT_INTERACTIVE)
+        setShouldHeadsUp(mEntry)
+        whenever(mNotifPipeline.allNotifs).thenReturn(listOf(mEntry))
+        mCollectionListener.onRankingApplied()
+        mBeforeTransformGroupsListener.onBeforeTransformGroups(listOf(mEntry))
+        mBeforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(mEntry))
+
+        // THEN it should full screen and log but it should NOT HUN
+        verify(mLaunchFullScreenIntentProvider).launchFullScreenIntent(mEntry)
+        verify(mHeadsUpViewBinder, never()).bindHeadsUpView(any(), any())
+        verify(mHeadsUpManager, never()).showNotification(any())
+        verify(mNotificationInterruptStateProvider).logFullScreenIntentDecision(mEntry,
+                FullScreenIntentDecision.FSI_DEVICE_NOT_INTERACTIVE)
+        clearInvocations(mNotificationInterruptStateProvider)
+    }
+
+    @Test
+    fun testOnRankingApplied_newNonFullScreenAnswerInvalidatesCandidate() {
+        // Turn on the feature
+        whenever(mFlags.fsiOnDNDUpdate()).thenReturn(true)
+
+        // GIVEN that mEntry was previously suppressed from full-screen only by DND
+        whenever(mNotifPipeline.allNotifs).thenReturn(listOf(mEntry))
+        setShouldFullScreen(mEntry, FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND)
+        mCollectionListener.onEntryAdded(mEntry)
+
+        // at this point, it should not have full screened
+        verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(mEntry)
+
+        // now some other condition blocks FSI in addition to DND
+        setShouldFullScreen(mEntry, FullScreenIntentDecision.NO_FSI_SUPPRESSED_BY_DND)
+        mCollectionListener.onRankingApplied()
+        mBeforeTransformGroupsListener.onBeforeTransformGroups(listOf(mEntry))
+        mBeforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(mEntry))
+
+        // THEN it should NOT full screen or HUN
+        verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(any())
+        verify(mHeadsUpViewBinder, never()).bindHeadsUpView(any(), any())
+        verify(mHeadsUpManager, never()).showNotification(any())
+
+        // NOW the DND logic changes and FSI and HUN are available
+        clearInvocations(mLaunchFullScreenIntentProvider)
+        setShouldFullScreen(mEntry, FullScreenIntentDecision.FSI_DEVICE_NOT_INTERACTIVE)
+        setShouldHeadsUp(mEntry)
+        mCollectionListener.onRankingApplied()
+        mBeforeTransformGroupsListener.onBeforeTransformGroups(listOf(mEntry))
+        mBeforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(mEntry))
+
+        // VERIFY that the FSI didn't happen, but that we do HUN
+        verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(any())
+        finishBind(mEntry)
+        verify(mHeadsUpManager).showNotification(mEntry)
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepoTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepoTest.kt
deleted file mode 100644
index a6a9e51..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepoTest.kt
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.fsi
-
-import android.R
-import android.app.Notification
-import android.app.NotificationManager
-import android.app.PendingIntent
-import android.content.pm.ApplicationInfo
-import android.content.pm.PackageManager
-import android.graphics.drawable.Drawable
-import android.os.UserHandle
-import android.service.dreams.IDreamManager
-import android.service.notification.StatusBarNotification
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper.RunWithLooper
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
-import com.android.systemui.statusbar.notification.collection.NotificationEntry
-import com.android.systemui.statusbar.notification.collection.provider.LaunchFullScreenIntentProvider
-import com.android.systemui.statusbar.phone.CentralSurfaces
-import java.util.concurrent.Executor
-import junit.framework.Assert.assertEquals
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.any
-import org.mockito.ArgumentMatchers.anyString
-import org.mockito.Mock
-import org.mockito.Mockito
-import org.mockito.Mockito.never
-import org.mockito.Mockito.times
-import org.mockito.Mockito.`when` as whenever
-import org.mockito.MockitoAnnotations
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-@RunWithLooper(setAsMainLooper = true)
-class FsiChromeRepoTest : SysuiTestCase() {
-
-    @Mock lateinit var centralSurfaces: CentralSurfaces
-    @Mock lateinit var fsiChromeRepo: FsiChromeRepo
-    @Mock lateinit var packageManager: PackageManager
-
-    var keyguardRepo = FakeKeyguardRepository()
-    @Mock private lateinit var applicationInfo: ApplicationInfo
-
-    @Mock lateinit var launchFullScreenIntentProvider: LaunchFullScreenIntentProvider
-    var featureFlags = FakeFeatureFlags()
-    @Mock lateinit var dreamManager: IDreamManager
-
-    // Execute all foreground & background requests immediately
-    private val uiBgExecutor = Executor { r -> r.run() }
-
-    private val appName: String = "appName"
-    private val appIcon: Drawable = context.getDrawable(com.android.systemui.R.drawable.ic_android)
-    private val fsi: PendingIntent = Mockito.mock(PendingIntent::class.java)
-
-    @Before
-    fun setUp() {
-        MockitoAnnotations.initMocks(this)
-
-        // Set up package manager mocks
-        whenever(packageManager.getApplicationIcon(anyString())).thenReturn(appIcon)
-        whenever(packageManager.getApplicationIcon(any(ApplicationInfo::class.java)))
-            .thenReturn(appIcon)
-        whenever(packageManager.getApplicationLabel(any())).thenReturn(appName)
-        mContext.setMockPackageManager(packageManager)
-
-        fsiChromeRepo =
-            FsiChromeRepo(
-                mContext,
-                packageManager,
-                keyguardRepo,
-                launchFullScreenIntentProvider,
-                featureFlags,
-                uiBgExecutor,
-                dreamManager,
-                centralSurfaces
-            )
-    }
-
-    private fun createFsiEntry(fsi: PendingIntent): NotificationEntry {
-        val nb =
-            Notification.Builder(mContext, "a")
-                .setContentTitle("foo")
-                .setSmallIcon(R.drawable.sym_def_app_icon)
-                .setFullScreenIntent(fsi, /* highPriority= */ true)
-
-        val sbn =
-            StatusBarNotification(
-                "pkg",
-                "opPkg",
-                /* id= */ 0,
-                "tag" + System.currentTimeMillis(),
-                /* uid= */ 0,
-                /* initialPid */ 0,
-                nb.build(),
-                UserHandle(0),
-                /* overrideGroupKey= */ null,
-                /* postTime= */ 0
-            )
-
-        val entry = Mockito.mock(NotificationEntry::class.java)
-        whenever(entry.importance).thenReturn(NotificationManager.IMPORTANCE_HIGH)
-        whenever(entry.sbn).thenReturn(sbn)
-        return entry
-    }
-
-    @Test
-    fun testLaunchFullscreenIntent_flagNotEnabled_noLaunch() {
-        // Setup
-        featureFlags.set(Flags.FSI_CHROME, false)
-
-        // Test
-        val entry = createFsiEntry(fsi)
-        fsiChromeRepo.launchFullscreenIntent(entry)
-
-        // Verify
-        Mockito.verify(centralSurfaces, never()).wakeUpForFullScreenIntent()
-    }
-
-    @Test
-    fun testLaunchFullscreenIntent_notOnKeyguard_noLaunch() {
-        // Setup
-        featureFlags.set(Flags.FSI_CHROME, true)
-        keyguardRepo.setKeyguardShowing(false)
-
-        // Test
-        val entry = createFsiEntry(fsi)
-        fsiChromeRepo.launchFullscreenIntent(entry)
-
-        // Verify
-        Mockito.verify(centralSurfaces, never()).wakeUpForFullScreenIntent()
-    }
-
-    @Test
-    fun testLaunchFullscreenIntent_stopsScreensaver() {
-        // Setup
-        featureFlags.set(Flags.FSI_CHROME, true)
-        keyguardRepo.setKeyguardShowing(true)
-
-        // Test
-        val entry = createFsiEntry(fsi)
-        fsiChromeRepo.launchFullscreenIntent(entry)
-
-        // Verify
-        Mockito.verify(dreamManager, times(1)).awaken()
-    }
-
-    @Test
-    fun testLaunchFullscreenIntent_updatesFsiInfoFlow() {
-        // Setup
-        featureFlags.set(Flags.FSI_CHROME, true)
-        keyguardRepo.setKeyguardShowing(true)
-
-        // Test
-        val entry = createFsiEntry(fsi)
-        fsiChromeRepo.launchFullscreenIntent(entry)
-
-        // Verify
-        val expectedFsiInfo = FsiChromeRepo.FSIInfo(appName, appIcon, fsi)
-        assertEquals(expectedFsiInfo, fsiChromeRepo.infoFlow.value)
-    }
-
-    @Test
-    fun testLaunchFullscreenIntent_notifyFsiLaunched() {
-        // Setup
-        featureFlags.set(Flags.FSI_CHROME, true)
-        keyguardRepo.setKeyguardShowing(true)
-
-        // Test
-        val entry = createFsiEntry(fsi)
-        fsiChromeRepo.launchFullscreenIntent(entry)
-
-        // Verify
-        Mockito.verify(entry, times(1)).notifyFullScreenIntentLaunched()
-    }
-
-    @Test
-    fun testLaunchFullscreenIntent_wakesUpDevice() {
-        // Setup
-        featureFlags.set(Flags.FSI_CHROME, true)
-        keyguardRepo.setKeyguardShowing(true)
-
-        // Test
-        val entry = createFsiEntry(fsi)
-        fsiChromeRepo.launchFullscreenIntent(entry)
-
-        // Verify
-        Mockito.verify(centralSurfaces, times(1)).wakeUpForFullScreenIntent()
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactoryTest.kt
deleted file mode 100644
index 5cee9e3..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactoryTest.kt
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.fsi
-
-import android.app.PendingIntent
-import android.graphics.drawable.Drawable
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper.RunWithLooper
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.util.concurrency.FakeExecutor
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.mock
-import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.mockito.withArgCaptor
-import com.android.systemui.util.time.FakeSystemClock
-import com.android.wm.shell.TaskView
-import com.android.wm.shell.TaskViewFactory
-import com.google.common.truth.Truth.assertThat
-import java.util.Optional
-import java.util.function.Consumer
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.onStart
-import kotlinx.coroutines.flow.stateIn
-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
-import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-@RunWithLooper(setAsMainLooper = true)
-class FsiChromeViewModelFactoryTest : SysuiTestCase() {
-    @Mock private lateinit var taskViewFactoryOptional: Optional<TaskViewFactory>
-    @Mock private lateinit var taskViewFactory: TaskViewFactory
-    @Mock lateinit var taskView: TaskView
-
-    @Main var mainExecutor = FakeExecutor(FakeSystemClock())
-    lateinit var viewModelFactory: FsiChromeViewModelFactory
-
-    private val fakeInfoFlow = MutableStateFlow<FsiChromeRepo.FSIInfo?>(null)
-    private var fsiChromeRepo: FsiChromeRepo =
-        mock<FsiChromeRepo>().apply { whenever(infoFlow).thenReturn(fakeInfoFlow) }
-
-    private val appName = "appName"
-    private val appIcon: Drawable = context.getDrawable(com.android.systemui.R.drawable.ic_android)
-    private val fsi: PendingIntent = Mockito.mock(PendingIntent::class.java)
-    private val fsiInfo = FsiChromeRepo.FSIInfo(appName, appIcon, fsi)
-
-    @Before
-    fun setUp() {
-        MockitoAnnotations.initMocks(this)
-
-        whenever(taskViewFactoryOptional.get()).thenReturn(taskViewFactory)
-
-        viewModelFactory =
-            FsiChromeViewModelFactory(fsiChromeRepo, taskViewFactoryOptional, context, mainExecutor)
-    }
-
-    @Test
-    fun testViewModelFlow_update_createsTaskView() {
-        runTest {
-            val latestViewModel =
-                viewModelFactory.viewModelFlow
-                    .onStart { FsiDebug.log("viewModelFactory.viewModelFlow.onStart") }
-                    .stateIn(
-                        backgroundScope, // stateIn runs forever, don't count it as test coroutine
-                        SharingStarted.Eagerly,
-                        null
-                    )
-            runCurrent() // Drain queued backgroundScope operations
-
-            // Test: emit the fake FSIInfo
-            fakeInfoFlow.emit(fsiInfo)
-            runCurrent()
-
-            val taskViewFactoryCallback: Consumer<TaskView> = withArgCaptor {
-                verify(taskViewFactory).create(any(), any(), capture())
-            }
-            taskViewFactoryCallback.accept(taskView) // this will call k.resume
-            runCurrent()
-
-            // Verify that the factory has produced a new ViewModel
-            // containing the relevant data from FsiInfo
-            val expectedViewModel =
-                FsiChromeViewModel(appName, appIcon, taskView, fsi, fsiChromeRepo)
-
-            assertThat(latestViewModel.value).isEqualTo(expectedViewModel)
-        }
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
index 07d0dbd..8acf507 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
@@ -36,9 +36,12 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.contains;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
@@ -76,6 +79,10 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
 /**
  * Tests for the interruption state provider which understands whether the system & notification
  * is in a state allowing a particular notification to hun, pulse, or bubble.
@@ -560,7 +567,7 @@
                 .isFalse();
         verify(mLogger, never()).logFullscreen(any(), any());
         verify(mLogger, never()).logNoFullscreenWarning(any(), any());
-        verify(mLogger).logNoFullscreen(entry, "Suppressed by DND");
+        verify(mLogger).logNoFullscreen(entry, "NO_FSI_SUPPRESSED_ONLY_BY_DND");
     }
 
     @Test
@@ -579,7 +586,7 @@
                 .isFalse();
         verify(mLogger, never()).logFullscreen(any(), any());
         verify(mLogger, never()).logNoFullscreenWarning(any(), any());
-        verify(mLogger).logNoFullscreen(entry, "Suppressed by DND");
+        verify(mLogger).logNoFullscreen(entry, "NO_FSI_SUPPRESSED_BY_DND");
     }
 
     @Test
@@ -599,7 +606,7 @@
                 .isEqualTo(FullScreenIntentDecision.NO_FSI_NOT_IMPORTANT_ENOUGH);
         assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
                 .isFalse();
-        verify(mLogger).logNoFullscreen(entry, "Not important enough");
+        verify(mLogger).logNoFullscreen(entry, "NO_FSI_NOT_IMPORTANT_ENOUGH");
         verify(mLogger, never()).logNoFullscreenWarning(any(), any());
         verify(mLogger, never()).logFullscreen(any(), any());
     }
@@ -622,7 +629,8 @@
         assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
                 .isFalse();
         verify(mLogger, never()).logNoFullscreen(any(), any());
-        verify(mLogger).logNoFullscreenWarning(entry, "GroupAlertBehavior will prevent HUN");
+        verify(mLogger).logNoFullscreenWarning(entry,
+                "NO_FSI_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR: GroupAlertBehavior will prevent HUN");
         verify(mLogger, never()).logFullscreen(any(), any());
 
         assertThat(mUiEventLoggerFake.numLogs()).isEqualTo(1);
@@ -652,7 +660,7 @@
                 .isTrue();
         verify(mLogger, never()).logNoFullscreen(any(), any());
         verify(mLogger, never()).logNoFullscreenWarning(any(), any());
-        verify(mLogger).logFullscreen(entry, "Device is not interactive");
+        verify(mLogger).logFullscreen(entry, "FSI_DEVICE_NOT_INTERACTIVE");
     }
 
     @Test
@@ -674,7 +682,7 @@
                 .isTrue();
         verify(mLogger, never()).logNoFullscreen(any(), any());
         verify(mLogger, never()).logNoFullscreenWarning(any(), any());
-        verify(mLogger).logFullscreen(entry, "Device is dreaming");
+        verify(mLogger).logFullscreen(entry, "FSI_DEVICE_IS_DREAMING");
     }
 
     @Test
@@ -696,7 +704,7 @@
                 .isTrue();
         verify(mLogger, never()).logNoFullscreen(any(), any());
         verify(mLogger, never()).logNoFullscreenWarning(any(), any());
-        verify(mLogger).logFullscreen(entry, "Keyguard is showing");
+        verify(mLogger).logFullscreen(entry, "FSI_KEYGUARD_SHOWING");
     }
 
     @Test
@@ -717,7 +725,7 @@
                 .isEqualTo(FullScreenIntentDecision.NO_FSI_EXPECTED_TO_HUN);
         assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
                 .isFalse();
-        verify(mLogger).logNoFullscreen(entry, "Expected to HUN");
+        verify(mLogger).logNoFullscreen(entry, "NO_FSI_EXPECTED_TO_HUN");
         verify(mLogger, never()).logNoFullscreenWarning(any(), any());
         verify(mLogger, never()).logFullscreen(any(), any());
     }
@@ -737,7 +745,7 @@
                 .isTrue();
         verify(mLogger, never()).logNoFullscreen(any(), any());
         verify(mLogger, never()).logNoFullscreenWarning(any(), any());
-        verify(mLogger).logFullscreen(entry, "Expected not to HUN");
+        verify(mLogger).logFullscreen(entry, "FSI_EXPECTED_NOT_TO_HUN");
     }
 
     @Test
@@ -756,7 +764,7 @@
                 .isEqualTo(FullScreenIntentDecision.NO_FSI_EXPECTED_TO_HUN);
         assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
                 .isFalse();
-        verify(mLogger).logNoFullscreen(entry, "Expected to HUN");
+        verify(mLogger).logNoFullscreen(entry, "NO_FSI_EXPECTED_TO_HUN");
         verify(mLogger, never()).logNoFullscreenWarning(any(), any());
         verify(mLogger, never()).logFullscreen(any(), any());
     }
@@ -802,7 +810,7 @@
                 .isEqualTo(FullScreenIntentDecision.NO_FSI_EXPECTED_TO_HUN);
         assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
                 .isFalse();
-        verify(mLogger).logNoFullscreen(entry, "Expected to HUN");
+        verify(mLogger).logNoFullscreen(entry, "NO_FSI_EXPECTED_TO_HUN");
         verify(mLogger, never()).logNoFullscreenWarning(any(), any());
         verify(mLogger, never()).logFullscreen(any(), any());
     }
@@ -848,12 +856,37 @@
                 .isEqualTo(FullScreenIntentDecision.NO_FSI_EXPECTED_TO_HUN);
         assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
                 .isFalse();
-        verify(mLogger).logNoFullscreen(entry, "Expected to HUN");
+        verify(mLogger).logNoFullscreen(entry, "NO_FSI_EXPECTED_TO_HUN");
         verify(mLogger, never()).logNoFullscreenWarning(any(), any());
         verify(mLogger, never()).logFullscreen(any(), any());
     }
 
     @Test
+    public void logFullScreenIntentDecision_shouldAlmostAlwaysLogOneTime() {
+        NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
+        Set<FullScreenIntentDecision> warnings = new HashSet<>(Arrays.asList(
+                FullScreenIntentDecision.NO_FSI_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR,
+                FullScreenIntentDecision.NO_FSI_NO_HUN_OR_KEYGUARD
+        ));
+        for (FullScreenIntentDecision decision : FullScreenIntentDecision.values()) {
+            clearInvocations(mLogger);
+            boolean expectedToLog = decision != FullScreenIntentDecision.NO_FULL_SCREEN_INTENT;
+            boolean isWarning = warnings.contains(decision);
+            mNotifInterruptionStateProvider.logFullScreenIntentDecision(entry, decision);
+            if (decision.shouldLaunch) {
+                verify(mLogger).logFullscreen(eq(entry), contains(decision.name()));
+            } else if (expectedToLog) {
+                if (isWarning) {
+                    verify(mLogger).logNoFullscreenWarning(eq(entry), contains(decision.name()));
+                } else {
+                    verify(mLogger).logNoFullscreen(eq(entry), contains(decision.name()));
+                }
+            }
+            verifyNoMoreInteractions(mLogger);
+        }
+    }
+
+    @Test
     public void testShouldHeadsUp_snoozed_unlocked_withStrictRules() throws Exception {
         when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true);
         NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt
index fb3aba1..c92134b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt
@@ -28,7 +28,6 @@
 import com.android.systemui.plugins.FalsingManager
 import com.android.systemui.plugins.PluginManager
 import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.statusbar.NotificationMediaManager
 import com.android.systemui.statusbar.SmartReplyController
 import com.android.systemui.statusbar.notification.collection.provider.NotificationDismissibilityProvider
 import com.android.systemui.statusbar.notification.collection.render.FakeNodeController
@@ -73,7 +72,6 @@
     private val logBufferLogger: NotificationRowLogger = mock()
     private val listContainer: NotificationListContainer = mock()
     private val childrenContainer: NotificationChildrenContainer = mock()
-    private val mediaManager: NotificationMediaManager = mock()
     private val smartReplyConstants: SmartReplyConstants = mock()
     private val smartReplyController: SmartReplyController = mock()
     private val pluginManager: PluginManager = mock()
@@ -95,6 +93,7 @@
     private val bubblesManager: BubblesManager = mock()
     private val dragController: ExpandableNotificationRowDragController = mock()
     private val dismissibilityProvider: NotificationDismissibilityProvider = mock()
+
     private lateinit var controller: ExpandableNotificationRowController
 
     @Before
@@ -108,7 +107,6 @@
                 metricsLogger,
                 logBufferLogger,
                 listContainer,
-                mediaManager,
                 smartReplyConstants,
                 smartReplyController,
                 pluginManager,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
index 110926c..7d02219 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -67,6 +67,7 @@
 import com.android.systemui.statusbar.notification.row.ExpandableView.OnHeightChangedListener;
 import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
 import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
 
 import org.junit.Assert;
 import org.junit.Before;
@@ -100,10 +101,66 @@
 
         FakeFeatureFlags fakeFeatureFlags = new FakeFeatureFlags();
         fakeFeatureFlags.set(Flags.NOTIFICATION_ANIMATE_BIG_PICTURE, true);
+        fakeFeatureFlags.set(Flags.SENSITIVE_REVEAL_ANIM, false);
         mNotificationTestHelper.setFeatureFlags(fakeFeatureFlags);
     }
 
     @Test
+    public void testCanShowHeadsUp_notOnKeyguard_true() throws Exception {
+        ExpandableNotificationRow row = mNotificationTestHelper.createRow();
+
+        row.setOnKeyguard(false);
+
+        assertTrue(row.canShowHeadsUp());
+    }
+
+    @Test
+    public void testCanShowHeadsUp_dozing_true() throws Exception {
+        ExpandableNotificationRow row = mNotificationTestHelper.createRow();
+
+        StatusBarStateController statusBarStateControllerMock =
+                mNotificationTestHelper.getStatusBarStateController();
+        when(statusBarStateControllerMock.isDozing()).thenReturn(true);
+
+        assertTrue(row.canShowHeadsUp());
+    }
+
+    @Test
+    public void testCanShowHeadsUp_bypassEnabled_true() throws Exception {
+        ExpandableNotificationRow row = mNotificationTestHelper.createRow();
+
+        KeyguardBypassController keyguardBypassControllerMock =
+                mNotificationTestHelper.getKeyguardBypassController();
+        when(keyguardBypassControllerMock.getBypassEnabled()).thenReturn(true);
+
+        assertTrue(row.canShowHeadsUp());
+    }
+
+    @Test
+    public void testCanShowHeadsUp_stickyAndNotDemoted_true() throws Exception {
+        ExpandableNotificationRow row = mNotificationTestHelper.createStickyRow();
+
+        assertTrue(row.canShowHeadsUp());
+    }
+
+    @Test
+    public void testCanShowHeadsUp_false() throws Exception {
+        ExpandableNotificationRow row = mNotificationTestHelper.createRow();
+
+        row.setOnKeyguard(true);
+
+        StatusBarStateController statusBarStateControllerMock =
+                mNotificationTestHelper.getStatusBarStateController();
+        when(statusBarStateControllerMock.isDozing()).thenReturn(false);
+
+        KeyguardBypassController keyguardBypassControllerMock =
+                mNotificationTestHelper.getKeyguardBypassController();
+        when(keyguardBypassControllerMock.getBypassEnabled()).thenReturn(false);
+
+        assertFalse(row.canShowHeadsUp());
+    }
+
+    @Test
     public void testUpdateBackgroundColors_isRecursive() throws Exception {
         ExpandableNotificationRow group = mNotificationTestHelper.createGroup();
         group.setTintColor(Color.RED);
@@ -399,17 +456,6 @@
     }
 
     @Test
-    public void testIsBlockingHelperShowing_isCorrectlyUpdated() throws Exception {
-        ExpandableNotificationRow group = mNotificationTestHelper.createGroup();
-
-        group.setBlockingHelperShowing(true);
-        assertTrue(group.isBlockingHelperShowing());
-
-        group.setBlockingHelperShowing(false);
-        assertFalse(group.isBlockingHelperShowing());
-    }
-
-    @Test
     public void testGetNumUniqueChildren_defaultChannel() throws Exception {
         ExpandableNotificationRow groupRow = mNotificationTestHelper.createGroup();
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index d7ac6b4..3d8a744 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -117,7 +117,6 @@
     @Mock private NotificationPresenter mPresenter;
     @Mock private NotificationActivityStarter mNotificationActivityStarter;
     @Mock private NotificationListContainer mNotificationListContainer;
-    @Mock private NotificationInfo.CheckSaveListener mCheckSaveListener;
     @Mock private OnSettingsClickListener mOnSettingsClickListener;
     @Mock private DeviceProvisionedController mDeviceProvisionedController;
     @Mock private CentralSurfaces mCentralSurfaces;
@@ -173,7 +172,6 @@
 
         // Test doesn't support animation since the guts view is not attached.
         doNothing().when(guts).openControls(
-                eq(true) /* shouldDoCircularReveal */,
                 anyInt(),
                 anyInt(),
                 anyBoolean(),
@@ -190,7 +188,6 @@
         assertEquals(View.INVISIBLE, guts.getVisibility());
         mTestableLooper.processAllMessages();
         verify(guts).openControls(
-                eq(true),
                 anyInt(),
                 anyInt(),
                 anyBoolean(),
@@ -213,7 +210,6 @@
 
         // Test doesn't support animation since the guts view is not attached.
         doNothing().when(guts).openControls(
-                eq(true) /* shouldDoCircularReveal */,
                 anyInt(),
                 anyInt(),
                 anyBoolean(),
@@ -237,7 +233,6 @@
         assertTrue(mGutsManager.openGutsInternal(row, 0, 0, menuItem));
         mTestableLooper.processAllMessages();
         verify(guts).openControls(
-                eq(true),
                 anyInt(),
                 anyInt(),
                 anyBoolean(),
@@ -379,7 +374,6 @@
     public void testInitializeNotificationInfoView_PassesAlongProvisionedState() throws Exception {
         NotificationInfo notificationInfoView = mock(NotificationInfo.class);
         ExpandableNotificationRow row = spy(mHelper.createRow());
-        row.setBlockingHelperShowing(false);
         modifyRanking(row.getEntry())
                 .setUserSentiment(USER_SENTIMENT_NEGATIVE)
                 .build();
@@ -414,7 +408,6 @@
     public void testInitializeNotificationInfoView_withInitialAction() throws Exception {
         NotificationInfo notificationInfoView = mock(NotificationInfo.class);
         ExpandableNotificationRow row = spy(mHelper.createRow());
-        row.setBlockingHelperShowing(true);
         modifyRanking(row.getEntry())
                 .setUserSentiment(USER_SENTIMENT_NEGATIVE)
                 .build();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsTest.kt
index e696c87..fdfb4f4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsTest.kt
@@ -76,7 +76,7 @@
     fun openControls() {
         guts.gutsContent = gutsContent
 
-        guts.openControls(true, 0, 0, false, null)
+        guts.openControls(0, 0, false, null)
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index f92678f..f8a8e50 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.notification.row;
 
 import static android.app.Notification.FLAG_BUBBLE;
+import static android.app.Notification.FLAG_FSI_REQUESTED_BUT_DENIED;
 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
 import static android.app.NotificationManager.IMPORTANCE_HIGH;
 
@@ -74,6 +75,7 @@
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow.ExpandableNotificationRowLogger;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow.OnExpandClickListener;
 import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
+import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm;
 import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.policy.InflatedSmartReplyState;
@@ -121,6 +123,7 @@
     private final RowContentBindStage mBindStage;
     private final IconManager mIconManager;
     private final StatusBarStateController mStatusBarStateController;
+    private final KeyguardBypassController mKeyguardBypassController;
     private final PeopleNotificationIdentifier mPeopleNotificationIdentifier;
     private final OnUserInteractionCallback mOnUserInteractionCallback;
     private final NotificationDismissibilityProvider mDismissibilityProvider;
@@ -139,6 +142,7 @@
         dependency.injectMockDependency(MediaOutputDialogFactory.class);
         mMockLogger = mock(ExpandableNotificationRowLogger.class);
         mStatusBarStateController = mock(StatusBarStateController.class);
+        mKeyguardBypassController = mock(KeyguardBypassController.class);
         mGroupMembershipManager = mock(GroupMembershipManager.class);
         mGroupExpansionManager = mock(GroupExpansionManager.class);
         mHeadsUpManager = mock(HeadsUpManagerPhone.class);
@@ -309,6 +313,21 @@
     }
 
     /**
+     * Returns an {@link ExpandableNotificationRow} that shows as a sticky FSI HUN.
+     */
+    public ExpandableNotificationRow createStickyRow()
+            throws Exception {
+        Notification n = createNotification(false /* isGroupSummary */,
+                null /* groupKey */,
+                makeBubbleMetadata(null /* deleteIntent */, false /* autoExpand */));
+        n.flags |= FLAG_FSI_REQUESTED_BUT_DENIED;
+        ExpandableNotificationRow row = generateRow(n, PKG, UID, USER_HANDLE,
+                mDefaultInflationFlags, IMPORTANCE_HIGH);
+        return row;
+    }
+
+
+    /**
      * Returns an {@link ExpandableNotificationRow} that should be shown as a bubble.
      */
     public ExpandableNotificationRow createShortcutBubble(String shortcutId)
@@ -483,6 +502,10 @@
         return mStatusBarStateController;
     }
 
+    public KeyguardBypassController getKeyguardBypassController() {
+        return mKeyguardBypassController;
+    }
+
     private ExpandableNotificationRow generateRow(
             Notification notification,
             String pkg,
@@ -541,13 +564,12 @@
                 APP_NAME,
                 entry.getKey(),
                 mMockLogger,
-                mock(KeyguardBypassController.class),
+                mKeyguardBypassController,
                 mGroupMembershipManager,
                 mGroupExpansionManager,
                 mHeadsUpManager,
                 mBindStage,
                 mock(OnExpandClickListener.class),
-                mock(NotificationMediaManager.class),
                 mock(ExpandableNotificationRow.CoordinateOnClickListener.class),
                 new FalsingManagerFake(),
                 new FalsingCollectorFake(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/AmbientStateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/AmbientStateTest.kt
index 87f4c32..09382ec 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/AmbientStateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/AmbientStateTest.kt
@@ -20,6 +20,8 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolator
 import com.android.systemui.statusbar.StatusBarState
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
 import com.android.systemui.util.mockito.mock
@@ -39,6 +41,8 @@
     private val sectionProvider = StackScrollAlgorithm.SectionProvider { _, _ -> false }
     private val bypassController = StackScrollAlgorithm.BypassController { false }
     private val statusBarKeyguardViewManager = mock<StatusBarKeyguardViewManager>()
+    private val largeScreenShadeInterpolator = mock<LargeScreenShadeInterpolator>()
+    private val featureFlags = mock<FeatureFlags>()
 
     private lateinit var sut: AmbientState
 
@@ -51,6 +55,8 @@
                 sectionProvider,
                 bypassController,
                 statusBarKeyguardViewManager,
+                largeScreenShadeInterpolator,
+                featureFlags
             )
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt
index 9d759c4..b1d3daa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt
@@ -7,6 +7,9 @@
 import com.android.keyguard.BouncerPanelExpansionCalculator.aboutToShowBouncerProgress
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.animation.ShadeInterpolation
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolator
 import com.android.systemui.statusbar.NotificationShelf
 import com.android.systemui.statusbar.StatusBarIconView
 import com.android.systemui.statusbar.notification.LegacySourceType
@@ -21,7 +24,9 @@
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.Mock
 import org.mockito.Mockito.mock
+import org.mockito.MockitoAnnotations
 import org.mockito.Mockito.`when` as whenever
 
 /**
@@ -32,6 +37,9 @@
 @RunWithLooper
 class NotificationShelfTest : SysuiTestCase() {
 
+    @Mock private lateinit var largeScreenShadeInterpolator: LargeScreenShadeInterpolator
+    @Mock private lateinit var flags: FeatureFlags
+
     private val shelf = NotificationShelf(
             context,
             /* attrs */ null,
@@ -50,8 +58,12 @@
 
     @Before
     fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        whenever(ambientState.largeScreenShadeInterpolator).thenReturn(largeScreenShadeInterpolator)
+        whenever(ambientState.featureFlags).thenReturn(flags)
         shelf.bind(ambientState, /* hostLayoutController */ hostLayoutController)
         shelf.layout(/* left */ 0, /* top */ 0, /* right */ 30, /* bottom */5)
+        whenever(ambientState.isSmallScreen).thenReturn(true)
     }
 
     @Test
@@ -295,7 +307,35 @@
     fun updateState_expansionChanging_shelfAlphaUpdated() {
         updateState_expansionChanging_shelfAlphaUpdated(
                 expansionFraction = 0.6f,
-                expectedAlpha = ShadeInterpolation.getContentAlpha(0.6f)
+                expectedAlpha = ShadeInterpolation.getContentAlpha(0.6f),
+        )
+    }
+
+    @Test
+    fun updateState_flagTrue_largeScreen_expansionChanging_shelfAlphaUpdated_largeScreenValue() {
+        val expansionFraction = 0.6f
+        whenever(flags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)).thenReturn(true)
+        whenever(ambientState.isSmallScreen).thenReturn(false)
+        whenever(largeScreenShadeInterpolator.getNotificationContentAlpha(expansionFraction))
+            .thenReturn(0.123f)
+
+        updateState_expansionChanging_shelfAlphaUpdated(
+            expansionFraction = expansionFraction,
+            expectedAlpha = 0.123f
+        )
+    }
+
+    @Test
+    fun updateState_flagFalse_largeScreen_expansionChanging_shelfAlphaUpdated_standardValue() {
+        val expansionFraction = 0.6f
+        whenever(flags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION)).thenReturn(false)
+        whenever(ambientState.isSmallScreen).thenReturn(false)
+        whenever(largeScreenShadeInterpolator.getNotificationContentAlpha(expansionFraction))
+            .thenReturn(0.123f)
+
+        updateState_expansionChanging_shelfAlphaUpdated(
+            expansionFraction = expansionFraction,
+            expectedAlpha = ShadeInterpolation.getContentAlpha(expansionFraction)
         )
     }
 
@@ -305,7 +345,17 @@
 
         updateState_expansionChanging_shelfAlphaUpdated(
                 expansionFraction = 0.95f,
-                expectedAlpha = aboutToShowBouncerProgress(0.95f)
+                expectedAlpha = aboutToShowBouncerProgress(0.95f),
+        )
+    }
+
+    @Test
+    fun updateState_largeScreen_expansionChangingWhileBouncerInTransit_bouncerInterpolatorUsed() {
+        whenever(ambientState.isBouncerInTransit).thenReturn(true)
+
+        updateState_expansionChanging_shelfAlphaUpdated(
+                expansionFraction = 0.95f,
+                expectedAlpha = aboutToShowBouncerProgress(0.95f),
         )
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
index 5b8305d..485f2be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
@@ -52,7 +52,6 @@
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEventListener;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.shade.ShadeController;
-import com.android.systemui.shade.transition.ShadeTransitionController;
 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
@@ -136,7 +135,6 @@
     @Mock private StackStateLogger mStackLogger;
     @Mock private NotificationStackScrollLogger mLogger;
     @Mock private NotificationStackSizeCalculator mNotificationStackSizeCalculator;
-    @Mock private ShadeTransitionController mShadeTransitionController;
     @Mock private FeatureFlags mFeatureFlags;
     @Mock private NotificationTargetsHelper mNotificationTargetsHelper;
     @Mock private SecureSettings mSecureSettings;
@@ -184,7 +182,6 @@
                 mNotifPipelineFlags,
                 mNotifCollection,
                 mLockscreenShadeTransitionController,
-                mShadeTransitionController,
                 mUiEventLogger,
                 mRemoteInputManager,
                 mVisibilityLocationProviderDelegator,
@@ -415,6 +412,37 @@
         verify(mNotificationStackScrollLayout).updateEmptyShadeView(anyBoolean(), anyBoolean());
     }
 
+    @Test
+    public void testAttach_updatesViewStatusBarState() {
+        // GIVEN: Controller is attached
+        mController.attach(mNotificationStackScrollLayout);
+        ArgumentCaptor<StatusBarStateController.StateListener> captor =
+                ArgumentCaptor.forClass(StatusBarStateController.StateListener.class);
+        verify(mSysuiStatusBarStateController).addCallback(captor.capture(), anyInt());
+        StatusBarStateController.StateListener stateListener = captor.getValue();
+
+        // WHEN: StatusBarState changes to SHADE
+        when(mSysuiStatusBarStateController.getState()).thenReturn(SHADE);
+        stateListener.onStateChanged(SHADE);
+
+        // THEN: NSSL is updated with the current state
+        verify(mNotificationStackScrollLayout).setStatusBarState(SHADE);
+
+        // WHEN: Controller is detached
+        mController.mOnAttachStateChangeListener
+                .onViewDetachedFromWindow(mNotificationStackScrollLayout);
+
+        // WHEN: StatusBarState changes to KEYGUARD
+        when(mSysuiStatusBarStateController.getState()).thenReturn(KEYGUARD);
+
+        // WHEN: Controller is re-attached
+        mController.mOnAttachStateChangeListener
+                .onViewAttachedToWindow(mNotificationStackScrollLayout);
+
+        // THEN: NSSL is updated with the current state
+        verify(mNotificationStackScrollLayout).setStatusBarState(KEYGUARD);
+    }
+
     private LogMaker logMatcher(int category, int type) {
         return argThat(new LogMatcher(category, type));
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index dd7143a..7153e59 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.notification.stack;
 
 import static android.view.View.GONE;
+import static android.view.WindowInsets.Type.ime;
 
 import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL;
 import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_GENTLE;
@@ -46,6 +47,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.graphics.Insets;
 import android.graphics.Rect;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -54,6 +56,8 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.WindowInsets;
+import android.view.WindowInsetsAnimation;
 import android.widget.TextView;
 
 import androidx.test.annotation.UiThreadTest;
@@ -64,7 +68,9 @@
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.shade.ShadeController;
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
 import com.android.systemui.statusbar.EmptyShadeView;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.NotificationShelfController;
@@ -91,6 +97,8 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
+import java.util.ArrayList;
+
 /**
  * Tests for {@link NotificationStackScrollLayout}.
  */
@@ -123,6 +131,8 @@
     @Mock private NotificationShelf mNotificationShelf;
     @Mock private NotificationStackSizeCalculator mNotificationStackSizeCalculator;
     @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+    @Mock private LargeScreenShadeInterpolator mLargeScreenShadeInterpolator;
+    @Mock private FeatureFlags mFeatureFlags;
 
     @Before
     @UiThreadTest
@@ -136,7 +146,10 @@
                 mDumpManager,
                 mNotificationSectionsManager,
                 mBypassController,
-                mStatusBarKeyguardViewManager));
+                mStatusBarKeyguardViewManager,
+                mLargeScreenShadeInterpolator,
+                mFeatureFlags
+        ));
 
         // Inject dependencies before initializing the layout
         mDependency.injectTestDependency(SysuiStatusBarStateController.class, mBarState);
@@ -843,6 +856,19 @@
         verify(mEmptyShadeView).setFooterText(not(0));
     }
 
+    @Test
+    public void testWindowInsetAnimationProgress_updatesBottomInset() {
+        int bottomImeInset = 100;
+        mStackScrollerInternal.setAnimatedInsetsEnabled(true);
+        WindowInsets windowInsets = new WindowInsets.Builder()
+                .setInsets(ime(), Insets.of(0, 0, 0, bottomImeInset)).build();
+        ArrayList<WindowInsetsAnimation> windowInsetsAnimations = new ArrayList<>();
+        mStackScrollerInternal
+                .dispatchWindowInsetsAnimationProgress(windowInsets, windowInsetsAnimations);
+
+        assertEquals(bottomImeInset, mStackScrollerInternal.mBottomInset);
+    }
+
     private void setBarStateForTest(int state) {
         // Can't inject this through the listener or we end up on the actual implementation
         // rather than the mock because the spy just coppied the anonymous inner /shruggie.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt
index 55dae9d..e6f10cd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt
@@ -219,6 +219,25 @@
     }
 
     @Test
+    fun spaceNeeded_fsiHunOnLockscreen_usesIntrinsicHeight() {
+        setGapHeight(0f)
+        // No divider height since we're testing one element where index = 0
+
+        val expandableView = createMockStickyRow(rowHeight)
+        whenever(expandableView.getMinHeight(any())).thenReturn(5)
+        whenever(expandableView.intrinsicHeight).thenReturn(10)
+
+        val space =
+                sizeCalculator.spaceNeeded(
+                        expandableView,
+                        visibleIndex = 0,
+                        previousView = null,
+                        stack = stackLayout,
+                        onLockscreen = true)
+        assertThat(space).isEqualTo(10)
+    }
+
+    @Test
     fun spaceNeeded_notOnLockscreen_usesIntrinsicHeight() {
         setGapHeight(0f)
         // No divider height since we're testing one element where index = 0
@@ -276,6 +295,25 @@
         return row
     }
 
+    private fun createMockStickyRow(
+            height: Float = rowHeight,
+            isRemoved: Boolean = false,
+            visibility: Int = VISIBLE
+    ): ExpandableNotificationRow {
+        val row = mock(ExpandableNotificationRow::class.java)
+        val entry = mock(NotificationEntry::class.java)
+        whenever(entry.isStickyAndNotDemoted).thenReturn(true)
+
+        val sbn = mock(StatusBarNotification::class.java)
+        whenever(entry.sbn).thenReturn(sbn)
+        whenever(row.entry).thenReturn(entry)
+        whenever(row.isRemoved).thenReturn(isRemoved)
+        whenever(row.visibility).thenReturn(visibility)
+        whenever(row.getMinHeight(any())).thenReturn(height.toInt())
+        whenever(row.intrinsicHeight).thenReturn(height.toInt())
+        return row
+    }
+
     private fun setGapHeight(height: Float) {
         whenever(stackLayout.calculateGapHeight(nullable(), nullable(), any())).thenReturn(height)
         whenever(stackLayout.calculateGapHeight(nullable(), nullable(), /* visibleIndex= */ eq(0)))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
index 680a323..78da782 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
@@ -20,6 +20,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
@@ -227,14 +228,154 @@
     }
 
     @Test
-    public void testHandleUpEvent_menuRow() {
-        when(mSwipeHelper.getCurrentMenuRow()).thenReturn(mMenuRow);
-        doNothing().when(mSwipeHelper).handleMenuRowSwipe(mEvent, mView, 0, mMenuRow);
+    public void testHandleUpEvent_menuRowWithoutMenu_dismiss() {
+        doNothing().when(mSwipeHelper).dismiss(any(), anyFloat());
+        doReturn(true).when(mSwipeHelper).isDismissGesture(any());
+        doReturn(true).when(mSwipeHelper).swipedFarEnough();
+        when(mMenuRow.shouldShowMenu()).thenReturn(true);
+        mSwipeHelper.setCurrentMenuRow(mMenuRow);
 
         assertTrue("Menu row exists",
                 mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
         verify(mMenuRow, times(1)).onTouchEnd();
-        verify(mSwipeHelper, times(1)).handleMenuRowSwipe(mEvent, mView, 0, mMenuRow);
+        verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+        verify(mSwipeHelper, times(1)).dismiss(mView, 0);
+        verify(mSwipeHelper, never()).isFalseGesture();
+    }
+
+    @Test
+    public void testHandleUpEvent_menuRowWithoutMenu_snapback() {
+        doNothing().when(mSwipeHelper).snapChild(any(), anyInt(), anyFloat());
+        doReturn(false).when(mSwipeHelper).isDismissGesture(any());
+        doReturn(true).when(mSwipeHelper).swipedFarEnough();
+        when(mMenuRow.shouldShowMenu()).thenReturn(true);
+        mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+        assertTrue("Menu row exists",
+                mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+        verify(mMenuRow, times(1)).onTouchEnd();
+        verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+        verify(mSwipeHelper, times(1)).snapClosed(mView, 0);
+        verify(mMenuRow, times(1)).onSnapClosed();
+        verify(mSwipeHelper, never()).isFalseGesture();
+    }
+
+    @Test
+    public void testHandleUpEvent_menuRowWithOpenMenu_dismissed() {
+        doNothing().when(mSwipeHelper).dismiss(any(), anyFloat());
+        doReturn(true).when(mSwipeHelper).isDismissGesture(any());
+        doReturn(true).when(mSwipeHelper).swipedFarEnough();
+        when(mMenuRow.shouldShowMenu()).thenReturn(true);
+        when(mMenuRow.isSnappedAndOnSameSide()).thenReturn(true);
+        mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+        assertTrue("Menu row exists",
+                mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+        verify(mMenuRow, times(1)).onTouchEnd();
+        verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+        verify(mSwipeHelper, times(1)).dismiss(mView, 0);
+        verify(mSwipeHelper, never()).isFalseGesture();
+    }
+
+    @Test
+    public void testHandleUpEvent_menuRowWithOpenMenu_snapback() {
+        doNothing().when(mSwipeHelper).snapChild(any(), anyInt(), anyFloat());
+        doReturn(false).when(mSwipeHelper).isDismissGesture(any());
+        doReturn(true).when(mSwipeHelper).swipedFarEnough();
+        when(mMenuRow.shouldShowMenu()).thenReturn(true);
+        when(mMenuRow.isSnappedAndOnSameSide()).thenReturn(true);
+        mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+        assertTrue("Menu row exists",
+                mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+        verify(mMenuRow, times(1)).onTouchEnd();
+        verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+        verify(mSwipeHelper, times(1)).snapClosed(mView, 0);
+        verify(mMenuRow, times(1)).onSnapClosed();
+        verify(mSwipeHelper, never()).isFalseGesture();
+    }
+
+    @Test
+    public void testHandleUpEvent_menuRowWithClosedMenu_dismissed() {
+        doNothing().when(mSwipeHelper).dismiss(any(), anyFloat());
+        doReturn(true).when(mSwipeHelper).isDismissGesture(any());
+        doReturn(true).when(mSwipeHelper).swipedFarEnough();
+        when(mMenuRow.shouldShowMenu()).thenReturn(true);
+        when(mMenuRow.isSnappedAndOnSameSide()).thenReturn(false);
+        mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+        assertTrue("Menu row exists",
+                mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+        verify(mMenuRow, times(1)).onTouchEnd();
+        verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+        verify(mSwipeHelper, times(1)).dismiss(mView, 0);
+        verify(mSwipeHelper, never()).isFalseGesture();
+    }
+
+    @Test
+    public void testHandleUpEvent_menuRowWithClosedMenu_snapback() {
+        doNothing().when(mSwipeHelper).snapChild(any(), anyInt(), anyFloat());
+        doReturn(false).when(mSwipeHelper).isDismissGesture(any());
+        doReturn(true).when(mSwipeHelper).swipedFarEnough();
+        when(mMenuRow.shouldShowMenu()).thenReturn(true);
+        when(mMenuRow.isSnappedAndOnSameSide()).thenReturn(false);
+        mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+        assertTrue("Menu row exists",
+                mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+        verify(mMenuRow, times(1)).onTouchEnd();
+        verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+        verify(mSwipeHelper, times(1)).snapClosed(mView, 0);
+        verify(mMenuRow, times(1)).onSnapClosed();
+        verify(mSwipeHelper, never()).isFalseGesture();
+    }
+
+    @Test
+    public void testIsDismissGesture() {
+        doReturn(false).when(mSwipeHelper).isFalseGesture();
+        doReturn(true).when(mSwipeHelper).swipedFarEnough();
+        doReturn(true).when(mSwipeHelper).swipedFastEnough();
+        when(mCallback.canChildBeDismissedInDirection(any(), anyBoolean())).thenReturn(true);
+        when(mEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_UP);
+
+        assertTrue("Should be a dismiss gesture", mSwipeHelper.isDismissGesture(mEvent));
+        verify(mSwipeHelper, times(1)).isFalseGesture();
+    }
+
+    @Test
+    public void testIsDismissGesture_falseGesture() {
+        doReturn(true).when(mSwipeHelper).isFalseGesture();
+        doReturn(true).when(mSwipeHelper).swipedFarEnough();
+        doReturn(true).when(mSwipeHelper).swipedFastEnough();
+        when(mCallback.canChildBeDismissedInDirection(any(), anyBoolean())).thenReturn(true);
+        when(mEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_UP);
+
+        assertFalse("False gesture should stop dismissal", mSwipeHelper.isDismissGesture(mEvent));
+        verify(mSwipeHelper, times(1)).isFalseGesture();
+    }
+
+    @Test
+    public void testIsDismissGesture_farEnough() {
+        doReturn(false).when(mSwipeHelper).isFalseGesture();
+        doReturn(true).when(mSwipeHelper).swipedFarEnough();
+        doReturn(false).when(mSwipeHelper).swipedFastEnough();
+        when(mCallback.canChildBeDismissedInDirection(any(), anyBoolean())).thenReturn(true);
+        when(mEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_UP);
+
+        assertTrue("Should be a dismissal", mSwipeHelper.isDismissGesture(mEvent));
+        verify(mSwipeHelper, times(1)).isFalseGesture();
+    }
+
+    @Test
+    public void testIsDismissGesture_notFarOrFastEnough() {
+        doReturn(false).when(mSwipeHelper).isFalseGesture();
+        doReturn(false).when(mSwipeHelper).swipedFarEnough();
+        doReturn(false).when(mSwipeHelper).swipedFastEnough();
+        when(mCallback.canChildBeDismissedInDirection(any(), anyBoolean())).thenReturn(true);
+        when(mEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_UP);
+
+        assertFalse("Should not be a dismissal", mSwipeHelper.isDismissGesture(mEvent));
+        verify(mSwipeHelper, times(1)).isFalseGesture();
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
index 4d9db8c..7f20f1e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
@@ -8,6 +8,9 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.animation.ShadeInterpolation.getContentAlpha
 import com.android.systemui.dump.DumpManager
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolator
 import com.android.systemui.statusbar.EmptyShadeView
 import com.android.systemui.statusbar.NotificationShelf
 import com.android.systemui.statusbar.StatusBarState
@@ -15,11 +18,13 @@
 import com.android.systemui.statusbar.notification.row.ExpandableView
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
 import com.android.systemui.util.mockito.mock
+import com.google.common.truth.Expect
 import com.google.common.truth.Truth.assertThat
 import junit.framework.Assert.assertEquals
 import junit.framework.Assert.assertFalse
 import junit.framework.Assert.assertTrue
 import org.junit.Before
+import org.junit.Rule
 import org.junit.Test
 import org.mockito.Mockito.any
 import org.mockito.Mockito.eq
@@ -30,12 +35,19 @@
 @SmallTest
 class StackScrollAlgorithmTest : SysuiTestCase() {
 
+
+    @JvmField @Rule
+    var expect: Expect = Expect.create()
+
+    private val largeScreenShadeInterpolator = mock<LargeScreenShadeInterpolator>()
+
     private val hostView = FrameLayout(context)
     private val stackScrollAlgorithm = StackScrollAlgorithm(context, hostView)
     private val notificationRow = mock<ExpandableNotificationRow>()
     private val dumpManager = mock<DumpManager>()
     private val mStatusBarKeyguardViewManager = mock<StatusBarKeyguardViewManager>()
     private val notificationShelf = mock<NotificationShelf>()
+    private val featureFlags = mock<FeatureFlags>()
     private val emptyShadeView = EmptyShadeView(context, /* attrs= */ null).apply {
         layout(/* l= */ 0, /* t= */ 0, /* r= */ 100, /* b= */ 100)
     }
@@ -44,8 +56,10 @@
             dumpManager,
             /* sectionProvider */ { _, _ -> false },
             /* bypassController */ { false },
-            mStatusBarKeyguardViewManager
-    )
+            mStatusBarKeyguardViewManager,
+            largeScreenShadeInterpolator,
+            featureFlags,
+        )
 
     private val testableResources = mContext.getOrCreateTestableResources()
 
@@ -59,6 +73,7 @@
     fun setUp() {
         whenever(notificationShelf.viewState).thenReturn(ExpandableViewState())
         whenever(notificationRow.viewState).thenReturn(ExpandableViewState())
+        ambientState.isSmallScreen = true
 
         hostView.addView(notificationRow)
     }
@@ -145,11 +160,46 @@
     }
 
     @Test
-    fun resetViewStates_expansionChangingWhileBouncerInTransit_notificationAlphaUpdated() {
+    fun resetViewStates_flagTrue_largeScreen_expansionChanging_alphaUpdated_largeScreenValue() {
+        val expansionFraction = 0.6f
+        val surfaceAlpha = 123f
+        ambientState.isSmallScreen = false
+        whenever(featureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
+                .thenReturn(true)
+        whenever(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit).thenReturn(false)
+        whenever(largeScreenShadeInterpolator.getNotificationContentAlpha(expansionFraction))
+            .thenReturn(surfaceAlpha)
+
+        resetViewStates_expansionChanging_notificationAlphaUpdated(
+            expansionFraction = expansionFraction,
+            expectedAlpha = surfaceAlpha,
+        )
+    }
+
+    @Test
+    fun resetViewStates_flagFalse_largeScreen_expansionChanging_alphaUpdated_standardValue() {
+        val expansionFraction = 0.6f
+        val surfaceAlpha = 123f
+        ambientState.isSmallScreen = false
+        whenever(featureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
+                .thenReturn(false)
+        whenever(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit).thenReturn(false)
+        whenever(largeScreenShadeInterpolator.getNotificationContentAlpha(expansionFraction))
+            .thenReturn(surfaceAlpha)
+
+        resetViewStates_expansionChanging_notificationAlphaUpdated(
+            expansionFraction = expansionFraction,
+            expectedAlpha = getContentAlpha(expansionFraction),
+        )
+    }
+
+    @Test
+    fun expansionChanging_largeScreen_bouncerInTransit_alphaUpdated_bouncerValues() {
+        ambientState.isSmallScreen = false
         whenever(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit).thenReturn(true)
         resetViewStates_expansionChanging_notificationAlphaUpdated(
                 expansionFraction = 0.95f,
-                expectedAlpha = aboutToShowBouncerProgress(0.95f)
+                expectedAlpha = aboutToShowBouncerProgress(0.95f),
         )
     }
 
@@ -696,7 +746,7 @@
 
     private fun resetViewStates_expansionChanging_notificationAlphaUpdated(
             expansionFraction: Float,
-            expectedAlpha: Float
+            expectedAlpha: Float,
     ) {
         ambientState.isExpansionChanging = true
         ambientState.expansionFraction = expansionFraction
@@ -704,7 +754,7 @@
 
         stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
 
-        assertThat(notificationRow.viewState.alpha).isEqualTo(expectedAlpha)
+        expect.that(notificationRow.viewState.alpha).isEqualTo(expectedAlpha)
     }
 }
 
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 ec294b1..68d67ca 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
@@ -517,6 +517,26 @@
         verify(mVibratorHelper).vibrateAuthError(anyString());
     }
 
+    @Test
+    public void onFingerprintDetect_showBouncer() {
+        // WHEN fingerprint detect occurs
+        mBiometricUnlockController.onBiometricDetected(UserHandle.USER_CURRENT,
+                BiometricSourceType.FINGERPRINT, true /* isStrongBiometric */);
+
+        // THEN shows primary bouncer
+        verify(mStatusBarKeyguardViewManager).showPrimaryBouncer(anyBoolean());
+    }
+
+    @Test
+    public void onFaceDetect_showBouncer() {
+        // WHEN face detect occurs
+        mBiometricUnlockController.onBiometricDetected(UserHandle.USER_CURRENT,
+                BiometricSourceType.FACE, false /* isStrongBiometric */);
+
+        // THEN shows primary bouncer
+        verify(mStatusBarKeyguardViewManager).showPrimaryBouncer(anyBoolean());
+    }
+
     private void givenFingerprintModeUnlockCollapsing() {
         when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
         when(mUpdateMonitor.isDeviceInteractive()).thenReturn(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index db4bb45..031c17f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -77,6 +77,8 @@
 import android.view.ViewGroup.LayoutParams;
 import android.view.ViewRootImpl;
 import android.view.WindowManager;
+import android.window.BackEvent;
+import android.window.OnBackAnimationCallback;
 import android.window.OnBackInvokedCallback;
 import android.window.OnBackInvokedDispatcher;
 import android.window.WindowOnBackInvokedDispatcher;
@@ -182,6 +184,8 @@
 import com.android.wm.shell.bubbles.Bubbles;
 import com.android.wm.shell.startingsurface.StartingSurface;
 
+import dagger.Lazy;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -194,8 +198,6 @@
 import java.io.PrintWriter;
 import java.util.Optional;
 
-import dagger.Lazy;
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper(setAsMainLooper = true)
@@ -333,6 +335,10 @@
         mFeatureFlags.set(Flags.WM_ENABLE_PREDICTIVE_BACK_SYSUI, false);
         // Set default value to avoid IllegalStateException.
         mFeatureFlags.set(Flags.SHORTCUT_LIST_SEARCH_LAYOUT, false);
+        // For the Shade to respond to Back gesture, we must enable the event routing
+        mFeatureFlags.set(Flags.WM_SHADE_ALLOW_BACK_GESTURE, true);
+        // For the Shade to animate during the Back gesture, we must enable the animation flag.
+        mFeatureFlags.set(Flags.WM_SHADE_ANIMATE_BACK_GESTURE, true);
 
         IThermalService thermalService = mock(IThermalService.class);
         mPowerManager = new PowerManager(mContext, mPowerManagerService, thermalService,
@@ -855,6 +861,50 @@
         verify(mShadeController).animateCollapseShade();
     }
 
+    /**
+     * When back progress is at 100%, the onBackProgressed animation driver inside
+     * NotificationPanelViewController should be invoked appropriately (with 1.0f passed in).
+     */
+    @Test
+    public void testPredictiveBackAnimation_progressMaxScalesPanel() {
+        mCentralSurfaces.setNotificationShadeWindowViewController(
+                mNotificationShadeWindowViewController);
+        mCentralSurfaces.handleVisibleToUserChanged(true);
+        verify(mOnBackInvokedDispatcher).registerOnBackInvokedCallback(
+                eq(OnBackInvokedDispatcher.PRIORITY_DEFAULT),
+                mOnBackInvokedCallback.capture());
+
+        OnBackAnimationCallback onBackAnimationCallback =
+                (OnBackAnimationCallback) (mOnBackInvokedCallback.getValue());
+        when(mNotificationPanelViewController.canPanelBeCollapsed()).thenReturn(true);
+
+        BackEvent fakeSwipeInFromLeftEdge = new BackEvent(20.0f, 100.0f, 1.0f, BackEvent.EDGE_LEFT);
+        onBackAnimationCallback.onBackProgressed(fakeSwipeInFromLeftEdge);
+        verify(mNotificationPanelViewController).onBackProgressed(eq(1.0f));
+    }
+
+    /**
+     * When back progress is at 0%, the onBackProgressed animation driver inside
+     * NotificationPanelViewController should be invoked appropriately (with 0.0f passed in).
+     */
+    @Test
+    public void testPredictiveBackAnimation_progressMinScalesPanel() {
+        mCentralSurfaces.setNotificationShadeWindowViewController(
+                mNotificationShadeWindowViewController);
+        mCentralSurfaces.handleVisibleToUserChanged(true);
+        verify(mOnBackInvokedDispatcher).registerOnBackInvokedCallback(
+                eq(OnBackInvokedDispatcher.PRIORITY_DEFAULT),
+                mOnBackInvokedCallback.capture());
+
+        OnBackAnimationCallback onBackAnimationCallback =
+                (OnBackAnimationCallback) (mOnBackInvokedCallback.getValue());
+        when(mNotificationPanelViewController.canPanelBeCollapsed()).thenReturn(true);
+
+        BackEvent fakeSwipeInFromLeftEdge = new BackEvent(20.0f, 10.0f, 0.0f, BackEvent.EDGE_LEFT);
+        onBackAnimationCallback.onBackProgressed(fakeSwipeInFromLeftEdge);
+        verify(mNotificationPanelViewController).onBackProgressed(eq(0.0f));
+    }
+
     @Test
     public void testPanelOpenForHeadsUp() {
         when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
@@ -1030,6 +1080,45 @@
     }
 
     @Test
+    public void testSetDozingNotUnlocking_transitionToAuthScrimmed_cancelKeyguardFadingAway() {
+        when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
+        when(mKeyguardStateController.isKeyguardFadingAway()).thenReturn(true);
+
+        mCentralSurfaces.updateScrimController();
+
+        verify(mScrimController).transitionTo(eq(ScrimState.AUTH_SCRIMMED_SHADE));
+        verify(mStatusBarKeyguardViewManager).onKeyguardFadedAway();
+    }
+
+    @Test
+    public void testOccludingQSNotExpanded_transitionToAuthScrimmed() {
+        when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
+
+        // GIVEN device occluded and panel is NOT expanded
+        mCentralSurfaces.setBarStateForTest(SHADE); // occluding on LS has StatusBarState = SHADE
+        when(mKeyguardStateController.isOccluded()).thenReturn(true);
+        mCentralSurfaces.mPanelExpanded = false;
+
+        mCentralSurfaces.updateScrimController();
+
+        verify(mScrimController).transitionTo(eq(ScrimState.AUTH_SCRIMMED));
+    }
+
+    @Test
+    public void testOccludingQSExpanded_transitionToAuthScrimmedShade() {
+        when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
+
+        // GIVEN device occluded and qs IS expanded
+        mCentralSurfaces.setBarStateForTest(SHADE); // occluding on LS has StatusBarState = SHADE
+        when(mKeyguardStateController.isOccluded()).thenReturn(true);
+        mCentralSurfaces.mPanelExpanded = true;
+
+        mCentralSurfaces.updateScrimController();
+
+        verify(mScrimController).transitionTo(eq(ScrimState.AUTH_SCRIMMED_SHADE));
+    }
+
+    @Test
     public void testShowKeyguardImplementation_setsState() {
         when(mLockscreenUserManager.getCurrentProfiles()).thenReturn(new SparseArray<>());
 
@@ -1253,6 +1342,15 @@
         verify(mPowerManagerService, never()).wakeUp(anyLong(), anyInt(), anyString(), anyString());
     }
 
+    @Test
+    public void frpLockedDevice_shadeDisabled() {
+        when(mDeviceProvisionedController.isFrpActive()).thenReturn(true);
+        when(mDozeServiceHost.isPulsing()).thenReturn(true);
+        mCentralSurfaces.updateNotificationPanelTouchState();
+
+        verify(mNotificationPanelViewController).setTouchAndAnimationDisabled(true);
+    }
+
     /**
      * Configures the appropriate mocks and then calls {@link CentralSurfacesImpl#updateIsKeyguard}
      * to reconfigure the keyguard to reflect the requested showing/occluded states.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
index eb5edbc..f5b7ca8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
@@ -180,6 +180,7 @@
         when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true);
         mDozeParameters.onTuningChanged(Settings.Secure.DOZE_ALWAYS_ON, "1");
 
+        verify(mScreenOffAnimationController).onAlwaysOnChanged(false);
         assertThat(mDozeParameters.getAlwaysOn()).isFalse();
     }
 
@@ -196,13 +197,16 @@
         mBatteryStateChangeCallback.getValue().onPowerSaveChanged(true);
 
         verify(callback, times(2)).onAlwaysOnChange();
+        verify(mScreenOffAnimationController, times(2)).onAlwaysOnChanged(false);
         assertThat(mDozeParameters.getAlwaysOn()).isFalse();
 
+        reset(mScreenOffAnimationController);
         reset(callback);
         when(mBatteryController.isAodPowerSave()).thenReturn(false);
         mBatteryStateChangeCallback.getValue().onPowerSaveChanged(true);
 
         verify(callback).onAlwaysOnChange();
+        verify(mScreenOffAnimationController).onAlwaysOnChanged(true);
         assertThat(mDozeParameters.getAlwaysOn()).isTrue();
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
index 305b9fe..6b18169 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.phone
 
 import android.app.AlarmManager
-import android.app.IActivityManager
 import android.app.admin.DevicePolicyManager
 import android.content.SharedPreferences
 import android.os.UserManager
@@ -87,7 +86,6 @@
     @Mock private lateinit var keyguardStateController: KeyguardStateController
     @Mock private lateinit var locationController: LocationController
     @Mock private lateinit var sensorPrivacyController: SensorPrivacyController
-    @Mock private lateinit var iActivityManager: IActivityManager
     @Mock private lateinit var alarmManager: AlarmManager
     @Mock private lateinit var userManager: UserManager
     @Mock private lateinit var userTracker: UserTracker
@@ -176,6 +174,7 @@
             commandQueue,
             broadcastDispatcher,
             executor,
+            executor,
             testableLooper.looper,
             context.resources,
             castController,
@@ -190,7 +189,6 @@
             keyguardStateController,
             locationController,
             sensorPrivacyController,
-            iActivityManager,
             alarmManager,
             userManager,
             userTracker,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
index 14d239a..cdc9898 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
@@ -18,7 +18,6 @@
 
 import android.view.LayoutInflater
 import android.view.MotionEvent
-import android.view.ViewGroup
 import android.view.ViewTreeObserver
 import android.view.ViewTreeObserver.OnPreDrawListener
 import android.widget.FrameLayout
@@ -55,8 +54,6 @@
     @Mock
     private lateinit var notificationPanelViewController: NotificationPanelViewController
     @Mock
-    private lateinit var panelView: ViewGroup
-    @Mock
     private lateinit var moveFromCenterAnimation: StatusBarMoveFromCenterAnimationController
     @Mock
     private lateinit var sysuiUnfoldComponent: SysUIUnfoldComponent
@@ -116,7 +113,7 @@
         val returnVal = view.onTouchEvent(
                         MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0))
         assertThat(returnVal).isFalse()
-        verify(notificationPanelViewController, never()).sendTouchEventToView(any())
+        verify(notificationPanelViewController, never()).handleExternalTouch(any())
     }
 
     @Test
@@ -128,7 +125,7 @@
         val returnVal = view.onTouchEvent(
                 MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0))
         assertThat(returnVal).isTrue()
-        verify(notificationPanelViewController, never()).sendTouchEventToView(any())
+        verify(notificationPanelViewController, never()).handleExternalTouch(any())
     }
 
     @Test
@@ -141,7 +138,7 @@
 
         view.onTouchEvent(event)
 
-        verify(notificationPanelViewController).sendTouchEventToView(event)
+        verify(notificationPanelViewController).handleExternalTouch(event)
     }
 
     @Test
@@ -154,7 +151,7 @@
 
         view.onTouchEvent(event)
 
-        verify(notificationPanelViewController).sendTouchEventToView(event)
+        verify(notificationPanelViewController).handleExternalTouch(event)
     }
 
     @Test
@@ -167,7 +164,7 @@
 
         view.onTouchEvent(event)
 
-        verify(notificationPanelViewController, never()).sendTouchEventToView(any())
+        verify(notificationPanelViewController, never()).handleExternalTouch(any())
     }
 
     private fun createViewMock(): PhoneStatusBarView {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
index 27b1da0..3ed454f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
@@ -19,6 +19,7 @@
 import android.view.MotionEvent
 import android.view.ViewGroup
 import androidx.test.filters.SmallTest
+import com.android.systemui.Gefingerpoken
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.shade.NotificationPanelViewController
 import com.google.common.truth.Truth.assertThat
@@ -94,16 +95,17 @@
         // No assert needed, just testing no crash
     }
 
-    private class TestTouchEventHandler : PhoneStatusBarView.TouchEventHandler {
+    private class TestTouchEventHandler : Gefingerpoken {
         var lastInterceptEvent: MotionEvent? = null
         var lastEvent: MotionEvent? = null
         var handleTouchReturnValue: Boolean = false
 
-        override fun onInterceptTouchEvent(event: MotionEvent?) {
+        override fun onInterceptTouchEvent(event: MotionEvent?): Boolean {
             lastInterceptEvent = event
+            return handleTouchReturnValue
         }
 
-        override fun handleTouchEvent(event: MotionEvent?): Boolean {
+        override fun onTouchEvent(event: MotionEvent?): Boolean {
             lastEvent = event
             return handleTouchReturnValue
         }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index dc5a047..7a1270f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -39,6 +39,8 @@
 import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
+import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
+
 import android.animation.Animator;
 import android.app.AlarmManager;
 import android.graphics.Color;
@@ -57,9 +59,18 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.animation.ShadeInterpolation;
 import com.android.systemui.dock.DockManager;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
 import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants;
+import com.android.systemui.keyguard.shared.model.KeyguardState;
+import com.android.systemui.keyguard.shared.model.TransitionState;
+import com.android.systemui.keyguard.shared.model.TransitionStep;
+import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
 import com.android.systemui.scrim.ScrimView;
+import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
+import com.android.systemui.shade.transition.LinearLargeScreenShadeInterpolator;
 import com.android.systemui.statusbar.policy.FakeConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.concurrency.FakeExecutor;
@@ -85,8 +96,10 @@
 import java.util.HashSet;
 import java.util.Map;
 
+import kotlinx.coroutines.CoroutineDispatcher;
+
 @RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
 @SmallTest
 public class ScrimControllerTest extends SysuiTestCase {
 
@@ -94,6 +107,8 @@
 
     private final FakeConfigurationController mConfigurationController =
             new FakeConfigurationController();
+    private final LargeScreenShadeInterpolator
+            mLinearLargeScreenShadeInterpolator = new LinearLargeScreenShadeInterpolator();
 
     private ScrimController mScrimController;
     private ScrimView mScrimBehind;
@@ -115,9 +130,14 @@
     @Mock private DockManager mDockManager;
     @Mock private ScreenOffAnimationController mScreenOffAnimationController;
     @Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
+    @Mock private PrimaryBouncerToGoneTransitionViewModel mPrimaryBouncerToGoneTransitionViewModel;
+    @Mock private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
+    @Mock private CoroutineDispatcher mMainDispatcher;
+
     // TODO(b/204991468): Use a real PanelExpansionStateManager object once this bug is fixed. (The
     //   event-dispatch-on-registration pattern caused some of these unit tests to fail.)
     @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+    @Mock private FeatureFlags mFeatureFlags;
 
     private static class AnimatorListener implements Animator.AnimatorListener {
         private int mNumStarts;
@@ -225,13 +245,30 @@
         when(mDelayedWakeLockBuilder.build()).thenReturn(mWakeLock);
         when(mDockManager.isDocked()).thenReturn(false);
 
-        mScrimController = new ScrimController(mLightBarController,
-                mDozeParameters, mAlarmManager, mKeyguardStateController, mDelayedWakeLockBuilder,
-                new FakeHandler(mLooper.getLooper()), mKeyguardUpdateMonitor,
-                mDockManager, mConfigurationController, new FakeExecutor(new FakeSystemClock()),
+        when(mKeyguardTransitionInteractor.getPrimaryBouncerToGoneTransition())
+                .thenReturn(emptyFlow());
+        when(mPrimaryBouncerToGoneTransitionViewModel.getScrimAlpha())
+                .thenReturn(emptyFlow());
+
+        mScrimController = new ScrimController(
+                mLightBarController,
+                mDozeParameters,
+                mAlarmManager,
+                mKeyguardStateController,
+                mDelayedWakeLockBuilder,
+                new FakeHandler(mLooper.getLooper()),
+                mKeyguardUpdateMonitor,
+                mDockManager,
+                mConfigurationController,
+                new FakeExecutor(new FakeSystemClock()),
                 mScreenOffAnimationController,
                 mKeyguardUnlockAnimationController,
-                mStatusBarKeyguardViewManager);
+                mStatusBarKeyguardViewManager,
+                mPrimaryBouncerToGoneTransitionViewModel,
+                mKeyguardTransitionInteractor,
+                mMainDispatcher,
+                mLinearLargeScreenShadeInterpolator,
+                mFeatureFlags);
         mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);
         mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront);
         mScrimController.setAnimatorListener(mAnimatorListener);
@@ -629,7 +666,81 @@
     }
 
     @Test
-    public void transitionToUnlocked() {
+    public void transitionToUnlocked_clippedQs() {
+        mScrimController.setClipsQsScrim(true);
+        mScrimController.setRawPanelExpansionFraction(0f);
+        mScrimController.transitionTo(ScrimState.UNLOCKED);
+        finishAnimationsImmediately();
+
+        assertScrimTinted(Map.of(
+                mNotificationsScrim, false,
+                mScrimInFront, false,
+                mScrimBehind, true
+        ));
+        assertScrimAlpha(Map.of(
+                mScrimInFront, TRANSPARENT,
+                mNotificationsScrim, TRANSPARENT,
+                mScrimBehind, OPAQUE));
+
+        mScrimController.setRawPanelExpansionFraction(0.25f);
+        assertScrimAlpha(Map.of(
+                mScrimInFront, TRANSPARENT,
+                mNotificationsScrim, SEMI_TRANSPARENT,
+                mScrimBehind, OPAQUE));
+
+        mScrimController.setRawPanelExpansionFraction(0.5f);
+        assertScrimAlpha(Map.of(
+                mScrimInFront, TRANSPARENT,
+                mNotificationsScrim, OPAQUE,
+                mScrimBehind, OPAQUE));
+    }
+
+    @Test
+    public void transitionToUnlocked_nonClippedQs_flagTrue_followsLargeScreensInterpolator() {
+        when(mFeatureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
+                .thenReturn(true);
+        mScrimController.setClipsQsScrim(false);
+        mScrimController.setRawPanelExpansionFraction(0f);
+        mScrimController.transitionTo(ScrimState.UNLOCKED);
+        finishAnimationsImmediately();
+
+        assertScrimTinted(Map.of(
+                mNotificationsScrim, false,
+                mScrimInFront, false,
+                mScrimBehind, true
+        ));
+        // The large screens interpolator used in this test is a linear one, just for tests.
+        // Assertions below are based on this assumption, and that the code uses that interpolator
+        // when on a large screen (QS not clipped).
+        assertScrimAlpha(Map.of(
+                mScrimInFront, TRANSPARENT,
+                mNotificationsScrim, TRANSPARENT,
+                mScrimBehind, TRANSPARENT));
+
+        mScrimController.setRawPanelExpansionFraction(0.5f);
+        assertScrimAlpha(Map.of(
+                mScrimInFront, TRANSPARENT,
+                mNotificationsScrim, SEMI_TRANSPARENT,
+                mScrimBehind, SEMI_TRANSPARENT));
+
+        mScrimController.setRawPanelExpansionFraction(0.99f);
+        assertScrimAlpha(Map.of(
+                mScrimInFront, TRANSPARENT,
+                mNotificationsScrim, SEMI_TRANSPARENT,
+                mScrimBehind, SEMI_TRANSPARENT));
+
+        mScrimController.setRawPanelExpansionFraction(1f);
+        assertScrimAlpha(Map.of(
+                mScrimInFront, TRANSPARENT,
+                mNotificationsScrim, OPAQUE,
+                mScrimBehind, OPAQUE));
+    }
+
+
+    @Test
+    public void transitionToUnlocked_nonClippedQs_flagFalse() {
+        when(mFeatureFlags.isEnabled(Flags.LARGE_SHADE_GRANULAR_ALPHA_INTERPOLATION))
+                .thenReturn(false);
         mScrimController.setClipsQsScrim(false);
         mScrimController.setRawPanelExpansionFraction(0f);
         mScrimController.transitionTo(ScrimState.UNLOCKED);
@@ -667,7 +778,6 @@
                 mScrimBehind, OPAQUE));
     }
 
-
     @Test
     public void scrimStateCallback() {
         mScrimController.transitionTo(ScrimState.UNLOCKED);
@@ -855,13 +965,25 @@
         // GIVEN display does NOT need blanking
         when(mDozeParameters.getDisplayNeedsBlanking()).thenReturn(false);
 
-        mScrimController = new ScrimController(mLightBarController,
-                mDozeParameters, mAlarmManager, mKeyguardStateController, mDelayedWakeLockBuilder,
-                new FakeHandler(mLooper.getLooper()), mKeyguardUpdateMonitor,
-                mDockManager, mConfigurationController, new FakeExecutor(new FakeSystemClock()),
+        mScrimController = new ScrimController(
+                mLightBarController,
+                mDozeParameters,
+                mAlarmManager,
+                mKeyguardStateController,
+                mDelayedWakeLockBuilder,
+                new FakeHandler(mLooper.getLooper()),
+                mKeyguardUpdateMonitor,
+                mDockManager,
+                mConfigurationController,
+                new FakeExecutor(new FakeSystemClock()),
                 mScreenOffAnimationController,
                 mKeyguardUnlockAnimationController,
-                mStatusBarKeyguardViewManager);
+                mStatusBarKeyguardViewManager,
+                mPrimaryBouncerToGoneTransitionViewModel,
+                mKeyguardTransitionInteractor,
+                mMainDispatcher,
+                mLinearLargeScreenShadeInterpolator,
+                mFeatureFlags);
         mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);
         mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront);
         mScrimController.setAnimatorListener(mAnimatorListener);
@@ -1629,6 +1751,28 @@
         assertScrimAlpha(mScrimBehind, 0);
     }
 
+    @Test
+    public void ignoreTransitionRequestWhileKeyguardTransitionRunning() {
+        mScrimController.transitionTo(ScrimState.UNLOCKED);
+        mScrimController.mPrimaryBouncerToGoneTransition.accept(
+                new TransitionStep(KeyguardState.PRIMARY_BOUNCER, KeyguardState.GONE, 0f,
+                        TransitionState.RUNNING, "ScrimControllerTest"));
+
+        // This request should not happen
+        mScrimController.transitionTo(ScrimState.BOUNCER);
+        assertThat(mScrimController.getState()).isEqualTo(ScrimState.UNLOCKED);
+    }
+
+    @Test
+    public void primaryBouncerToGoneOnFinishCallsKeyguardFadedAway() {
+        when(mKeyguardStateController.isKeyguardFadingAway()).thenReturn(true);
+        mScrimController.mPrimaryBouncerToGoneTransition.accept(
+                new TransitionStep(KeyguardState.PRIMARY_BOUNCER, KeyguardState.GONE, 0f,
+                        TransitionState.FINISHED, "ScrimControllerTest"));
+
+        verify(mStatusBarKeyguardViewManager).onKeyguardFadedAway();
+    }
+
     private void assertAlphaAfterExpansion(ScrimView scrim, float expectedAlpha, float expansion) {
         mScrimController.setRawPanelExpansionFraction(expansion);
         finishAnimationsImmediately();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 158e9ad..3146262 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -19,6 +19,7 @@
 import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN;
 import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE;
 
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -35,6 +36,7 @@
 
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewRootImpl;
@@ -683,4 +685,74 @@
         // the following call before registering centralSurfaces should NOT throw a NPE:
         mStatusBarKeyguardViewManager.hideAlternateBouncer(true);
     }
+
+    @Test
+    public void testResetHideBouncerWhenShowing_alternateBouncerHides() {
+        // GIVEN the keyguard is showing
+        reset(mAlternateBouncerInteractor);
+        when(mKeyguardStateController.isShowing()).thenReturn(true);
+
+        // WHEN SBKV is reset with hideBouncerWhenShowing=true
+        mStatusBarKeyguardViewManager.reset(true);
+
+        // THEN alternate bouncer is hidden
+        verify(mAlternateBouncerInteractor).hide();
+    }
+
+    @Test
+    public void testResetHideBouncerWhenShowingIsFalse_alternateBouncerHides() {
+        // GIVEN the keyguard is showing
+        reset(mAlternateBouncerInteractor);
+        when(mKeyguardStateController.isShowing()).thenReturn(true);
+
+        // WHEN SBKV is reset with hideBouncerWhenShowing=false
+        mStatusBarKeyguardViewManager.reset(false);
+
+        // THEN alternate bouncer is NOT hidden
+        verify(mAlternateBouncerInteractor, never()).hide();
+    }
+
+    @Test
+    public void testAlternateBouncerToShowPrimaryBouncer_updatesScrimControllerOnce() {
+        // GIVEN the alternate bouncer has shown and calls to hide()  will result in successfully
+        // hiding it
+        when(mAlternateBouncerInteractor.hide()).thenReturn(true);
+        when(mKeyguardStateController.isShowing()).thenReturn(true);
+        when(mPrimaryBouncerInteractor.isFullyShowing()).thenReturn(false);
+        when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(false);
+
+        // WHEN request to show primary bouncer
+        mStatusBarKeyguardViewManager.showPrimaryBouncer(true);
+
+        // THEN the scrim isn't updated from StatusBarKeyguardViewManager
+        verify(mCentralSurfaces, never()).updateScrimController();
+    }
+
+    @Test
+    public void testAlternateBouncerOnTouch_actionDown_doesNotHandleTouch() {
+        // GIVEN the alternate bouncer has shown for a minimum amount of time
+        when(mAlternateBouncerInteractor.hasAlternateBouncerShownWithMinTime()).thenReturn(true);
+        when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
+
+        // WHEN ACTION_DOWN touch event comes
+        boolean touchHandled = mStatusBarKeyguardViewManager.onTouch(
+                MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0));
+
+        // THEN the touch is not handled
+        assertFalse(touchHandled);
+    }
+
+    @Test
+    public void testAlternateBouncerOnTouch_actionUp_handlesTouch() {
+        // GIVEN the alternate bouncer has shown for a minimum amount of time
+        when(mAlternateBouncerInteractor.hasAlternateBouncerShownWithMinTime()).thenReturn(true);
+        when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
+
+        // WHEN ACTION_UP touch event comes
+        boolean touchHandled = mStatusBarKeyguardViewManager.onTouch(
+                MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0f, 0f, 0));
+
+        // THEN the touch is handled
+        assertTrue(touchHandled);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationControllerTest.kt
index 1779de7..7594c90 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationControllerTest.kt
@@ -8,13 +8,14 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.unfold.TestUnfoldTransitionProvider
+import com.android.systemui.unfold.util.CurrentActivityTypeProvider
 import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
+import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Test
 import org.mockito.ArgumentMatchers.any
 import org.mockito.Mock
-import org.mockito.Mockito.`when`
 import org.mockito.MockitoAnnotations
 
 @SmallTest
@@ -26,6 +27,9 @@
     @Mock
     private lateinit var display: Display
 
+    @Mock
+    private lateinit var currentActivityTypeProvider: CurrentActivityTypeProvider
+
     private val view: View = View(context)
     private val progressProvider = TestUnfoldTransitionProvider()
     private val scopedProvider = ScopedUnfoldTransitionProgressProvider(progressProvider)
@@ -36,9 +40,9 @@
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
-        `when`(windowManager.defaultDisplay).thenReturn(display)
-        `when`(display.rotation).thenReturn(Surface.ROTATION_0)
-        `when`(display.getSize(any())).thenAnswer {
+        whenever(windowManager.defaultDisplay).thenReturn(display)
+        whenever(display.rotation).thenReturn(Surface.ROTATION_0)
+        whenever(display.getSize(any())).thenAnswer {
             val point = it.arguments[0] as Point
             point.x = 100
             point.y = 100
@@ -47,7 +51,12 @@
 
         scopedProvider.setReadyToHandleTransition(true)
 
-        controller = StatusBarMoveFromCenterAnimationController(scopedProvider, windowManager)
+        controller =
+            StatusBarMoveFromCenterAnimationController(
+                scopedProvider,
+                currentActivityTypeProvider,
+                windowManager
+            )
     }
 
     @Test
@@ -99,6 +108,31 @@
     }
 
     @Test
+    fun alpha_onLauncher_alphaDoesNotChange() {
+        whenever(currentActivityTypeProvider.isHomeActivity).thenReturn(true)
+        controller.onViewsReady(arrayOf(view))
+        progressProvider.onTransitionStarted()
+        progressProvider.onTransitionProgress(0.0f)
+        assertThat(view.alpha).isEqualTo(1.0f)
+
+        progressProvider.onTransitionProgress(1.0f)
+
+        assertThat(view.alpha).isEqualTo(1.0f)
+    }
+
+    @Test
+    fun alpha_NotOnLauncher_alphaChanges() {
+        whenever(currentActivityTypeProvider.isHomeActivity).thenReturn(false)
+        controller.onViewsReady(arrayOf(view))
+        progressProvider.onTransitionStarted()
+        assertThat(view.alpha).isEqualTo(1.0f)
+
+        progressProvider.onTransitionProgress(0.5f)
+
+        assertThat(view.alpha).isNotEqualTo(1.0f)
+    }
+
+    @Test
     fun transitionFinished_viewReAttached_noChangesToTranslation() {
         controller.onViewsReady(arrayOf(view))
         progressProvider.onTransitionProgress(0.5f)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/shared/MobileInputLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLoggerTest.kt
similarity index 91%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/shared/MobileInputLoggerTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLoggerTest.kt
index 86529dc..7c9351c8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/shared/MobileInputLoggerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLoggerTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.pipeline.mobile.shared
+package com.android.systemui.statusbar.pipeline.mobile.data
 
 import android.net.Network
 import android.net.NetworkCapabilities
@@ -47,14 +47,14 @@
         val expectedNetId = NET_1_ID.toString()
         val expectedCaps = NET_1_CAPS.toString()
 
-        assertThat(actualString).contains("true")
+        assertThat(actualString).contains("onDefaultCapabilitiesChanged")
         assertThat(actualString).contains(expectedNetId)
         assertThat(actualString).contains(expectedCaps)
     }
 
     @Test
     fun testLogOnLost_bufferHasNetIdOfLostNetwork() {
-        logger.logOnLost(NET_1)
+        logger.logOnLost(NET_1, isDefaultNetworkCallback = false)
 
         val stringWriter = StringWriter()
         buffer.dump(PrintWriter(stringWriter), tailLength = 0)
@@ -62,6 +62,7 @@
 
         val expectedNetId = NET_1_ID.toString()
 
+        assertThat(actualString).contains("onLost")
         assertThat(actualString).contains(expectedNetId)
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModelTest.kt
deleted file mode 100644
index 45189cf..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModelTest.kt
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.pipeline.mobile.data.model
-
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.log.table.TableRowLogger
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_ACTIVITY_DIRECTION_IN
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_ACTIVITY_DIRECTION_OUT
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_CARRIER_NETWORK_CHANGE
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_CDMA_LEVEL
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_CONNECTION_STATE
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_EMERGENCY
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_IS_GSM
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_OPERATOR
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_PRIMARY_LEVEL
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_RESOLVED_NETWORK_TYPE
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_ROAMING
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-
-@SmallTest
-class MobileConnectionModelTest : SysuiTestCase() {
-
-    @Test
-    fun `log diff - initial log contains all columns`() {
-        val logger = TestLogger()
-        val connection = MobileConnectionModel()
-
-        connection.logFull(logger)
-
-        assertThat(logger.changes)
-            .contains(Pair(COL_EMERGENCY, connection.isEmergencyOnly.toString()))
-        assertThat(logger.changes).contains(Pair(COL_ROAMING, connection.isRoaming.toString()))
-        assertThat(logger.changes)
-            .contains(Pair(COL_OPERATOR, connection.operatorAlphaShort.toString()))
-        assertThat(logger.changes).contains(Pair(COL_IS_GSM, connection.isGsm.toString()))
-        assertThat(logger.changes).contains(Pair(COL_CDMA_LEVEL, connection.cdmaLevel.toString()))
-        assertThat(logger.changes)
-            .contains(Pair(COL_PRIMARY_LEVEL, connection.primaryLevel.toString()))
-        assertThat(logger.changes)
-            .contains(Pair(COL_CONNECTION_STATE, connection.dataConnectionState.toString()))
-        assertThat(logger.changes)
-            .contains(
-                Pair(
-                    COL_ACTIVITY_DIRECTION_IN,
-                    connection.dataActivityDirection.hasActivityIn.toString(),
-                )
-            )
-        assertThat(logger.changes)
-            .contains(
-                Pair(
-                    COL_ACTIVITY_DIRECTION_OUT,
-                    connection.dataActivityDirection.hasActivityOut.toString(),
-                )
-            )
-        assertThat(logger.changes)
-            .contains(
-                Pair(COL_CARRIER_NETWORK_CHANGE, connection.carrierNetworkChangeActive.toString())
-            )
-        assertThat(logger.changes)
-            .contains(Pair(COL_RESOLVED_NETWORK_TYPE, connection.resolvedNetworkType.toString()))
-    }
-
-    @Test
-    fun `log diff - primary level changes - only level is logged`() {
-        val logger = TestLogger()
-        val connectionOld = MobileConnectionModel(primaryLevel = 1)
-
-        val connectionNew = MobileConnectionModel(primaryLevel = 2)
-
-        connectionNew.logDiffs(connectionOld, logger)
-
-        assertThat(logger.changes).isEqualTo(listOf(Pair(COL_PRIMARY_LEVEL, "2")))
-    }
-
-    private class TestLogger : TableRowLogger {
-        val changes = mutableListOf<Pair<String, String>>()
-
-        override fun logChange(columnName: String, value: String?) {
-            changes.add(Pair(columnName, value.toString()))
-        }
-
-        override fun logChange(columnName: String, value: Int) {
-            changes.add(Pair(columnName, value.toString()))
-        }
-
-        override fun logChange(columnName: String, value: Boolean) {
-            changes.add(Pair(columnName, value.toString()))
-        }
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt
index 0145103..dfef62e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt
@@ -24,8 +24,8 @@
 import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfigTest.Companion.createTestConfig
-import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt
index 53cd71f1..44fbd5b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt
@@ -17,9 +17,11 @@
 package com.android.systemui.statusbar.pipeline.mobile.data.repository
 
 import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
+import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
 import kotlinx.coroutines.flow.MutableStateFlow
 
 // TODO(b/261632894): remove this in favor of the real impl or DemoMobileConnectionRepository
@@ -27,8 +29,19 @@
     override val subId: Int,
     override val tableLogBuffer: TableLogBuffer,
 ) : MobileConnectionRepository {
-    private val _connectionInfo = MutableStateFlow(MobileConnectionModel())
-    override val connectionInfo = _connectionInfo
+    override val isEmergencyOnly = MutableStateFlow(false)
+    override val isRoaming = MutableStateFlow(false)
+    override val operatorAlphaShort: MutableStateFlow<String?> = MutableStateFlow(null)
+    override val isInService = MutableStateFlow(false)
+    override val isGsm = MutableStateFlow(false)
+    override val cdmaLevel = MutableStateFlow(0)
+    override val primaryLevel = MutableStateFlow(0)
+    override val dataConnectionState = MutableStateFlow(DataConnectionState.Disconnected)
+    override val dataActivityDirection =
+        MutableStateFlow(DataActivityModel(hasActivityIn = false, hasActivityOut = false))
+    override val carrierNetworkChangeActive = MutableStateFlow(false)
+    override val resolvedNetworkType: MutableStateFlow<ResolvedNetworkType> =
+        MutableStateFlow(ResolvedNetworkType.UnknownNetworkType)
 
     override val numberOfLevels = MutableStateFlow(DEFAULT_NUM_LEVELS)
 
@@ -40,10 +53,6 @@
     override val networkName =
         MutableStateFlow<NetworkNameModel>(NetworkNameModel.Default("default"))
 
-    fun setConnectionInfo(model: MobileConnectionModel) {
-        _connectionInfo.value = model
-    }
-
     fun setDataEnabled(enabled: Boolean) {
         _dataEnabled.value = enabled
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
index 17502f2..07c8cee 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
@@ -27,13 +27,13 @@
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.log.table.TableLogBufferFactory
+import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.DemoMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.DemoModeMobileConnectionDataSource
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.validMobileEvent
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileConnectionsRepositoryImpl
-import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
 import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
index 00ce412..37fac34 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
@@ -25,7 +25,6 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.log.table.TableLogBufferFactory
 import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
 import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
@@ -36,8 +35,11 @@
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.Job
 import kotlinx.coroutines.cancel
 import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.launch
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.UnconfinedTestDispatcher
 import kotlinx.coroutines.test.runTest
@@ -123,34 +125,49 @@
             assertConnection(underTest, networkModel)
         }
 
-    private fun assertConnection(
+    private fun TestScope.startCollection(conn: DemoMobileConnectionRepository): Job {
+        val job = launch {
+            launch { conn.cdmaLevel.collect {} }
+            launch { conn.primaryLevel.collect {} }
+            launch { conn.dataActivityDirection.collect {} }
+            launch { conn.carrierNetworkChangeActive.collect {} }
+            launch { conn.isRoaming.collect {} }
+            launch { conn.networkName.collect {} }
+            launch { conn.isEmergencyOnly.collect {} }
+            launch { conn.dataConnectionState.collect {} }
+        }
+        return job
+    }
+
+    private fun TestScope.assertConnection(
         conn: DemoMobileConnectionRepository,
         model: FakeNetworkEventModel
     ) {
+        val job = startCollection(underTest)
         when (model) {
             is FakeNetworkEventModel.Mobile -> {
-                val connectionInfo: MobileConnectionModel = conn.connectionInfo.value
                 assertThat(conn.subId).isEqualTo(model.subId)
-                assertThat(connectionInfo.cdmaLevel).isEqualTo(model.level)
-                assertThat(connectionInfo.primaryLevel).isEqualTo(model.level)
-                assertThat(connectionInfo.dataActivityDirection)
+                assertThat(conn.cdmaLevel.value).isEqualTo(model.level)
+                assertThat(conn.primaryLevel.value).isEqualTo(model.level)
+                assertThat(conn.dataActivityDirection.value)
                     .isEqualTo((model.activity ?: DATA_ACTIVITY_NONE).toMobileDataActivityModel())
-                assertThat(connectionInfo.carrierNetworkChangeActive)
+                assertThat(conn.carrierNetworkChangeActive.value)
                     .isEqualTo(model.carrierNetworkChange)
-                assertThat(connectionInfo.isRoaming).isEqualTo(model.roaming)
+                assertThat(conn.isRoaming.value).isEqualTo(model.roaming)
                 assertThat(conn.networkName.value)
                     .isEqualTo(NetworkNameModel.IntentDerived(model.name))
 
                 // TODO(b/261029387): check these once we start handling them
-                assertThat(connectionInfo.isEmergencyOnly).isFalse()
-                assertThat(connectionInfo.isGsm).isFalse()
-                assertThat(connectionInfo.dataConnectionState)
-                    .isEqualTo(DataConnectionState.Connected)
+                assertThat(conn.isEmergencyOnly.value).isFalse()
+                assertThat(conn.isGsm.value).isFalse()
+                assertThat(conn.dataConnectionState.value).isEqualTo(DataConnectionState.Connected)
             }
             // MobileDisabled isn't combinatorial in nature, and is tested in
             // DemoMobileConnectionsRepositoryTest.kt
             else -> {}
         }
+
+        job.cancel()
     }
 
     /** Matches [FakeNetworkEventModel] */
@@ -239,6 +256,7 @@
          *    list2 = [false, true]
          *    list3 = [a, b, c]
          * ```
+         *
          * We'll generate test cases for:
          *
          * Test (1, false, a) Test (2, false, a) Test (3, false, a) Test (1, true, a) Test (1,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
index f60d92b..0e45d8e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
@@ -26,7 +26,6 @@
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.log.table.TableLogBufferFactory
 import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
@@ -40,9 +39,11 @@
 import com.google.common.truth.Truth.assertThat
 import junit.framework.Assert
 import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.Job
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.launch
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.UnconfinedTestDispatcher
 import kotlinx.coroutines.test.runTest
@@ -524,47 +525,65 @@
             job.cancel()
         }
 
-    private fun assertConnection(
+    private fun TestScope.startCollection(conn: DemoMobileConnectionRepository): Job {
+        val job = launch {
+            launch { conn.cdmaLevel.collect {} }
+            launch { conn.primaryLevel.collect {} }
+            launch { conn.dataActivityDirection.collect {} }
+            launch { conn.carrierNetworkChangeActive.collect {} }
+            launch { conn.isRoaming.collect {} }
+            launch { conn.networkName.collect {} }
+            launch { conn.isEmergencyOnly.collect {} }
+            launch { conn.dataConnectionState.collect {} }
+        }
+        return job
+    }
+
+    private fun TestScope.assertConnection(
         conn: DemoMobileConnectionRepository,
-        model: FakeNetworkEventModel
+        model: FakeNetworkEventModel,
     ) {
+        val job = startCollection(conn)
+        // Assert the fields using the `MutableStateFlow` so that we don't have to start up
+        // a collector for every field for every test
         when (model) {
             is FakeNetworkEventModel.Mobile -> {
-                val connectionInfo: MobileConnectionModel = conn.connectionInfo.value
                 assertThat(conn.subId).isEqualTo(model.subId)
-                assertThat(connectionInfo.cdmaLevel).isEqualTo(model.level)
-                assertThat(connectionInfo.primaryLevel).isEqualTo(model.level)
-                assertThat(connectionInfo.dataActivityDirection)
+                assertThat(conn.cdmaLevel.value).isEqualTo(model.level)
+                assertThat(conn.primaryLevel.value).isEqualTo(model.level)
+                assertThat(conn.dataActivityDirection.value)
                     .isEqualTo((model.activity ?: DATA_ACTIVITY_NONE).toMobileDataActivityModel())
-                assertThat(connectionInfo.carrierNetworkChangeActive)
+                assertThat(conn.carrierNetworkChangeActive.value)
                     .isEqualTo(model.carrierNetworkChange)
-                assertThat(connectionInfo.isRoaming).isEqualTo(model.roaming)
+                assertThat(conn.isRoaming.value).isEqualTo(model.roaming)
                 assertThat(conn.networkName.value)
                     .isEqualTo(NetworkNameModel.IntentDerived(model.name))
 
                 // TODO(b/261029387) check these once we start handling them
-                assertThat(connectionInfo.isEmergencyOnly).isFalse()
-                assertThat(connectionInfo.isGsm).isFalse()
-                assertThat(connectionInfo.dataConnectionState)
-                    .isEqualTo(DataConnectionState.Connected)
+                assertThat(conn.isEmergencyOnly.value).isFalse()
+                assertThat(conn.isGsm.value).isFalse()
+                assertThat(conn.dataConnectionState.value).isEqualTo(DataConnectionState.Connected)
             }
             else -> {}
         }
+
+        job.cancel()
     }
 
-    private fun assertCarrierMergedConnection(
+    private fun TestScope.assertCarrierMergedConnection(
         conn: DemoMobileConnectionRepository,
         model: FakeWifiEventModel.CarrierMerged,
     ) {
-        val connectionInfo: MobileConnectionModel = conn.connectionInfo.value
+        val job = startCollection(conn)
         assertThat(conn.subId).isEqualTo(model.subscriptionId)
-        assertThat(connectionInfo.cdmaLevel).isEqualTo(model.level)
-        assertThat(connectionInfo.primaryLevel).isEqualTo(model.level)
-        assertThat(connectionInfo.carrierNetworkChangeActive).isEqualTo(false)
-        assertThat(connectionInfo.isRoaming).isEqualTo(false)
-        assertThat(connectionInfo.isEmergencyOnly).isFalse()
-        assertThat(connectionInfo.isGsm).isFalse()
-        assertThat(connectionInfo.dataConnectionState).isEqualTo(DataConnectionState.Connected)
+        assertThat(conn.cdmaLevel.value).isEqualTo(model.level)
+        assertThat(conn.primaryLevel.value).isEqualTo(model.level)
+        assertThat(conn.carrierNetworkChangeActive.value).isEqualTo(false)
+        assertThat(conn.isRoaming.value).isEqualTo(false)
+        assertThat(conn.isEmergencyOnly.value).isFalse()
+        assertThat(conn.isGsm.value).isFalse()
+        assertThat(conn.dataConnectionState.value).isEqualTo(DataConnectionState.Connected)
+        job.cancel()
     }
 }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt
index f0f213b..441186a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt
@@ -22,7 +22,6 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
@@ -75,36 +74,48 @@
     }
 
     @Test
-    fun connectionInfo_inactiveWifi_isDefault() =
+    fun inactiveWifi_isDefault() =
         testScope.runTest {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latestConnState: DataConnectionState? = null
+            var latestNetType: ResolvedNetworkType? = null
+
+            val dataJob =
+                underTest.dataConnectionState.onEach { latestConnState = it }.launchIn(this)
+            val netJob = underTest.resolvedNetworkType.onEach { latestNetType = it }.launchIn(this)
 
             wifiRepository.setWifiNetwork(WifiNetworkModel.Inactive)
 
-            assertThat(latest).isEqualTo(MobileConnectionModel())
+            assertThat(latestConnState).isEqualTo(DataConnectionState.Disconnected)
+            assertThat(latestNetType).isNotEqualTo(ResolvedNetworkType.CarrierMergedNetworkType)
 
-            job.cancel()
+            dataJob.cancel()
+            netJob.cancel()
         }
 
     @Test
-    fun connectionInfo_activeWifi_isDefault() =
+    fun activeWifi_isDefault() =
         testScope.runTest {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latestConnState: DataConnectionState? = null
+            var latestNetType: ResolvedNetworkType? = null
+
+            val dataJob =
+                underTest.dataConnectionState.onEach { latestConnState = it }.launchIn(this)
+            val netJob = underTest.resolvedNetworkType.onEach { latestNetType = it }.launchIn(this)
 
             wifiRepository.setWifiNetwork(WifiNetworkModel.Active(networkId = NET_ID, level = 1))
 
-            assertThat(latest).isEqualTo(MobileConnectionModel())
+            assertThat(latestConnState).isEqualTo(DataConnectionState.Disconnected)
+            assertThat(latestNetType).isNotEqualTo(ResolvedNetworkType.CarrierMergedNetworkType)
 
-            job.cancel()
+            dataJob.cancel()
+            netJob.cancel()
         }
 
     @Test
-    fun connectionInfo_carrierMergedWifi_isValidAndFieldsComeFromWifiNetwork() =
+    fun carrierMergedWifi_isValidAndFieldsComeFromWifiNetwork() =
         testScope.runTest {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latest: Int? = null
+            val job = underTest.primaryLevel.onEach { latest = it }.launchIn(this)
 
             wifiRepository.setIsWifiEnabled(true)
             wifiRepository.setIsWifiDefault(true)
@@ -117,34 +128,16 @@
                 )
             )
 
-            val expected =
-                MobileConnectionModel(
-                    primaryLevel = 3,
-                    cdmaLevel = 3,
-                    dataConnectionState = DataConnectionState.Connected,
-                    dataActivityDirection =
-                        DataActivityModel(
-                            hasActivityIn = false,
-                            hasActivityOut = false,
-                        ),
-                    resolvedNetworkType = ResolvedNetworkType.CarrierMergedNetworkType,
-                    isRoaming = false,
-                    isEmergencyOnly = false,
-                    operatorAlphaShort = null,
-                    isInService = true,
-                    isGsm = false,
-                    carrierNetworkChangeActive = false,
-                )
-            assertThat(latest).isEqualTo(expected)
+            assertThat(latest).isEqualTo(3)
 
             job.cancel()
         }
 
     @Test
-    fun connectionInfo_activity_comesFromWifiActivity() =
+    fun activity_comesFromWifiActivity() =
         testScope.runTest {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latest: DataActivityModel? = null
+            val job = underTest.dataActivityDirection.onEach { latest = it }.launchIn(this)
 
             wifiRepository.setIsWifiEnabled(true)
             wifiRepository.setIsWifiDefault(true)
@@ -162,8 +155,8 @@
                 )
             )
 
-            assertThat(latest!!.dataActivityDirection.hasActivityIn).isTrue()
-            assertThat(latest!!.dataActivityDirection.hasActivityOut).isFalse()
+            assertThat(latest!!.hasActivityIn).isTrue()
+            assertThat(latest!!.hasActivityOut).isFalse()
 
             wifiRepository.setWifiActivity(
                 DataActivityModel(
@@ -172,17 +165,19 @@
                 )
             )
 
-            assertThat(latest!!.dataActivityDirection.hasActivityIn).isFalse()
-            assertThat(latest!!.dataActivityDirection.hasActivityOut).isTrue()
+            assertThat(latest!!.hasActivityIn).isFalse()
+            assertThat(latest!!.hasActivityOut).isTrue()
 
             job.cancel()
         }
 
     @Test
-    fun connectionInfo_carrierMergedWifi_wrongSubId_isDefault() =
+    fun carrierMergedWifi_wrongSubId_isDefault() =
         testScope.runTest {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latestLevel: Int? = null
+            var latestType: ResolvedNetworkType? = null
+            val levelJob = underTest.primaryLevel.onEach { latestLevel = it }.launchIn(this)
+            val typeJob = underTest.resolvedNetworkType.onEach { latestType = it }.launchIn(this)
 
             wifiRepository.setWifiNetwork(
                 WifiNetworkModel.CarrierMerged(
@@ -192,20 +187,19 @@
                 )
             )
 
-            assertThat(latest).isEqualTo(MobileConnectionModel())
-            assertThat(latest!!.primaryLevel).isNotEqualTo(3)
-            assertThat(latest!!.resolvedNetworkType)
-                .isNotEqualTo(ResolvedNetworkType.CarrierMergedNetworkType)
+            assertThat(latestLevel).isNotEqualTo(3)
+            assertThat(latestType).isNotEqualTo(ResolvedNetworkType.CarrierMergedNetworkType)
 
-            job.cancel()
+            levelJob.cancel()
+            typeJob.cancel()
         }
 
     // This scenario likely isn't possible, but write a test for it anyway
     @Test
-    fun connectionInfo_carrierMergedButNotEnabled_isDefault() =
+    fun carrierMergedButNotEnabled_isDefault() =
         testScope.runTest {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latest: Int? = null
+            val job = underTest.primaryLevel.onEach { latest = it }.launchIn(this)
 
             wifiRepository.setWifiNetwork(
                 WifiNetworkModel.CarrierMerged(
@@ -216,17 +210,17 @@
             )
             wifiRepository.setIsWifiEnabled(false)
 
-            assertThat(latest).isEqualTo(MobileConnectionModel())
+            assertThat(latest).isNotEqualTo(3)
 
             job.cancel()
         }
 
     // This scenario likely isn't possible, but write a test for it anyway
     @Test
-    fun connectionInfo_carrierMergedButWifiNotDefault_isDefault() =
+    fun carrierMergedButWifiNotDefault_isDefault() =
         testScope.runTest {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latest: Int? = null
+            val job = underTest.primaryLevel.onEach { latest = it }.launchIn(this)
 
             wifiRepository.setWifiNetwork(
                 WifiNetworkModel.CarrierMerged(
@@ -237,7 +231,7 @@
             )
             wifiRepository.setIsWifiDefault(false)
 
-            assertThat(latest).isEqualTo(MobileConnectionModel())
+            assertThat(latest).isNotEqualTo(3)
 
             job.cancel()
         }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
index cd4d847..db5a7d1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
@@ -24,13 +24,12 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.log.table.TableLogBufferFactory
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_EMERGENCY
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_OPERATOR
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_PRIMARY_LEVEL
 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_EMERGENCY
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_OPERATOR
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_PRIMARY_LEVEL
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers.getTelephonyCallbackForType
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
@@ -94,16 +93,16 @@
     @Test
     fun startingIsCarrierMerged_usesCarrierMergedInitially() =
         testScope.runTest {
-            val carrierMergedConnectionInfo =
-                MobileConnectionModel(
-                    operatorAlphaShort = "Carrier Merged Operator",
-                )
-            carrierMergedRepo.setConnectionInfo(carrierMergedConnectionInfo)
+            val carrierMergedOperatorName = "Carrier Merged Operator"
+            val nonCarrierMergedName = "Non-carrier-merged"
+
+            carrierMergedRepo.operatorAlphaShort.value = carrierMergedOperatorName
+            mobileRepo.operatorAlphaShort.value = nonCarrierMergedName
 
             initializeRepo(startingIsCarrierMerged = true)
 
             assertThat(underTest.activeRepo.value).isEqualTo(carrierMergedRepo)
-            assertThat(underTest.connectionInfo.value).isEqualTo(carrierMergedConnectionInfo)
+            assertThat(underTest.operatorAlphaShort.value).isEqualTo(carrierMergedOperatorName)
             verify(mobileFactory, never())
                 .build(
                     SUB_ID,
@@ -116,16 +115,16 @@
     @Test
     fun startingNotCarrierMerged_usesTypicalInitially() =
         testScope.runTest {
-            val mobileConnectionInfo =
-                MobileConnectionModel(
-                    operatorAlphaShort = "Typical Operator",
-                )
-            mobileRepo.setConnectionInfo(mobileConnectionInfo)
+            val carrierMergedOperatorName = "Carrier Merged Operator"
+            val nonCarrierMergedName = "Typical Operator"
+
+            carrierMergedRepo.operatorAlphaShort.value = carrierMergedOperatorName
+            mobileRepo.operatorAlphaShort.value = nonCarrierMergedName
 
             initializeRepo(startingIsCarrierMerged = false)
 
             assertThat(underTest.activeRepo.value).isEqualTo(mobileRepo)
-            assertThat(underTest.connectionInfo.value).isEqualTo(mobileConnectionInfo)
+            assertThat(underTest.operatorAlphaShort.value).isEqualTo(nonCarrierMergedName)
             verify(carrierMergedFactory, never()).build(SUB_ID, tableLogBuffer)
         }
 
@@ -156,39 +155,40 @@
         testScope.runTest {
             initializeRepo(startingIsCarrierMerged = false)
 
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latestName: String? = null
+            var latestLevel: Int? = null
+
+            val nameJob = underTest.operatorAlphaShort.onEach { latestName = it }.launchIn(this)
+            val levelJob = underTest.primaryLevel.onEach { latestLevel = it }.launchIn(this)
 
             underTest.setIsCarrierMerged(true)
 
-            val info1 =
-                MobileConnectionModel(
-                    operatorAlphaShort = "Carrier Merged Operator",
-                    primaryLevel = 1,
-                )
-            carrierMergedRepo.setConnectionInfo(info1)
+            val operator1 = "Carrier Merged Operator"
+            val level1 = 1
+            carrierMergedRepo.operatorAlphaShort.value = operator1
+            carrierMergedRepo.primaryLevel.value = level1
 
-            assertThat(latest).isEqualTo(info1)
+            assertThat(latestName).isEqualTo(operator1)
+            assertThat(latestLevel).isEqualTo(level1)
 
-            val info2 =
-                MobileConnectionModel(
-                    operatorAlphaShort = "Carrier Merged Operator #2",
-                    primaryLevel = 2,
-                )
-            carrierMergedRepo.setConnectionInfo(info2)
+            val operator2 = "Carrier Merged Operator #2"
+            val level2 = 2
+            carrierMergedRepo.operatorAlphaShort.value = operator2
+            carrierMergedRepo.primaryLevel.value = level2
 
-            assertThat(latest).isEqualTo(info2)
+            assertThat(latestName).isEqualTo(operator2)
+            assertThat(latestLevel).isEqualTo(level2)
 
-            val info3 =
-                MobileConnectionModel(
-                    operatorAlphaShort = "Carrier Merged Operator #3",
-                    primaryLevel = 3,
-                )
-            carrierMergedRepo.setConnectionInfo(info3)
+            val operator3 = "Carrier Merged Operator #3"
+            val level3 = 3
+            carrierMergedRepo.operatorAlphaShort.value = operator3
+            carrierMergedRepo.primaryLevel.value = level3
 
-            assertThat(latest).isEqualTo(info3)
+            assertThat(latestName).isEqualTo(operator3)
+            assertThat(latestLevel).isEqualTo(level3)
 
-            job.cancel()
+            nameJob.cancel()
+            levelJob.cancel()
         }
 
     @Test
@@ -196,39 +196,40 @@
         testScope.runTest {
             initializeRepo(startingIsCarrierMerged = false)
 
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latestName: String? = null
+            var latestLevel: Int? = null
+
+            val nameJob = underTest.operatorAlphaShort.onEach { latestName = it }.launchIn(this)
+            val levelJob = underTest.primaryLevel.onEach { latestLevel = it }.launchIn(this)
 
             underTest.setIsCarrierMerged(false)
 
-            val info1 =
-                MobileConnectionModel(
-                    operatorAlphaShort = "Typical Merged Operator",
-                    primaryLevel = 1,
-                )
-            mobileRepo.setConnectionInfo(info1)
+            val operator1 = "Typical Merged Operator"
+            val level1 = 1
+            mobileRepo.operatorAlphaShort.value = operator1
+            mobileRepo.primaryLevel.value = level1
 
-            assertThat(latest).isEqualTo(info1)
+            assertThat(latestName).isEqualTo(operator1)
+            assertThat(latestLevel).isEqualTo(level1)
 
-            val info2 =
-                MobileConnectionModel(
-                    operatorAlphaShort = "Typical Merged Operator #2",
-                    primaryLevel = 2,
-                )
-            mobileRepo.setConnectionInfo(info2)
+            val operator2 = "Typical Merged Operator #2"
+            val level2 = 2
+            mobileRepo.operatorAlphaShort.value = operator2
+            mobileRepo.primaryLevel.value = level2
 
-            assertThat(latest).isEqualTo(info2)
+            assertThat(latestName).isEqualTo(operator2)
+            assertThat(latestLevel).isEqualTo(level2)
 
-            val info3 =
-                MobileConnectionModel(
-                    operatorAlphaShort = "Typical Merged Operator #3",
-                    primaryLevel = 3,
-                )
-            mobileRepo.setConnectionInfo(info3)
+            val operator3 = "Typical Merged Operator #3"
+            val level3 = 3
+            mobileRepo.operatorAlphaShort.value = operator3
+            mobileRepo.primaryLevel.value = level3
 
-            assertThat(latest).isEqualTo(info3)
+            assertThat(latestName).isEqualTo(operator3)
+            assertThat(latestLevel).isEqualTo(level3)
 
-            job.cancel()
+            nameJob.cancel()
+            levelJob.cancel()
         }
 
     @Test
@@ -236,57 +237,58 @@
         testScope.runTest {
             initializeRepo(startingIsCarrierMerged = false)
 
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latestName: String? = null
+            var latestLevel: Int? = null
 
-            val carrierMergedInfo =
-                MobileConnectionModel(
-                    operatorAlphaShort = "Carrier Merged Operator",
-                    primaryLevel = 4,
-                )
-            carrierMergedRepo.setConnectionInfo(carrierMergedInfo)
+            val nameJob = underTest.operatorAlphaShort.onEach { latestName = it }.launchIn(this)
+            val levelJob = underTest.primaryLevel.onEach { latestLevel = it }.launchIn(this)
 
-            val mobileInfo =
-                MobileConnectionModel(
-                    operatorAlphaShort = "Typical Operator",
-                    primaryLevel = 2,
-                )
-            mobileRepo.setConnectionInfo(mobileInfo)
+            val carrierMergedOperator = "Carrier Merged Operator"
+            val carrierMergedLevel = 4
+            carrierMergedRepo.operatorAlphaShort.value = carrierMergedOperator
+            carrierMergedRepo.primaryLevel.value = carrierMergedLevel
+
+            val mobileName = "Typical Operator"
+            val mobileLevel = 2
+            mobileRepo.operatorAlphaShort.value = mobileName
+            mobileRepo.primaryLevel.value = mobileLevel
 
             // Start with the mobile info
-            assertThat(latest).isEqualTo(mobileInfo)
+            assertThat(latestName).isEqualTo(mobileName)
+            assertThat(latestLevel).isEqualTo(mobileLevel)
 
             // WHEN isCarrierMerged is set to true
             underTest.setIsCarrierMerged(true)
 
             // THEN the carrier merged info is used
-            assertThat(latest).isEqualTo(carrierMergedInfo)
+            assertThat(latestName).isEqualTo(carrierMergedOperator)
+            assertThat(latestLevel).isEqualTo(carrierMergedLevel)
 
-            val newCarrierMergedInfo =
-                MobileConnectionModel(
-                    operatorAlphaShort = "New CM Operator",
-                    primaryLevel = 0,
-                )
-            carrierMergedRepo.setConnectionInfo(newCarrierMergedInfo)
+            val newCarrierMergedName = "New CM Operator"
+            val newCarrierMergedLevel = 0
+            carrierMergedRepo.operatorAlphaShort.value = newCarrierMergedName
+            carrierMergedRepo.primaryLevel.value = newCarrierMergedLevel
 
-            assertThat(latest).isEqualTo(newCarrierMergedInfo)
+            assertThat(latestName).isEqualTo(newCarrierMergedName)
+            assertThat(latestLevel).isEqualTo(newCarrierMergedLevel)
 
             // WHEN isCarrierMerged is set to false
             underTest.setIsCarrierMerged(false)
 
             // THEN the typical info is used
-            assertThat(latest).isEqualTo(mobileInfo)
+            assertThat(latestName).isEqualTo(mobileName)
+            assertThat(latestLevel).isEqualTo(mobileLevel)
 
-            val newMobileInfo =
-                MobileConnectionModel(
-                    operatorAlphaShort = "New Mobile Operator",
-                    primaryLevel = 3,
-                )
-            mobileRepo.setConnectionInfo(newMobileInfo)
+            val newMobileName = "New MobileOperator"
+            val newMobileLevel = 3
+            mobileRepo.operatorAlphaShort.value = newMobileName
+            mobileRepo.primaryLevel.value = newMobileLevel
 
-            assertThat(latest).isEqualTo(newMobileInfo)
+            assertThat(latestName).isEqualTo(newMobileName)
+            assertThat(latestLevel).isEqualTo(newMobileLevel)
 
-            job.cancel()
+            nameJob.cancel()
+            levelJob.cancel()
         }
 
     @Test
@@ -370,7 +372,8 @@
 
             initializeRepo(startingIsCarrierMerged = false)
 
-            val job = underTest.connectionInfo.launchIn(this)
+            val emergencyJob = underTest.isEmergencyOnly.launchIn(this)
+            val operatorJob = underTest.operatorAlphaShort.launchIn(this)
 
             // WHEN we set up some mobile connection info
             val serviceState = ServiceState()
@@ -394,7 +397,8 @@
             assertThat(dumpBuffer()).contains("$COL_OPERATOR${BUFFER_SEPARATOR}OpDiff")
             assertThat(dumpBuffer()).contains("$COL_EMERGENCY${BUFFER_SEPARATOR}true")
 
-            job.cancel()
+            emergencyJob.cancel()
+            operatorJob.cancel()
         }
 
     @Test
@@ -409,7 +413,7 @@
 
             initializeRepo(startingIsCarrierMerged = true)
 
-            val job = underTest.connectionInfo.launchIn(this)
+            val job = underTest.primaryLevel.launchIn(this)
 
             // WHEN we set up carrier merged info
             val networkId = 2
@@ -452,7 +456,7 @@
 
             initializeRepo(startingIsCarrierMerged = false)
 
-            val job = underTest.connectionInfo.launchIn(this)
+            val job = underTest.primaryLevel.launchIn(this)
 
             // WHEN we set up some mobile connection info
             val signalStrength = mock<SignalStrength>()
@@ -502,12 +506,7 @@
             assertThat(bufferAfterCarrierMerged).contains("$COL_PRIMARY_LEVEL${BUFFER_SEPARATOR}1")
 
             // WHEN the normal network is updated
-            val newMobileInfo =
-                MobileConnectionModel(
-                    operatorAlphaShort = "Mobile Operator 2",
-                    primaryLevel = 0,
-                )
-            mobileRepo.setConnectionInfo(newMobileInfo)
+            mobileRepo.primaryLevel.value = 0
 
             // THEN the new level is logged
             assertThat(dumpBuffer()).contains("$COL_PRIMARY_LEVEL${BUFFER_SEPARATOR}0")
@@ -529,7 +528,7 @@
             // WHEN isCarrierMerged = false
             initializeRepo(startingIsCarrierMerged = false)
 
-            val job = underTest.connectionInfo.launchIn(this)
+            val job = underTest.primaryLevel.launchIn(this)
 
             val signalStrength = mock<SignalStrength>()
             whenever(signalStrength.level).thenReturn(1)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
index b2577e3..542b688 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
@@ -18,17 +18,16 @@
 
 import android.content.Intent
 import android.telephony.CarrierConfigManager.KEY_INFLATE_SIGNAL_STRENGTH_BOOL
-import android.telephony.CellSignalStrengthCdma
 import android.telephony.NetworkRegistrationInfo
 import android.telephony.ServiceState
 import android.telephony.ServiceState.STATE_IN_SERVICE
 import android.telephony.ServiceState.STATE_OUT_OF_SERVICE
-import android.telephony.SignalStrength
 import android.telephony.TelephonyCallback
 import android.telephony.TelephonyCallback.DataActivityListener
 import android.telephony.TelephonyCallback.ServiceStateListener
 import android.telephony.TelephonyDisplayInfo
 import android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA
+import android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE
 import android.telephony.TelephonyManager
 import android.telephony.TelephonyManager.DATA_ACTIVITY_DORMANT
 import android.telephony.TelephonyManager.DATA_ACTIVITY_IN
@@ -50,12 +49,15 @@
 import android.telephony.TelephonyManager.EXTRA_SPN
 import android.telephony.TelephonyManager.EXTRA_SUBSCRIPTION_ID
 import android.telephony.TelephonyManager.NETWORK_TYPE_LTE
+import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
 import androidx.test.filters.SmallTest
+import com.android.settingslib.mobile.MobileMappings
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
 import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.OverrideNetworkType
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.UnknownNetworkType
@@ -65,7 +67,7 @@
 import com.android.systemui.statusbar.pipeline.mobile.data.model.toNetworkNameModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
-import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers.signalStrength
 import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
 import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
@@ -73,14 +75,12 @@
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.cancel
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.runBlocking
-import org.junit.After
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Test
 import org.mockito.Mock
@@ -97,7 +97,6 @@
     @Mock private lateinit var logger: MobileInputLogger
     @Mock private lateinit var tableLogger: TableLogBuffer
 
-    private val scope = CoroutineScope(IMMEDIATE)
     private val mobileMappings = FakeMobileMappingsProxy()
     private val systemUiCarrierConfig =
         SystemUiCarrierConfig(
@@ -105,6 +104,9 @@
             createTestConfig(),
         )
 
+    private val testDispatcher = UnconfinedTestDispatcher()
+    private val testScope = TestScope(testDispatcher)
+
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
@@ -122,265 +124,312 @@
                 systemUiCarrierConfig,
                 fakeBroadcastDispatcher,
                 mobileMappings,
-                IMMEDIATE,
+                testDispatcher,
                 logger,
                 tableLogger,
-                scope,
+                testScope.backgroundScope,
             )
     }
 
-    @After
-    fun tearDown() {
-        scope.cancel()
-    }
-
     @Test
-    fun testFlowForSubId_default() =
-        runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
-
-            assertThat(latest).isEqualTo(MobileConnectionModel())
-
-            job.cancel()
-        }
-
-    @Test
-    fun testFlowForSubId_emergencyOnly() =
-        runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+    fun emergencyOnly() =
+        testScope.runTest {
+            var latest: Boolean? = null
+            val job = underTest.isEmergencyOnly.onEach { latest = it }.launchIn(this)
 
             val serviceState = ServiceState()
             serviceState.isEmergencyOnly = true
 
             getTelephonyCallbackForType<ServiceStateListener>().onServiceStateChanged(serviceState)
 
-            assertThat(latest?.isEmergencyOnly).isEqualTo(true)
+            assertThat(latest).isEqualTo(true)
 
             job.cancel()
         }
 
     @Test
-    fun testFlowForSubId_emergencyOnly_toggles() =
-        runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+    fun emergencyOnly_toggles() =
+        testScope.runTest {
+            var latest: Boolean? = null
+            val job = underTest.isEmergencyOnly.onEach { latest = it }.launchIn(this)
 
             val callback = getTelephonyCallbackForType<ServiceStateListener>()
-            val serviceState = ServiceState()
-            serviceState.isEmergencyOnly = true
-            callback.onServiceStateChanged(serviceState)
-            serviceState.isEmergencyOnly = false
-            callback.onServiceStateChanged(serviceState)
+            callback.onServiceStateChanged(ServiceState().also { it.isEmergencyOnly = true })
+            assertThat(latest).isTrue()
 
-            assertThat(latest?.isEmergencyOnly).isEqualTo(false)
+            callback.onServiceStateChanged(ServiceState().also { it.isEmergencyOnly = false })
+
+            assertThat(latest).isFalse()
 
             job.cancel()
         }
 
     @Test
-    fun testFlowForSubId_signalStrengths_levelsUpdate() =
-        runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+    fun cdmaLevelUpdates() =
+        testScope.runTest {
+            var latest: Int? = null
+            val job = underTest.cdmaLevel.onEach { latest = it }.launchIn(this)
 
             val callback = getTelephonyCallbackForType<TelephonyCallback.SignalStrengthsListener>()
-            val strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = true)
+            var strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = true)
             callback.onSignalStrengthsChanged(strength)
 
-            assertThat(latest?.isGsm).isEqualTo(true)
-            assertThat(latest?.primaryLevel).isEqualTo(1)
-            assertThat(latest?.cdmaLevel).isEqualTo(2)
+            assertThat(latest).isEqualTo(2)
+
+            // gsmLevel updates, no change to cdmaLevel
+            strength = signalStrength(gsmLevel = 3, cdmaLevel = 2, isGsm = true)
+
+            assertThat(latest).isEqualTo(2)
 
             job.cancel()
         }
 
     @Test
-    fun testFlowForSubId_dataConnectionState_connected() =
-        runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+    fun gsmLevelUpdates() =
+        testScope.runTest {
+            var latest: Int? = null
+            val job = underTest.primaryLevel.onEach { latest = it }.launchIn(this)
+
+            val callback = getTelephonyCallbackForType<TelephonyCallback.SignalStrengthsListener>()
+            var strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = true)
+            callback.onSignalStrengthsChanged(strength)
+
+            assertThat(latest).isEqualTo(1)
+
+            strength = signalStrength(gsmLevel = 3, cdmaLevel = 2, isGsm = true)
+            callback.onSignalStrengthsChanged(strength)
+
+            assertThat(latest).isEqualTo(3)
+
+            job.cancel()
+        }
+
+    @Test
+    fun isGsm() =
+        testScope.runTest {
+            var latest: Boolean? = null
+            val job = underTest.isGsm.onEach { latest = it }.launchIn(this)
+
+            val callback = getTelephonyCallbackForType<TelephonyCallback.SignalStrengthsListener>()
+            var strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = true)
+            callback.onSignalStrengthsChanged(strength)
+
+            assertThat(latest).isTrue()
+
+            strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = false)
+            callback.onSignalStrengthsChanged(strength)
+
+            assertThat(latest).isFalse()
+
+            job.cancel()
+        }
+
+    @Test
+    fun dataConnectionState_connected() =
+        testScope.runTest {
+            var latest: DataConnectionState? = null
+            val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
 
             val callback =
                 getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
             callback.onDataConnectionStateChanged(DATA_CONNECTED, 200 /* unused */)
 
-            assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Connected)
+            assertThat(latest).isEqualTo(DataConnectionState.Connected)
 
             job.cancel()
         }
 
     @Test
-    fun testFlowForSubId_dataConnectionState_connecting() =
-        runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+    fun dataConnectionState_connecting() =
+        testScope.runTest {
+            var latest: DataConnectionState? = null
+            val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
 
             val callback =
                 getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
             callback.onDataConnectionStateChanged(DATA_CONNECTING, 200 /* unused */)
 
-            assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Connecting)
+            assertThat(latest).isEqualTo(DataConnectionState.Connecting)
 
             job.cancel()
         }
 
     @Test
-    fun testFlowForSubId_dataConnectionState_disconnected() =
-        runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+    fun dataConnectionState_disconnected() =
+        testScope.runTest {
+            var latest: DataConnectionState? = null
+            val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
 
             val callback =
                 getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
             callback.onDataConnectionStateChanged(DATA_DISCONNECTED, 200 /* unused */)
 
-            assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Disconnected)
+            assertThat(latest).isEqualTo(DataConnectionState.Disconnected)
 
             job.cancel()
         }
 
     @Test
-    fun testFlowForSubId_dataConnectionState_disconnecting() =
-        runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+    fun dataConnectionState_disconnecting() =
+        testScope.runTest {
+            var latest: DataConnectionState? = null
+            val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
 
             val callback =
                 getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
             callback.onDataConnectionStateChanged(DATA_DISCONNECTING, 200 /* unused */)
 
-            assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Disconnecting)
+            assertThat(latest).isEqualTo(DataConnectionState.Disconnecting)
 
             job.cancel()
         }
 
     @Test
-    fun testFlowForSubId_dataConnectionState_suspended() =
-        runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+    fun dataConnectionState_suspended() =
+        testScope.runTest {
+            var latest: DataConnectionState? = null
+            val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
 
             val callback =
                 getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
             callback.onDataConnectionStateChanged(DATA_SUSPENDED, 200 /* unused */)
 
-            assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Suspended)
+            assertThat(latest).isEqualTo(DataConnectionState.Suspended)
 
             job.cancel()
         }
 
     @Test
-    fun testFlowForSubId_dataConnectionState_handoverInProgress() =
-        runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+    fun dataConnectionState_handoverInProgress() =
+        testScope.runTest {
+            var latest: DataConnectionState? = null
+            val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
 
             val callback =
                 getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
             callback.onDataConnectionStateChanged(DATA_HANDOVER_IN_PROGRESS, 200 /* unused */)
 
-            assertThat(latest?.dataConnectionState)
-                .isEqualTo(DataConnectionState.HandoverInProgress)
+            assertThat(latest).isEqualTo(DataConnectionState.HandoverInProgress)
 
             job.cancel()
         }
 
     @Test
-    fun testFlowForSubId_dataConnectionState_unknown() =
-        runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+    fun dataConnectionState_unknown() =
+        testScope.runTest {
+            var latest: DataConnectionState? = null
+            val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
 
             val callback =
                 getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
             callback.onDataConnectionStateChanged(DATA_UNKNOWN, 200 /* unused */)
 
-            assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Unknown)
+            assertThat(latest).isEqualTo(DataConnectionState.Unknown)
 
             job.cancel()
         }
 
     @Test
-    fun testFlowForSubId_dataConnectionState_invalid() =
-        runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+    fun dataConnectionState_invalid() =
+        testScope.runTest {
+            var latest: DataConnectionState? = null
+            val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
 
             val callback =
                 getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
             callback.onDataConnectionStateChanged(45, 200 /* unused */)
 
-            assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Invalid)
+            assertThat(latest).isEqualTo(DataConnectionState.Invalid)
 
             job.cancel()
         }
 
     @Test
-    fun testFlowForSubId_dataActivity() =
-        runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+    fun dataActivity() =
+        testScope.runTest {
+            var latest: DataActivityModel? = null
+            val job = underTest.dataActivityDirection.onEach { latest = it }.launchIn(this)
 
             val callback = getTelephonyCallbackForType<DataActivityListener>()
             callback.onDataActivity(DATA_ACTIVITY_INOUT)
 
-            assertThat(latest?.dataActivityDirection)
-                .isEqualTo(DATA_ACTIVITY_INOUT.toMobileDataActivityModel())
+            assertThat(latest).isEqualTo(DATA_ACTIVITY_INOUT.toMobileDataActivityModel())
 
             job.cancel()
         }
 
     @Test
-    fun testFlowForSubId_carrierNetworkChange() =
-        runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+    fun carrierNetworkChange() =
+        testScope.runTest {
+            var latest: Boolean? = null
+            val job = underTest.carrierNetworkChangeActive.onEach { latest = it }.launchIn(this)
 
             val callback = getTelephonyCallbackForType<TelephonyCallback.CarrierNetworkListener>()
             callback.onCarrierNetworkChange(true)
 
-            assertThat(latest?.carrierNetworkChangeActive).isEqualTo(true)
+            assertThat(latest).isEqualTo(true)
 
             job.cancel()
         }
 
     @Test
-    fun subscriptionFlow_networkType_default() =
-        runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+    fun networkType_default() =
+        testScope.runTest {
+            var latest: ResolvedNetworkType? = null
+            val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this)
 
             val expected = UnknownNetworkType
 
-            assertThat(latest?.resolvedNetworkType).isEqualTo(expected)
+            assertThat(latest).isEqualTo(expected)
 
             job.cancel()
         }
 
     @Test
-    fun subscriptionFlow_networkType_updatesUsingDefault() =
-        runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+    fun networkType_unknown_hasCorrectKey() =
+        testScope.runTest {
+            var latest: ResolvedNetworkType? = null
+            val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this)
 
             val callback = getTelephonyCallbackForType<TelephonyCallback.DisplayInfoListener>()
-            val type = NETWORK_TYPE_LTE
-            val expected = DefaultNetworkType(mobileMappings.toIconKey(type))
+            val type = NETWORK_TYPE_UNKNOWN
+            val expected = UnknownNetworkType
             val ti = mock<TelephonyDisplayInfo>().also { whenever(it.networkType).thenReturn(type) }
             callback.onDisplayInfoChanged(ti)
 
-            assertThat(latest?.resolvedNetworkType).isEqualTo(expected)
+            assertThat(latest).isEqualTo(expected)
+            assertThat(latest!!.lookupKey).isEqualTo(MobileMappings.toIconKey(type))
 
             job.cancel()
         }
 
     @Test
-    fun subscriptionFlow_networkType_updatesUsingOverride() =
-        runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+    fun networkType_updatesUsingDefault() =
+        testScope.runTest {
+            var latest: ResolvedNetworkType? = null
+            val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this)
+
+            val callback = getTelephonyCallbackForType<TelephonyCallback.DisplayInfoListener>()
+            val overrideType = OVERRIDE_NETWORK_TYPE_NONE
+            val type = NETWORK_TYPE_LTE
+            val expected = DefaultNetworkType(mobileMappings.toIconKey(type))
+            val ti =
+                mock<TelephonyDisplayInfo>().also {
+                    whenever(it.overrideNetworkType).thenReturn(overrideType)
+                    whenever(it.networkType).thenReturn(type)
+                }
+            callback.onDisplayInfoChanged(ti)
+
+            assertThat(latest).isEqualTo(expected)
+
+            job.cancel()
+        }
+
+    @Test
+    fun networkType_updatesUsingOverride() =
+        testScope.runTest {
+            var latest: ResolvedNetworkType? = null
+            val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this)
 
             val callback = getTelephonyCallbackForType<TelephonyCallback.DisplayInfoListener>()
             val type = OVERRIDE_NETWORK_TYPE_LTE_CA
@@ -392,22 +441,44 @@
                 }
             callback.onDisplayInfoChanged(ti)
 
-            assertThat(latest?.resolvedNetworkType).isEqualTo(expected)
+            assertThat(latest).isEqualTo(expected)
+
+            job.cancel()
+        }
+
+    @Test
+    fun networkType_unknownNetworkWithOverride_usesOverrideKey() =
+        testScope.runTest {
+            var latest: ResolvedNetworkType? = null
+            val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this)
+
+            val callback = getTelephonyCallbackForType<TelephonyCallback.DisplayInfoListener>()
+            val unknown = NETWORK_TYPE_UNKNOWN
+            val type = OVERRIDE_NETWORK_TYPE_LTE_CA
+            val expected = OverrideNetworkType(mobileMappings.toIconKeyOverride(type))
+            val ti =
+                mock<TelephonyDisplayInfo>().also {
+                    whenever(it.networkType).thenReturn(unknown)
+                    whenever(it.overrideNetworkType).thenReturn(type)
+                }
+            callback.onDisplayInfoChanged(ti)
+
+            assertThat(latest).isEqualTo(expected)
 
             job.cancel()
         }
 
     @Test
     fun dataEnabled_initial_false() =
-        runBlocking(IMMEDIATE) {
+        testScope.runTest {
             whenever(telephonyManager.isDataConnectionAllowed).thenReturn(false)
 
             assertThat(underTest.dataEnabled.value).isFalse()
         }
 
     @Test
-    fun `is data enabled - tracks telephony callback`() =
-        runBlocking(IMMEDIATE) {
+    fun isDataEnabled_tracksTelephonyCallback() =
+        testScope.runTest {
             var latest: Boolean? = null
             val job = underTest.dataEnabled.onEach { latest = it }.launchIn(this)
 
@@ -427,7 +498,7 @@
 
     @Test
     fun numberOfLevels_isDefault() =
-        runBlocking(IMMEDIATE) {
+        testScope.runTest {
             var latest: Int? = null
             val job = underTest.numberOfLevels.onEach { latest = it }.launchIn(this)
 
@@ -437,51 +508,68 @@
         }
 
     @Test
-    fun `roaming - cdma - queries telephony manager`() =
-        runBlocking(IMMEDIATE) {
+    fun roaming_cdma_queriesTelephonyManager() =
+        testScope.runTest {
             var latest: Boolean? = null
             val job = underTest.cdmaRoaming.onEach { latest = it }.launchIn(this)
 
             val cb = getTelephonyCallbackForType<ServiceStateListener>()
 
-            val serviceState = ServiceState()
-            serviceState.roaming = false
-
-            // CDMA roaming is off, GSM roaming is off
+            // CDMA roaming is off, GSM roaming is on
             whenever(telephonyManager.cdmaEnhancedRoamingIndicatorDisplayNumber).thenReturn(ERI_OFF)
-            cb.onServiceStateChanged(serviceState)
+            cb.onServiceStateChanged(ServiceState().also { it.roaming = true })
 
             assertThat(latest).isFalse()
 
-            // CDMA roaming is off, GSM roaming is on
+            // CDMA roaming is on, GSM roaming is off
             whenever(telephonyManager.cdmaEnhancedRoamingIndicatorDisplayNumber).thenReturn(ERI_ON)
-            cb.onServiceStateChanged(serviceState)
+            cb.onServiceStateChanged(ServiceState().also { it.roaming = false })
 
             assertThat(latest).isTrue()
 
             job.cancel()
         }
 
+    /**
+     * [TelephonyManager.getCdmaEnhancedRoamingIndicatorDisplayNumber] returns -1 if the service is
+     * not running or if there is an error while retrieving the cdma ERI
+     */
     @Test
-    fun `roaming - gsm - queries service state`() =
-        runBlocking(IMMEDIATE) {
+    fun cdmaRoaming_ignoresNegativeOne() =
+        testScope.runTest {
             var latest: Boolean? = null
-            val job = underTest.connectionInfo.onEach { latest = it.isRoaming }.launchIn(this)
+            val job = underTest.cdmaRoaming.onEach { latest = it }.launchIn(this)
 
             val serviceState = ServiceState()
             serviceState.roaming = false
 
             val cb = getTelephonyCallbackForType<ServiceStateListener>()
 
-            // CDMA roaming is off, GSM roaming is off
-            whenever(telephonyManager.cdmaEnhancedRoamingIndicatorDisplayNumber).thenReturn(ERI_OFF)
+            // CDMA roaming is unavailable (-1), GSM roaming is off
+            whenever(telephonyManager.cdmaEnhancedRoamingIndicatorDisplayNumber).thenReturn(-1)
             cb.onServiceStateChanged(serviceState)
 
             assertThat(latest).isFalse()
 
+            job.cancel()
+        }
+
+    @Test
+    fun roaming_gsm_queriesServiceState() =
+        testScope.runTest {
+            var latest: Boolean? = null
+            val job = underTest.isRoaming.onEach { latest = it }.launchIn(this)
+
+            val cb = getTelephonyCallbackForType<ServiceStateListener>()
+
+            // CDMA roaming is off, GSM roaming is off
+            whenever(telephonyManager.cdmaEnhancedRoamingIndicatorDisplayNumber).thenReturn(ERI_OFF)
+            cb.onServiceStateChanged(ServiceState().also { it.roaming = false })
+
+            assertThat(latest).isFalse()
+
             // CDMA roaming is off, GSM roaming is on
-            serviceState.roaming = true
-            cb.onServiceStateChanged(serviceState)
+            cb.onServiceStateChanged(ServiceState().also { it.roaming = true })
 
             assertThat(latest).isTrue()
 
@@ -489,11 +577,10 @@
         }
 
     @Test
-    fun `activity - updates from callback`() =
-        runBlocking(IMMEDIATE) {
+    fun activity_updatesFromCallback() =
+        testScope.runTest {
             var latest: DataActivityModel? = null
-            val job =
-                underTest.connectionInfo.onEach { latest = it.dataActivityDirection }.launchIn(this)
+            val job = underTest.dataActivityDirection.onEach { latest = it }.launchIn(this)
 
             assertThat(latest)
                 .isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = false))
@@ -527,8 +614,8 @@
         }
 
     @Test
-    fun `network name - default`() =
-        runBlocking(IMMEDIATE) {
+    fun networkName_default() =
+        testScope.runTest {
             var latest: NetworkNameModel? = null
             val job = underTest.networkName.onEach { latest = it }.launchIn(this)
 
@@ -538,8 +625,8 @@
         }
 
     @Test
-    fun `network name - uses broadcast info - returns derived`() =
-        runBlocking(IMMEDIATE) {
+    fun networkName_usesBroadcastInfo_returnsDerived() =
+        testScope.runTest {
             var latest: NetworkNameModel? = null
             val job = underTest.networkName.onEach { latest = it }.launchIn(this)
 
@@ -555,8 +642,8 @@
         }
 
     @Test
-    fun `network name - broadcast not for this sub id - keeps old value`() =
-        runBlocking(IMMEDIATE) {
+    fun networkName_broadcastNotForThisSubId_keepsOldValue() =
+        testScope.runTest {
             var latest: NetworkNameModel? = null
             val job = underTest.networkName.onEach { latest = it }.launchIn(this)
 
@@ -580,8 +667,8 @@
         }
 
     @Test
-    fun `network name - broadcast has no data - updates to default`() =
-        runBlocking(IMMEDIATE) {
+    fun networkName_broadcastHasNoData_updatesToDefault() =
+        testScope.runTest {
             var latest: NetworkNameModel? = null
             val job = underTest.networkName.onEach { latest = it }.launchIn(this)
 
@@ -607,12 +694,11 @@
         }
 
     @Test
-    fun `operatorAlphaShort - tracked`() =
-        runBlocking(IMMEDIATE) {
+    fun operatorAlphaShort_tracked() =
+        testScope.runTest {
             var latest: String? = null
 
-            val job =
-                underTest.connectionInfo.onEach { latest = it.operatorAlphaShort }.launchIn(this)
+            val job = underTest.operatorAlphaShort.onEach { latest = it }.launchIn(this)
 
             val shortName = "short name"
             val serviceState = ServiceState()
@@ -630,35 +716,47 @@
         }
 
     @Test
-    fun `connection model - isInService - not iwlan`() =
-        runBlocking(IMMEDIATE) {
+    fun isInService_notIwlan() =
+        testScope.runTest {
             var latest: Boolean? = null
-            val job = underTest.connectionInfo.onEach { latest = it.isInService }.launchIn(this)
+            val job = underTest.isInService.onEach { latest = it }.launchIn(this)
 
-            val serviceState = ServiceState()
-            serviceState.voiceRegState = STATE_IN_SERVICE
-            serviceState.dataRegState = STATE_IN_SERVICE
-
-            getTelephonyCallbackForType<ServiceStateListener>().onServiceStateChanged(serviceState)
+            getTelephonyCallbackForType<ServiceStateListener>()
+                .onServiceStateChanged(
+                    ServiceState().also {
+                        it.voiceRegState = STATE_IN_SERVICE
+                        it.dataRegState = STATE_IN_SERVICE
+                    }
+                )
 
             assertThat(latest).isTrue()
 
-            serviceState.voiceRegState = STATE_OUT_OF_SERVICE
-            getTelephonyCallbackForType<ServiceStateListener>().onServiceStateChanged(serviceState)
+            getTelephonyCallbackForType<ServiceStateListener>()
+                .onServiceStateChanged(
+                    ServiceState().also {
+                        it.dataRegState = STATE_IN_SERVICE
+                        it.voiceRegState = STATE_OUT_OF_SERVICE
+                    }
+                )
             assertThat(latest).isTrue()
 
-            serviceState.dataRegState = STATE_OUT_OF_SERVICE
-            getTelephonyCallbackForType<ServiceStateListener>().onServiceStateChanged(serviceState)
+            getTelephonyCallbackForType<ServiceStateListener>()
+                .onServiceStateChanged(
+                    ServiceState().also {
+                        it.voiceRegState = STATE_OUT_OF_SERVICE
+                        it.dataRegState = STATE_OUT_OF_SERVICE
+                    }
+                )
             assertThat(latest).isFalse()
 
             job.cancel()
         }
 
     @Test
-    fun `connection model - isInService - is iwlan - voice out of service - data in service`() =
-        runBlocking(IMMEDIATE) {
+    fun isInService_isIwlan_voiceOutOfService_dataInService() =
+        testScope.runTest {
             var latest: Boolean? = null
-            val job = underTest.connectionInfo.onEach { latest = it.isInService }.launchIn(this)
+            val job = underTest.isInService.onEach { latest = it }.launchIn(this)
 
             // Mock the service state here so we can make it specifically IWLAN
             val serviceState: ServiceState = mock()
@@ -680,8 +778,8 @@
         }
 
     @Test
-    fun `number of levels - uses carrier config`() =
-        runBlocking(IMMEDIATE) {
+    fun numberOfLevels_usesCarrierConfig() =
+        testScope.runTest {
             var latest: Int? = null
             val job = underTest.numberOfLevels.onEach { latest = it }.launchIn(this)
 
@@ -706,19 +804,6 @@
         return MobileTelephonyHelpers.getTelephonyCallbackForType(telephonyManager)
     }
 
-    /** Convenience constructor for SignalStrength */
-    private fun signalStrength(gsmLevel: Int, cdmaLevel: Int, isGsm: Boolean): SignalStrength {
-        val signalStrength = mock<SignalStrength>()
-        whenever(signalStrength.isGsm).thenReturn(isGsm)
-        whenever(signalStrength.level).thenReturn(gsmLevel)
-        val cdmaStrength =
-            mock<CellSignalStrengthCdma>().also { whenever(it.level).thenReturn(cdmaLevel) }
-        whenever(signalStrength.getCellSignalStrengths(CellSignalStrengthCdma::class.java))
-            .thenReturn(listOf(cdmaStrength))
-
-        return signalStrength
-    }
-
     private fun spnIntent(
         subId: Int = SUB_1_ID,
         showSpn: Boolean = true,
@@ -735,7 +820,6 @@
         }
 
     companion object {
-        private val IMMEDIATE = Dispatchers.Main.immediate
         private const val SUB_1_ID = 1
 
         private val DEFAULT_NAME = NetworkNameModel.Default("default name")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt
new file mode 100644
index 0000000..bbf04ed2
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt
@@ -0,0 +1,341 @@
+/*
+ * 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.pipeline.mobile.data.repository.prod
+
+import android.telephony.ServiceState
+import android.telephony.TelephonyCallback
+import android.telephony.TelephonyCallback.CarrierNetworkListener
+import android.telephony.TelephonyCallback.DataActivityListener
+import android.telephony.TelephonyCallback.DataConnectionStateListener
+import android.telephony.TelephonyCallback.DataEnabledListener
+import android.telephony.TelephonyCallback.DisplayInfoListener
+import android.telephony.TelephonyCallback.ServiceStateListener
+import android.telephony.TelephonyDisplayInfo
+import android.telephony.TelephonyManager
+import android.telephony.TelephonyManager.DATA_ACTIVITY_INOUT
+import android.telephony.TelephonyManager.NETWORK_TYPE_LTE
+import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
+import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
+import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
+import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
+import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfigTest
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers.getTelephonyCallbackForType
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers.signalStrength
+import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
+import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+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.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+/**
+ * Test class to stress test the TelephonyCallbacks that we listen to. In particular, the callbacks
+ * all come back in on a single listener (for reasons defined in the system). This test is built to
+ * ensure that we don't miss any important callbacks.
+ *
+ * Kind of like an interaction test case build just for [TelephonyCallback]
+ *
+ * The list of telephony callbacks we use is: [TelephonyCallback.CarrierNetworkListener]
+ * [TelephonyCallback.DataActivityListener] [TelephonyCallback.DataConnectionStateListener]
+ * [TelephonyCallback.DataEnabledListener] [TelephonyCallback.DisplayInfoListener]
+ * [TelephonyCallback.ServiceStateListener] [TelephonyCallback.SignalStrengthsListener]
+ *
+ * Because each of these callbacks comes in on the same callbackFlow, collecting on a field backed
+ * by only a single callback can immediately create backpressure on the other fields related to a
+ * mobile connection.
+ *
+ * This test should be designed to test _at least_ each individual callback in a smoke-test fashion.
+ * The way we will achieve this is as follows:
+ * 1. Start up a listener (A) collecting on a field which is _not under test_
+ * 2. Send a single event to a telephony callback which supports the field under test (B)
+ * 3. Send many (may be as few as 2) events to the callback backing A to ensure we start seeing
+ *    backpressure on other fields NOTE: poor handling of backpressure here would normally cause B
+ *    to get dropped
+ * 4. Start up a new collector for B
+ * 5. Assert that B has the state sent in step #2
+ */
+@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+class MobileConnectionTelephonySmokeTests : SysuiTestCase() {
+    private lateinit var underTest: MobileConnectionRepositoryImpl
+    private lateinit var connectionsRepo: FakeMobileConnectionsRepository
+
+    @Mock private lateinit var telephonyManager: TelephonyManager
+    @Mock private lateinit var logger: MobileInputLogger
+    @Mock private lateinit var tableLogger: TableLogBuffer
+
+    private val mobileMappings = FakeMobileMappingsProxy()
+    private val systemUiCarrierConfig =
+        SystemUiCarrierConfig(
+            SUB_1_ID,
+            SystemUiCarrierConfigTest.createTestConfig(),
+        )
+
+    private val testDispatcher = UnconfinedTestDispatcher()
+    private val testScope = TestScope(testDispatcher)
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        whenever(telephonyManager.subscriptionId).thenReturn(SUB_1_ID)
+
+        connectionsRepo = FakeMobileConnectionsRepository(mobileMappings, tableLogger)
+
+        underTest =
+            MobileConnectionRepositoryImpl(
+                context,
+                SUB_1_ID,
+                DEFAULT_NAME,
+                SEP,
+                telephonyManager,
+                systemUiCarrierConfig,
+                fakeBroadcastDispatcher,
+                mobileMappings,
+                testDispatcher,
+                logger,
+                tableLogger,
+                testScope.backgroundScope,
+            )
+    }
+
+    @Test
+    fun carrierNetworkChangeListener_noisyActivity() =
+        testScope.runTest {
+            var latest: Boolean? = null
+
+            // Start collecting data activity; don't care about the result
+            val activityJob = underTest.dataActivityDirection.launchIn(this)
+            val activityCallback = getTelephonyCallbackForType<DataActivityListener>()
+
+            val callback = getTelephonyCallbackForType<CarrierNetworkListener>()
+            callback.onCarrierNetworkChange(true)
+
+            flipActivity(100, activityCallback)
+
+            val job = underTest.carrierNetworkChangeActive.onEach { latest = it }.launchIn(this)
+
+            assertThat(latest).isTrue()
+
+            activityJob.cancel()
+            job.cancel()
+        }
+
+    @Test
+    fun dataActivityLate_noisyDisplayInfo() =
+        testScope.runTest {
+            var latest: DataActivityModel? = null
+
+            // start collecting displayInfo; don't care about the result
+            val displayInfoJob = underTest.resolvedNetworkType.launchIn(this)
+
+            val activityCallback = getTelephonyCallbackForType<DataActivityListener>()
+            activityCallback.onDataActivity(DATA_ACTIVITY_INOUT)
+
+            val displayInfoCallback = getTelephonyCallbackForType<DisplayInfoListener>()
+            val type1 = NETWORK_TYPE_UNKNOWN
+            val type2 = NETWORK_TYPE_LTE
+            val t1 =
+                mock<TelephonyDisplayInfo>().also { whenever(it.networkType).thenReturn(type1) }
+            val t2 =
+                mock<TelephonyDisplayInfo>().also { whenever(it.networkType).thenReturn(type2) }
+
+            flipDisplayInfo(100, listOf(t1, t2), displayInfoCallback)
+
+            val job = underTest.dataActivityDirection.onEach { latest = it }.launchIn(this)
+
+            assertThat(latest)
+                .isEqualTo(
+                    DataActivityModel(
+                        hasActivityIn = true,
+                        hasActivityOut = true,
+                    )
+                )
+
+            displayInfoJob.cancel()
+            job.cancel()
+        }
+
+    @Test
+    fun dataConnectionStateListener_noisyActivity() =
+        testScope.runTest {
+            var latest: DataConnectionState? = null
+
+            // Start collecting data activity; don't care about the result
+            val activityJob = underTest.dataActivityDirection.launchIn(this)
+
+            val connectionCallback = getTelephonyCallbackForType<DataConnectionStateListener>()
+            val activityCallback = getTelephonyCallbackForType<DataActivityListener>()
+
+            connectionCallback.onDataConnectionStateChanged(
+                TelephonyManager.DATA_CONNECTED,
+                200 /* unused */
+            )
+
+            // Send a bunch of events that we don't care about, to overrun the replay buffer
+            flipActivity(100, activityCallback)
+
+            val connectionJob = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
+
+            assertThat(latest).isEqualTo(DataConnectionState.Connected)
+
+            activityJob.cancel()
+            connectionJob.cancel()
+        }
+
+    @Test
+    fun dataEnabledLate_noisyActivity() =
+        testScope.runTest {
+            var latest: Boolean? = null
+
+            // Start collecting data activity; don't care about the result
+            val activityJob = underTest.dataActivityDirection.launchIn(this)
+
+            val enabledCallback = getTelephonyCallbackForType<DataEnabledListener>()
+            val activityCallback = getTelephonyCallbackForType<DataActivityListener>()
+
+            enabledCallback.onDataEnabledChanged(true, 1 /* unused */)
+
+            // Send a bunch of events that we don't care about, to overrun the replay buffer
+            flipActivity(100, activityCallback)
+
+            val job = underTest.dataEnabled.onEach { latest = it }.launchIn(this)
+
+            assertThat(latest).isTrue()
+
+            activityJob.cancel()
+            job.cancel()
+        }
+
+    @Test
+    fun displayInfoLate_noisyActivity() =
+        testScope.runTest {
+            var latest: ResolvedNetworkType? = null
+
+            // Start collecting data activity; don't care about the result
+            val activityJob = underTest.dataActivityDirection.launchIn(this)
+
+            val displayInfoCallback = getTelephonyCallbackForType<DisplayInfoListener>()
+            val activityCallback = getTelephonyCallbackForType<DataActivityListener>()
+
+            val type = NETWORK_TYPE_LTE
+            val expected = ResolvedNetworkType.DefaultNetworkType(mobileMappings.toIconKey(type))
+            val ti = mock<TelephonyDisplayInfo>().also { whenever(it.networkType).thenReturn(type) }
+            displayInfoCallback.onDisplayInfoChanged(ti)
+
+            // Send a bunch of events that we don't care about, to overrun the replay buffer
+            flipActivity(100, activityCallback)
+
+            val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this)
+
+            assertThat(latest).isEqualTo(expected)
+
+            activityJob.cancel()
+            job.cancel()
+        }
+
+    @Test
+    fun serviceStateListener_noisyActivity() =
+        testScope.runTest {
+            var latest: Boolean? = null
+
+            // Start collecting data activity; don't care about the result
+            val activityJob = underTest.dataActivityDirection.launchIn(this)
+
+            val serviceStateCallback = getTelephonyCallbackForType<ServiceStateListener>()
+            val activityCallback = getTelephonyCallbackForType<DataActivityListener>()
+
+            // isEmergencyOnly comes in
+            val serviceState = ServiceState()
+            serviceState.isEmergencyOnly = true
+            serviceStateCallback.onServiceStateChanged(serviceState)
+
+            flipActivity(100, activityCallback)
+
+            val job = underTest.isEmergencyOnly.onEach { latest = it }.launchIn(this)
+
+            assertThat(latest).isTrue()
+
+            activityJob.cancel()
+            job.cancel()
+        }
+
+    @Test
+    fun signalStrengthsListenerLate_noisyActivity() =
+        testScope.runTest {
+            var latest: Int? = null
+
+            // Start collecting data activity; don't care about the result
+            val activityJob = underTest.dataActivityDirection.launchIn(this)
+            val activityCallback = getTelephonyCallbackForType<DataActivityListener>()
+
+            val callback = getTelephonyCallbackForType<TelephonyCallback.SignalStrengthsListener>()
+            val strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = true)
+            callback.onSignalStrengthsChanged(strength)
+
+            flipActivity(100, activityCallback)
+
+            val job = underTest.cdmaLevel.onEach { latest = it }.launchIn(this)
+
+            assertThat(latest).isEqualTo(2)
+
+            activityJob.cancel()
+            job.cancel()
+        }
+
+    private fun flipActivity(
+        times: Int,
+        callback: DataActivityListener,
+    ) {
+        repeat(times) { index -> callback.onDataActivity(index % 4) }
+    }
+
+    private fun flipDisplayInfo(
+        times: Int,
+        infos: List<TelephonyDisplayInfo>,
+        callback: DisplayInfoListener,
+    ) {
+        val len = infos.size
+        repeat(times) { index -> callback.onDisplayInfoChanged(infos[index % len]) }
+    }
+
+    private inline fun <reified T> getTelephonyCallbackForType(): T {
+        return getTelephonyCallbackForType(telephonyManager)
+    }
+
+    companion object {
+        private const val SUB_1_ID = 1
+
+        private val DEFAULT_NAME = NetworkNameModel.Default("default name")
+        private const val SEP = "-"
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
index 09b7a66..68b1cda 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
@@ -37,12 +37,12 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.log.table.TableLogBufferFactory
+import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
 import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.CarrierConfigRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Factory.Companion.tableBufferLogName
-import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
 import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileTelephonyHelpers.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileTelephonyHelpers.kt
index 621f793..d07b96f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileTelephonyHelpers.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileTelephonyHelpers.kt
@@ -16,10 +16,14 @@
 
 package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod
 
+import android.telephony.CellSignalStrengthCdma
+import android.telephony.SignalStrength
 import android.telephony.TelephonyCallback
 import android.telephony.TelephonyManager
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
 import org.mockito.Mockito.verify
 
@@ -31,6 +35,19 @@
         return callbackCaptor.allValues
     }
 
+    /** Convenience constructor for SignalStrength */
+    fun signalStrength(gsmLevel: Int, cdmaLevel: Int, isGsm: Boolean): SignalStrength {
+        val signalStrength = mock<SignalStrength>()
+        whenever(signalStrength.isGsm).thenReturn(isGsm)
+        whenever(signalStrength.level).thenReturn(gsmLevel)
+        val cdmaStrength =
+            mock<CellSignalStrengthCdma>().also { whenever(it.level).thenReturn(cdmaLevel) }
+        whenever(signalStrength.getCellSignalStrengths(CellSignalStrengthCdma::class.java))
+            .thenReturn(listOf(cdmaStrength))
+
+        return signalStrength
+    }
+
     inline fun <reified T> getTelephonyCallbackForType(mockTelephonyManager: TelephonyManager): T {
         val cbs = getTelephonyCallbacks(mockTelephonyManager).filterIsInstance<T>()
         assertThat(cbs.size).isEqualTo(1)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
index fa072fc..1eb1056 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
@@ -23,7 +23,6 @@
 import com.android.settingslib.mobile.TelephonyIcons
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.CarrierMergedNetworkType
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
@@ -74,9 +73,7 @@
     @Test
     fun gsm_level_default_unknown() =
         runBlocking(IMMEDIATE) {
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(isGsm = true),
-            )
+            connectionRepository.isGsm.value = true
 
             var latest: Int? = null
             val job = underTest.level.onEach { latest = it }.launchIn(this)
@@ -89,13 +86,9 @@
     @Test
     fun gsm_usesGsmLevel() =
         runBlocking(IMMEDIATE) {
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    isGsm = true,
-                    primaryLevel = GSM_LEVEL,
-                    cdmaLevel = CDMA_LEVEL
-                ),
-            )
+            connectionRepository.isGsm.value = true
+            connectionRepository.primaryLevel.value = GSM_LEVEL
+            connectionRepository.cdmaLevel.value = CDMA_LEVEL
 
             var latest: Int? = null
             val job = underTest.level.onEach { latest = it }.launchIn(this)
@@ -108,13 +101,9 @@
     @Test
     fun gsm_alwaysShowCdmaTrue_stillUsesGsmLevel() =
         runBlocking(IMMEDIATE) {
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    isGsm = true,
-                    primaryLevel = GSM_LEVEL,
-                    cdmaLevel = CDMA_LEVEL,
-                ),
-            )
+            connectionRepository.isGsm.value = true
+            connectionRepository.primaryLevel.value = GSM_LEVEL
+            connectionRepository.cdmaLevel.value = CDMA_LEVEL
             mobileIconsInteractor.alwaysUseCdmaLevel.value = true
 
             var latest: Int? = null
@@ -128,9 +117,7 @@
     @Test
     fun notGsm_level_default_unknown() =
         runBlocking(IMMEDIATE) {
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(isGsm = false),
-            )
+            connectionRepository.isGsm.value = false
 
             var latest: Int? = null
             val job = underTest.level.onEach { latest = it }.launchIn(this)
@@ -142,13 +129,9 @@
     @Test
     fun notGsm_alwaysShowCdmaTrue_usesCdmaLevel() =
         runBlocking(IMMEDIATE) {
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    isGsm = false,
-                    primaryLevel = GSM_LEVEL,
-                    cdmaLevel = CDMA_LEVEL
-                ),
-            )
+            connectionRepository.isGsm.value = false
+            connectionRepository.primaryLevel.value = GSM_LEVEL
+            connectionRepository.cdmaLevel.value = CDMA_LEVEL
             mobileIconsInteractor.alwaysUseCdmaLevel.value = true
 
             var latest: Int? = null
@@ -162,13 +145,9 @@
     @Test
     fun notGsm_alwaysShowCdmaFalse_usesPrimaryLevel() =
         runBlocking(IMMEDIATE) {
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    isGsm = false,
-                    primaryLevel = GSM_LEVEL,
-                    cdmaLevel = CDMA_LEVEL,
-                ),
-            )
+            connectionRepository.isGsm.value = false
+            connectionRepository.primaryLevel.value = GSM_LEVEL
+            connectionRepository.cdmaLevel.value = CDMA_LEVEL
             mobileIconsInteractor.alwaysUseCdmaLevel.value = false
 
             var latest: Int? = null
@@ -197,11 +176,8 @@
     @Test
     fun iconGroup_three_g() =
         runBlocking(IMMEDIATE) {
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    resolvedNetworkType = DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G))
-                ),
-            )
+            connectionRepository.resolvedNetworkType.value =
+                DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G))
 
             var latest: MobileIconGroup? = null
             val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
@@ -214,23 +190,14 @@
     @Test
     fun iconGroup_updates_on_change() =
         runBlocking(IMMEDIATE) {
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    resolvedNetworkType = DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G))
-                ),
-            )
+            connectionRepository.resolvedNetworkType.value =
+                DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G))
 
             var latest: MobileIconGroup? = null
             val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
 
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    resolvedNetworkType =
-                        DefaultNetworkType(
-                            mobileMappingsProxy.toIconKey(FOUR_G),
-                        ),
-                ),
-            )
+            connectionRepository.resolvedNetworkType.value =
+                DefaultNetworkType(mobileMappingsProxy.toIconKey(FOUR_G))
             yield()
 
             assertThat(latest).isEqualTo(TelephonyIcons.FOUR_G)
@@ -241,12 +208,8 @@
     @Test
     fun iconGroup_5g_override_type() =
         runBlocking(IMMEDIATE) {
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    resolvedNetworkType =
-                        OverrideNetworkType(mobileMappingsProxy.toIconKeyOverride(FIVE_G_OVERRIDE))
-                ),
-            )
+            connectionRepository.resolvedNetworkType.value =
+                OverrideNetworkType(mobileMappingsProxy.toIconKeyOverride(FIVE_G_OVERRIDE))
 
             var latest: MobileIconGroup? = null
             val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
@@ -259,12 +222,8 @@
     @Test
     fun iconGroup_default_if_no_lookup() =
         runBlocking(IMMEDIATE) {
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    resolvedNetworkType =
-                        DefaultNetworkType(mobileMappingsProxy.toIconKey(NETWORK_TYPE_UNKNOWN)),
-                ),
-            )
+            connectionRepository.resolvedNetworkType.value =
+                DefaultNetworkType(mobileMappingsProxy.toIconKey(NETWORK_TYPE_UNKNOWN))
 
             var latest: MobileIconGroup? = null
             val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
@@ -277,11 +236,7 @@
     @Test
     fun iconGroup_carrierMerged_usesOverride() =
         runBlocking(IMMEDIATE) {
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    resolvedNetworkType = CarrierMergedNetworkType,
-                ),
-            )
+            connectionRepository.resolvedNetworkType.value = CarrierMergedNetworkType
 
             var latest: MobileIconGroup? = null
             val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
@@ -295,11 +250,8 @@
     fun `icon group - checks default data`() =
         runBlocking(IMMEDIATE) {
             mobileIconsInteractor.defaultDataSubId.value = SUB_1_ID
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    resolvedNetworkType = DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G))
-                ),
-            )
+            connectionRepository.resolvedNetworkType.value =
+                DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G))
 
             var latest: MobileIconGroup? = null
             val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
@@ -380,9 +332,7 @@
             var latest: Boolean? = null
             val job = underTest.isDataConnected.onEach { latest = it }.launchIn(this)
 
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(dataConnectionState = DataConnectionState.Connected)
-            )
+            connectionRepository.dataConnectionState.value = DataConnectionState.Connected
             yield()
 
             assertThat(latest).isTrue()
@@ -396,9 +346,7 @@
             var latest: Boolean? = null
             val job = underTest.isDataConnected.onEach { latest = it }.launchIn(this)
 
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(dataConnectionState = DataConnectionState.Disconnected)
-            )
+            connectionRepository.dataConnectionState.value = DataConnectionState.Disconnected
 
             assertThat(latest).isFalse()
 
@@ -411,11 +359,11 @@
             var latest: Boolean? = null
             val job = underTest.isInService.onEach { latest = it }.launchIn(this)
 
-            connectionRepository.setConnectionInfo(MobileConnectionModel(isInService = true))
+            connectionRepository.isInService.value = true
 
             assertThat(latest).isTrue()
 
-            connectionRepository.setConnectionInfo(MobileConnectionModel(isInService = false))
+            connectionRepository.isInService.value = false
 
             assertThat(latest).isFalse()
 
@@ -429,22 +377,13 @@
             val job = underTest.isRoaming.onEach { latest = it }.launchIn(this)
 
             connectionRepository.cdmaRoaming.value = true
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    isGsm = true,
-                    isRoaming = false,
-                )
-            )
+            connectionRepository.isGsm.value = true
+            connectionRepository.isRoaming.value = false
             yield()
 
             assertThat(latest).isFalse()
 
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    isGsm = true,
-                    isRoaming = true,
-                )
-            )
+            connectionRepository.isRoaming.value = true
             yield()
 
             assertThat(latest).isTrue()
@@ -459,23 +398,15 @@
             val job = underTest.isRoaming.onEach { latest = it }.launchIn(this)
 
             connectionRepository.cdmaRoaming.value = false
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    isGsm = false,
-                    isRoaming = true,
-                )
-            )
+            connectionRepository.isGsm.value = false
+            connectionRepository.isRoaming.value = true
             yield()
 
             assertThat(latest).isFalse()
 
             connectionRepository.cdmaRoaming.value = true
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    isGsm = false,
-                    isRoaming = false,
-                )
-            )
+            connectionRepository.isGsm.value = false
+            connectionRepository.isRoaming.value = false
             yield()
 
             assertThat(latest).isTrue()
@@ -490,25 +421,15 @@
             val job = underTest.isRoaming.onEach { latest = it }.launchIn(this)
 
             connectionRepository.cdmaRoaming.value = true
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    isGsm = false,
-                    isRoaming = true,
-                    carrierNetworkChangeActive = true,
-                )
-            )
+            connectionRepository.isGsm.value = false
+            connectionRepository.isRoaming.value = true
+            connectionRepository.carrierNetworkChangeActive.value = true
             yield()
 
             assertThat(latest).isFalse()
 
             connectionRepository.cdmaRoaming.value = true
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    isGsm = true,
-                    isRoaming = true,
-                    carrierNetworkChangeActive = true,
-                )
-            )
+            connectionRepository.isGsm.value = true
             yield()
 
             assertThat(latest).isFalse()
@@ -526,24 +447,20 @@
 
             // Default network name, operator name is non-null, uses the operator name
             connectionRepository.networkName.value = DEFAULT_NAME
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(operatorAlphaShort = testOperatorName)
-            )
+            connectionRepository.operatorAlphaShort.value = testOperatorName
             yield()
 
             assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived(testOperatorName))
 
             // Default network name, operator name is null, uses the default
-            connectionRepository.setConnectionInfo(MobileConnectionModel(operatorAlphaShort = null))
+            connectionRepository.operatorAlphaShort.value = null
             yield()
 
             assertThat(latest).isEqualTo(DEFAULT_NAME)
 
             // Derived network name, operator name non-null, uses the derived name
             connectionRepository.networkName.value = DERIVED_NAME
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(operatorAlphaShort = testOperatorName)
-            )
+            connectionRepository.operatorAlphaShort.value = testOperatorName
             yield()
 
             assertThat(latest).isEqualTo(DERIVED_NAME)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLoggerTest.kt
new file mode 100644
index 0000000..4aa48d6
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLoggerTest.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.systemui.statusbar.pipeline.mobile.ui
+
+import android.widget.TextView
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.log.LogBufferFactory
+import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
+import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger.Companion.getIdForLogging
+import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.KeyguardMobileIconViewModel
+import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconViewModel
+import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.QsMobileIconViewModel
+import com.android.systemui.util.mockito.mock
+import com.google.common.truth.Truth.assertThat
+import java.io.PrintWriter
+import java.io.StringWriter
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+class MobileViewLoggerTest : SysuiTestCase() {
+    private val buffer = LogBufferFactory(DumpManager(), mock()).create("buffer", 10)
+    private val stringWriter = StringWriter()
+    private val printWriter = PrintWriter(stringWriter)
+
+    private val underTest = MobileViewLogger(buffer, mock())
+
+    @Mock private lateinit var flags: StatusBarPipelineFlags
+    @Mock private lateinit var commonViewModel: MobileIconViewModel
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+    }
+
+    @Test
+    fun collectionStarted_dumpHasInfo() {
+        val view = TextView(context)
+        val viewModel = QsMobileIconViewModel(commonViewModel, flags)
+
+        underTest.logCollectionStarted(view, viewModel)
+
+        val dumpString = getDumpString()
+        assertThat(dumpString).contains("${view.getIdForLogging()}, isCollecting=true")
+    }
+
+    @Test
+    fun collectionStarted_multipleViews_dumpHasInfo() {
+        val view = TextView(context)
+        val view2 = TextView(context)
+        val viewModel = QsMobileIconViewModel(commonViewModel, flags)
+        val viewModel2 = KeyguardMobileIconViewModel(commonViewModel, flags)
+
+        underTest.logCollectionStarted(view, viewModel)
+        underTest.logCollectionStarted(view2, viewModel2)
+
+        val dumpString = getDumpString()
+        assertThat(dumpString).contains("${view.getIdForLogging()}, isCollecting=true")
+        assertThat(dumpString).contains("${view2.getIdForLogging()}, isCollecting=true")
+    }
+
+    @Test
+    fun collectionStopped_dumpHasInfo() {
+        val view = TextView(context)
+        val view2 = TextView(context)
+        val viewModel = QsMobileIconViewModel(commonViewModel, flags)
+        val viewModel2 = KeyguardMobileIconViewModel(commonViewModel, flags)
+
+        underTest.logCollectionStarted(view, viewModel)
+        underTest.logCollectionStarted(view2, viewModel2)
+        underTest.logCollectionStopped(view, viewModel)
+
+        val dumpString = getDumpString()
+        assertThat(dumpString).contains("${view.getIdForLogging()}, isCollecting=false")
+        assertThat(dumpString).contains("${view2.getIdForLogging()}, isCollecting=true")
+    }
+
+    private fun getDumpString(): String {
+        underTest.dump(printWriter, args = arrayOf())
+        return stringWriter.toString()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileViewTest.kt
index e68a397..7420db2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileViewTest.kt
@@ -32,6 +32,7 @@
 import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
 import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconInteractor
+import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger
 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.LocationBasedMobileViewModel
 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconViewModel
 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.QsMobileIconViewModel
@@ -60,6 +61,7 @@
 
     @Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags
     @Mock private lateinit var tableLogBuffer: TableLogBuffer
+    @Mock private lateinit var viewLogger: MobileViewLogger
     @Mock private lateinit var constants: ConnectivityConstants
     private lateinit var interactor: FakeMobileIconInteractor
     private lateinit var airplaneModeRepository: FakeAirplaneModeRepository
@@ -94,7 +96,13 @@
 
     @Test
     fun setVisibleState_icon_iconShownDotHidden() {
-        val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
+        val view =
+            ModernStatusBarMobileView.constructAndBind(
+                context,
+                viewLogger,
+                SLOT_NAME,
+                viewModel,
+            )
 
         view.setVisibleState(StatusBarIconView.STATE_ICON, /* animate= */ false)
 
@@ -109,8 +117,13 @@
 
     @Test
     fun setVisibleState_dot_iconHiddenDotShown() {
-        val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
-
+        val view =
+            ModernStatusBarMobileView.constructAndBind(
+                context,
+                viewLogger,
+                SLOT_NAME,
+                viewModel,
+            )
         view.setVisibleState(StatusBarIconView.STATE_DOT, /* animate= */ false)
 
         ViewUtils.attachView(view)
@@ -124,8 +137,13 @@
 
     @Test
     fun setVisibleState_hidden_iconAndDotHidden() {
-        val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
-
+        val view =
+            ModernStatusBarMobileView.constructAndBind(
+                context,
+                viewLogger,
+                SLOT_NAME,
+                viewModel,
+            )
         view.setVisibleState(StatusBarIconView.STATE_HIDDEN, /* animate= */ false)
 
         ViewUtils.attachView(view)
@@ -142,8 +160,13 @@
         whenever(constants.hasDataCapabilities).thenReturn(false)
         createViewModel()
 
-        val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
-
+        val view =
+            ModernStatusBarMobileView.constructAndBind(
+                context,
+                viewLogger,
+                SLOT_NAME,
+                viewModel,
+            )
         ViewUtils.attachView(view)
         testableLooper.processAllMessages()
 
@@ -157,8 +180,13 @@
         whenever(constants.hasDataCapabilities).thenReturn(true)
         createViewModel()
 
-        val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
-
+        val view =
+            ModernStatusBarMobileView.constructAndBind(
+                context,
+                viewLogger,
+                SLOT_NAME,
+                viewModel,
+            )
         ViewUtils.attachView(view)
         testableLooper.processAllMessages()
 
@@ -171,8 +199,13 @@
     fun isIconVisible_notAirplaneMode_outputsTrue() {
         airplaneModeRepository.setIsAirplaneMode(false)
 
-        val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
-
+        val view =
+            ModernStatusBarMobileView.constructAndBind(
+                context,
+                viewLogger,
+                SLOT_NAME,
+                viewModel,
+            )
         ViewUtils.attachView(view)
         testableLooper.processAllMessages()
 
@@ -185,8 +218,13 @@
     fun isIconVisible_airplaneMode_outputsTrue() {
         airplaneModeRepository.setIsAirplaneMode(true)
 
-        val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
-
+        val view =
+            ModernStatusBarMobileView.constructAndBind(
+                context,
+                viewLogger,
+                SLOT_NAME,
+                viewModel,
+            )
         ViewUtils.attachView(view)
         testableLooper.processAllMessages()
 
@@ -198,7 +236,13 @@
     @Test
     fun onDarkChanged_iconHasNewColor() {
         whenever(statusBarPipelineFlags.useDebugColoring()).thenReturn(false)
-        val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
+        val view =
+            ModernStatusBarMobileView.constructAndBind(
+                context,
+                viewLogger,
+                SLOT_NAME,
+                viewModel,
+            )
         ViewUtils.attachView(view)
         testableLooper.processAllMessages()
 
@@ -214,7 +258,13 @@
     @Test
     fun setStaticDrawableColor_iconHasNewColor() {
         whenever(statusBarPipelineFlags.useDebugColoring()).thenReturn(false)
-        val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
+        val view =
+            ModernStatusBarMobileView.constructAndBind(
+                context,
+                viewLogger,
+                SLOT_NAME,
+                viewModel,
+            )
         ViewUtils.attachView(view)
         testableLooper.processAllMessages()
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt
index f983030..a6d9152 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt
@@ -28,6 +28,7 @@
 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconViewModelTest.Companion.defaultSignal
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
 import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
+import com.android.systemui.util.mockito.mock
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.launchIn
@@ -84,7 +85,7 @@
                 testScope.backgroundScope,
             )
 
-        homeIcon = HomeMobileIconViewModel(commonImpl, statusBarPipelineFlags)
+        homeIcon = HomeMobileIconViewModel(commonImpl, statusBarPipelineFlags, mock())
         qsIcon = QsMobileIconViewModel(commonImpl, statusBarPipelineFlags)
         keyguardIcon = KeyguardMobileIconViewModel(commonImpl, statusBarPipelineFlags)
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt
index 4628f84..ddb7f4d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt
@@ -24,6 +24,8 @@
 import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor
+import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger
+import com.android.systemui.statusbar.pipeline.mobile.ui.VerboseMobileViewLogger
 import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
 import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
@@ -51,6 +53,8 @@
     private lateinit var airplaneModeInteractor: AirplaneModeInteractor
     @Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags
     @Mock private lateinit var constants: ConnectivityConstants
+    @Mock private lateinit var logger: MobileViewLogger
+    @Mock private lateinit var verboseLogger: VerboseMobileViewLogger
 
     private val testDispatcher = UnconfinedTestDispatcher()
     private val testScope = TestScope(testDispatcher)
@@ -73,6 +77,8 @@
         underTest =
             MobileIconsViewModel(
                 subscriptionIdsFlow,
+                logger,
+                verboseLogger,
                 interactor,
                 airplaneModeInteractor,
                 constants,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarViewTest.kt
index e4c8fd0..b4039d9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarViewTest.kt
@@ -164,6 +164,10 @@
         override fun getShouldIconBeVisible(): Boolean {
             return shouldIconBeVisibleInternal
         }
+
+        override fun isCollecting(): Boolean {
+            return true
+        }
     }
 }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt
index 12b1664..1c71f8b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt
@@ -368,40 +368,37 @@
 
                 // network = CarrierMerged => not shown
                 TestCase(
+                    enabled = true,
+                    isDefault = true,
+                    forceHidden = false,
                     network =
                         WifiNetworkModel.CarrierMerged(NETWORK_ID, subscriptionId = 1, level = 1),
                     expected = null,
                 ),
 
-                // network = Inactive => not shown
+                // isDefault = false => no networks shown
                 TestCase(
+                    isDefault = false,
                     network = WifiNetworkModel.Inactive,
                     expected = null,
                 ),
-
-                // network = Unavailable => not shown
                 TestCase(
+                    isDefault = false,
                     network = WifiNetworkModel.Unavailable,
                     expected = null,
                 ),
-
-                // network = Active & validated = false => not shown
                 TestCase(
+                    isDefault = false,
                     network = WifiNetworkModel.Active(NETWORK_ID, isValidated = false, level = 3),
                     expected = null,
                 ),
 
-                // network = Active & validated = true => shown
+                // Even though this network is active and validated, we still doesn't want it shown
+                // because wifi isn't the default connection (b/272509965).
                 TestCase(
+                    isDefault = false,
                     network = WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 4),
-                    expected =
-                        Expected(
-                            iconResource = WIFI_FULL_ICONS[4],
-                            contentDescription = { context ->
-                                context.getString(WIFI_CONNECTION_STRENGTH[4])
-                            },
-                            description = "Full internet level 4 icon",
-                        ),
+                    expected = null,
                 ),
             )
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImplTest.kt
index 5129f85..6980a0b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImplTest.kt
@@ -90,6 +90,12 @@
     }
 
     @Test
+    fun testFrpNotActiveByDefault() {
+        init()
+        assertThat(controller.isFrpActive).isFalse()
+    }
+
+    @Test
     fun testNotUserSetupByDefault() {
         init()
         assertThat(controller.isUserSetup(START_USER)).isFalse()
@@ -104,6 +110,14 @@
     }
 
     @Test
+    fun testFrpActiveWhenCreated() {
+        settings.putInt(Settings.Secure.SECURE_FRP_MODE, 1)
+        init()
+
+        assertThat(controller.isFrpActive).isTrue()
+    }
+
+    @Test
     fun testUserSetupWhenCreated() {
         settings.putIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 1, START_USER)
         init()
@@ -122,6 +136,16 @@
     }
 
     @Test
+    fun testFrpActiveChange() {
+        init()
+
+        settings.putInt(Settings.Secure.SECURE_FRP_MODE, 1)
+        testableLooper.processAllMessages() // background observer
+
+        assertThat(controller.isFrpActive).isTrue()
+    }
+
+    @Test
     fun testUserSetupChange() {
         init()
 
@@ -164,6 +188,7 @@
         mainExecutor.runAllReady()
 
         verify(listener, never()).onDeviceProvisionedChanged()
+        verify(listener, never()).onFrpActiveChanged()
         verify(listener, never()).onUserSetupChanged()
         verify(listener, never()).onUserSwitched()
     }
@@ -181,6 +206,7 @@
         verify(listener).onUserSwitched()
         verify(listener, never()).onUserSetupChanged()
         verify(listener, never()).onDeviceProvisionedChanged()
+        verify(listener, never()).onFrpActiveChanged()
     }
 
     @Test
@@ -195,6 +221,7 @@
         verify(listener, never()).onUserSwitched()
         verify(listener).onUserSetupChanged()
         verify(listener, never()).onDeviceProvisionedChanged()
+        verify(listener, never()).onFrpActiveChanged()
     }
 
     @Test
@@ -208,10 +235,26 @@
 
         verify(listener, never()).onUserSwitched()
         verify(listener, never()).onUserSetupChanged()
+        verify(listener, never()).onFrpActiveChanged()
         verify(listener).onDeviceProvisionedChanged()
     }
 
     @Test
+    fun testListenerCalledOnFrpActiveChanged() {
+        init()
+        controller.addCallback(listener)
+
+        settings.putInt(Settings.Secure.SECURE_FRP_MODE, 1)
+        testableLooper.processAllMessages()
+        mainExecutor.runAllReady()
+
+        verify(listener, never()).onUserSwitched()
+        verify(listener, never()).onUserSetupChanged()
+        verify(listener, never()).onDeviceProvisionedChanged()
+        verify(listener).onFrpActiveChanged()
+    }
+
+    @Test
     fun testRemoveListener() {
         init()
         controller.addCallback(listener)
@@ -220,11 +263,13 @@
         switchUser(10)
         settings.putIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 1, START_USER)
         settings.putInt(Settings.Global.DEVICE_PROVISIONED, 1)
+        settings.putInt(Settings.Secure.SECURE_FRP_MODE, 1)
 
         testableLooper.processAllMessages()
         mainExecutor.runAllReady()
 
         verify(listener, never()).onDeviceProvisionedChanged()
+        verify(listener, never()).onFrpActiveChanged()
         verify(listener, never()).onUserSetupChanged()
         verify(listener, never()).onUserSwitched()
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerTest.java
index 48b1732..481d453 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerTest.java
@@ -38,6 +38,7 @@
 import com.android.internal.view.RotationPolicy;
 import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
 import com.android.systemui.util.wrapper.RotationPolicyWrapper;
@@ -55,10 +56,12 @@
 
     private static final String[] DEFAULT_SETTINGS = new String[]{"0:1", "2:0:1", "1:2"};
 
+    @Mock private DeviceStateManager mDeviceStateManager;
+    @Mock private DeviceStateRotationLockSettingControllerLogger mLogger;
+    @Mock private DumpManager mDumpManager;
+
     private final FakeSystemClock mFakeSystemClock = new FakeSystemClock();
     private final FakeExecutor mFakeExecutor = new FakeExecutor(mFakeSystemClock);
-    @Mock
-    private DeviceStateManager mDeviceStateManager;
     private final RotationPolicyWrapper mFakeRotationPolicy = new FakeRotationPolicy();
     private DeviceStateRotationLockSettingController mDeviceStateRotationLockSettingController;
     private DeviceStateManager.DeviceStateCallback mDeviceStateCallback;
@@ -78,7 +81,13 @@
         mSettingsManager = DeviceStateRotationLockSettingsManager.getInstance(mContext);
         mDeviceStateRotationLockSettingController =
                 new DeviceStateRotationLockSettingController(
-                        mFakeRotationPolicy, mDeviceStateManager, mFakeExecutor, mSettingsManager);
+                        mFakeRotationPolicy,
+                        mDeviceStateManager,
+                        mFakeExecutor,
+                        mSettingsManager,
+                        mLogger,
+                        mDumpManager
+                );
 
         mDeviceStateRotationLockSettingController.setListening(true);
         verify(mDeviceStateManager)
@@ -173,15 +182,11 @@
     }
 
     @Test
-    public void whenDeviceStateSwitchedToIgnoredState_usePreviousSetting() {
-        initializeSettingsWith(
-                0, DEVICE_STATE_ROTATION_LOCK_IGNORED, 1, DEVICE_STATE_ROTATION_LOCK_UNLOCKED);
-        mFakeRotationPolicy.setRotationLock(true);
-
-        mDeviceStateCallback.onStateChanged(1);
-        assertThat(mFakeRotationPolicy.isRotationLocked()).isFalse();
-
+    public void whenDeviceStateSwitchedToIgnoredState_useFallbackSetting() {
         mDeviceStateCallback.onStateChanged(0);
+        assertThat(mFakeRotationPolicy.isRotationLocked()).isTrue();
+
+        mDeviceStateCallback.onStateChanged(2);
         assertThat(mFakeRotationPolicy.isRotationLocked()).isFalse();
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/stylus/OWNERS b/packages/SystemUI/tests/src/com/android/systemui/stylus/OWNERS
index 7ccb316..0ec996b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/stylus/OWNERS
+++ b/packages/SystemUI/tests/src/com/android/systemui/stylus/OWNERS
@@ -5,4 +5,6 @@
 madym@google.com
 mgalhardo@google.com
 petrcermak@google.com
+stevenckng@google.com
+tkachenkoi@google.com
 vanjan@google.com
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusManagerTest.kt
index f8bf4b9..4525ad2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusManagerTest.kt
@@ -65,8 +65,6 @@
     @Mock lateinit var uiEventLogger: UiEventLogger
     @Mock lateinit var stylusCallback: StylusManager.StylusCallback
     @Mock lateinit var otherStylusCallback: StylusManager.StylusCallback
-    @Mock lateinit var stylusBatteryCallback: StylusManager.StylusBatteryCallback
-    @Mock lateinit var otherStylusBatteryCallback: StylusManager.StylusBatteryCallback
 
     private lateinit var mockitoSession: StaticMockitoSession
     private lateinit var stylusManager: StylusManager
@@ -123,7 +121,6 @@
 
         stylusManager.startListener()
         stylusManager.registerCallback(stylusCallback)
-        stylusManager.registerBatteryCallback(stylusBatteryCallback)
         clearInvocations(inputManager)
     }
 
@@ -434,23 +431,6 @@
     }
 
     @Test
-    fun onMetadataChanged_multipleRegisteredBatteryCallbacks_executesAll() {
-        stylusManager.onInputDeviceAdded(BT_STYLUS_DEVICE_ID)
-        stylusManager.registerBatteryCallback(otherStylusBatteryCallback)
-
-        stylusManager.onMetadataChanged(
-            bluetoothDevice,
-            BluetoothDevice.METADATA_MAIN_CHARGING,
-            "true".toByteArray()
-        )
-
-        verify(stylusBatteryCallback, times(1))
-            .onStylusBluetoothChargingStateChanged(BT_STYLUS_DEVICE_ID, bluetoothDevice, true)
-        verify(otherStylusBatteryCallback, times(1))
-            .onStylusBluetoothChargingStateChanged(BT_STYLUS_DEVICE_ID, bluetoothDevice, true)
-    }
-
-    @Test
     fun onMetadataChanged_chargingStateTrue_executesBatteryCallbacks() {
         stylusManager.onInputDeviceAdded(BT_STYLUS_DEVICE_ID)
 
@@ -460,7 +440,7 @@
             "true".toByteArray()
         )
 
-        verify(stylusBatteryCallback, times(1))
+        verify(stylusCallback, times(1))
             .onStylusBluetoothChargingStateChanged(BT_STYLUS_DEVICE_ID, bluetoothDevice, true)
     }
 
@@ -474,7 +454,7 @@
             "false".toByteArray()
         )
 
-        verify(stylusBatteryCallback, times(1))
+        verify(stylusCallback, times(1))
             .onStylusBluetoothChargingStateChanged(BT_STYLUS_DEVICE_ID, bluetoothDevice, false)
     }
 
@@ -486,7 +466,7 @@
             "true".toByteArray()
         )
 
-        verifyNoMoreInteractions(stylusBatteryCallback)
+        verifyNoMoreInteractions(stylusCallback)
     }
 
     @Test
@@ -499,8 +479,7 @@
             "true".toByteArray()
         )
 
-        verify(stylusBatteryCallback, never())
-            .onStylusBluetoothChargingStateChanged(any(), any(), any())
+        verify(stylusCallback, never()).onStylusBluetoothChargingStateChanged(any(), any(), any())
     }
 
     @Test
@@ -614,7 +593,7 @@
     fun onBatteryStateChanged_executesBatteryCallbacks() {
         stylusManager.onBatteryStateChanged(STYLUS_DEVICE_ID, 1, batteryState)
 
-        verify(stylusBatteryCallback, times(1))
+        verify(stylusCallback, times(1))
             .onStylusUsiBatteryStateChanged(STYLUS_DEVICE_ID, 1, batteryState)
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerStartableTest.kt
index 82b80f5..3db0ecc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerStartableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerStartableTest.kt
@@ -96,7 +96,6 @@
         startable.start()
 
         verify(stylusManager, times(1)).registerCallback(startable)
-        verify(stylusManager, times(1)).registerBatteryCallback(startable)
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShaderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShaderTest.kt
new file mode 100644
index 0000000..71bd511
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShaderTest.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.surfaceeffects.turbulencenoise
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class TurbulenceNoiseShaderTest : SysuiTestCase() {
+
+    private lateinit var turbulenceNoiseShader: TurbulenceNoiseShader
+
+    @Test
+    fun compliesSimplexNoise() {
+        turbulenceNoiseShader = TurbulenceNoiseShader()
+    }
+
+    @Test
+    fun compliesFractalNoise() {
+        turbulenceNoiseShader = TurbulenceNoiseShader(useFractal = true)
+    }
+}
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 f9b5767..17b5e05 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
@@ -33,6 +33,7 @@
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
+import android.app.UiModeManager;
 import android.app.WallpaperColors;
 import android.app.WallpaperManager;
 import android.content.BroadcastReceiver;
@@ -47,7 +48,6 @@
 import android.os.UserManager;
 import android.provider.Settings;
 import android.testing.AndroidTestingRunner;
-import android.view.accessibility.AccessibilityManager;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.test.filters.SmallTest;
@@ -116,7 +116,7 @@
     @Mock
     private WakefulnessLifecycle mWakefulnessLifecycle;
     @Mock
-    private AccessibilityManager mAccessibilityManager;
+    private UiModeManager mUiModeManager;
     @Captor
     private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiver;
     @Captor
@@ -135,7 +135,7 @@
         MockitoAnnotations.initMocks(this);
         when(mFeatureFlags.isEnabled(Flags.MONET)).thenReturn(true);
         when(mWakefulnessLifecycle.getWakefulness()).thenReturn(WAKEFULNESS_AWAKE);
-        when(mAccessibilityManager.getUiContrast()).thenReturn(0.5f);
+        when(mUiModeManager.getContrast()).thenReturn(0.5f);
         when(mDeviceProvisionedController.isCurrentUserSetup()).thenReturn(true);
         when(mResources.getColor(eq(android.R.color.system_accent1_500), any()))
                 .thenReturn(Color.RED);
@@ -151,7 +151,7 @@
                 mBroadcastDispatcher, mBgHandler, mMainExecutor, mBgExecutor, mThemeOverlayApplier,
                 mSecureSettings, mWallpaperManager, mUserManager, mDeviceProvisionedController,
                 mUserTracker, mDumpManager, mFeatureFlags, mResources, mWakefulnessLifecycle,
-                mAccessibilityManager) {
+                mUiModeManager) {
             @VisibleForTesting
             protected boolean isNightMode() {
                 return false;
@@ -733,7 +733,7 @@
                 mBroadcastDispatcher, mBgHandler, executor, executor, mThemeOverlayApplier,
                 mSecureSettings, mWallpaperManager, mUserManager, mDeviceProvisionedController,
                 mUserTracker, mDumpManager, mFeatureFlags, mResources, mWakefulnessLifecycle,
-                mAccessibilityManager) {
+                mUiModeManager) {
             @VisibleForTesting
             protected boolean isNightMode() {
                 return false;
@@ -773,7 +773,7 @@
                 mBroadcastDispatcher, mBgHandler, executor, executor, mThemeOverlayApplier,
                 mSecureSettings, mWallpaperManager, mUserManager, mDeviceProvisionedController,
                 mUserTracker, mDumpManager, mFeatureFlags, mResources, mWakefulnessLifecycle,
-                mAccessibilityManager) {
+                mUiModeManager) {
             @VisibleForTesting
             protected boolean isNightMode() {
                 return false;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
index 5288608..0413d92 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
@@ -25,7 +25,6 @@
 import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_HALF_OPEN
 import com.android.systemui.unfold.updates.FOLD_UPDATE_START_CLOSING
 import com.android.systemui.unfold.updates.FOLD_UPDATE_START_OPENING
-import com.android.systemui.unfold.updates.FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE
 import com.android.systemui.unfold.util.TestFoldStateProvider
 import org.junit.Before
 import org.junit.Test
@@ -50,7 +49,7 @@
         runOnMainThreadWithInterval(
             { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
             { foldStateProvider.sendHingeAngleUpdate(10f) },
-            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+            { foldStateProvider.sendUnfoldedScreenAvailable() },
             { foldStateProvider.sendHingeAngleUpdate(90f) },
             { foldStateProvider.sendHingeAngleUpdate(180f) },
             { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN) },
@@ -67,7 +66,7 @@
         runOnMainThreadWithInterval(
             { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
             { foldStateProvider.sendHingeAngleUpdate(10f) },
-            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+            { foldStateProvider.sendUnfoldedScreenAvailable() },
             { foldStateProvider.sendHingeAngleUpdate(90f) },
             { foldStateProvider.sendHingeAngleUpdate(180f) },
             { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN) },
@@ -84,7 +83,7 @@
             { foldStateProvider.sendHingeAngleUpdate(90f) },
             { foldStateProvider.sendHingeAngleUpdate(180f) },
             { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN) },
-            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+            { foldStateProvider.sendUnfoldedScreenAvailable() },
         )
 
         with(listener.ensureTransitionFinished()) {
@@ -113,7 +112,7 @@
     fun testUnfoldAndStopUnfolding_finishesTheUnfoldTransition() {
         runOnMainThreadWithInterval(
             { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
-            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+            { foldStateProvider.sendUnfoldedScreenAvailable() },
             { foldStateProvider.sendHingeAngleUpdate(10f) },
             { foldStateProvider.sendHingeAngleUpdate(90f) },
             { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_HALF_OPEN) },
@@ -129,7 +128,7 @@
     fun testFoldImmediatelyAfterUnfold_runsFoldAnimation() {
         runOnMainThreadWithInterval(
             { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
-            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+            { foldStateProvider.sendUnfoldedScreenAvailable() },
             { foldStateProvider.sendHingeAngleUpdate(10f) },
             { foldStateProvider.sendHingeAngleUpdate(90f) },
             {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
index 6086e16..8476d0d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
@@ -26,6 +26,7 @@
 import com.android.systemui.unfold.system.ActivityManagerActivityTypeProvider
 import com.android.systemui.unfold.updates.FoldProvider.FoldCallback
 import com.android.systemui.unfold.updates.RotationChangeProvider.RotationListener
+import com.android.systemui.unfold.updates.hinge.FULLY_OPEN_DEGREES
 import com.android.systemui.unfold.updates.hinge.HingeAngleProvider
 import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
 import com.android.systemui.unfold.updates.screen.ScreenStatusProvider.ScreenListener
@@ -71,6 +72,7 @@
 
     private val foldUpdates: MutableList<Int> = arrayListOf()
     private val hingeAngleUpdates: MutableList<Float> = arrayListOf()
+    private val unfoldedScreenAvailabilityUpdates: MutableList<Unit> = arrayListOf()
 
     private var scheduledRunnable: Runnable? = null
     private var scheduledRunnableDelay: Long? = null
@@ -106,6 +108,10 @@
                 override fun onFoldUpdate(update: Int) {
                     foldUpdates.add(update)
                 }
+
+                override fun onUnfoldedScreenAvailable() {
+                    unfoldedScreenAvailabilityUpdates.add(Unit)
+                }
             })
         foldStateProvider.start()
 
@@ -156,8 +162,8 @@
         sendHingeAngleEvent(10)
         screenOnStatusProvider.notifyScreenTurnedOn()
 
-        assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_OPENING,
-                FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE)
+        assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_OPENING)
+        assertThat(unfoldedScreenAvailabilityUpdates).hasSize(1)
     }
 
     @Test
@@ -174,8 +180,9 @@
         sendHingeAngleEvent(40)
         sendHingeAngleEvent(10)
 
-        assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_OPENING,
-                FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE, FOLD_UPDATE_START_CLOSING)
+        assertThat(foldUpdates)
+                .containsExactly(FOLD_UPDATE_START_OPENING, FOLD_UPDATE_START_CLOSING)
+        assertThat(unfoldedScreenAvailabilityUpdates).hasSize(1)
     }
 
     @Test
@@ -223,7 +230,7 @@
 
         fireScreenOnEvent()
 
-        assertThat(foldUpdates).containsExactly(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE)
+        assertThat(unfoldedScreenAvailabilityUpdates).hasSize(1)
     }
 
     @Test
@@ -277,7 +284,7 @@
 
     @Test
     fun startClosingEvent_afterTimeout_finishHalfOpenEventEmitted() {
-        sendHingeAngleEvent(90)
+        setInitialHingeAngle(90)
         sendHingeAngleEvent(80)
 
         simulateTimeout(HALF_OPENED_TIMEOUT_MILLIS)
@@ -288,7 +295,7 @@
 
     @Test
     fun startClosingEvent_beforeTimeout_abortNotEmitted() {
-        sendHingeAngleEvent(90)
+        setInitialHingeAngle(90)
         sendHingeAngleEvent(80)
 
         simulateTimeout(HALF_OPENED_TIMEOUT_MILLIS - 1)
@@ -298,7 +305,7 @@
 
     @Test
     fun startClosingEvent_eventBeforeTimeout_oneEventEmitted() {
-        sendHingeAngleEvent(180)
+        setInitialHingeAngle(180)
         sendHingeAngleEvent(90)
 
         simulateTimeout(HALF_OPENED_TIMEOUT_MILLIS - 1)
@@ -309,7 +316,7 @@
 
     @Test
     fun startClosingEvent_timeoutAfterTimeoutRescheduled_finishHalfOpenStateEmitted() {
-        sendHingeAngleEvent(180)
+        setInitialHingeAngle(180)
         sendHingeAngleEvent(90)
 
         // The timeout should not trigger here.
@@ -323,7 +330,7 @@
 
     @Test
     fun startClosingEvent_shortTimeBetween_emitsOnlyOneEvents() {
-        sendHingeAngleEvent(180)
+        setInitialHingeAngle(180)
 
         sendHingeAngleEvent(90)
         sendHingeAngleEvent(80)
@@ -334,20 +341,19 @@
     @Test
     fun startClosingEvent_whileClosing_emittedDespiteInitialAngle() {
         val maxAngle = 180 - FULLY_OPEN_THRESHOLD_DEGREES.toInt()
-        for (i in 1..maxAngle) {
-            foldUpdates.clear()
-
-            simulateFolding(startAngle = i)
+        val minAngle = Math.ceil(HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES.toDouble()).toInt() + 1
+        for (startAngle in minAngle..maxAngle) {
+            setInitialHingeAngle(startAngle)
+            sendHingeAngleEvent(startAngle - HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES.toInt() - 1)
 
             assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
-            simulateTimeout() // Timeout to set the state to aborted.
         }
     }
 
     @Test
     fun startClosingEvent_whileNotOnLauncher_doesNotTriggerBeforeThreshold() {
         setupForegroundActivityType(isHomeActivity = false)
-        sendHingeAngleEvent(180)
+        setInitialHingeAngle(180)
 
         sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
 
@@ -357,7 +363,7 @@
     @Test
     fun startClosingEvent_whileActivityTypeNotAvailable_triggerBeforeThreshold() {
         setupForegroundActivityType(isHomeActivity = null)
-        sendHingeAngleEvent(180)
+        setInitialHingeAngle(180)
 
         sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
 
@@ -367,7 +373,7 @@
     @Test
     fun startClosingEvent_whileOnLauncher_doesTriggerBeforeThreshold() {
         setupForegroundActivityType(isHomeActivity = true)
-        sendHingeAngleEvent(180)
+        setInitialHingeAngle(180)
 
         sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
 
@@ -377,9 +383,11 @@
     @Test
     fun startClosingEvent_whileNotOnLauncher_triggersAfterThreshold() {
         setupForegroundActivityType(isHomeActivity = false)
-        sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)
+        setInitialHingeAngle(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)
 
-        sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES - 1)
+        sendHingeAngleEvent(
+                START_CLOSING_ON_APPS_THRESHOLD_DEGREES -
+                        HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES.toInt() - 1)
 
         assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
     }
@@ -388,7 +396,7 @@
     fun startClosingEvent_whileNotOnKeyguardAndNotOnLauncher_doesNotTriggerBeforeThreshold() {
         setKeyguardVisibility(visible = false)
         setupForegroundActivityType(isHomeActivity = false)
-        sendHingeAngleEvent(180)
+        setInitialHingeAngle(180)
 
         sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
 
@@ -398,7 +406,7 @@
     @Test
     fun startClosingEvent_whileKeyguardStateNotAvailable_triggerBeforeThreshold() {
         setKeyguardVisibility(visible = null)
-        sendHingeAngleEvent(180)
+        setInitialHingeAngle(180)
 
         sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
 
@@ -408,7 +416,7 @@
     @Test
     fun startClosingEvent_whileonKeyguard_doesTriggerBeforeThreshold() {
         setKeyguardVisibility(visible = true)
-        sendHingeAngleEvent(180)
+        setInitialHingeAngle(180)
 
         sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
 
@@ -418,9 +426,59 @@
     @Test
     fun startClosingEvent_whileNotOnKeyguard_triggersAfterThreshold() {
         setKeyguardVisibility(visible = false)
-        sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)
+        setInitialHingeAngle(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)
 
-        sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES - 1)
+        sendHingeAngleEvent(
+                START_CLOSING_ON_APPS_THRESHOLD_DEGREES -
+                        HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES.toInt() - 1)
+
+        assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
+    }
+
+    @Test
+    fun startClosingEvent_doesNotTriggerBelowThreshold() {
+        val thresholdAngle = (FULLY_OPEN_DEGREES - FULLY_OPEN_THRESHOLD_DEGREES).toInt()
+        setInitialHingeAngle(180)
+        sendHingeAngleEvent(thresholdAngle + 1)
+
+        assertThat(foldUpdates).isEmpty()
+    }
+
+    @Test
+    fun startClosingEvent_triggersAfterThreshold() {
+        val thresholdAngle = (FULLY_OPEN_DEGREES - FULLY_OPEN_THRESHOLD_DEGREES).toInt()
+        setInitialHingeAngle(180)
+        sendHingeAngleEvent(thresholdAngle + 1)
+        sendHingeAngleEvent(thresholdAngle - 1)
+
+        assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
+    }
+
+    @Test
+    fun startClosingEvent_triggersAfterThreshold_fromHalfOpen() {
+        setInitialHingeAngle(120)
+        sendHingeAngleEvent((120 - HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES + 1).toInt())
+        assertThat(foldUpdates).isEmpty()
+        sendHingeAngleEvent((120 - HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES - 1).toInt())
+
+        assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
+    }
+
+    @Test
+    fun startOpeningAndClosingEvents_triggerWithOpenAndClose() {
+        setInitialHingeAngle(120)
+        sendHingeAngleEvent(130)
+        sendHingeAngleEvent(120)
+        assertThat(foldUpdates)
+                .containsExactly(FOLD_UPDATE_START_OPENING, FOLD_UPDATE_START_CLOSING)
+    }
+
+    @Test
+    fun startClosingEvent_notInterrupted_whenAngleIsSlightlyIncreased() {
+        setInitialHingeAngle(120)
+        sendHingeAngleEvent(110)
+        sendHingeAngleEvent(111)
+        sendHingeAngleEvent(100)
 
         assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
     }
@@ -504,11 +562,6 @@
         }
     }
 
-    private fun simulateFolding(startAngle: Int) {
-        sendHingeAngleEvent(startAngle)
-        sendHingeAngleEvent(startAngle - 1)
-    }
-
     private fun setFoldState(folded: Boolean) {
         foldProvider.notifyFolded(folded)
     }
@@ -521,6 +574,17 @@
         testHingeAngleProvider.notifyAngle(angle.toFloat())
     }
 
+    private fun setInitialHingeAngle(angle: Int) {
+        setFoldState(angle == 0)
+        sendHingeAngleEvent(angle)
+        if (scheduledRunnableDelay != null) {
+            simulateTimeout()
+        }
+        hingeAngleUpdates.clear()
+        foldUpdates.clear()
+        unfoldedScreenAvailabilityUpdates.clear()
+    }
+
     private class TestFoldProvider : FoldProvider {
         private val callbacks = arrayListOf<FoldCallback>()
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/RotationChangeProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/RotationChangeProviderTest.kt
index 85cfef7..fd368eb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/RotationChangeProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/RotationChangeProviderTest.kt
@@ -16,22 +16,24 @@
 
 package com.android.systemui.unfold.updates
 
+import android.content.Context
+import android.hardware.display.DisplayManager
+import android.os.Looper
 import android.testing.AndroidTestingRunner
-import android.view.IRotationWatcher
-import android.view.IWindowManager
+import android.view.Display
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.unfold.updates.RotationChangeProvider.RotationListener
-import com.android.systemui.util.concurrency.FakeExecutor
-import com.android.systemui.util.time.FakeSystemClock
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.utils.os.FakeHandler
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.ArgumentCaptor
 import org.mockito.ArgumentMatchers.any
-import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.Captor
 import org.mockito.Mock
+import org.mockito.Mockito.spy
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.verifyNoMoreInteractions
 import org.mockito.MockitoAnnotations
@@ -42,19 +44,23 @@
 
     private lateinit var rotationChangeProvider: RotationChangeProvider
 
-    @Mock lateinit var windowManagerInterface: IWindowManager
+    @Mock lateinit var displayManager: DisplayManager
     @Mock lateinit var listener: RotationListener
-    @Captor lateinit var rotationWatcher: ArgumentCaptor<IRotationWatcher>
-    private val fakeExecutor = FakeExecutor(FakeSystemClock())
+    @Mock lateinit var display: Display
+    @Captor lateinit var displayListener: ArgumentCaptor<DisplayManager.DisplayListener>
+    private val fakeHandler = FakeHandler(Looper.getMainLooper())
+
+    private lateinit var spyContext: Context
 
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
-        rotationChangeProvider =
-            RotationChangeProvider(windowManagerInterface, context, fakeExecutor)
+        spyContext = spy(context)
+        whenever(spyContext.display).thenReturn(display)
+        rotationChangeProvider = RotationChangeProvider(displayManager, spyContext, fakeHandler)
         rotationChangeProvider.addCallback(listener)
-        fakeExecutor.runAllReady()
-        verify(windowManagerInterface).watchRotation(rotationWatcher.capture(), anyInt())
+        fakeHandler.dispatchQueuedMessages()
+        verify(displayManager).registerDisplayListener(displayListener.capture(), any())
     }
 
     @Test
@@ -70,15 +76,16 @@
         verify(listener).onRotationChanged(42)
 
         rotationChangeProvider.removeCallback(listener)
-        fakeExecutor.runAllReady()
+        fakeHandler.dispatchQueuedMessages()
         sendRotationUpdate(43)
 
-        verify(windowManagerInterface).removeRotationWatcher(any())
+        verify(displayManager).unregisterDisplayListener(any())
         verifyNoMoreInteractions(listener)
     }
 
     private fun sendRotationUpdate(newRotation: Int) {
-        rotationWatcher.value.onRotationChanged(newRotation)
-        fakeExecutor.runAllReady()
+        whenever(display.rotation).thenReturn(newRotation)
+        displayListener.allValues.forEach { it.onDisplayChanged(display.displayId) }
+        fakeHandler.dispatchQueuedMessages()
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
index a064e8c..fbb0e5a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
@@ -57,4 +57,8 @@
     fun sendHingeAngleUpdate(angle: Float) {
         listeners.forEach { it.onHingeAngleUpdate(angle) }
     }
+
+    fun sendUnfoldedScreenAvailable() {
+        listeners.forEach { it.onUnfoldedScreenAvailable() }
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
index 9312643..e2f3cf7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
@@ -17,10 +17,7 @@
 
 package com.android.systemui.user.data.repository
 
-import android.app.IActivityManager
-import android.app.UserSwitchObserver
 import android.content.pm.UserInfo
-import android.os.IRemoteCallback
 import android.os.UserHandle
 import android.os.UserManager
 import android.provider.Settings
@@ -44,14 +41,8 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
-import org.mockito.ArgumentCaptor
-import org.mockito.Captor
 import org.mockito.Mock
-import org.mockito.Mockito.any
-import org.mockito.Mockito.anyString
 import org.mockito.Mockito.mock
-import org.mockito.Mockito.times
-import org.mockito.Mockito.verify
 import org.mockito.Mockito.`when` as whenever
 import org.mockito.MockitoAnnotations
 
@@ -60,8 +51,6 @@
 class UserRepositoryImplTest : SysuiTestCase() {
 
     @Mock private lateinit var manager: UserManager
-    @Mock private lateinit var activityManager: IActivityManager
-    @Captor private lateinit var userSwitchObserver: ArgumentCaptor<UserSwitchObserver>
 
     private lateinit var underTest: UserRepositoryImpl
 
@@ -235,30 +224,31 @@
     }
 
     @Test
-    fun userSwitchingInProgress_registersOnlyOneUserSwitchObserver() = runSelfCancelingTest {
+    fun userSwitchingInProgress_registersUserTrackerCallback() = runSelfCancelingTest {
         underTest = create(this)
 
         underTest.userSwitchingInProgress.launchIn(this)
         underTest.userSwitchingInProgress.launchIn(this)
         underTest.userSwitchingInProgress.launchIn(this)
 
-        verify(activityManager, times(1)).registerUserSwitchObserver(any(), anyString())
+        // Two callbacks registered - one for observing user switching and one for observing the
+        // selected user
+        assertThat(tracker.callbacks.size).isEqualTo(2)
     }
 
     @Test
-    fun userSwitchingInProgress_propagatesStateFromActivityManager() = runSelfCancelingTest {
+    fun userSwitchingInProgress_propagatesStateFromUserTracker() = runSelfCancelingTest {
         underTest = create(this)
-        verify(activityManager)
-            .registerUserSwitchObserver(userSwitchObserver.capture(), anyString())
+        assertThat(tracker.callbacks.size).isEqualTo(2)
 
-        userSwitchObserver.value.onUserSwitching(0, mock(IRemoteCallback::class.java))
+        tracker.onUserChanging(0)
 
         var mostRecentSwitchingValue = false
         underTest.userSwitchingInProgress.onEach { mostRecentSwitchingValue = it }.launchIn(this)
 
         assertThat(mostRecentSwitchingValue).isTrue()
 
-        userSwitchObserver.value.onUserSwitchComplete(0)
+        tracker.onUserChanged(0)
         assertThat(mostRecentSwitchingValue).isFalse()
     }
 
@@ -338,7 +328,6 @@
             backgroundDispatcher = IMMEDIATE,
             globalSettings = globalSettings,
             tracker = tracker,
-            activityManager = activityManager,
             featureFlags = featureFlags,
         )
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
index f0a53ae..8d74c82 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
@@ -29,6 +29,8 @@
 import android.provider.Settings
 import androidx.test.filters.SmallTest
 import com.android.internal.logging.UiEventLogger
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.KeyguardUpdateMonitorCallback
 import com.android.systemui.GuestResetOrExitSessionReceiver
 import com.android.systemui.GuestResumeSessionReceiver
 import com.android.systemui.R
@@ -63,6 +65,7 @@
 import com.android.systemui.util.mockito.nullable
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
+import junit.framework.Assert.assertNotNull
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.test.StandardTestDispatcher
@@ -73,6 +76,7 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
+import org.mockito.ArgumentCaptor
 import org.mockito.ArgumentMatchers.anyBoolean
 import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.Mock
@@ -98,6 +102,7 @@
     @Mock private lateinit var resumeSessionReceiver: GuestResumeSessionReceiver
     @Mock private lateinit var resetOrExitSessionReceiver: GuestResetOrExitSessionReceiver
     @Mock private lateinit var commandQueue: CommandQueue
+    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
 
     private lateinit var underTest: UserInteractor
 
@@ -156,6 +161,7 @@
                         repository = telephonyRepository,
                     ),
                 broadcastDispatcher = fakeBroadcastDispatcher,
+                keyguardUpdateMonitor = keyguardUpdateMonitor,
                 backgroundDispatcher = testDispatcher,
                 activityManager = activityManager,
                 refreshUsersScheduler = refreshUsersScheduler,
@@ -180,6 +186,18 @@
     }
 
     @Test
+    fun `testKeyguardUpdateMonitor_onKeyguardGoingAway`() =
+        testScope.runTest {
+            val argumentCaptor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
+            verify(keyguardUpdateMonitor).registerCallback(argumentCaptor.capture())
+
+            argumentCaptor.value.onKeyguardGoingAway()
+
+            val lastValue = collectLastValue(underTest.dialogDismissRequests)
+            assertNotNull(lastValue)
+        }
+
+    @Test
     fun `onRecordSelected - user`() =
         testScope.runTest {
             val userInfos = createUserInfos(count = 3, includeGuest = false)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
index bc0881c..9b74c1f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
@@ -25,6 +25,7 @@
 import android.os.UserManager
 import androidx.test.filters.SmallTest
 import com.android.internal.logging.UiEventLogger
+import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.systemui.GuestResetOrExitSessionReceiver
 import com.android.systemui.GuestResumeSessionReceiver
 import com.android.systemui.SysuiTestCase
@@ -80,6 +81,7 @@
     @Mock private lateinit var resumeSessionReceiver: GuestResumeSessionReceiver
     @Mock private lateinit var resetOrExitSessionReceiver: GuestResetOrExitSessionReceiver
     @Mock private lateinit var commandQueue: CommandQueue
+    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
 
     private lateinit var underTest: StatusBarUserChipViewModel
 
@@ -263,6 +265,7 @@
                             repository = FakeTelephonyRepository(),
                         ),
                     broadcastDispatcher = fakeBroadcastDispatcher,
+                    keyguardUpdateMonitor = keyguardUpdateMonitor,
                     backgroundDispatcher = testDispatcher,
                     activityManager = activityManager,
                     refreshUsersScheduler = refreshUsersScheduler,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
index c8b0496..7780a43 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
@@ -23,6 +23,7 @@
 import android.os.UserManager
 import androidx.test.filters.SmallTest
 import com.android.internal.logging.UiEventLogger
+import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.systemui.GuestResetOrExitSessionReceiver
 import com.android.systemui.GuestResumeSessionReceiver
 import com.android.systemui.SysuiTestCase
@@ -81,6 +82,7 @@
     @Mock private lateinit var resumeSessionReceiver: GuestResumeSessionReceiver
     @Mock private lateinit var resetOrExitSessionReceiver: GuestResetOrExitSessionReceiver
     @Mock private lateinit var commandQueue: CommandQueue
+    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
 
     private lateinit var underTest: UserSwitcherViewModel
 
@@ -165,6 +167,7 @@
                                     repository = FakeTelephonyRepository(),
                                 ),
                             broadcastDispatcher = fakeBroadcastDispatcher,
+                            keyguardUpdateMonitor = keyguardUpdateMonitor,
                             backgroundDispatcher = testDispatcher,
                             activityManager = activityManager,
                             refreshUsersScheduler = refreshUsersScheduler,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/service/ObservableServiceConnectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/service/ObservableServiceConnectionTest.java
index 046ad12..f9bfafc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/service/ObservableServiceConnectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/service/ObservableServiceConnectionTest.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.util.service;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.clearInvocations;
@@ -169,4 +171,19 @@
         verify(mCallback).onDisconnected(eq(connection),
                 eq(ObservableServiceConnection.DISCONNECT_REASON_UNBIND));
     }
+
+    @Test
+    public void testBindServiceThrowsError() {
+        ObservableServiceConnection<Foo> connection = new ObservableServiceConnection<>(mContext,
+                mIntent, mExecutor, mTransformer);
+        connection.addCallback(mCallback);
+
+        when(mContext.bindService(eq(mIntent), anyInt(), eq(mExecutor), eq(connection)))
+                .thenThrow(new SecurityException());
+
+        // Verify that the exception was caught and that bind returns false, and we properly
+        // unbind.
+        assertThat(connection.bind()).isFalse();
+        verify(mContext).unbindService(connection);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java
index 31cce4f..468c5a7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java
@@ -88,7 +88,7 @@
     @Mock
     private Bitmap mWallpaperBitmap;
     FakeSystemClock mFakeSystemClock = new FakeSystemClock();
-    FakeExecutor mFakeBackgroundExecutor = new FakeExecutor(mFakeSystemClock);
+    FakeExecutor mFakeExecutor = new FakeExecutor(mFakeSystemClock);
 
     @Before
     public void setUp() throws Exception {
@@ -125,7 +125,7 @@
 
     @Test
     public void testBitmapWallpaper_normal() {
-        // Will use a image wallpaper with dimensions DISPLAY_WIDTH x DISPLAY_WIDTH.
+        // Will use an image wallpaper with dimensions DISPLAY_WIDTH x DISPLAY_WIDTH.
         // Then we expect the surface size will be also DISPLAY_WIDTH x DISPLAY_WIDTH.
         int bitmapSide = DISPLAY_WIDTH;
         testSurfaceHelper(
@@ -137,7 +137,7 @@
 
     @Test
     public void testBitmapWallpaper_low_resolution() {
-        // Will use a image wallpaper with dimensions BMP_WIDTH x BMP_HEIGHT.
+        // Will use an image wallpaper with dimensions BMP_WIDTH x BMP_HEIGHT.
         // Then we expect the surface size will be also BMP_WIDTH x BMP_HEIGHT.
         testSurfaceHelper(LOW_BMP_WIDTH /* bitmapWidth */,
                 LOW_BMP_HEIGHT /* bitmapHeight */,
@@ -161,13 +161,13 @@
         ImageWallpaper.CanvasEngine spyEngine = getSpyEngine();
         spyEngine.onCreate(mSurfaceHolder);
         spyEngine.onSurfaceRedrawNeeded(mSurfaceHolder);
-        assertThat(mFakeBackgroundExecutor.numPending()).isAtLeast(1);
+        assertThat(mFakeExecutor.numPending()).isAtLeast(1);
 
         int n = 0;
-        while (mFakeBackgroundExecutor.numPending() >= 1) {
+        while (mFakeExecutor.numPending() >= 1) {
             n++;
             assertThat(n).isAtMost(10);
-            mFakeBackgroundExecutor.runNextReady();
+            mFakeExecutor.runNextReady();
             mFakeSystemClock.advanceTime(1000);
         }
 
@@ -176,7 +176,7 @@
     }
 
     private ImageWallpaper createImageWallpaper() {
-        return new ImageWallpaper(mFakeBackgroundExecutor, mUserTracker) {
+        return new ImageWallpaper(mFakeExecutor, mUserTracker) {
             @Override
             public Engine onCreateEngine() {
                 return new CanvasEngine() {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt
index 9b4f496..c2947b4 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt
@@ -29,6 +29,7 @@
 
 /**
  * Collect [flow] in a new [Job] and return a getter for the last collected value.
+ *
  * ```
  * fun myTest() = runTest {
  *   // ...
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/data/repository/FakeKeyboardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/data/repository/FakeKeyboardRepository.kt
new file mode 100644
index 0000000..4e43546
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/data/repository/FakeKeyboardRepository.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyboard.data.repository
+
+import com.android.systemui.keyboard.shared.model.BacklightModel
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.filterNotNull
+
+class FakeKeyboardRepository : KeyboardRepository {
+
+    private val _keyboardConnected = MutableStateFlow(false)
+    override val keyboardConnected: Flow<Boolean> = _keyboardConnected
+
+    private val _backlightState: MutableStateFlow<BacklightModel?> = MutableStateFlow(null)
+    // filtering to make sure backlight doesn't have default initial value
+    override val backlight: Flow<BacklightModel> = _backlightState.filterNotNull()
+
+    fun setBacklight(state: BacklightModel) {
+        _backlightState.value = state
+    }
+
+    fun setKeyboardConnected(connected: Boolean) {
+        _keyboardConnected.value = connected
+    }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt
index 01dac36..d4b1701 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt
@@ -21,6 +21,7 @@
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.flowOf
 
 class FakeBiometricSettingsRepository : BiometricSettingsRepository {
 
@@ -42,6 +43,9 @@
     override val isFingerprintEnabledByDevicePolicy =
         _isFingerprintEnabledByDevicePolicy.asStateFlow()
 
+    override val isFaceAuthSupportedInCurrentPosture: Flow<Boolean>
+        get() = flowOf(true)
+
     fun setFingerprintEnrolled(isFingerprintEnrolled: Boolean) {
         _isFingerprintEnrolled.value = isFingerprintEnrolled
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDevicePostureRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDevicePostureRepository.kt
new file mode 100644
index 0000000..914c786
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDevicePostureRepository.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.keyguard.data.repository
+
+import com.android.systemui.keyguard.shared.model.DevicePosture
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+
+class FakeDevicePostureRepository : DevicePostureRepository {
+    private val _currentDevicePosture = MutableStateFlow(DevicePosture.UNKNOWN)
+    override val currentDevicePosture: Flow<DevicePosture>
+        get() = _currentDevicePosture
+
+    fun setCurrentPosture(posture: DevicePosture) {
+        _currentDevicePosture.value = posture
+    }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt
index 9cdce20..1dda472 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt
@@ -19,21 +19,16 @@
 
 import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
 import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
-import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
 
 /** Fake implementation of [KeyguardRepository] */
 class FakeKeyguardBouncerRepository : KeyguardBouncerRepository {
-    private val _primaryBouncerVisible = MutableStateFlow(false)
-    override val primaryBouncerVisible = _primaryBouncerVisible.asStateFlow()
-    private val _primaryBouncerShow = MutableStateFlow<KeyguardBouncerModel?>(null)
+    private val _primaryBouncerShow = MutableStateFlow(false)
     override val primaryBouncerShow = _primaryBouncerShow.asStateFlow()
     private val _primaryBouncerShowingSoon = MutableStateFlow(false)
     override val primaryBouncerShowingSoon = _primaryBouncerShowingSoon.asStateFlow()
-    private val _primaryBouncerHide = MutableStateFlow(false)
-    override val primaryBouncerHide = _primaryBouncerHide.asStateFlow()
     private val _primaryBouncerStartingToHide = MutableStateFlow(false)
     override val primaryBouncerStartingToHide = _primaryBouncerStartingToHide.asStateFlow()
     private val _primaryBouncerDisappearAnimation = MutableStateFlow<Runnable?>(null)
@@ -67,10 +62,6 @@
         _primaryBouncerScrimmed.value = isScrimmed
     }
 
-    override fun setPrimaryVisible(isVisible: Boolean) {
-        _primaryBouncerVisible.value = isVisible
-    }
-
     override fun setAlternateVisible(isVisible: Boolean) {
         _isAlternateBouncerVisible.value = isVisible
     }
@@ -79,18 +70,14 @@
         _isAlternateBouncerUIAvailable.value = isAvailable
     }
 
-    override fun setPrimaryShow(keyguardBouncerModel: KeyguardBouncerModel?) {
-        _primaryBouncerShow.value = keyguardBouncerModel
+    override fun setPrimaryShow(isShowing: Boolean) {
+        _primaryBouncerShow.value = isShowing
     }
 
     override fun setPrimaryShowingSoon(showingSoon: Boolean) {
         _primaryBouncerShowingSoon.value = showingSoon
     }
 
-    override fun setPrimaryHide(hide: Boolean) {
-        _primaryBouncerHide.value = hide
-    }
-
     override fun setPrimaryStartingToHide(startingToHide: Boolean) {
         _primaryBouncerStartingToHide.value = startingToHide
     }
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 1a371c7..194ed02 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
@@ -47,6 +47,9 @@
     private val _isKeyguardShowing = MutableStateFlow(false)
     override val isKeyguardShowing: Flow<Boolean> = _isKeyguardShowing
 
+    private val _isKeyguardUnlocked = MutableStateFlow(false)
+    override val isKeyguardUnlocked: Flow<Boolean> = _isKeyguardUnlocked
+
     private val _isKeyguardOccluded = MutableStateFlow(false)
     override val isKeyguardOccluded: Flow<Boolean> = _isKeyguardOccluded
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt
index eac1bd1..16442bb 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt
@@ -37,7 +37,7 @@
         _transitions.emit(step)
     }
 
-    override fun startTransition(info: TransitionInfo): UUID? {
+    override fun startTransition(info: TransitionInfo, resetIfCanceled: Boolean): UUID? {
         return null
     }
 
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 251014f..4242c16 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
@@ -22,6 +22,7 @@
 import android.os.UserHandle
 import android.test.mock.MockContentResolver
 import com.android.systemui.util.mockito.mock
+import java.util.concurrent.CountDownLatch
 import java.util.concurrent.Executor
 
 /** A fake [UserTracker] to be used in tests. */
@@ -66,11 +67,19 @@
         _userId = _userInfo.id
         _userHandle = UserHandle.of(_userId)
 
+        onUserChanging()
+        onUserChanged()
+    }
+
+    fun onUserChanging(userId: Int = _userId) {
         val copy = callbacks.toList()
-        copy.forEach {
-            it.onUserChanging(_userId, userContext)
-            it.onUserChanged(_userId, userContext)
-        }
+        val latch = CountDownLatch(copy.size)
+        copy.forEach { it.onUserChanging(userId, userContext, latch) }
+    }
+
+    fun onUserChanged(userId: Int = _userId) {
+        val copy = callbacks.toList()
+        copy.forEach { it.onUserChanged(userId, userContext) }
     }
 
     fun onProfileChanged() {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSystemUIDialogController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSystemUIDialogController.kt
new file mode 100644
index 0000000..0c9ce0f
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSystemUIDialogController.kt
@@ -0,0 +1,86 @@
+/*
+ * 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
+
+import android.content.DialogInterface
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import org.mockito.ArgumentCaptor
+import org.mockito.Mockito.doAnswer
+import org.mockito.Mockito.verify
+import org.mockito.stubbing.Stubber
+
+class FakeSystemUIDialogController {
+
+    val dialog: SystemUIDialog = mock()
+
+    private val clickListeners: MutableMap<Int, DialogInterface.OnClickListener> = mutableMapOf()
+
+    init {
+        saveListener(DialogInterface.BUTTON_POSITIVE)
+            .whenever(dialog)
+            .setPositiveButton(any(), any())
+        saveListener(DialogInterface.BUTTON_POSITIVE)
+            .whenever(dialog)
+            .setPositiveButton(any(), any(), any())
+
+        saveListener(DialogInterface.BUTTON_NEGATIVE)
+            .whenever(dialog)
+            .setNegativeButton(any(), any())
+        saveListener(DialogInterface.BUTTON_NEGATIVE)
+            .whenever(dialog)
+            .setNegativeButton(any(), any(), any())
+
+        saveListener(DialogInterface.BUTTON_NEUTRAL).whenever(dialog).setNeutralButton(any(), any())
+        saveListener(DialogInterface.BUTTON_NEUTRAL)
+            .whenever(dialog)
+            .setNeutralButton(any(), any(), any())
+    }
+
+    fun clickNegative() {
+        performClick(DialogInterface.BUTTON_NEGATIVE, "This dialog has no negative button")
+    }
+
+    fun clickPositive() {
+        performClick(DialogInterface.BUTTON_POSITIVE, "This dialog has no positive button")
+    }
+
+    fun clickNeutral() {
+        performClick(DialogInterface.BUTTON_NEUTRAL, "This dialog has no neutral button")
+    }
+
+    fun cancel() {
+        val captor = ArgumentCaptor.forClass(DialogInterface.OnCancelListener::class.java)
+        verify(dialog).setOnCancelListener(captor.capture())
+        captor.value.onCancel(dialog)
+    }
+
+    private fun performClick(which: Int, errorMessage: String) {
+        clickListeners
+            .getOrElse(which) { throw IllegalAccessException(errorMessage) }
+            .onClick(dialog, which)
+    }
+
+    private fun saveListener(which: Int): Stubber = doAnswer {
+        val listener = it.getArgument<DialogInterface.OnClickListener>(1)
+        clickListeners[which] = listener
+        Unit
+    }
+}
diff --git a/packages/SystemUI/unfold/Android.bp b/packages/SystemUI/unfold/Android.bp
index 180b611..2e0a946 100644
--- a/packages/SystemUI/unfold/Android.bp
+++ b/packages/SystemUI/unfold/Android.bp
@@ -35,6 +35,7 @@
     ],
     kotlincflags: ["-Xjvm-default=enable"],
     java_version: "1.8",
+    sdk_version: "current",
     min_sdk_version: "current",
     plugins: ["dagger2-compiler"],
 }
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedComponent.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedComponent.kt
index 068347c..c3a6cf0 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedComponent.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedComponent.kt
@@ -19,14 +19,15 @@
 import android.content.ContentResolver
 import android.content.Context
 import android.hardware.SensorManager
+import android.hardware.display.DisplayManager
 import android.os.Handler
-import android.view.IWindowManager
 import com.android.systemui.unfold.config.UnfoldTransitionConfig
 import com.android.systemui.unfold.dagger.UnfoldMain
 import com.android.systemui.unfold.dagger.UnfoldSingleThreadBg
 import com.android.systemui.unfold.progress.RemoteUnfoldTransitionReceiver
 import com.android.systemui.unfold.updates.FoldProvider
 import com.android.systemui.unfold.updates.RotationChangeProvider
+import com.android.systemui.unfold.updates.hinge.HingeAngleProvider
 import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
 import com.android.systemui.unfold.util.CurrentActivityTypeProvider
 import com.android.systemui.unfold.util.UnfoldTransitionATracePrefix
@@ -61,12 +62,13 @@
             @BindsInstance @UnfoldMain executor: Executor,
             @BindsInstance @UnfoldSingleThreadBg singleThreadBgExecutor: Executor,
             @BindsInstance @UnfoldTransitionATracePrefix tracingTagPrefix: String,
-            @BindsInstance windowManager: IWindowManager,
+            @BindsInstance displayManager: DisplayManager,
             @BindsInstance contentResolver: ContentResolver = context.contentResolver
         ): UnfoldSharedComponent
     }
 
     val unfoldTransitionProvider: Optional<UnfoldTransitionProgressProvider>
+    val hingeAngleProvider: HingeAngleProvider
     val rotationChangeProvider: RotationChangeProvider
 }
 
@@ -84,8 +86,9 @@
             @BindsInstance context: Context,
             @BindsInstance config: UnfoldTransitionConfig,
             @BindsInstance @UnfoldMain executor: Executor,
+            @BindsInstance @UnfoldMain handler: Handler,
             @BindsInstance @UnfoldSingleThreadBg singleThreadBgExecutor: Executor,
-            @BindsInstance windowManager: IWindowManager,
+            @BindsInstance displayManager: DisplayManager,
             @BindsInstance @UnfoldTransitionATracePrefix tracingTagPrefix: String,
         ): RemoteUnfoldSharedComponent
     }
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
index 8eb79df..1839919 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
@@ -19,8 +19,8 @@
 
 import android.content.Context
 import android.hardware.SensorManager
+import android.hardware.display.DisplayManager
 import android.os.Handler
-import android.view.IWindowManager
 import com.android.systemui.unfold.config.UnfoldTransitionConfig
 import com.android.systemui.unfold.updates.FoldProvider
 import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
@@ -47,7 +47,7 @@
         mainExecutor: Executor,
         singleThreadBgExecutor: Executor,
         tracingTagPrefix: String,
-        windowManager: IWindowManager,
+        displayManager: DisplayManager,
 ): UnfoldSharedComponent =
         DaggerUnfoldSharedComponent.factory()
                 .create(
@@ -61,7 +61,7 @@
                         mainExecutor,
                         singleThreadBgExecutor,
                         tracingTagPrefix,
-                        windowManager,
+                        displayManager,
                 )
 
 /**
@@ -73,16 +73,18 @@
         context: Context,
         config: UnfoldTransitionConfig,
         mainExecutor: Executor,
+        mainHandler: Handler,
         singleThreadBgExecutor: Executor,
         tracingTagPrefix: String,
-        windowManager: IWindowManager,
+        displayManager: DisplayManager,
         ): RemoteUnfoldSharedComponent =
         DaggerRemoteUnfoldSharedComponent.factory()
                 .create(
                         context,
                         config,
                         mainExecutor,
+                        mainHandler,
                         singleThreadBgExecutor,
-                        windowManager,
+                        displayManager,
                         tracingTagPrefix,
                 )
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
index 4622464..c437e5c 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
@@ -21,7 +21,6 @@
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
 import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_CLOSED
-import com.android.systemui.unfold.updates.FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE
 import com.android.systemui.unfold.updates.FoldStateProvider
 import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdate
 import javax.inject.Inject
@@ -59,12 +58,15 @@
     }
 
     override fun onFoldUpdate(@FoldUpdate update: Int) {
-        when (update) {
-            FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE -> animator.start()
-            FOLD_UPDATE_FINISH_CLOSED -> animator.cancel()
+        if (update == FOLD_UPDATE_FINISH_CLOSED) {
+             animator.cancel()
         }
     }
 
+    override fun onUnfoldedScreenAvailable() {
+        animator.start()
+    }
+
     override fun addCallback(listener: TransitionProgressListener) {
         listeners.add(listener)
     }
@@ -73,8 +75,6 @@
         listeners.remove(listener)
     }
 
-    override fun onHingeAngleUpdate(angle: Float) {}
-
     private object AnimationProgressProperty :
         FloatProperty<FixedTimingTransitionProgressProvider>("animation_progress") {
 
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
index 6ffbe5a..28e4936 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
@@ -16,7 +16,6 @@
 package com.android.systemui.unfold.progress
 
 import android.os.Trace
-import android.os.Trace.TRACE_TAG_APP
 import android.util.Log
 import androidx.dynamicanimation.animation.DynamicAnimation
 import androidx.dynamicanimation.animation.FloatPropertyCompat
@@ -28,7 +27,6 @@
 import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_FULL_OPEN
 import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_HALF_OPEN
 import com.android.systemui.unfold.updates.FOLD_UPDATE_START_CLOSING
-import com.android.systemui.unfold.updates.FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE
 import com.android.systemui.unfold.updates.FoldStateProvider
 import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdate
 import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdatesListener
@@ -78,21 +76,11 @@
 
     override fun onFoldUpdate(@FoldUpdate update: Int) {
         when (update) {
-            FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE -> {
-                startTransition(startValue = 0f)
-
-                // Stop the animation if the device has already opened by the time when
-                // the display is available as we won't receive the full open event anymore
-                if (foldStateProvider.isFinishedOpening) {
-                    cancelTransition(endValue = 1f, animate = true)
-                }
-            }
             FOLD_UPDATE_FINISH_FULL_OPEN, FOLD_UPDATE_FINISH_HALF_OPEN -> {
                 // Do not cancel if we haven't started the transition yet.
                 // This could happen when we fully unfolded the device before the screen
                 // became available. In this case we start and immediately cancel the animation
-                // in FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE event handler, so we don't need to
-                // cancel it here.
+                // in onUnfoldedScreenAvailable event handler, so we don't need to cancel it here.
                 if (isTransitionRunning) {
                     cancelTransition(endValue = 1f, animate = true)
                 }
@@ -121,7 +109,17 @@
 
         if (DEBUG) {
             Log.d(TAG, "onFoldUpdate = ${update.name()}")
-            Trace.traceCounter(Trace.TRACE_TAG_APP, "fold_update", update)
+            Trace.setCounter("fold_update", update.toLong())
+        }
+    }
+
+    override fun onUnfoldedScreenAvailable() {
+        startTransition(startValue = 0f)
+
+        // Stop the animation if the device has already opened by the time when
+        // the display is available as we won't receive the full open event anymore
+        if (foldStateProvider.isFinishedOpening) {
+            cancelTransition(endValue = 1f, animate = true)
         }
     }
 
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
index 97c9ba9..d653fc7 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
@@ -54,6 +54,7 @@
     @FoldUpdate private var lastFoldUpdate: Int? = null
 
     @FloatRange(from = 0.0, to = 180.0) private var lastHingeAngle: Float = 0f
+    @FloatRange(from = 0.0, to = 180.0) private var lastHingeAngleBeforeTransition: Float = 0f
 
     private val hingeAngleListener = HingeAngleListener()
     private val screenListener = ScreenStatusListener()
@@ -112,29 +113,45 @@
 
     private fun onHingeAngle(angle: Float) {
         if (DEBUG) {
-            Log.d(TAG, "Hinge angle: $angle, lastHingeAngle: $lastHingeAngle")
-            Trace.traceCounter(Trace.TRACE_TAG_APP, "hinge_angle", angle.toInt())
+            Log.d(
+                TAG,
+                "Hinge angle: $angle, " +
+                    "lastHingeAngle: $lastHingeAngle, " +
+                    "lastHingeAngleBeforeTransition: $lastHingeAngleBeforeTransition"
+            )
+            Trace.setCounter( "hinge_angle", angle.toLong())
         }
 
-        val isClosing = angle < lastHingeAngle
+        val currentDirection =
+                if (angle < lastHingeAngle) FOLD_UPDATE_START_CLOSING else FOLD_UPDATE_START_OPENING
+        if (isTransitionInProgress && currentDirection != lastFoldUpdate) {
+            lastHingeAngleBeforeTransition = lastHingeAngle
+        }
+
+        val isClosing = angle < lastHingeAngleBeforeTransition
+        val transitionUpdate =
+                if (isClosing) FOLD_UPDATE_START_CLOSING else FOLD_UPDATE_START_OPENING
+        val angleChangeSurpassedThreshold =
+            Math.abs(angle - lastHingeAngleBeforeTransition) > HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES
         val isFullyOpened = FULLY_OPEN_DEGREES - angle < FULLY_OPEN_THRESHOLD_DEGREES
-        val closingEventDispatched = lastFoldUpdate == FOLD_UPDATE_START_CLOSING
+        val eventNotAlreadyDispatched = lastFoldUpdate != transitionUpdate
         val screenAvailableEventSent = isUnfoldHandled
 
-        if (isClosing // hinge angle should be decreasing since last update
-                && !closingEventDispatched  // we haven't sent closing event already
-                && !isFullyOpened // do not send closing event if we are in fully opened hinge
+        if (
+            angleChangeSurpassedThreshold && // Do not react immediately to small changes in angle
+                eventNotAlreadyDispatched && // we haven't sent transition event already
+                !isFullyOpened && // do not send transition event if we are in fully opened hinge
                                   // angle range as closing threshold could overlap this range
-                && screenAvailableEventSent // do not send closing event if we are still in
-                                            // the process of turning on the inner display
-                && isClosingThresholdMet(angle) // hinge angle is below certain threshold.
+                screenAvailableEventSent && // do not send transition event if we are still in the
+                                            // process of turning on the inner display
+                isClosingThresholdMet(angle) // hinge angle is below certain threshold.
         ) {
-            notifyFoldUpdate(FOLD_UPDATE_START_CLOSING)
+            notifyFoldUpdate(transitionUpdate, lastHingeAngle)
         }
 
         if (isTransitionInProgress) {
             if (isFullyOpened) {
-                notifyFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN)
+                notifyFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN, angle)
                 cancelTimeout()
             } else {
                 // The timeout will trigger some constant time after the last angle update.
@@ -146,7 +163,7 @@
         outputListeners.forEach { it.onHingeAngleUpdate(angle) }
     }
 
-    private fun isClosingThresholdMet(currentAngle: Float) : Boolean {
+    private fun isClosingThresholdMet(currentAngle: Float): Boolean {
         val closingThreshold = getClosingThreshold()
         return closingThreshold == null || currentAngle < closingThreshold
     }
@@ -179,23 +196,29 @@
 
             if (isFolded) {
                 hingeAngleProvider.stop()
-                notifyFoldUpdate(FOLD_UPDATE_FINISH_CLOSED)
+                notifyFoldUpdate(FOLD_UPDATE_FINISH_CLOSED, lastHingeAngle)
                 cancelTimeout()
                 isUnfoldHandled = false
             } else {
-                notifyFoldUpdate(FOLD_UPDATE_START_OPENING)
+                notifyFoldUpdate(FOLD_UPDATE_START_OPENING, lastHingeAngle)
                 rescheduleAbortAnimationTimeout()
                 hingeAngleProvider.start()
             }
         }
     }
 
-    private fun notifyFoldUpdate(@FoldUpdate update: Int) {
+    private fun notifyFoldUpdate(@FoldUpdate update: Int, angle: Float) {
         if (DEBUG) {
             Log.d(TAG, update.name())
         }
+        val previouslyTransitioning = isTransitionInProgress
+
         outputListeners.forEach { it.onFoldUpdate(update) }
         lastFoldUpdate = update
+
+        if (previouslyTransitioning != isTransitionInProgress) {
+            lastHingeAngleBeforeTransition = angle
+        }
     }
 
     private fun rescheduleAbortAnimationTimeout() {
@@ -209,7 +232,8 @@
         handler.removeCallbacks(timeoutRunnable)
     }
 
-    private fun cancelAnimation(): Unit = notifyFoldUpdate(FOLD_UPDATE_FINISH_HALF_OPEN)
+    private fun cancelAnimation(): Unit =
+            notifyFoldUpdate(FOLD_UPDATE_FINISH_HALF_OPEN, lastHingeAngle)
 
     private inner class ScreenStatusListener : ScreenStatusProvider.ScreenListener {
 
@@ -221,7 +245,7 @@
             // receive 'folded' event. If SystemUI started when device is already folded it will
             // still receive 'folded' event on startup.
             if (!isFolded && !isUnfoldHandled) {
-                outputListeners.forEach { it.onFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) }
+                outputListeners.forEach { it.onUnfoldedScreenAvailable() }
                 isUnfoldHandled = true
             }
         }
@@ -257,7 +281,6 @@
     when (this) {
         FOLD_UPDATE_START_OPENING -> "START_OPENING"
         FOLD_UPDATE_START_CLOSING -> "START_CLOSING"
-        FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE -> "UNFOLDED_SCREEN_AVAILABLE"
         FOLD_UPDATE_FINISH_HALF_OPEN -> "FINISH_HALF_OPEN"
         FOLD_UPDATE_FINISH_FULL_OPEN -> "FINISH_FULL_OPEN"
         FOLD_UPDATE_FINISH_CLOSED -> "FINISH_CLOSED"
@@ -270,5 +293,8 @@
 /** Threshold after which we consider the device fully unfolded. */
 @VisibleForTesting const val FULLY_OPEN_THRESHOLD_DEGREES = 15f
 
+/** Threshold after which hinge angle updates are considered. This is to eliminate noise. */
+@VisibleForTesting const val HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES = 7.5f
+
 /** Fold animation on top of apps only when the angle exceeds this threshold. */
 @VisibleForTesting const val START_CLOSING_ON_APPS_THRESHOLD_DEGREES = 60
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
index c7a8bf3..0af372f 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
@@ -31,8 +31,9 @@
     val isFinishedOpening: Boolean
 
     interface FoldUpdatesListener {
-        fun onHingeAngleUpdate(@FloatRange(from = 0.0, to = 180.0) angle: Float)
-        fun onFoldUpdate(@FoldUpdate update: Int)
+        @JvmDefault fun onHingeAngleUpdate(@FloatRange(from = 0.0, to = 180.0) angle: Float) {}
+        @JvmDefault fun onFoldUpdate(@FoldUpdate update: Int) {}
+        @JvmDefault fun onUnfoldedScreenAvailable() {}
     }
 
     @IntDef(
@@ -40,7 +41,6 @@
             [
                 FOLD_UPDATE_START_OPENING,
                 FOLD_UPDATE_START_CLOSING,
-                FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE,
                 FOLD_UPDATE_FINISH_HALF_OPEN,
                 FOLD_UPDATE_FINISH_FULL_OPEN,
                 FOLD_UPDATE_FINISH_CLOSED])
@@ -50,7 +50,6 @@
 
 const val FOLD_UPDATE_START_OPENING = 0
 const val FOLD_UPDATE_START_CLOSING = 1
-const val FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE = 2
-const val FOLD_UPDATE_FINISH_HALF_OPEN = 3
-const val FOLD_UPDATE_FINISH_FULL_OPEN = 4
-const val FOLD_UPDATE_FINISH_CLOSED = 5
+const val FOLD_UPDATE_FINISH_HALF_OPEN = 2
+const val FOLD_UPDATE_FINISH_FULL_OPEN = 3
+const val FOLD_UPDATE_FINISH_CLOSED = 4
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/RotationChangeProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/RotationChangeProvider.kt
index 0cf8224..ce8f1a1 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/RotationChangeProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/RotationChangeProvider.kt
@@ -17,36 +17,32 @@
 package com.android.systemui.unfold.updates
 
 import android.content.Context
+import android.hardware.display.DisplayManager
+import android.os.Handler
 import android.os.RemoteException
-import android.view.IRotationWatcher
-import android.view.IWindowManager
-import android.view.Surface.Rotation
 import com.android.systemui.unfold.dagger.UnfoldMain
 import com.android.systemui.unfold.util.CallbackController
-import java.util.concurrent.Executor
 import javax.inject.Inject
 
 /**
- * Allows to subscribe to rotation changes.
- *
- * This is needed as rotation updates from [IWindowManager] are received in a binder thread, while
- * most of the times we want them in the main one. Updates are provided for the display associated
+ * Allows to subscribe to rotation changes. Updates are provided for the display associated
  * to [context].
  */
 class RotationChangeProvider
 @Inject
 constructor(
-    private val windowManagerInterface: IWindowManager,
+    private val displayManager: DisplayManager,
     private val context: Context,
-    @UnfoldMain private val mainExecutor: Executor,
+    @UnfoldMain private val mainHandler: Handler,
 ) : CallbackController<RotationChangeProvider.RotationListener> {
 
     private val listeners = mutableListOf<RotationListener>()
 
-    private val rotationWatcher = RotationWatcher()
+    private val displayListener = RotationDisplayListener()
+    private var lastRotation: Int? = null
 
     override fun addCallback(listener: RotationListener) {
-        mainExecutor.execute {
+        mainHandler.post {
             if (listeners.isEmpty()) {
                 subscribeToRotation()
             }
@@ -55,17 +51,18 @@
     }
 
     override fun removeCallback(listener: RotationListener) {
-        mainExecutor.execute {
+        mainHandler.post {
             listeners -= listener
             if (listeners.isEmpty()) {
                 unsubscribeToRotation()
+                lastRotation = null
             }
         }
     }
 
     private fun subscribeToRotation() {
         try {
-            windowManagerInterface.watchRotation(rotationWatcher, context.displayId)
+            displayManager.registerDisplayListener(displayListener, mainHandler)
         } catch (e: RemoteException) {
             throw e.rethrowFromSystemServer()
         }
@@ -73,7 +70,7 @@
 
     private fun unsubscribeToRotation() {
         try {
-            windowManagerInterface.removeRotationWatcher(rotationWatcher)
+            displayManager.unregisterDisplayListener(displayListener)
         } catch (e: RemoteException) {
             throw e.rethrowFromSystemServer()
         }
@@ -82,12 +79,25 @@
     /** Gets notified of rotation changes. */
     fun interface RotationListener {
         /** Called once rotation changes. */
-        fun onRotationChanged(@Rotation newRotation: Int)
+        fun onRotationChanged(newRotation: Int)
     }
 
-    private inner class RotationWatcher : IRotationWatcher.Stub() {
-        override fun onRotationChanged(rotation: Int) {
-            mainExecutor.execute { listeners.forEach { it.onRotationChanged(rotation) } }
+    private inner class RotationDisplayListener : DisplayManager.DisplayListener {
+
+        override fun onDisplayChanged(displayId: Int) {
+            val display = context.display ?: return
+
+            if (displayId == display.displayId) {
+                val currentRotation = display.rotation
+                if (lastRotation == null || lastRotation != currentRotation) {
+                    listeners.forEach { it.onRotationChanged(currentRotation) }
+                    lastRotation = currentRotation
+                }
+            }
         }
+
+        override fun onDisplayAdded(displayId: Int) {}
+
+        override fun onDisplayRemoved(displayId: Int) {}
     }
 }
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt
index 06ca153..ce5c5f9 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt
@@ -79,10 +79,9 @@
     companion object {
         fun ContentResolver.areAnimationsEnabled(): Boolean {
             val animationScale =
-                Settings.Global.getStringForUser(
+                Settings.Global.getString(
                         this,
                         Settings.Global.ANIMATOR_DURATION_SCALE,
-                        this.userId
                     )
                     ?.toFloatOrNull()
                     ?: 1f
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt
index b7bab3e..f9751d9 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt
@@ -47,6 +47,7 @@
     /**
      * Sets the source for the unfold transition progress updates. Replaces current provider if it
      * is already set
+     *
      * @param provider transition provider that emits transition progress updates
      */
     fun setSourceProvider(provider: UnfoldTransitionProgressProvider?) {
diff --git a/packages/VpnDialogs/res/values-fr/strings.xml b/packages/VpnDialogs/res/values-fr/strings.xml
index cdec614..c70fd54 100644
--- a/packages/VpnDialogs/res/values-fr/strings.xml
+++ b/packages/VpnDialogs/res/values-fr/strings.xml
@@ -32,7 +32,7 @@
     <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Modifier les paramètres VPN"</string>
     <string name="configure" msgid="4905518375574791375">"Configurer"</string>
     <string name="disconnect" msgid="971412338304200056">"Déconnecter"</string>
-    <string name="open_app" msgid="3717639178595958667">"Ouvrir l\'application"</string>
+    <string name="open_app" msgid="3717639178595958667">"Ouvrir l\'appli"</string>
     <string name="dismiss" msgid="6192859333764711227">"Ignorer"</string>
     <string name="sanitized_vpn_label_with_ellipsis" msgid="7014327474633422235">"<xliff:g id="SANITIZED_VPN_LABEL_WITH_ELLIPSIS_0">%1$s</xliff:g>… (<xliff:g id="SANITIZED_VPN_LABEL_WITH_ELLIPSIS_1">%2$s</xliff:g>)"</string>
     <string name="sanitized_vpn_label" msgid="1877415015009794766">"<xliff:g id="SANITIZED_VPN_LABEL_0">%1$s</xliff:g> (<xliff:g id="SANITIZED_VPN_LABEL_1">%2$s</xliff:g>)"</string>
diff --git a/packages/overlays/Android.mk b/packages/overlays/Android.mk
index 69641e6..cbca3f0 100644
--- a/packages/overlays/Android.mk
+++ b/packages/overlays/Android.mk
@@ -31,6 +31,7 @@
 	NavigationBarModeGesturalOverlayNarrowBack \
 	NavigationBarModeGesturalOverlayWideBack \
 	NavigationBarModeGesturalOverlayExtraWideBack \
+	TransparentNavigationBarOverlay \
 	preinstalled-packages-platform-overlays.xml
 
 include $(BUILD_PHONY_PACKAGE)
diff --git a/packages/overlays/TransparentNavigationBarOverlay/Android.bp b/packages/overlays/TransparentNavigationBarOverlay/Android.bp
new file mode 100644
index 0000000..43dc82b
--- /dev/null
+++ b/packages/overlays/TransparentNavigationBarOverlay/Android.bp
@@ -0,0 +1,30 @@
+//
+//  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 {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+runtime_resource_overlay {
+    name: "TransparentNavigationBarOverlay",
+    theme: "TransparentNavigationBar",
+    product_specific: true,
+}
diff --git a/packages/SettingsLib/res/values-mcc310-mnc012/strings.xml b/packages/overlays/TransparentNavigationBarOverlay/AndroidManifest.xml
similarity index 61%
copy from packages/SettingsLib/res/values-mcc310-mnc012/strings.xml
copy to packages/overlays/TransparentNavigationBarOverlay/AndroidManifest.xml
index aa504ef..d69abfa 100644
--- a/packages/SettingsLib/res/values-mcc310-mnc012/strings.xml
+++ b/packages/overlays/TransparentNavigationBarOverlay/AndroidManifest.xml
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="utf-8"?>
 <!--
 /**
  * Copyright (c) 2023, The Android Open Source Project
@@ -16,8 +15,12 @@
  * limitations under the License.
  */
 -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.internal.systemui.navbar.transparent"
+        android:versionCode="1"
+        android:versionName="1.0">
+    <overlay android:targetPackage="android"
+        android:priority="1"/>
 
+    <application android:label="@string/transparent_navigation_bar_title" android:hasCode="false"/>
+</manifest>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values-mcc310-mnc012/strings.xml b/packages/overlays/TransparentNavigationBarOverlay/res/values/config.xml
similarity index 73%
copy from packages/SettingsLib/res/values-mcc310-mnc012/strings.xml
copy to packages/overlays/TransparentNavigationBarOverlay/res/values/config.xml
index aa504ef..3b358ea 100644
--- a/packages/SettingsLib/res/values-mcc310-mnc012/strings.xml
+++ b/packages/overlays/TransparentNavigationBarOverlay/res/values/config.xml
@@ -16,8 +16,8 @@
  * limitations under the License.
  */
 -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
-
+<resources>
+    <!-- Controls whether the navigation bar background color provided by the app is transparent by
+         default. This should be controlled in developer options. -->
+    <bool name="config_navBarDefaultTransparent">true</bool>
+</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values-mcc310-mnc012/strings.xml b/packages/overlays/TransparentNavigationBarOverlay/res/values/strings.xml
similarity index 81%
rename from packages/SettingsLib/res/values-mcc310-mnc012/strings.xml
rename to packages/overlays/TransparentNavigationBarOverlay/res/values/strings.xml
index aa504ef..0e3462e 100644
--- a/packages/SettingsLib/res/values-mcc310-mnc012/strings.xml
+++ b/packages/overlays/TransparentNavigationBarOverlay/res/values/strings.xml
@@ -17,7 +17,6 @@
  */
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G UW</string>
-</resources>
-
+    <!-- Name of overlay [CHAR LIMIT=64] -->
+    <string name="transparent_navigation_bar_title" translatable="false">Transparent navigation bar</string>
+</resources>
\ No newline at end of file
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index a359216..e159f18 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -1635,7 +1635,7 @@
             return false;
         }
 
-        if (event.isAccessibilityDataPrivate()
+        if (event.isAccessibilityDataSensitive()
                 && (mFetchFlags & AccessibilityNodeInfo.FLAG_SERVICE_IS_ACCESSIBILITY_TOOL) == 0) {
             return false;
         }
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 25381be..d422f9a 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -26,11 +26,8 @@
 import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOW_MAGNIFICATION_CONNECTION;
 import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOW_MANAGER_INTERNAL;
 import static android.provider.Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED;
-import static android.provider.Settings.Secure.CONTRAST_LEVEL;
 import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_BUTTON;
 import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY;
-import static android.view.accessibility.AccessibilityManager.CONTRAST_DEFAULT_VALUE;
-import static android.view.accessibility.AccessibilityManager.CONTRAST_NOT_SET;
 import static android.view.accessibility.AccessibilityManager.FlashNotificationReason;
 import static android.view.accessibility.AccessibilityManager.ShortcutType;
 
@@ -42,6 +39,7 @@
 import static com.android.internal.util.FunctionalUtils.ignoreRemoteException;
 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
 import static com.android.server.accessibility.AccessibilityUserState.doesShortcutTargetsStringContain;
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 
 import android.Manifest;
 import android.accessibilityservice.AccessibilityGestureEvent;
@@ -57,8 +55,10 @@
 import android.annotation.UserIdInt;
 import android.app.ActivityOptions;
 import android.app.AlertDialog;
+import android.app.AppOpsManager;
 import android.app.PendingIntent;
 import android.app.RemoteAction;
+import android.app.admin.DevicePolicyManager;
 import android.appwidget.AppWidgetManagerInternal;
 import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
@@ -159,6 +159,7 @@
 import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.wm.ActivityTaskManagerInternal;
 import com.android.server.wm.WindowManagerInternal;
+import com.android.settingslib.RestrictedLockUtils;
 
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -1997,16 +1998,6 @@
         return false;
     }
 
-    private boolean readUiContrastLocked(AccessibilityUserState userState) {
-        float contrast = Settings.Secure.getFloatForUser(mContext.getContentResolver(),
-                CONTRAST_LEVEL, CONTRAST_DEFAULT_VALUE, userState.mUserId);
-        if (Math.abs(userState.getUiContrastLocked() - contrast) >= 1e-10) {
-            userState.setUiContrastLocked(contrast);
-            return true;
-        }
-        return false;
-    }
-
     /**
      * Performs {@link AccessibilityService}s delayed notification. The delay is configurable
      * and denotes the period after the last event before notifying the service.
@@ -2676,7 +2667,6 @@
         somethingChanged |= readMagnificationCapabilitiesLocked(userState);
         somethingChanged |= readMagnificationFollowTypingLocked(userState);
         somethingChanged |= readAlwaysOnMagnificationLocked(userState);
-        somethingChanged |= readUiContrastLocked(userState);
         return somethingChanged;
     }
 
@@ -3801,6 +3791,7 @@
     public boolean registerProxyForDisplay(IAccessibilityServiceClient client, int displayId)
             throws RemoteException {
         mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
+        mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.CREATE_VIRTUAL_DEVICE);
         if (client == null) {
             return false;
         }
@@ -3837,6 +3828,7 @@
     @Override
     public boolean unregisterProxyForDisplay(int displayId) {
         mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
+        mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.CREATE_VIRTUAL_DEVICE);
         final long identity = Binder.clearCallingIdentity();
         try {
             return mProxyManager.unregisterProxy(displayId);
@@ -3849,19 +3841,6 @@
         return mProxyManager.isProxyed(displayId);
     }
 
-    @Override public float getUiContrast() {
-        if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
-            mTraceManager.logTrace(LOG_TAG + ".getUiContrast", FLAGS_ACCESSIBILITY_MANAGER);
-        }
-        synchronized (mLock) {
-            AccessibilityUserState userState = getCurrentUserStateLocked();
-            float contrast = userState.getUiContrastLocked();
-            if (contrast != CONTRAST_NOT_SET) return contrast;
-            readUiContrastLocked(userState);
-            return userState.getUiContrastLocked();
-        }
-    }
-
     @Override
     public boolean startFlashNotificationSequence(String opPkg,
             @FlashNotificationReason int reason, IBinder token) {
@@ -3897,6 +3876,51 @@
     }
 
     @Override
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.QUERY_ADMIN_POLICY})
+    public boolean isAccessibilityTargetAllowed(String packageName, int uid, int userId) {
+        final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
+        final List<String> permittedServices = dpm.getPermittedAccessibilityServices(userId);
+
+        // permittedServices null means all accessibility services are allowed.
+        boolean allowed = permittedServices == null || permittedServices.contains(packageName);
+        if (allowed) {
+            final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
+            final int mode = appOps.noteOpNoThrow(
+                    AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
+                    uid, packageName, /* attributionTag= */ null, /* message= */ null);
+            final boolean ecmEnabled = mContext.getResources().getBoolean(
+                    R.bool.config_enhancedConfirmationModeEnabled);
+            return !ecmEnabled || mode == AppOpsManager.MODE_ALLOWED;
+        }
+        return false;
+    }
+
+    @Override
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.QUERY_ADMIN_POLICY})
+    public boolean sendRestrictedDialogIntent(String packageName, int uid, int userId) {
+        // The accessibility service is allowed. Don't show the restricted dialog.
+        if (isAccessibilityTargetAllowed(packageName, uid, userId)) {
+            return false;
+        }
+
+        final EnforcedAdmin admin =
+                RestrictedLockUtilsInternal.checkIfAccessibilityServiceDisallowed(
+                        mContext, packageName, userId);
+        if (admin != null) {
+            RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext, admin);
+            return true;
+        }
+
+        RestrictedLockUtils.sendShowRestrictedSettingDialogIntent(mContext,
+                packageName, uid);
+        return true;
+    }
+
+    @Override
     public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
         synchronized (mLock) {
@@ -4348,9 +4372,6 @@
         private final Uri mAlwaysOnMagnificationUri = Settings.Secure.getUriFor(
                 Settings.Secure.ACCESSIBILITY_MAGNIFICATION_ALWAYS_ON_ENABLED);
 
-        private final Uri mUiContrastUri = Settings.Secure.getUriFor(
-                CONTRAST_LEVEL);
-
         public AccessibilityContentObserver(Handler handler) {
             super(handler);
         }
@@ -4393,8 +4414,6 @@
                     mMagnificationFollowTypingUri, false, this, UserHandle.USER_ALL);
             contentResolver.registerContentObserver(
                     mAlwaysOnMagnificationUri, false, this, UserHandle.USER_ALL);
-            contentResolver.registerContentObserver(
-                    mUiContrastUri, false, this, UserHandle.USER_ALL);
         }
 
         @Override
@@ -4466,10 +4485,6 @@
                     readMagnificationFollowTypingLocked(userState);
                 } else if (mAlwaysOnMagnificationUri.equals(uri)) {
                     readAlwaysOnMagnificationLocked(userState);
-                } else if (mUiContrastUri.equals(uri)) {
-                    if (readUiContrastLocked(userState)) {
-                        updateUiContrastLocked(userState);
-                    }
                 }
             }
         }
@@ -4786,22 +4801,7 @@
                         userState.getFocusColorLocked());
             }));
         });
-    }
 
-    private void updateUiContrastLocked(AccessibilityUserState userState) {
-        if (userState.mUserId != mCurrentUserId) {
-            return;
-        }
-        if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_SERVICE_CLIENT)) {
-            mTraceManager.logTrace(LOG_TAG + ".updateUiContrastLocked",
-                    FLAGS_ACCESSIBILITY_SERVICE_CLIENT, "userState=" + userState);
-        }
-        float contrast = userState.getUiContrastLocked();
-        mMainHandler.post(() -> {
-            broadcastToClients(userState, ignoreRemoteException(client -> {
-                client.mCallback.setUiContrast(contrast);
-            }));
-        });
     }
 
     public AccessibilityTraceManager getTraceManager() {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java b/services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java
index 4806001..c37ea50 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java
@@ -24,9 +24,7 @@
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.UserIdInt;
 import android.app.AppOpsManager;
-import android.app.admin.DevicePolicyManager;
 import android.appwidget.AppWidgetManagerInternal;
 import android.content.ComponentName;
 import android.content.Context;
@@ -46,7 +44,6 @@
 
 import com.android.internal.util.ArrayUtils;
 import com.android.server.inputmethod.InputMethodManagerInternal;
-import com.android.settingslib.RestrictedLockUtils;
 
 import libcore.util.EmptyArray;
 
@@ -420,7 +417,7 @@
 
         // TODO(b/207697949, b/208872785): Add cts test for managed device.
         //  Use RestrictedLockUtilsInternal in AccessibilitySecurityPolicy
-        if (checkIfInputMethodDisallowed(
+        if (RestrictedLockUtilsInternal.checkIfInputMethodDisallowed(
                 mContext, inputMethodInfo.getPackageName(), callingUserId) != null) {
             return ENABLE_IME_FAIL_BY_ADMIN;
         }
@@ -429,72 +426,6 @@
     }
 
     /**
-     * @return the UserHandle for a userId. Return null for USER_NULL
-     */
-    private static UserHandle getUserHandleOf(@UserIdInt int userId) {
-        if (userId == UserHandle.USER_NULL) {
-            return null;
-        } else {
-            return UserHandle.of(userId);
-        }
-    }
-
-    private static int getManagedProfileId(Context context, int userId) {
-        UserManager um = context.getSystemService(UserManager.class);
-        List<UserInfo> userProfiles = um.getProfiles(userId);
-        for (UserInfo uInfo : userProfiles) {
-            if (uInfo.id == userId) {
-                continue;
-            }
-            if (uInfo.isManagedProfile()) {
-                return uInfo.id;
-            }
-        }
-        return UserHandle.USER_NULL;
-    }
-
-    private static RestrictedLockUtils.EnforcedAdmin checkIfInputMethodDisallowed(Context context,
-            String packageName, int userId) {
-        DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
-        if (dpm == null) {
-            return null;
-        }
-        RestrictedLockUtils.EnforcedAdmin admin =
-                RestrictedLockUtils.getProfileOrDeviceOwner(context, getUserHandleOf(userId));
-        boolean permitted = true;
-        if (admin != null) {
-            permitted = dpm.isInputMethodPermittedByAdmin(admin.component,
-                    packageName, userId);
-        }
-
-        boolean permittedByParentAdmin = true;
-        RestrictedLockUtils.EnforcedAdmin profileAdmin = null;
-        int managedProfileId = getManagedProfileId(context, userId);
-        if (managedProfileId != UserHandle.USER_NULL) {
-            profileAdmin = RestrictedLockUtils.getProfileOrDeviceOwner(
-                    context, getUserHandleOf(managedProfileId));
-            // If the device is an organization-owned device with a managed profile, the
-            // managedProfileId will be used instead of the affected userId. This is because
-            // isInputMethodPermittedByAdmin is called on the parent DPM instance, which will
-            // return results affecting the personal profile.
-            if (profileAdmin != null && dpm.isOrganizationOwnedDeviceWithManagedProfile()) {
-                DevicePolicyManager parentDpm = dpm.getParentProfileInstance(
-                        UserManager.get(context).getUserInfo(managedProfileId));
-                permittedByParentAdmin = parentDpm.isInputMethodPermittedByAdmin(
-                        profileAdmin.component, packageName, managedProfileId);
-            }
-        }
-        if (!permitted && !permittedByParentAdmin) {
-            return RestrictedLockUtils.EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
-        } else if (!permitted) {
-            return admin;
-        } else if (!permittedByParentAdmin) {
-            return profileAdmin;
-        }
-        return null;
-    }
-
-    /**
      * Returns the parent userId of the profile according to the specified userId.
      *
      * @param userId The userId to check
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
index 1c9ce3c..3b169f8 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
@@ -26,8 +26,6 @@
 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
 import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_BUTTON;
 import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY;
-import static android.view.accessibility.AccessibilityManager.CONTRAST_DEFAULT_VALUE;
-import static android.view.accessibility.AccessibilityManager.CONTRAST_NOT_SET;
 import static android.view.accessibility.AccessibilityManager.ShortcutType;
 
 import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
@@ -147,8 +145,6 @@
     private final int mFocusStrokeWidthDefaultValue;
     // The default value of the focus color.
     private final int mFocusColorDefaultValue;
-    /** The color contrast in [-1, 1] */
-    private float mUiContrast = CONTRAST_DEFAULT_VALUE;
 
     private Context mContext;
 
@@ -224,7 +220,6 @@
         mFocusColor = mFocusColorDefaultValue;
         mMagnificationFollowTypingEnabled = true;
         mAlwaysOnMagnificationEnabled = false;
-        mUiContrast = CONTRAST_NOT_SET;
     }
 
     void addServiceLocked(AccessibilityServiceConnection serviceConnection) {
@@ -1001,7 +996,6 @@
         return mFocusColor;
     }
 
-
     /**
      * Sets the stroke width and color of the focus rectangle.
      *
@@ -1027,20 +1021,4 @@
         }
         return false;
     }
-
-    /**
-     * Get the color contrast
-     * @return color contrast in [-1, 1]
-     */
-    public float getUiContrastLocked() {
-        return mUiContrast;
-    }
-
-    /**
-     * Set the color contrast
-     * @param contrast the new color contrast in [-1, 1]
-     */
-    public void setUiContrastLocked(float contrast) {
-        mUiContrast = contrast;
-    }
 }
diff --git a/services/accessibility/java/com/android/server/accessibility/FlashNotificationsController.java b/services/accessibility/java/com/android/server/accessibility/FlashNotificationsController.java
index 86b5a12..fa30a6f 100644
--- a/services/accessibility/java/com/android/server/accessibility/FlashNotificationsController.java
+++ b/services/accessibility/java/com/android/server/accessibility/FlashNotificationsController.java
@@ -53,6 +53,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.util.FeatureFlagUtils;
 import android.util.Log;
 import android.view.Display;
 import android.view.View;
@@ -254,7 +255,7 @@
         broadcastFilter.addAction(ACTION_FLASH_NOTIFICATION_STOP_PREVIEW);
         mFlashBroadcastReceiver = new FlashBroadcastReceiver();
         mContext.registerReceiver(
-                mFlashBroadcastReceiver, broadcastFilter, Context.RECEIVER_EXPORTED);
+                mFlashBroadcastReceiver, broadcastFilter, Context.RECEIVER_NOT_EXPORTED);
 
         final PowerManager powerManager = mContext.getSystemService(PowerManager.class);
         mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKE_LOCK_TAG);
@@ -342,10 +343,12 @@
     private void requestStartFlashNotification(FlashNotification flashNotification) {
         if (DEBUG) Log.d(LOG_TAG, "requestStartFlashNotification");
 
-        mIsCameraFlashNotificationEnabled = Settings.System.getIntForUser(
+        boolean isFeatureOn = FeatureFlagUtils.isEnabled(mContext,
+                FeatureFlagUtils.SETTINGS_FLASH_NOTIFICATIONS);
+        mIsCameraFlashNotificationEnabled = isFeatureOn && Settings.System.getIntForUser(
                 mContext.getContentResolver(), SETTING_KEY_CAMERA_FLASH_NOTIFICATION, 0,
                 UserHandle.USER_CURRENT) != 0;
-        mIsScreenFlashNotificationEnabled = Settings.System.getIntForUser(
+        mIsScreenFlashNotificationEnabled = isFeatureOn && Settings.System.getIntForUser(
                 mContext.getContentResolver(), SETTING_KEY_SCREEN_FLASH_NOTIFICATION, 0,
                 UserHandle.USER_CURRENT) != 0;
 
diff --git a/services/accessibility/java/com/android/server/accessibility/RestrictedLockUtilsInternal.java b/services/accessibility/java/com/android/server/accessibility/RestrictedLockUtilsInternal.java
new file mode 100644
index 0000000..28810e6
--- /dev/null
+++ b/services/accessibility/java/com/android/server/accessibility/RestrictedLockUtilsInternal.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.server.accessibility;
+
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
+import android.annotation.UserIdInt;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.UserHandle;
+import android.os.UserManager;
+
+import com.android.settingslib.RestrictedLockUtils;
+
+import java.util.List;
+
+/**
+ * Utility class to host methods usable to return {@link EnforcedAdmin} instances based on device
+ * admin policy.
+ */
+public class RestrictedLockUtilsInternal {
+
+    /**
+     * Disables accessibility service that are not permitted.
+     */
+    public static EnforcedAdmin checkIfAccessibilityServiceDisallowed(Context context,
+            String packageName, int userId) {
+        final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
+        if (dpm == null) {
+            return null;
+        }
+        final EnforcedAdmin admin =
+                RestrictedLockUtils.getProfileOrDeviceOwner(context, getUserHandleOf(userId));
+        boolean permitted = true;
+        if (admin != null) {
+            permitted = dpm.isAccessibilityServicePermittedByAdmin(admin.component,
+                    packageName, userId);
+        }
+        int managedProfileId = getManagedProfileId(context, userId);
+        final EnforcedAdmin profileAdmin = RestrictedLockUtils.getProfileOrDeviceOwner(context,
+                getUserHandleOf(managedProfileId));
+        boolean permittedByProfileAdmin = true;
+        if (profileAdmin != null) {
+            permittedByProfileAdmin = dpm.isAccessibilityServicePermittedByAdmin(
+                    profileAdmin.component, packageName, managedProfileId);
+        }
+        if (!permitted && !permittedByProfileAdmin) {
+            return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
+        } else if (!permitted) {
+            return admin;
+        } else if (!permittedByProfileAdmin) {
+            return profileAdmin;
+        }
+        return null;
+    }
+
+    /**
+     * Disables input method that are not permitted.
+     */
+    public static EnforcedAdmin checkIfInputMethodDisallowed(Context context, String packageName,
+            int userId) {
+        final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
+        if (dpm == null) {
+            return null;
+        }
+        final EnforcedAdmin admin =
+                RestrictedLockUtils.getProfileOrDeviceOwner(context, getUserHandleOf(userId));
+        boolean permitted = true;
+        if (admin != null) {
+            permitted = dpm.isInputMethodPermittedByAdmin(admin.component,
+                    packageName, userId);
+        }
+
+        boolean permittedByParentAdmin = true;
+        EnforcedAdmin profileAdmin = null;
+        int managedProfileId = getManagedProfileId(context, userId);
+        if (managedProfileId != UserHandle.USER_NULL) {
+            profileAdmin = RestrictedLockUtils.getProfileOrDeviceOwner(
+                    context, getUserHandleOf(managedProfileId));
+            // If the device is an organization-owned device with a managed profile, the
+            // managedProfileId will be used instead of the affected userId. This is because
+            // isInputMethodPermittedByAdmin is called on the parent DPM instance, which will
+            // return results affecting the personal profile.
+            if (profileAdmin != null && dpm.isOrganizationOwnedDeviceWithManagedProfile()) {
+                final DevicePolicyManager parentDpm = dpm.getParentProfileInstance(
+                        UserManager.get(context).getUserInfo(managedProfileId));
+                permittedByParentAdmin = parentDpm.isInputMethodPermittedByAdmin(
+                        profileAdmin.component, packageName, managedProfileId);
+            }
+        }
+        if (!permitted && !permittedByParentAdmin) {
+            return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
+        } else if (!permitted) {
+            return admin;
+        } else if (!permittedByParentAdmin) {
+            return profileAdmin;
+        }
+        return null;
+    }
+
+    private static int getManagedProfileId(Context context, int userId) {
+        final UserManager um = context.getSystemService(UserManager.class);
+        final List<UserInfo> userProfiles = um.getProfiles(userId);
+        for (UserInfo uInfo : userProfiles) {
+            if (uInfo.id == userId) {
+                continue;
+            }
+            if (uInfo.isManagedProfile()) {
+                return uInfo.id;
+            }
+        }
+        return UserHandle.USER_NULL;
+    }
+
+    /**
+     * @return the UserHandle for a userId. Return null for USER_NULL
+     */
+    private static UserHandle getUserHandleOf(@UserIdInt int userId) {
+        if (userId == UserHandle.USER_NULL) {
+            return null;
+        } else {
+            return UserHandle.of(userId);
+        }
+    }
+}
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
index f8ab0d5..ed8a35f 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
@@ -63,6 +63,7 @@
 import com.android.server.accessibility.AccessibilityTraceManager;
 import com.android.server.wm.WindowManagerInternal;
 
+import java.util.ArrayList;
 import java.util.Locale;
 import java.util.function.Supplier;
 
@@ -90,7 +91,9 @@
 
     private final ScreenStateObserver mScreenStateObserver;
 
-    private final MagnificationInfoChangedCallback mMagnificationInfoChangedCallback;
+    @GuardedBy("mLock")
+    private final ArrayList<MagnificationInfoChangedCallback>
+            mMagnificationInfoChangedCallbacks = new ArrayList<>();
 
     private final MagnificationScaleProvider mScaleProvider;
 
@@ -393,8 +396,10 @@
                     .setScale(scale)
                     .setCenterX(centerX)
                     .setCenterY(centerY).build();
-            mMagnificationInfoChangedCallback.onFullScreenMagnificationChanged(mDisplayId,
-                    mMagnificationRegion, config);
+            mMagnificationInfoChangedCallbacks.forEach(callback -> {
+                callback.onFullScreenMagnificationChanged(mDisplayId,
+                        mMagnificationRegion, config);
+            });
             if (mUnregisterPending && !isActivated()) {
                 unregister(mDeleteAfterUnregister);
             }
@@ -502,8 +507,10 @@
 
             if (changed) {
                 mMagnificationActivated = activated;
-                mMagnificationInfoChangedCallback.onFullScreenMagnificationActivationState(
-                        mDisplayId, mMagnificationActivated);
+                mMagnificationInfoChangedCallbacks.forEach(callback -> {
+                    callback.onFullScreenMagnificationActivationState(
+                            mDisplayId, mMagnificationActivated);
+                });
                 mControllerCtx.getWindowManager().setForceShowMagnifiableBounds(
                         mDisplayId, activated);
             }
@@ -580,8 +587,10 @@
             sendSpecToAnimation(mCurrentMagnificationSpec, animationCallback);
             if (isActivated() && (id != INVALID_SERVICE_ID)) {
                 mIdOfLastServiceToMagnify = id;
-                mMagnificationInfoChangedCallback.onRequestMagnificationSpec(mDisplayId,
-                        mIdOfLastServiceToMagnify);
+                mMagnificationInfoChangedCallbacks.forEach(callback -> {
+                    callback.onRequestMagnificationSpec(mDisplayId,
+                            mIdOfLastServiceToMagnify);
+                });
             }
             return changed;
         }
@@ -787,7 +796,7 @@
         mLock = lock;
         mMainThreadId = mControllerCtx.getContext().getMainLooper().getThread().getId();
         mScreenStateObserver = new ScreenStateObserver(mControllerCtx.getContext(), this);
-        mMagnificationInfoChangedCallback = magnificationInfoChangedCallback;
+        addInfoChangedCallback(magnificationInfoChangedCallback);
         mScaleProvider = scaleProvider;
         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
         mThumbnailSupplier = thumbnailSupplier;
@@ -892,6 +901,10 @@
      */
     void onUserContextChanged(int displayId) {
         synchronized (mLock) {
+            if (!isActivated(displayId)) {
+                return;
+            }
+
             if (isAlwaysOnMagnificationEnabled()) {
                 setScaleAndCenter(displayId, 1.0f, Float.NaN, Float.NaN,
                         true,
@@ -1349,7 +1362,11 @@
      *                           hidden.
      */
     void notifyImeWindowVisibilityChanged(int displayId, boolean shown) {
-        mMagnificationInfoChangedCallback.onImeWindowVisibilityChanged(displayId, shown);
+        synchronized (mLock) {
+            mMagnificationInfoChangedCallbacks.forEach(callback -> {
+                callback.onImeWindowVisibilityChanged(displayId, shown);
+            });
+        }
     }
 
     private void onScreenTurnedOff() {
@@ -1411,6 +1428,18 @@
         }
     }
 
+    void addInfoChangedCallback(@NonNull MagnificationInfoChangedCallback callback) {
+        synchronized (mLock) {
+            mMagnificationInfoChangedCallbacks.add(callback);
+        }
+    }
+
+    void removeInfoChangedCallback(@NonNull MagnificationInfoChangedCallback callback) {
+        synchronized (mLock) {
+            mMagnificationInfoChangedCallbacks.remove(callback);
+        }
+    }
+
     private boolean traceEnabled() {
         return mControllerCtx.getTraceManager().isA11yTracingEnabledForTypes(
                 FLAGS_WINDOW_MANAGER_INTERNAL);
@@ -1709,7 +1738,7 @@
         return animate ? STUB_ANIMATION_CALLBACK : null;
     }
 
-    interface  MagnificationInfoChangedCallback {
+    interface MagnificationInfoChangedCallback {
 
         /**
          * Called when the {@link MagnificationSpec} is changed with non-default
@@ -1722,7 +1751,6 @@
 
         /**
          * Called when the state of the magnification activation is changed.
-         * It is for the logging data of the magnification activation state.
          *
          * @param displayId the logical display id
          * @param activated {@code true} if the magnification is activated, otherwise {@code false}.
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 f85ef43f..038847e 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
@@ -32,6 +32,7 @@
 import static java.util.Arrays.asList;
 import static java.util.Arrays.copyOfRange;
 
+import android.accessibilityservice.MagnificationConfig;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UiContext;
@@ -40,6 +41,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.graphics.PointF;
+import android.graphics.Region;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -129,6 +131,8 @@
 
     @VisibleForTesting final FullScreenMagnificationController mFullScreenMagnificationController;
 
+    private final FullScreenMagnificationController.MagnificationInfoChangedCallback
+            mMagnificationInfoChangedCallback;
     @VisibleForTesting final DelegatingState mDelegatingState;
     @VisibleForTesting final DetectingState mDetectingState;
     @VisibleForTesting final PanningScalingState mPanningScalingState;
@@ -158,6 +162,40 @@
                             + ", detectShortcutTrigger = " + detectShortcutTrigger + ")");
         }
         mFullScreenMagnificationController = fullScreenMagnificationController;
+        mMagnificationInfoChangedCallback =
+                new FullScreenMagnificationController.MagnificationInfoChangedCallback() {
+                    @Override
+                    public void onRequestMagnificationSpec(int displayId, int serviceId) {
+                        return;
+                    }
+
+                    @Override
+                    public void onFullScreenMagnificationActivationState(int displayId,
+                            boolean activated) {
+                        if (displayId != mDisplayId) {
+                            return;
+                        }
+
+                        if (!activated) {
+                            clearAndTransitionToStateDetecting();
+                        }
+                    }
+
+                    @Override
+                    public void onImeWindowVisibilityChanged(int displayId, boolean shown) {
+                        return;
+                    }
+
+                    @Override
+                    public void onFullScreenMagnificationChanged(int displayId,
+                            @NonNull Region region,
+                            @NonNull MagnificationConfig config) {
+                        return;
+                    }
+                };
+        mFullScreenMagnificationController.addInfoChangedCallback(
+                mMagnificationInfoChangedCallback);
+
         mPromptController = promptController;
 
         mDelegatingState = new DelegatingState();
@@ -217,6 +255,8 @@
         // Check if need to reset when MagnificationGestureHandler is the last magnifying service.
         mFullScreenMagnificationController.resetIfNeeded(
                 mDisplayId, AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
+        mFullScreenMagnificationController.removeInfoChangedCallback(
+                mMagnificationInfoChangedCallback);
         clearAndTransitionToStateDetecting();
     }
 
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index a3c09ab..01386da 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -200,7 +200,11 @@
     final AugmentedAutofillState mAugmentedAutofillState = new AugmentedAutofillState();
 
     /**
-     * Lock used to synchronize access to flags.
+     * Lock used to synchronize access to the flags.
+     * DO NOT USE ANY OTHER LOCK while holding this lock.
+     * NOTE: This lock should only be used for accessing flags. It should never call into other
+     * methods holding another lock. It can lead to potential deadlock if it calls into a method
+     * holding mLock.
      */
     private final Object mFlagLock = new Object();
 
@@ -1914,6 +1918,16 @@
                 synchronized (mLock) {
                     pw.print("sDebug: "); pw.print(realDebug);
                     pw.print(" sVerbose: "); pw.println(realVerbose);
+                    pw.print("Flags: ");
+                    synchronized (mFlagLock) {
+                        pw.print("mPccClassificationEnabled="); pw.print(mPccClassificationEnabled);
+                        pw.print(";");
+                        pw.print("mPccPreferProviderOverPcc="); pw.print(mPccPreferProviderOverPcc);
+                        pw.print(";");
+                        pw.print("mPccUseFallbackDetection="); pw.print(mPccUseFallbackDetection);
+                        pw.print(";");
+                        pw.print("mPccProviderHints="); pw.println(mPccProviderHints);
+                    }
                     // Dump per-user services
                     dumpLocked("", pw);
                     mAugmentedAutofillResolver.dumpShort(pw); pw.println();
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 43b816b..bea049c 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -849,6 +849,31 @@
         }
     }
 
+    /**
+     * Updates the last fill response when a view was entered.
+     */
+    void logViewEntered(int sessionId, @Nullable Bundle clientState) {
+        synchronized (mLock) {
+            if (!isValidEventLocked("logViewEntered", sessionId)) {
+                return;
+            }
+
+            if (mEventHistory.getEvents() != null) {
+                // Do not log this event more than once
+                for (Event event : mEventHistory.getEvents()) {
+                    if (event.getType() == Event.TYPE_VIEW_REQUESTED_AUTOFILL) {
+                        Slog.v(TAG, "logViewEntered: already logged TYPE_VIEW_REQUESTED_AUTOFILL");
+                        return;
+                    }
+                }
+            }
+
+            mEventHistory.addEvent(
+                    new Event(Event.TYPE_VIEW_REQUESTED_AUTOFILL, null, clientState, null,
+                            null, null, null, null, null, null, null));
+        }
+    }
+
     void logAugmentedAutofillAuthenticationSelected(int sessionId, @Nullable String selectedDataset,
             @Nullable Bundle clientState) {
         synchronized (mLock) {
diff --git a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
index 592045c..bcf50ad 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
@@ -356,6 +356,11 @@
                             public void onError() {
                                 onErrorCallback.run();
                             }
+
+                            @Override
+                            public void onInflate() {
+                                /* nothing */
+                            }
                         });
 
         if (inlineSuggestionsCallback.apply(inlineFillUi)) {
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 598521f..7f6ad43 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -276,6 +276,9 @@
     @GuardedBy("mLock")
     private DeathRecipient mClientVulture;
 
+    @GuardedBy("mLock")
+    private boolean mLoggedInlineDatasetShown;
+
     /**
      * Reference to the remote service.
      *
@@ -442,6 +445,18 @@
     private boolean mPreviouslyFillDialogPotentiallyStarted;
 
     /**
+     * Keeps track of if the user entered view, this is used to
+     * distinguish Fill Request that did not have user interaction
+     * with ones that did.
+     *
+     * This is set to true when entering view - after FillDialog FillRequest
+     * or on plain user tap.
+     */
+    @NonNull
+    @GuardedBy("mLock")
+    private boolean mLogViewEntered;
+
+    /**
      * Keeps the fill dialog trigger ids of the last response. This invalidates
      * the trigger ids of the previous response.
      */
@@ -727,6 +742,9 @@
             return Collections.EMPTY_LIST;
         }
         final String typeHints = mService.getMaster().getPccProviderHints();
+        if (sVerbose) {
+            Slog.v(TAG, "TypeHints flag:" + typeHints);
+        }
         if (TextUtils.isEmpty(typeHints)) {
             return new ArrayList<>();
         }
@@ -742,7 +760,7 @@
         @GuardedBy("mLock")
         void maybeRequestFieldClassificationFromServiceLocked() {
             if (mClassificationState.mPendingFieldClassificationRequest == null) {
-                Log.w(TAG, "Received AssistData without pending classification request");
+                Slog.w(TAG, "Received AssistData without pending classification request");
                 return;
             }
 
@@ -776,7 +794,8 @@
             final int requestId = receiverExtras.getInt(EXTRA_REQUEST_ID);
 
             if (sVerbose) {
-                Slog.v(TAG, "New structure for requestId " + requestId + ": " + structure);
+                Slog.v(TAG, "New structure for PCC Detection: requestId " + requestId + ": "
+                        + structure);
             }
 
             synchronized (mLock) {
@@ -1110,6 +1129,13 @@
         // structure is taken. This causes only one fill request per burst of focus changes.
         cancelCurrentRequestLocked();
 
+        if (mClassificationState.mHintsToAutofillIdMap == null) {
+            if (sVerbose) {
+                Slog.v(TAG, "triggering field classification");
+            }
+            requestAssistStructureForPccLocked(flags | FLAG_PCC_DETECTION);
+        }
+
         // Only ask IME to create inline suggestions request when
         // 1. Autofill provider supports it or client enabled client suggestions.
         // 2. The render service is available.
@@ -1289,6 +1315,7 @@
 
         mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_SESSION_STARTED)
                 .addTaggedData(MetricsEvent.FIELD_AUTOFILL_FLAGS, flags));
+        mLogViewEntered = false;
     }
 
     /**
@@ -1360,7 +1387,6 @@
     @Override
     public void onFillRequestSuccess(int requestId, @Nullable FillResponse response,
             @NonNull String servicePackageName, int requestFlags) {
-
         final AutofillId[] fieldClassificationIds;
 
         final LogMaker requestLog;
@@ -1413,6 +1439,14 @@
 
         mService.setLastResponse(id, response);
 
+        synchronized (mLock) {
+            if (mLogViewEntered) {
+                mLogViewEntered = false;
+                mService.logViewEntered(id, null);
+            }
+        }
+
+
         final long disableDuration = response.getDisableDuration();
         final boolean autofillDisabled = disableDuration > 0;
         if (autofillDisabled) {
@@ -1585,10 +1619,68 @@
         Set<Dataset> eligibleDatasets = new ArraySet<>();
         Set<AutofillId> eligibleAutofillIds = new ArraySet<>();
         for (Dataset dataset : response.getDatasets()) {
-            if (dataset.getFieldIds() == null) continue;
+            if (dataset.getFieldIds() == null || dataset.getFieldIds().isEmpty()) continue;
             if (dataset.getAutofillDatatypes() != null
-                    && dataset.getAutofillDatatypes().size() > 0) {
-                continue;
+                    && !dataset.getAutofillDatatypes().isEmpty()) {
+                // This dataset has information relevant for detection too, so we should filter
+                // them out. It's possible that some fields are applicable to hints only, as such,
+                // they need to be filtered off.
+                // TODO(b/266379948): Verify the logic and add tests
+                // Update dataset to only have non-null fieldValues
+
+                // Figure out if we need to process results.
+                boolean conversionRequired = false;
+                int newSize = dataset.getFieldIds().size();
+                for (AutofillId id : dataset.getFieldIds()) {
+                    if (id == null) {
+                        conversionRequired = true;
+                        newSize--;
+                    }
+                }
+
+                if (conversionRequired) {
+                    ArrayList<AutofillId> fieldIds = new ArrayList<>(newSize);
+                    ArrayList<AutofillValue> fieldValues = new ArrayList<>(newSize);
+                    ArrayList<RemoteViews> fieldPresentations = new ArrayList<>(newSize);
+                    ArrayList<RemoteViews> fieldDialogPresentations = new ArrayList<>(newSize);
+                    ArrayList<InlinePresentation> fieldInlinePresentations =
+                            new ArrayList<>(newSize);
+                    ArrayList<InlinePresentation> fieldInlineTooltipPresentations =
+                            new ArrayList<>(newSize);
+                    ArrayList<Dataset.DatasetFieldFilter> fieldFilters = new ArrayList<>(newSize);
+
+                    for (int i = 0; i < dataset.getFieldIds().size(); i++) {
+                        AutofillId id = dataset.getFieldIds().get(i);
+                        if (id != null) {
+                            // Copy over
+                            fieldIds.add(id);
+                            fieldValues.add(dataset.getFieldValues().get(i));
+                            fieldPresentations.add(dataset.getFieldPresentation(i));
+                            fieldDialogPresentations.add(dataset.getFieldDialogPresentation(i));
+                            fieldInlinePresentations.add(dataset.getFieldInlinePresentation(i));
+                            fieldInlineTooltipPresentations.add(
+                                    dataset.getFieldInlineTooltipPresentation(i));
+                            fieldFilters.add(dataset.getFilter(i));
+                        }
+                    }
+                    dataset =
+                            new Dataset(
+                                    fieldIds,
+                                    fieldValues,
+                                    fieldPresentations,
+                                    fieldDialogPresentations,
+                                    fieldInlinePresentations,
+                                    fieldInlineTooltipPresentations,
+                                    fieldFilters,
+                                    new ArrayList<>(),
+                                    dataset.getFieldContent(),
+                                    null,
+                                    null,
+                                    null,
+                                    null,
+                                    dataset.getId(),
+                                    dataset.getAuthentication());
+                }
             }
             eligibleDatasets.add(dataset);
             for (AutofillId id : dataset.getFieldIds()) {
@@ -1615,6 +1707,7 @@
             ArrayMap<String, Set<AutofillId>> hintsToAutofillIdMap =
                     mClassificationState.mHintsToAutofillIdMap;
 
+            // TODO(266379948): Handle group hints too.
             ArrayMap<String, Set<AutofillId>> groupHintsToAutofillIdMap =
                     mClassificationState.mGroupHintsToAutofillIdMap;
 
@@ -1625,7 +1718,8 @@
 
             for (int i = 0; i < datasets.size(); i++) {
                 Dataset dataset = datasets.get(i);
-                if (dataset.getAutofillDatatypes() == null) continue;
+                if (dataset.getAutofillDatatypes() == null
+                        || dataset.getAutofillDatatypes().isEmpty()) continue;
                 if (dataset.getFieldIds() != null && dataset.getFieldIds().size() > 0) continue;
 
                 ArrayList<AutofillId> fieldIds = new ArrayList<>();
@@ -1637,6 +1731,7 @@
                 ArrayList<Dataset.DatasetFieldFilter> fieldFilters = new ArrayList<>();
 
                 for (int j = 0; j < dataset.getAutofillDatatypes().size(); j++) {
+                    if (dataset.getAutofillDatatypes().get(0) == null) continue;
                     String hint = dataset.getAutofillDatatypes().get(j);
 
                     if (hintsToAutofillIdMap.containsKey(hint)) {
@@ -1960,6 +2055,22 @@
                 Session::removeFromService, this));
     }
 
+    // AutofillUiCallback
+    @Override
+    public void onShown(int uiType) {
+        synchronized (mLock) {
+            if (uiType == UI_TYPE_INLINE) {
+                if (mLoggedInlineDatasetShown) {
+                    // Chip inflation already logged, do not log again.
+                    // This is needed because every chip inflation will call this.
+                    return;
+                }
+                mLoggedInlineDatasetShown = true;
+            }
+            mService.logDatasetShown(this.id, mClientState, uiType);
+        }
+    }
+
     // AutoFillUiCallback
     @Override
     public void requestShowFillUi(AutofillId id, int width, int height,
@@ -3545,6 +3656,28 @@
                     return;
                 }
 
+                synchronized (mLock) {
+                    if (!mLogViewEntered) {
+                        // If the current request is for FillDialog (preemptive)
+                        // then this is the first time that the view is entered
+                        // (mLogViewEntered == false) in this case, setLastResponse()
+                        // has already been called, so just log here.
+                        // If the current request is not and (mLogViewEntered == false)
+                        // then the last session is being tracked (setLastResponse not called)
+                        // so this calling logViewEntered will be a nop.
+                        // Calling logViewEntered() twice will only log it once
+                        // TODO(271181979): this is broken for multiple partitions
+                        mService.logViewEntered(this.id, null);
+                    }
+
+                    // If this is the first time view is entered for inline, the last
+                    // session is still being tracked, so logViewEntered() needs
+                    // to be delayed until setLastResponse is called.
+                    // For fill dialog requests case logViewEntered is already called above
+                    // so this will do nothing. Assumption: only one fill dialog per session
+                    mLogViewEntered = true;
+                }
+
                 // Previously, fill request will only start whenever a view is entered.
                 // With Fill Dialog, request starts prior to view getting entered. So, we can't end
                 // the event at this moment, otherwise we will be wrongly attributing fill dialog
@@ -3818,8 +3951,6 @@
                 synchronized (mLock) {
                     final ViewState currentView = mViewStates.get(mCurrentViewId);
                     currentView.setState(ViewState.STATE_FILL_DIALOG_SHOWN);
-                    mService.logDatasetShown(id, mClientState, UI_TYPE_DIALOG);
-
                     mPresentationStatsEventLogger.maybeSetCountShown(
                             response.getDatasets(), mCurrentViewId);
                     mPresentationStatsEventLogger.maybeSetDisplayPresentationType(UI_TYPE_DIALOG);
@@ -3849,10 +3980,6 @@
                     // back a response via callback.
                     final ViewState currentView = mViewStates.get(mCurrentViewId);
                     currentView.setState(ViewState.STATE_INLINE_SHOWN);
-                    // TODO(b/248378401): Fix it to log showed only when IME asks for inflation,
-                    // rather than here where framework sends back the response.
-                    mService.logDatasetShown(id, mClientState, UI_TYPE_INLINE);
-
                     // TODO(b/234475358): Log more accurate value of number of inline suggestions
                     // shown, inflated, and filtered.
                     mPresentationStatsEventLogger.maybeSetCountShown(
@@ -3869,7 +3996,6 @@
                 targetLabel, targetIcon, this, id, mCompatMode);
 
         synchronized (mLock) {
-            mService.logDatasetShown(id, mClientState, UI_TYPE_MENU);
             mPresentationStatsEventLogger.maybeSetCountShown(
                     response.getDatasets(), mCurrentViewId);
             mPresentationStatsEventLogger.maybeSetDisplayPresentationType(UI_TYPE_MENU);
@@ -4081,6 +4207,12 @@
             return false;
         }
 
+        // Set this to false - we are requesting a new inline request and haven't shown
+        // anything yet
+        synchronized (mLock) {
+            mLoggedInlineDatasetShown = false;
+        }
+
         final InlineFillUi.InlineFillUiInfo inlineFillUiInfo =
                 new InlineFillUi.InlineFillUiInfo(request, focusedId,
                         filterText, remoteRenderService, userId, id);
@@ -4110,6 +4242,11 @@
                                     InlineFillUi.emptyUi(focusedId));
                         }
                     }
+
+                    @Override
+                    public void onInflate() {
+                        Session.this.onShown(UI_TYPE_INLINE);
+                    }
                 });
         return mInlineSessionController.setInlineFillUiLocked(inlineFillUi);
     }
@@ -4494,7 +4631,7 @@
         if (mResponses == null) {
             // Set initial capacity as 2 to handle cases where service always requires auth.
             // TODO: add a metric for number of responses set by server, so we can use its average
-            // as the initial array capacitiy.
+            // as the initial array capacity.
             mResponses = new SparseArray<>(2);
         }
         mResponses.put(requestId, newResponse);
@@ -4916,6 +5053,7 @@
             mClassificationGroupHintsMap = new ArrayMap<>();
             mHintsToAutofillIdMap = new ArrayMap<>();
             mGroupHintsToAutofillIdMap = new ArrayMap<>();
+            mClassificationCombinedHintsMap = new ArrayMap<>();
             Set<android.service.assist.classification.FieldClassification> classifications =
                     response.getClassifications();
 
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index 7db6e6f..8291610 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -98,6 +98,7 @@
         void cancelSession();
         void requestShowSoftInput(AutofillId id);
         void requestFallbackFromFillDialog();
+        void onShown(int uiType);
     }
 
     public AutoFillUI(@NonNull Context context) {
@@ -237,6 +238,13 @@
                 }
 
                 @Override
+                public void onShown() {
+                    if (mCallback != null) {
+                        mCallback.onShown(UI_TYPE_MENU);
+                    }
+                }
+
+                @Override
                 public void onDatasetPicked(Dataset dataset) {
                     log.setType(MetricsEvent.TYPE_ACTION);
                     hideFillUiUiThread(callback, true);
@@ -424,6 +432,11 @@
                         }
 
                         @Override
+                        public void onShown() {
+                            callback.onShown(UI_TYPE_DIALOG);
+                        }
+
+                        @Override
                         public void onDatasetPicked(Dataset dataset) {
                             log(MetricsEvent.TYPE_ACTION);
                             hideFillDialogUiThread(callback);
diff --git a/services/autofill/java/com/android/server/autofill/ui/DialogFillUi.java b/services/autofill/java/com/android/server/autofill/ui/DialogFillUi.java
index 72a38eb..dec0e76 100644
--- a/services/autofill/java/com/android/server/autofill/ui/DialogFillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/DialogFillUi.java
@@ -83,6 +83,7 @@
         void onDatasetPicked(@NonNull Dataset dataset);
         void onDismissed();
         void onCanceled();
+        void onShown();
         void startIntentSender(IntentSender intentSender);
     }
 
@@ -148,7 +149,7 @@
         mDialog.setContentView(decor);
         setDialogParamsAsBottomSheet();
         mDialog.setOnCancelListener((d) -> mCallback.onCanceled());
-
+        mDialog.setOnShowListener((d) -> mCallback.onShown());
         show();
     }
 
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index 8fbdd81..76f4505 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -86,6 +86,7 @@
         void onDatasetPicked(@NonNull Dataset dataset);
         void onCanceled();
         void onDestroy();
+        void onShown();
         void requestShowFillUi(int width, int height,
                 IAutofillWindowPresenter windowPresenter);
         void requestHideFillUi();
@@ -706,6 +707,7 @@
                     mWm.addView(mContentView, params);
                     mOverlayControl.hideOverlays();
                     mShowing = true;
+                    mCallback.onShown();
                 } else {
                     mWm.updateViewLayout(mContentView, params);
                 }
diff --git a/services/autofill/java/com/android/server/autofill/ui/InlineFillUi.java b/services/autofill/java/com/android/server/autofill/ui/InlineFillUi.java
index ff17590..ac8d962 100644
--- a/services/autofill/java/com/android/server/autofill/ui/InlineFillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/InlineFillUi.java
@@ -334,6 +334,17 @@
          * Callback on errors.
          */
         void onError();
+
+        /**
+         * Callback when the when the IME inflates the suggestion
+         *
+         * This goes through the following path:
+         * 1. IME Chip inflation inflate() ->
+         * 2. RemoteInlineSuggestionUi::handleInlineSuggestionUiReady() ->
+         * 3. RemoteInlineSuggestionViewConnector::onRender() ->
+         * 4. InlineSuggestionUiCallback::onInflate()
+         */
+        void onInflate();
     }
 
     /**
diff --git a/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java b/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
index 9d4c9eb..52109ba 100644
--- a/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
+++ b/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
@@ -198,6 +198,11 @@
                     public void onError() {
                         Slog.w(TAG, "An error happened on the tooltip");
                     }
+
+                    @Override
+                    public void onInflate() {
+                        /* nothing */
+                    }
                 };
 
         InlinePresentation tooltipInline = new InlinePresentation(tooltipPresentation.getSlice(),
diff --git a/services/autofill/java/com/android/server/autofill/ui/RemoteInlineSuggestionUi.java b/services/autofill/java/com/android/server/autofill/ui/RemoteInlineSuggestionUi.java
index 368f717..ddb60c6 100644
--- a/services/autofill/java/com/android/server/autofill/ui/RemoteInlineSuggestionUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/RemoteInlineSuggestionUi.java
@@ -221,6 +221,7 @@
         if (surfacePackage != null) {
             surfacePackage.release();
         }
+        mRemoteInlineSuggestionViewConnector.onRender();
     }
 
     private void handleOnClick() {
diff --git a/services/autofill/java/com/android/server/autofill/ui/RemoteInlineSuggestionViewConnector.java b/services/autofill/java/com/android/server/autofill/ui/RemoteInlineSuggestionViewConnector.java
index 46d435d..70443f9 100644
--- a/services/autofill/java/com/android/server/autofill/ui/RemoteInlineSuggestionViewConnector.java
+++ b/services/autofill/java/com/android/server/autofill/ui/RemoteInlineSuggestionViewConnector.java
@@ -54,6 +54,8 @@
     @NonNull
     private final Runnable mOnErrorCallback;
     @NonNull
+    private final Runnable mOnInflateCallback;
+    @NonNull
     private final Consumer<IntentSender> mStartIntentSenderFromClientApp;
 
     RemoteInlineSuggestionViewConnector(
@@ -70,6 +72,7 @@
 
         mOnAutofillCallback = onAutofillCallback;
         mOnErrorCallback = uiCallback::onError;
+        mOnInflateCallback = uiCallback::onInflate;
         mStartIntentSenderFromClientApp = uiCallback::startIntentSender;
     }
 
@@ -103,6 +106,10 @@
         mOnErrorCallback.run();
     }
 
+    public void onRender() {
+        mOnInflateCallback.run();
+    }
+
     /**
      * Handles the callback for transferring the touch event on the remote view to the IME
      * process.
diff --git a/services/companion/java/com/android/server/companion/CompanionApplicationController.java b/services/companion/java/com/android/server/companion/CompanionApplicationController.java
index 3814591..5a9c470 100644
--- a/services/companion/java/com/android/server/companion/CompanionApplicationController.java
+++ b/services/companion/java/com/android/server/companion/CompanionApplicationController.java
@@ -346,31 +346,31 @@
         // Make sure do not schedule rebind for the case ServiceConnector still gets callback after
         // app is uninstalled.
         boolean stillAssociated = false;
+        // Make sure to clean up the state for all the associations
+        // that associate with this package.
+        boolean shouldScheduleRebind = false;
 
         for (AssociationInfo ai :
                 mAssociationStore.getAssociationsForPackage(userId, packageName)) {
             final int associationId = ai.getId();
             stillAssociated = true;
-
             if (ai.isSelfManaged()) {
                 // Do not rebind if primary one is died for selfManaged application.
                 if (isPrimary
                         && mDevicePresenceMonitor.isDevicePresent(associationId)) {
                     mDevicePresenceMonitor.onSelfManagedDeviceReporterBinderDied(associationId);
-                    return false;
+                    shouldScheduleRebind = false;
                 }
                 // Do not rebind if both primary and secondary services are died for
                 // selfManaged application.
-                if (!isCompanionApplicationBound(userId, packageName)) {
-                    return false;
-                }
+                shouldScheduleRebind = isCompanionApplicationBound(userId, packageName);
             } else if (ai.isNotifyOnDeviceNearby()) {
                 // Always rebind for non-selfManaged devices.
-                return true;
+                shouldScheduleRebind = true;
             }
         }
 
-        return stillAssociated;
+        return stillAssociated && shouldScheduleRebind;
     }
 
     private class CompanionServicesRegister extends PerUser<Map<String, List<ComponentName>>> {
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index a35cae9..542cc2f 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -59,6 +59,8 @@
 import android.companion.IAssociationRequestCallback;
 import android.companion.ICompanionDeviceManager;
 import android.companion.IOnAssociationsChangedListener;
+import android.companion.IOnMessageReceivedListener;
+import android.companion.IOnTransportsChangedListener;
 import android.companion.ISystemDataTransferCallback;
 import android.content.ComponentName;
 import android.content.Context;
@@ -232,7 +234,7 @@
                 /* cdmService */this, mAssociationStore);
         mCompanionAppController = new CompanionApplicationController(
                 context, mAssociationStore, mDevicePresenceMonitor);
-        mTransportManager = new CompanionTransportManager(context);
+        mTransportManager = new CompanionTransportManager(context, mAssociationStore);
         mSystemDataTransferProcessor = new SystemDataTransferProcessor(this, mAssociationStore,
                 mSystemDataTransferRequestStore, mTransportManager);
 
@@ -601,6 +603,37 @@
         }
 
         @Override
+        @GuardedBy("CompanionDeviceManagerService.this.mTransportManager.mTransports")
+        public void addOnTransportsChangedListener(IOnTransportsChangedListener listener) {
+            mTransportManager.addListener(listener);
+        }
+
+        @Override
+        @GuardedBy("CompanionDeviceManagerService.this.mTransportManager.mTransports")
+        public void removeOnTransportsChangedListener(IOnTransportsChangedListener listener) {
+            mTransportManager.removeListener(listener);
+        }
+
+        @Override
+        @GuardedBy("CompanionDeviceManagerService.this.mTransportManager.mTransports")
+        public void sendMessage(int messageType, byte[] data, int[] associationIds) {
+            mTransportManager.sendMessage(messageType, data, associationIds);
+        }
+
+        @Override
+        @GuardedBy("CompanionDeviceManagerService.this.mTransportManager.mTransports")
+        public void addOnMessageReceivedListener(int messageType,
+                IOnMessageReceivedListener listener) {
+            mTransportManager.addListener(messageType, listener);
+        }
+
+        @Override
+        public void removeOnMessageReceivedListener(int messageType,
+                IOnMessageReceivedListener listener) {
+            mTransportManager.removeListener(messageType, listener);
+        }
+
+        @Override
         public void legacyDisassociate(String deviceMacAddress, String packageName, int userId) {
             Log.i(TAG, "legacyDisassociate() pkg=u" + userId + "/" + packageName
                     + ", macAddress=" + deviceMacAddress);
diff --git a/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java b/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java
index 9f27f72..f3a949d 100644
--- a/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java
+++ b/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java
@@ -23,6 +23,7 @@
 import static android.content.ComponentName.createRelative;
 
 import static com.android.server.companion.Utils.prepareForIpc;
+import static com.android.server.companion.transport.Transport.MESSAGE_REQUEST_PERMISSION_RESTORE;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -30,6 +31,7 @@
 import android.app.PendingIntent;
 import android.companion.AssociationInfo;
 import android.companion.DeviceNotAssociatedException;
+import android.companion.IOnMessageReceivedListener;
 import android.companion.ISystemDataTransferCallback;
 import android.companion.datatransfer.PermissionSyncRequest;
 import android.companion.datatransfer.SystemDataTransferRequest;
@@ -39,6 +41,7 @@
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.UserHandle;
@@ -91,7 +94,18 @@
         mAssociationStore = associationStore;
         mSystemDataTransferRequestStore = systemDataTransferRequestStore;
         mTransportManager = transportManager;
-        mTransportManager.setListener(this::onReceivePermissionRestore);
+        IOnMessageReceivedListener messageListener = new IOnMessageReceivedListener() {
+            @Override
+            public void onMessageReceived(int associationId, byte[] data) throws RemoteException {
+                onReceivePermissionRestore(data);
+            }
+
+            @Override
+            public IBinder asBinder() {
+                return null;
+            }
+        };
+        mTransportManager.addListener(MESSAGE_REQUEST_PERMISSION_RESTORE, messageListener);
         mPermissionControllerManager = mContext.getSystemService(PermissionControllerManager.class);
         mExecutor = Executors.newSingleThreadExecutor();
     }
diff --git a/services/companion/java/com/android/server/companion/presence/CompanionDevicePresenceMonitor.java b/services/companion/java/com/android/server/companion/presence/CompanionDevicePresenceMonitor.java
index d7a77cd..4010be9 100644
--- a/services/companion/java/com/android/server/companion/presence/CompanionDevicePresenceMonitor.java
+++ b/services/companion/java/com/android/server/companion/presence/CompanionDevicePresenceMonitor.java
@@ -232,11 +232,14 @@
         }
 
         final boolean alreadyPresent = isDevicePresent(newDeviceAssociationId);
-        if (DEBUG && alreadyPresent) Log.i(TAG, "Device is already present.");
+        if (alreadyPresent) {
+            Log.i(TAG, "Device" + "id (" + newDeviceAssociationId + ") already present.");
+        }
 
         final boolean added = presentDevicesForSource.add(newDeviceAssociationId);
-        if (DEBUG && !added) {
-            Log.w(TAG, "Association with id " + newDeviceAssociationId + " is ALREADY reported as "
+        if (!added) {
+            Log.w(TAG, "Association with id "
+                    + newDeviceAssociationId + " is ALREADY reported as "
                     + "present by this source (" + sourceLoggingTag + ")");
         }
 
@@ -256,16 +259,17 @@
 
         final boolean removed = presentDevicesForSource.remove(goneDeviceAssociationId);
         if (!removed) {
-            if (DEBUG) {
-                Log.w(TAG, "Association with id " + goneDeviceAssociationId + " was NOT reported "
-                        + "as present by this source (" + sourceLoggingTag + ")");
-            }
+            Log.w(TAG, "Association with id " + goneDeviceAssociationId + " was NOT reported "
+                    + "as present by this source (" + sourceLoggingTag + ")");
+
             return;
         }
 
         final boolean stillPresent = isDevicePresent(goneDeviceAssociationId);
         if (stillPresent) {
-            if (DEBUG) Log.i(TAG, "  Device is still present.");
+            if (DEBUG) {
+                Log.i(TAG, "  Device id (" + goneDeviceAssociationId + ") is still present.");
+            }
             return;
         }
 
diff --git a/services/companion/java/com/android/server/companion/securechannel/AttestationVerifier.java b/services/companion/java/com/android/server/companion/securechannel/AttestationVerifier.java
index adaee75..1559a3f 100644
--- a/services/companion/java/com/android/server/companion/securechannel/AttestationVerifier.java
+++ b/services/companion/java/com/android/server/companion/securechannel/AttestationVerifier.java
@@ -35,7 +35,7 @@
 /**
  * Helper class to perform attestation verification synchronously.
  */
-class AttestationVerifier {
+public class AttestationVerifier {
     private static final long ATTESTATION_VERIFICATION_TIMEOUT_SECONDS = 10; // 10 seconds
     private static final String PARAM_OWNED_BY_SYSTEM = "android.key_owned_by_system";
 
diff --git a/services/companion/java/com/android/server/companion/securechannel/SecureChannel.java b/services/companion/java/com/android/server/companion/securechannel/SecureChannel.java
index 13dba84..05b6022 100644
--- a/services/companion/java/com/android/server/companion/securechannel/SecureChannel.java
+++ b/services/companion/java/com/android/server/companion/securechannel/SecureChannel.java
@@ -110,7 +110,7 @@
         this(in, out, callback, null, new AttestationVerifier(context));
     }
 
-    private SecureChannel(
+    public SecureChannel(
             final InputStream in,
             final OutputStream out,
             Callback callback,
@@ -381,9 +381,10 @@
 
     private void exchangeAuthentication()
             throws IOException, GeneralSecurityException, BadHandleException, CryptoException {
-        if (mVerifier == null) {
+        if (mPreSharedKey != null) {
             exchangePreSharedKey();
-        } else {
+        }
+        if (mVerifier != null) {
             exchangeAttestation();
         }
     }
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 6a53adf..5390205 100644
--- a/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java
+++ b/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java
@@ -19,23 +19,35 @@
 import static android.Manifest.permission.DELIVER_COMPANION_MESSAGES;
 
 import static com.android.server.companion.transport.Transport.MESSAGE_REQUEST_PERMISSION_RESTORE;
+import static com.android.server.companion.transport.Transport.MESSAGE_REQUEST_PLATFORM_INFO;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SuppressLint;
 import android.app.ActivityManagerInternal;
+import android.companion.AssociationInfo;
+import android.companion.IOnMessageReceivedListener;
+import android.companion.IOnTransportsChangedListener;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.Binder;
 import android.os.Build;
+import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.util.Slog;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.server.LocalServices;
+import com.android.server.companion.AssociationStore;
 
 import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.Future;
 
@@ -44,6 +56,9 @@
     private static final String TAG = "CDM_CompanionTransportManager";
     private static final boolean DEBUG = false;
 
+    private static final int SECURE_CHANNEL_AVAILABLE_SDK = Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
+    private static final int NON_ANDROID = -1;
+
     private boolean mSecureTransportEnabled = true;
 
     private static boolean isRequest(int message) {
@@ -54,24 +69,98 @@
         return (message & 0xFF000000) == 0x33000000;
     }
 
-    public interface Listener {
-        void onRequestPermissionRestore(byte[] data);
-    }
-
     private final Context mContext;
+    private final AssociationStore mAssociationStore;
 
+    /** Association id -> Transport */
     @GuardedBy("mTransports")
     private final SparseArray<Transport> mTransports = new SparseArray<>();
+    @NonNull
+    private final RemoteCallbackList<IOnTransportsChangedListener> mTransportsListeners =
+            new RemoteCallbackList<>();
+    /** Message type -> IOnMessageReceivedListener */
+    @NonNull
+    private final SparseArray<IOnMessageReceivedListener> mMessageListeners = new SparseArray<>();
+
 
     @Nullable
-    private Listener mListener;
+    private Transport mTempTransport;
 
-    public CompanionTransportManager(Context context) {
+    public CompanionTransportManager(Context context, AssociationStore associationStore) {
         mContext = context;
+        mAssociationStore = associationStore;
     }
 
-    public void setListener(@NonNull Listener listener) {
-        mListener = listener;
+    /**
+     * Add a listener to receive callbacks when a message is received for the message type
+     */
+    @GuardedBy("mTransports")
+    public void addListener(int message, @NonNull IOnMessageReceivedListener listener) {
+        mMessageListeners.put(message, listener);
+        for (int i = 0; i < mTransports.size(); i++) {
+            mTransports.valueAt(i).addListener(message, listener);
+        }
+    }
+
+    /**
+     * Add a listener to receive callbacks when any of the transports is changed
+     */
+    @GuardedBy("mTransports")
+    public void addListener(IOnTransportsChangedListener listener) {
+        Slog.i(TAG, "Registering OnTransportsChangedListener");
+        mTransportsListeners.register(listener);
+        List<AssociationInfo> associations = new ArrayList<>();
+        for (int i = 0; i < mTransports.size(); i++) {
+            AssociationInfo association = mAssociationStore.getAssociationById(
+                    mTransports.keyAt(i));
+            if (association != null) {
+                associations.add(association);
+            }
+        }
+        mTransportsListeners.broadcast(listener1 -> {
+            // callback to the current listener with all the associations of the transports
+            // immediately
+            if (listener1 == listener) {
+                try {
+                    listener.onTransportsChanged(associations);
+                } catch (RemoteException ignored) {
+                }
+            }
+        });
+    }
+
+    /**
+     * Remove the listener for receiving callbacks when any of the transports is changed
+     */
+    public void removeListener(IOnTransportsChangedListener listener) {
+        mTransportsListeners.unregister(listener);
+    }
+
+    /**
+     * Remove the listener to stop receiving calbacks when a message is received for the given type
+     */
+    public void removeListener(int messageType, IOnMessageReceivedListener listener) {
+        mMessageListeners.remove(messageType);
+    }
+
+    /**
+     * Send a message to remote devices through the transports
+     */
+    @GuardedBy("mTransports")
+    public void sendMessage(int message, byte[] data, int[] associationIds) {
+        Slog.i(TAG, "Sending message 0x" + Integer.toHexString(message)
+                + " data length " + data.length);
+        for (int i = 0; i < associationIds.length; i++) {
+            if (mTransports.contains(associationIds[i])) {
+                try {
+                    mTransports.get(associationIds[i]).sendMessage(message, data);
+                } catch (IOException e) {
+                    Slog.e(TAG, "Failed to send message 0x" + Integer.toHexString(message)
+                            + " data length " + data.length + " to association "
+                            + associationIds[i]);
+                }
+            }
+        }
     }
 
     /**
@@ -105,15 +194,9 @@
                 detachSystemDataTransport(packageName, userId, associationId);
             }
 
-            final Transport transport;
-            if (isSecureTransportEnabled(associationId)) {
-                transport = new SecureTransport(associationId, fd, mContext, mListener);
-            } else {
-                transport = new RawTransport(associationId, fd, mContext, mListener);
-            }
+            initializeTransport(associationId, fd);
 
-            transport.start();
-            mTransports.put(associationId, transport);
+            notifyOnTransportsChanged();
         }
     }
 
@@ -125,16 +208,124 @@
                 mTransports.delete(associationId);
                 transport.stop();
             }
+
+            notifyOnTransportsChanged();
         }
     }
 
+    @GuardedBy("mTransports")
+    private void notifyOnTransportsChanged() {
+        List<AssociationInfo> associations = new ArrayList<>();
+        for (int i = 0; i < mTransports.size(); i++) {
+            AssociationInfo association = mAssociationStore.getAssociationById(
+                    mTransports.keyAt(i));
+            if (association != null) {
+                associations.add(association);
+            }
+        }
+        mTransportsListeners.broadcast(listener -> {
+            try {
+                listener.onTransportsChanged(associations);
+            } catch (RemoteException ignored) {
+            }
+        });
+    }
+
+    @GuardedBy("mTransports")
+    private void initializeTransport(int associationId, ParcelFileDescriptor fd) {
+        Slog.i(TAG, "Initializing transport");
+        if (!isSecureTransportEnabled()) {
+            Transport transport = new RawTransport(associationId, fd, mContext);
+            addMessageListenersToTransport(transport);
+            transport.start();
+            mTransports.put(associationId, transport);
+            Slog.i(TAG, "RawTransport is created");
+            return;
+        }
+
+        // Exchange platform info to decide which transport should be created
+        mTempTransport = new RawTransport(associationId, fd, mContext);
+        addMessageListenersToTransport(mTempTransport);
+        IOnMessageReceivedListener listener = new IOnMessageReceivedListener() {
+            @Override
+            public void onMessageReceived(int associationId, byte[] data) throws RemoteException {
+                synchronized (mTransports) {
+                    onPlatformInfoReceived(associationId, data);
+                }
+            }
+
+            @Override
+            public IBinder asBinder() {
+                return null;
+            }
+        };
+        mTempTransport.addListener(MESSAGE_REQUEST_PLATFORM_INFO, listener);
+        mTempTransport.start();
+
+        int sdk = Build.VERSION.SDK_INT;
+        String release = Build.VERSION.RELEASE;
+        // data format: | SDK_INT (int) | release length (int) | release |
+        final ByteBuffer data = ByteBuffer.allocate(4 + 4 + release.getBytes().length)
+                .putInt(sdk)
+                .putInt(release.getBytes().length)
+                .put(release.getBytes());
+
+        // TODO: it should check if preSharedKey is given
+        try {
+            mTempTransport.sendMessage(MESSAGE_REQUEST_PLATFORM_INFO, data.array());
+        } catch (IOException e) {
+            Slog.e(TAG, "Failed to exchange platform info");
+        }
+    }
+
+    /**
+     * Depending on the remote platform info to decide which transport should be created
+     */
+    @GuardedBy("CompanionTransportManager.this.mTransports")
+    private void onPlatformInfoReceived(int associationId, byte[] data) {
+        if (mTempTransport.getAssociationId() != associationId) {
+            return;
+        }
+        // TODO: it should check if preSharedKey is given
+
+        ByteBuffer buffer = ByteBuffer.wrap(data);
+        int remoteSdk = buffer.getInt();
+        byte[] remoteRelease = new byte[buffer.getInt()];
+        buffer.get(remoteRelease);
+
+        Slog.i(TAG, "Remote device SDK: " + remoteSdk + ", release:" + new String(remoteRelease));
+
+        Transport transport = mTempTransport;
+        mTempTransport = null;
+
+        int sdk = Build.VERSION.SDK_INT;
+        String release = Build.VERSION.RELEASE;
+        if (remoteSdk == NON_ANDROID) {
+            // TODO: pass in a real preSharedKey
+            transport = new SecureTransport(transport.getAssociationId(), transport.getFd(),
+                    mContext, null, null);
+        } else if (sdk < SECURE_CHANNEL_AVAILABLE_SDK
+                || remoteSdk < SECURE_CHANNEL_AVAILABLE_SDK) {
+            // TODO: depending on the release version, either
+            //       1) using a RawTransport for old T versions
+            //       2) or an Ukey2 handshaked transport for UKey2 backported T versions
+        } else {
+            Slog.i(TAG, "Creating a secure channel");
+            transport = new SecureTransport(transport.getAssociationId(), transport.getFd(),
+                    mContext);
+            addMessageListenersToTransport(transport);
+            transport.start();
+        }
+        mTransports.put(transport.getAssociationId(), transport);
+        // Doesn't need to notifyTransportsChanged here, it'll be done in attachSystemDataTransport
+    }
+
     public Future<?> requestPermissionRestore(int associationId, byte[] data) {
         synchronized (mTransports) {
             final Transport transport = mTransports.get(associationId);
             if (transport == null) {
                 return CompletableFuture.failedFuture(new IOException("Missing transport"));
             }
-
             return transport.requestForResponse(MESSAGE_REQUEST_PERMISSION_RESTORE, data);
         }
     }
@@ -146,10 +337,15 @@
         this.mSecureTransportEnabled = enabled;
     }
 
-    private boolean isSecureTransportEnabled(int associationId) {
+    private boolean isSecureTransportEnabled() {
         boolean enabled = !Build.IS_DEBUGGABLE || mSecureTransportEnabled;
 
-        // TODO: version comparison logic
         return enabled;
     }
+
+    private void addMessageListenersToTransport(Transport transport) {
+        for (int i = 0; i < mMessageListeners.size(); i++) {
+            transport.addListener(mMessageListeners.keyAt(i), mMessageListeners.valueAt(i));
+        }
+    }
 }
diff --git a/services/companion/java/com/android/server/companion/transport/CryptoManager.java b/services/companion/java/com/android/server/companion/transport/CryptoManager.java
index b08354a..a15939e 100644
--- a/services/companion/java/com/android/server/companion/transport/CryptoManager.java
+++ b/services/companion/java/com/android/server/companion/transport/CryptoManager.java
@@ -16,51 +16,51 @@
 
 package com.android.server.companion.transport;
 
-import android.security.keystore.KeyGenParameterSpec;
-import android.security.keystore.KeyProperties;
 import android.util.Slog;
 
-import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
-import java.security.UnrecoverableEntryException;
-import java.security.cert.CertificateException;
+import java.util.Arrays;
 
 import javax.crypto.BadPaddingException;
 import javax.crypto.Cipher;
 import javax.crypto.IllegalBlockSizeException;
-import javax.crypto.KeyGenerator;
 import javax.crypto.NoSuchPaddingException;
 import javax.crypto.SecretKey;
 import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
 
 /**
- * This class can be used to encrypt and decrypt bytes using Android Cryptography
+ * This class uses Java Cryptography to encrypt and decrypt messages
  */
 public class CryptoManager {
 
     private static final String TAG = "CDM_CryptoManager";
+    private static final int SECRET_KEY_LENGTH = 32;
+    private static final String ALGORITHM = "AES";
+    private static final String TRANSFORMATION = "AES/CBC/PKCS7Padding";
 
-    private static final String KEY_STORE_ALIAS = "cdm_secret";
-    private static final String ALGORITHM = KeyProperties.KEY_ALGORITHM_AES;
-    private static final String BLOCK_MODE = KeyProperties.BLOCK_MODE_CBC;
-    private static final String PADDING = KeyProperties.ENCRYPTION_PADDING_PKCS7;
-    private static final String TRANSFORMATION = ALGORITHM + "/" + BLOCK_MODE + "/" + PADDING;
+    private final byte[] mPreSharedKey;
+    private Cipher mEncryptCipher;
+    private Cipher mDecryptCipher;
 
-    private final KeyStore mKeyStore;
+    private SecretKey mSecretKey;
 
-    public CryptoManager() {
-        // Initialize KeyStore
+    public CryptoManager(byte[] preSharedKey) {
+        if (preSharedKey == null) {
+            mPreSharedKey = Arrays.copyOf(new byte[0], SECRET_KEY_LENGTH);
+        } else {
+            mPreSharedKey = Arrays.copyOf(preSharedKey, SECRET_KEY_LENGTH);
+        }
+        mSecretKey = new SecretKeySpec(mPreSharedKey, ALGORITHM);
         try {
-            mKeyStore = KeyStore.getInstance("AndroidKeyStore");
-            mKeyStore.load(null);
-        } catch (KeyStoreException | IOException | NoSuchAlgorithmException
-                 | CertificateException e) {
-            throw new RuntimeException(e);
+            mEncryptCipher = Cipher.getInstance(TRANSFORMATION);
+            mEncryptCipher.init(Cipher.ENCRYPT_MODE, mSecretKey);
+            mDecryptCipher = Cipher.getInstance(TRANSFORMATION);
+        } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException e) {
+            Slog.e(TAG, e.getMessage());
         }
     }
 
@@ -69,21 +69,19 @@
      */
     public byte[] encrypt(byte[] input) {
         try {
-            // Encrypt using Cipher
-            Cipher encryptCipher = Cipher.getInstance(TRANSFORMATION);
-            encryptCipher.init(Cipher.ENCRYPT_MODE, getKey());
-            byte[] encryptedBytes = encryptCipher.doFinal(input);
+            if (mEncryptCipher == null) {
+                return null;
+            }
 
-            // Write to bytes
+            byte[] encryptedBytes = mEncryptCipher.doFinal(input);
             ByteBuffer buffer = ByteBuffer.allocate(
-                            4 + encryptCipher.getIV().length + 4 + encryptedBytes.length)
-                    .putInt(encryptCipher.getIV().length)
-                    .put(encryptCipher.getIV())
+                            4 + mEncryptCipher.getIV().length + 4 + encryptedBytes.length)
+                    .putInt(mEncryptCipher.getIV().length)
+                    .put(mEncryptCipher.getIV())
                     .putInt(encryptedBytes.length)
                     .put(encryptedBytes);
             return buffer.array();
-        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
-                 | IllegalBlockSizeException | BadPaddingException e) {
+        } catch (IllegalBlockSizeException | BadPaddingException e) {
             Slog.e(TAG, e.getMessage());
             return null;
         }
@@ -99,45 +97,20 @@
         byte[] encryptedBytes = new byte[buffer.getInt()];
         buffer.get(encryptedBytes);
         try {
-            Cipher decryptCipher = Cipher.getInstance(TRANSFORMATION);
-            decryptCipher.init(Cipher.DECRYPT_MODE, getKey(), new IvParameterSpec(iv));
-            return decryptCipher.doFinal(encryptedBytes);
-        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
-                 | InvalidAlgorithmParameterException | IllegalBlockSizeException
-                 | BadPaddingException e) {
+            mDecryptCipher.init(Cipher.DECRYPT_MODE, getKey(), new IvParameterSpec(iv));
+            return mDecryptCipher.doFinal(encryptedBytes);
+        } catch (InvalidKeyException | InvalidAlgorithmParameterException
+                 | IllegalBlockSizeException | BadPaddingException e) {
             Slog.e(TAG, e.getMessage());
             return null;
         }
     }
 
     private SecretKey getKey() {
-        try {
-            KeyStore.Entry keyEntry = mKeyStore.getEntry(KEY_STORE_ALIAS, null);
-            if (keyEntry instanceof KeyStore.SecretKeyEntry
-                    && ((KeyStore.SecretKeyEntry) keyEntry).getSecretKey() != null) {
-                return ((KeyStore.SecretKeyEntry) keyEntry).getSecretKey();
-            } else {
-                return createKey();
-            }
-        } catch (NoSuchAlgorithmException | UnrecoverableEntryException | KeyStoreException e) {
-            throw new RuntimeException(e);
+        if (mSecretKey != null) {
+            return mSecretKey;
         }
-    }
-
-    private SecretKey createKey() {
-        try {
-            KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM);
-            keyGenerator.init(
-                    new KeyGenParameterSpec.Builder(KEY_STORE_ALIAS,
-                            KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
-                            .setBlockModes(BLOCK_MODE)
-                            .setEncryptionPaddings(PADDING)
-                            .setUserAuthenticationRequired(false)
-                            .setRandomizedEncryptionRequired(true)
-                            .build());
-            return keyGenerator.generateKey();
-        } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {
-            throw new RuntimeException(e);
-        }
+        mSecretKey = new SecretKeySpec(mPreSharedKey, ALGORITHM);
+        return mSecretKey;
     }
 }
diff --git a/services/companion/java/com/android/server/companion/transport/RawTransport.java b/services/companion/java/com/android/server/companion/transport/RawTransport.java
index 7c0c7cf..4060f6e 100644
--- a/services/companion/java/com/android/server/companion/transport/RawTransport.java
+++ b/services/companion/java/com/android/server/companion/transport/RawTransport.java
@@ -21,8 +21,6 @@
 import android.os.ParcelFileDescriptor;
 import android.util.Slog;
 
-import com.android.server.companion.transport.CompanionTransportManager.Listener;
-
 import libcore.io.IoUtils;
 import libcore.io.Streams;
 
@@ -32,8 +30,8 @@
 class RawTransport extends Transport {
     private volatile boolean mStopped;
 
-    RawTransport(int associationId, ParcelFileDescriptor fd, Context context, Listener listener) {
-        super(associationId, fd, context, listener);
+    RawTransport(int associationId, ParcelFileDescriptor fd, Context context) {
+        super(associationId, fd, context);
     }
 
     @Override
@@ -64,7 +62,7 @@
     protected void sendMessage(int message, int sequence, @NonNull byte[] data)
             throws IOException {
         if (DEBUG) {
-            Slog.d(TAG, "Sending message 0x" + Integer.toHexString(message)
+            Slog.e(TAG, "Sending message 0x" + Integer.toHexString(message)
                     + " sequence " + sequence + " length " + data.length
                     + " to association " + mAssociationId);
         }
diff --git a/services/companion/java/com/android/server/companion/transport/SecureTransport.java b/services/companion/java/com/android/server/companion/transport/SecureTransport.java
index 4194130..cca0843 100644
--- a/services/companion/java/com/android/server/companion/transport/SecureTransport.java
+++ b/services/companion/java/com/android/server/companion/transport/SecureTransport.java
@@ -21,8 +21,8 @@
 import android.os.ParcelFileDescriptor;
 import android.util.Slog;
 
+import com.android.server.companion.securechannel.AttestationVerifier;
 import com.android.server.companion.securechannel.SecureChannel;
-import com.android.server.companion.transport.CompanionTransportManager.Listener;
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
@@ -37,14 +37,17 @@
 
     private final BlockingQueue<byte[]> mRequestQueue = new ArrayBlockingQueue<>(100);
 
-    SecureTransport(int associationId,
-            ParcelFileDescriptor fd,
-            Context context,
-            Listener listener) {
-        super(associationId, fd, context, listener);
+    SecureTransport(int associationId, ParcelFileDescriptor fd, Context context) {
+        super(associationId, fd, context);
         mSecureChannel = new SecureChannel(mRemoteIn, mRemoteOut, this, context);
     }
 
+    SecureTransport(int associationId, ParcelFileDescriptor fd, Context context,
+            byte[] preSharedKey, AttestationVerifier verifier) {
+        super(associationId, fd, context);
+        mSecureChannel = new SecureChannel(mRemoteIn, mRemoteOut, this, preSharedKey, verifier);
+    }
+
     @Override
     public void start() {
         mSecureChannel.start();
diff --git a/services/companion/java/com/android/server/companion/transport/Transport.java b/services/companion/java/com/android/server/companion/transport/Transport.java
index 923d424..d69ce89 100644
--- a/services/companion/java/com/android/server/companion/transport/Transport.java
+++ b/services/companion/java/com/android/server/companion/transport/Transport.java
@@ -17,31 +17,39 @@
 package com.android.server.companion.transport;
 
 import android.annotation.NonNull;
+import android.companion.IOnMessageReceivedListener;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.Build;
 import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
 import android.util.Slog;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.server.companion.transport.CompanionTransportManager.Listener;
 
 import libcore.util.EmptyArray;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.Future;
 import java.util.concurrent.atomic.AtomicInteger;
 
-abstract class Transport {
+/**
+ * This class represents the channel established between two devices.
+ */
+public abstract class Transport {
     protected static final String TAG = "CDM_CompanionTransport";
     protected static final boolean DEBUG = Build.IS_DEBUGGABLE;
 
     static final int MESSAGE_REQUEST_PING = 0x63807378; // ?PIN
-    static final int MESSAGE_REQUEST_PERMISSION_RESTORE = 0x63826983; // ?RES
+    public static final int MESSAGE_REQUEST_PLATFORM_INFO = 0x63807073; // ?PFI
+    public static final int MESSAGE_REQUEST_CONTEXT_SYNC = 0x63678883; // ?CXS
+    public static final int MESSAGE_REQUEST_PERMISSION_RESTORE = 0x63826983; // ?RES
 
     static final int MESSAGE_RESPONSE_SUCCESS = 0x33838567; // !SUC
     static final int MESSAGE_RESPONSE_FAILURE = 0x33706573; // !FAI
@@ -49,11 +57,19 @@
     protected static final int HEADER_LENGTH = 12;
 
     protected final int mAssociationId;
+    protected final ParcelFileDescriptor mFd;
     protected final InputStream mRemoteIn;
     protected final OutputStream mRemoteOut;
     protected final Context mContext;
 
-    private final Listener mListener;
+    /**
+     * Message type -> Listener
+     *
+     * For now, the transport only supports 1 listener for each message type. If there's a need in
+     * the future to allow multiple listeners to receive callbacks for the same message type, the
+     * value of the map can be a list.
+     */
+    private final Map<Integer, IOnMessageReceivedListener> mListeners;
 
     private static boolean isRequest(int message) {
         return (message & 0xFF000000) == 0x63000000;
@@ -68,16 +84,43 @@
             new SparseArray<>();
     protected final AtomicInteger mNextSequence = new AtomicInteger();
 
-    Transport(int associationId, ParcelFileDescriptor fd, Context context, Listener listener) {
-        this.mAssociationId = associationId;
-        this.mRemoteIn = new ParcelFileDescriptor.AutoCloseInputStream(fd);
-        this.mRemoteOut = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
-        this.mContext = context;
-        this.mListener = listener;
+    Transport(int associationId, ParcelFileDescriptor fd, Context context) {
+        mAssociationId = associationId;
+        mFd = fd;
+        mRemoteIn = new ParcelFileDescriptor.AutoCloseInputStream(fd);
+        mRemoteOut = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
+        mContext = context;
+        mListeners = new HashMap<>();
+    }
+
+    /**
+     * Add a listener when a message is received for the message type
+     * @param message Message type
+     * @param listener Execute when a message with the type is received
+     */
+    public void addListener(int message, IOnMessageReceivedListener listener) {
+        mListeners.put(message, listener);
+    }
+
+    public int getAssociationId() {
+        return mAssociationId;
+    }
+
+    protected ParcelFileDescriptor getFd() {
+        return mFd;
     }
 
     public abstract void start();
     public abstract void stop();
+    protected abstract void sendMessage(int message, int sequence, @NonNull byte[] data)
+            throws IOException;
+
+    /**
+     * Send a message
+     */
+    public void sendMessage(int message, @NonNull byte[] data) throws IOException {
+        sendMessage(message, mNextSequence.incrementAndGet(), data);
+    }
 
     public Future<byte[]> requestForResponse(int message, byte[] data) {
         if (DEBUG) Slog.d(TAG, "Requesting for response");
@@ -99,9 +142,6 @@
         return pending;
     }
 
-    protected abstract void sendMessage(int message, int sequence, @NonNull byte[] data)
-            throws IOException;
-
     protected final void handleMessage(int message, int sequence, @NonNull byte[] data)
             throws IOException {
         if (DEBUG) {
@@ -130,6 +170,12 @@
                 sendMessage(MESSAGE_RESPONSE_SUCCESS, sequence, data);
                 break;
             }
+            case MESSAGE_REQUEST_PLATFORM_INFO:
+            case MESSAGE_REQUEST_CONTEXT_SYNC: {
+                callback(message, data);
+                sendMessage(MESSAGE_RESPONSE_SUCCESS, sequence, EmptyArray.BYTE);
+                break;
+            }
             case MESSAGE_REQUEST_PERMISSION_RESTORE: {
                 if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)
                         && !Build.isDebuggable()) {
@@ -138,7 +184,7 @@
                     break;
                 }
                 try {
-                    mListener.onRequestPermissionRestore(data);
+                    callback(message, data);
                     sendMessage(MESSAGE_RESPONSE_SUCCESS, sequence, EmptyArray.BYTE);
                 } catch (Exception e) {
                     Slog.w(TAG, "Failed to restore permissions");
@@ -154,6 +200,18 @@
         }
     }
 
+    private void callback(int message, byte[] data) {
+        if (mListeners.containsKey(message)) {
+            try {
+                mListeners.get(message).onMessageReceived(getAssociationId(), data);
+                Slog.i(TAG, "Message 0x" + Integer.toHexString(message)
+                        + " is received from associationId " + mAssociationId
+                        + ", sending data length " + data.length + " to the listener.");
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
     private void processResponse(int message, int sequence, byte[] data) {
         final CompletableFuture<byte[]> future;
         synchronized (mPendingRequests) {
diff --git a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
index e52f1d9..34033e2 100644
--- a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
+++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
@@ -16,7 +16,6 @@
 
 package com.android.server.companion.virtual;
 
-import static android.companion.virtual.VirtualDeviceParams.RECENTS_POLICY_ALLOW_IN_HOST_DEVICE_RECENTS;
 import static android.content.pm.ActivityInfo.FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES;
 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
 import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
@@ -29,7 +28,6 @@
 import android.companion.virtual.VirtualDeviceManager.ActivityListener;
 import android.companion.virtual.VirtualDeviceParams;
 import android.companion.virtual.VirtualDeviceParams.ActivityPolicy;
-import android.companion.virtual.VirtualDeviceParams.RecentsPolicy;
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledSince;
 import android.content.ComponentName;
@@ -136,9 +134,9 @@
     private final ArraySet<RunningAppsChangedListener> mRunningAppsChangedListeners =
             new ArraySet<>();
     @Nullable private final SecureWindowCallback mSecureWindowCallback;
-    @Nullable private final List<String> mDisplayCategories;
-    @RecentsPolicy
-    private final int mDefaultRecentsPolicy;
+    @Nullable private final Set<String> mDisplayCategories;
+
+    private final boolean mShowTasksInHostDeviceRecents;
 
     /**
      * Creates a window policy controller that is generic to the different use cases of virtual
@@ -166,7 +164,7 @@
      *   virtual display.
      * @param intentListenerCallback Callback that is called to intercept intents when matching
      *   passed in filters.
-     * @param defaultRecentsPolicy a policy to indicate how to handle activities in recents.
+     * @param showTasksInHostDeviceRecents whether to show activities in recents on the host device.
      */
     public GenericWindowPolicyController(int windowFlags, int systemWindowFlags,
             @NonNull ArraySet<UserHandle> allowedUsers,
@@ -180,8 +178,8 @@
             @NonNull ActivityBlockedCallback activityBlockedCallback,
             @NonNull SecureWindowCallback secureWindowCallback,
             @NonNull IntentListenerCallback intentListenerCallback,
-            @NonNull List<String> displayCategories,
-            @RecentsPolicy int defaultRecentsPolicy) {
+            @NonNull Set<String> displayCategories,
+            boolean showTasksInHostDeviceRecents) {
         super();
         mAllowedUsers = allowedUsers;
         mAllowedCrossTaskNavigations = new ArraySet<>(allowedCrossTaskNavigations);
@@ -196,7 +194,7 @@
         mSecureWindowCallback = secureWindowCallback;
         mIntentListenerCallback = intentListenerCallback;
         mDisplayCategories = displayCategories;
-        mDefaultRecentsPolicy = defaultRecentsPolicy;
+        mShowTasksInHostDeviceRecents = showTasksInHostDeviceRecents;
     }
 
     /**
@@ -337,7 +335,7 @@
 
     @Override
     public boolean canShowTasksInHostDeviceRecents() {
-        return (mDefaultRecentsPolicy & RECENTS_POLICY_ALLOW_IN_HOST_DEVICE_RECENTS) != 0;
+        return mShowTasksInHostDeviceRecents;
     }
 
     @Override
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 21b51b1..bd67889 100644
--- a/services/companion/java/com/android/server/companion/virtual/InputController.java
+++ b/services/companion/java/com/android/server/companion/virtual/InputController.java
@@ -23,6 +23,7 @@
 import android.hardware.display.DisplayManagerInternal;
 import android.hardware.input.InputDeviceIdentifier;
 import android.hardware.input.InputManager;
+import android.hardware.input.InputManagerGlobal;
 import android.hardware.input.VirtualKeyEvent;
 import android.hardware.input.VirtualMouseButtonEvent;
 import android.hardware.input.VirtualMouseRelativeEvent;
@@ -88,7 +89,7 @@
      */
     private static final int DEVICE_NAME_MAX_LENGTH = 80;
 
-    final Object mLock;
+    final Object mLock = new Object();
 
     /* Token -> file descriptor associations. */
     @GuardedBy("mLock")
@@ -101,18 +102,17 @@
     private final WindowManager mWindowManager;
     private final DeviceCreationThreadVerifier mThreadVerifier;
 
-    InputController(@NonNull Object lock, @NonNull Handler handler,
+    InputController(@NonNull Handler handler,
             @NonNull WindowManager windowManager) {
-        this(lock, new NativeWrapper(), handler, windowManager,
+        this(new NativeWrapper(), handler, windowManager,
                 // Verify that virtual devices are not created on the handler thread.
                 () -> !handler.getLooper().isCurrentThread());
     }
 
     @VisibleForTesting
-    InputController(@NonNull Object lock, @NonNull NativeWrapper nativeWrapper,
+    InputController(@NonNull NativeWrapper nativeWrapper,
             @NonNull Handler handler, @NonNull WindowManager windowManager,
             @NonNull DeviceCreationThreadVerifier threadVerifier) {
-        mLock = lock;
         mHandler = handler;
         mNativeWrapper = nativeWrapper;
         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
@@ -687,7 +687,7 @@
             mListener = new InputManager.InputDeviceListener() {
                 @Override
                 public void onInputDeviceAdded(int deviceId) {
-                    final InputDevice device = InputManager.getInstance().getInputDevice(
+                    final InputDevice device = InputManagerGlobal.getInstance().getInputDevice(
                             deviceId);
                     Objects.requireNonNull(device, "Newly added input device was null.");
                     if (!device.getName().equals(deviceName)) {
diff --git a/services/companion/java/com/android/server/companion/virtual/SensorController.java b/services/companion/java/com/android/server/companion/virtual/SensorController.java
index 7804ebf..7df0d86 100644
--- a/services/companion/java/com/android/server/companion/virtual/SensorController.java
+++ b/services/companion/java/com/android/server/companion/virtual/SensorController.java
@@ -22,8 +22,11 @@
 import android.companion.virtual.sensor.VirtualSensor;
 import android.companion.virtual.sensor.VirtualSensorConfig;
 import android.companion.virtual.sensor.VirtualSensorEvent;
+import android.hardware.SensorDirectChannel;
 import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
+import android.os.SharedMemory;
 import android.util.ArrayMap;
 import android.util.Slog;
 
@@ -36,6 +39,7 @@
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Objects;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /** Controls virtual sensors, including their lifecycle and sensor event dispatch. */
 public class SensorController {
@@ -47,6 +51,8 @@
     private static final int UNKNOWN_ERROR = (-2147483647 - 1); // INT32_MIN value
     private static final int BAD_VALUE = -22;
 
+    private static AtomicInteger sNextDirectChannelHandle = new AtomicInteger(1);
+
     private final Object mLock;
     private final int mVirtualDeviceId;
     @GuardedBy("mLock")
@@ -57,8 +63,6 @@
     private final SensorManagerInternal mSensorManagerInternal;
     private final VirtualDeviceManagerInternal mVdmInternal;
 
-
-
     public SensorController(@NonNull Object lock, int virtualDeviceId,
             @Nullable IVirtualSensorCallback virtualSensorCallback) {
         mLock = lock;
@@ -95,9 +99,12 @@
 
     private int createSensorInternal(IBinder sensorToken, VirtualSensorConfig config)
             throws SensorCreationException {
+        if (config.getType() <= 0) {
+            throw new SensorCreationException("Received an invalid virtual sensor type.");
+        }
         final int handle = mSensorManagerInternal.createRuntimeSensor(mVirtualDeviceId,
                 config.getType(), config.getName(),
-                config.getVendor() == null ? "" : config.getVendor(),
+                config.getVendor() == null ? "" : config.getVendor(), config.getFlags(),
                 mRuntimeSensorCallback);
         if (handle <= 0) {
             throw new SensorCreationException("Received an invalid virtual sensor handle.");
@@ -212,6 +219,66 @@
             }
             return OK;
         }
+
+        @Override
+        public int onDirectChannelCreated(ParcelFileDescriptor fd) {
+            if (mCallback == null) {
+                Slog.e(TAG, "No sensor callback for virtual deviceId " + mVirtualDeviceId);
+                return BAD_VALUE;
+            } else if (fd == null) {
+                Slog.e(TAG, "Received invalid ParcelFileDescriptor");
+                return BAD_VALUE;
+            }
+            final int channelHandle = sNextDirectChannelHandle.getAndIncrement();
+            SharedMemory sharedMemory = SharedMemory.fromFileDescriptor(fd);
+            try {
+                mCallback.onDirectChannelCreated(channelHandle, sharedMemory);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to call sensor callback: " + e);
+                return UNKNOWN_ERROR;
+            }
+            return channelHandle;
+        }
+
+        @Override
+        public void onDirectChannelDestroyed(int channelHandle) {
+            if (mCallback == null) {
+                Slog.e(TAG, "No sensor callback for virtual deviceId " + mVirtualDeviceId);
+                return;
+            }
+            try {
+                mCallback.onDirectChannelDestroyed(channelHandle);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to call sensor callback: " + e);
+            }
+        }
+
+        @Override
+        public int onDirectChannelConfigured(int channelHandle, int sensorHandle,
+                @SensorDirectChannel.RateLevel int rateLevel) {
+            if (mCallback == null) {
+                Slog.e(TAG, "No runtime sensor callback configured.");
+                return BAD_VALUE;
+            }
+            VirtualSensor sensor = mVdmInternal.getVirtualSensor(mVirtualDeviceId, sensorHandle);
+            if (sensor == null) {
+                Slog.e(TAG, "No sensor found for deviceId=" + mVirtualDeviceId
+                        + " and sensor handle=" + sensorHandle);
+                return BAD_VALUE;
+            }
+            try {
+                mCallback.onDirectChannelConfigured(channelHandle, sensor, rateLevel, sensorHandle);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to call sensor callback: " + e);
+                return UNKNOWN_ERROR;
+            }
+            if (rateLevel == SensorDirectChannel.RATE_STOP) {
+                return OK;
+            } else {
+                // Use the sensor handle as a report token, i.e. a unique identifier of the sensor.
+                return sensorHandle;
+            }
+        }
     }
 
     @VisibleForTesting
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 f650560..b338d89 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -97,6 +97,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 import java.util.function.Consumer;
 
 
@@ -105,6 +106,14 @@
 
     private static final String TAG = "VirtualDeviceImpl";
 
+    private static final int DEFAULT_VIRTUAL_DISPLAY_FLAGS =
+            DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC
+                    | DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT
+                    | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY
+                    | DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL
+                    | DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH
+                    | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_FOCUS;
+
     /**
      * Timeout until {@link #launchPendingIntent} stops waiting for an activity to be launched.
      */
@@ -251,7 +260,6 @@
         mDisplayManager = displayManager;
         if (inputController == null) {
             mInputController = new InputController(
-                    mVirtualDeviceLock,
                     context.getMainThreadHandler(),
                     context.getSystemService(WindowManager.class));
         } else {
@@ -281,7 +289,7 @@
      * device.
      */
     int getBaseVirtualDisplayFlags() {
-        int flags = 0;
+        int flags = DEFAULT_VIRTUAL_DISPLAY_FLAGS;
         if (mParams.getLockState() == VirtualDeviceParams.LOCK_STATE_ALWAYS_UNLOCKED) {
             flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
         }
@@ -823,7 +831,7 @@
     }
 
     private GenericWindowPolicyController createWindowPolicyController(
-            @NonNull List<String> displayCategories) {
+            @NonNull Set<String> displayCategories) {
         final GenericWindowPolicyController gwpc =
                 new GenericWindowPolicyController(FLAG_SECURE,
                         SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
@@ -839,7 +847,9 @@
                         this::onSecureWindowShown,
                         this::shouldInterceptIntent,
                         displayCategories,
-                        mParams.getDefaultRecentsPolicy());
+                        mParams.getDevicePolicy(
+                                VirtualDeviceParams.POLICY_TYPE_RECENTS)
+                                == VirtualDeviceParams.DEVICE_POLICY_DEFAULT);
         gwpc.registerRunningAppsChangedListener(/* listener= */ this);
         return gwpc;
     }
diff --git a/services/core/java/android/os/BatteryStatsInternal.java b/services/core/java/android/os/BatteryStatsInternal.java
index 17ef9a2..c6f63dd 100644
--- a/services/core/java/android/os/BatteryStatsInternal.java
+++ b/services/core/java/android/os/BatteryStatsInternal.java
@@ -38,11 +38,13 @@
 
     public static final int CPU_WAKEUP_SUBSYSTEM_UNKNOWN = -1;
     public static final int CPU_WAKEUP_SUBSYSTEM_ALARM = 1;
+    public static final int CPU_WAKEUP_SUBSYSTEM_WIFI = 2;
 
     /** @hide */
     @IntDef(prefix = {"CPU_WAKEUP_SUBSYSTEM_"}, value = {
             CPU_WAKEUP_SUBSYSTEM_UNKNOWN,
             CPU_WAKEUP_SUBSYSTEM_ALARM,
+            CPU_WAKEUP_SUBSYSTEM_WIFI,
     })
     @Retention(RetentionPolicy.SOURCE)
     @interface CpuWakeupSubsystem {
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 10cd6ac..e9a7f20 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -192,20 +192,21 @@
     private ArrayDeque<Bundle> mBatteryLevelsEventQueue;
     private long mLastBatteryLevelChangedSentMs;
 
-    private Bundle mBatteryChangedOptions = BroadcastOptions.makeRemovingMatchingFilter(
-            new IntentFilter(Intent.ACTION_BATTERY_CHANGED)).setDeferUntilActive(true)
+    private Bundle mBatteryChangedOptions = BroadcastOptions.makeBasic()
+            .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
+            .setDeferUntilActive(true)
             .toBundle();
-    private Bundle mPowerConnectedOptions = BroadcastOptions.makeRemovingMatchingFilter(
-            new IntentFilter(Intent.ACTION_POWER_DISCONNECTED)).setDeferUntilActive(true)
+    /** Used for both connected/disconnected, so match using key */
+    private Bundle mPowerOptions = BroadcastOptions.makeBasic()
+            .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
+            .setDeliveryGroupMatchingKey("android", Intent.ACTION_POWER_CONNECTED)
+            .setDeferUntilActive(true)
             .toBundle();
-    private Bundle mPowerDisconnectedOptions = BroadcastOptions.makeRemovingMatchingFilter(
-            new IntentFilter(Intent.ACTION_POWER_CONNECTED)).setDeferUntilActive(true)
-            .toBundle();
-    private Bundle mBatteryLowOptions = BroadcastOptions.makeRemovingMatchingFilter(
-            new IntentFilter(Intent.ACTION_BATTERY_OKAY)).setDeferUntilActive(true)
-            .toBundle();
-    private Bundle mBatteryOkayOptions = BroadcastOptions.makeRemovingMatchingFilter(
-            new IntentFilter(Intent.ACTION_BATTERY_LOW)).setDeferUntilActive(true)
+    /** Used for both low/okay, so match using key */
+    private Bundle mBatteryOptions = BroadcastOptions.makeBasic()
+            .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
+            .setDeliveryGroupMatchingKey("android", Intent.ACTION_BATTERY_OKAY)
+            .setDeferUntilActive(true)
             .toBundle();
 
     private MetricsLogger mMetricsLogger;
@@ -636,7 +637,7 @@
                     @Override
                     public void run() {
                         mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL, null,
-                                mPowerConnectedOptions);
+                                mPowerOptions);
                     }
                 });
             }
@@ -648,7 +649,7 @@
                     @Override
                     public void run() {
                         mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL, null,
-                                mPowerDisconnectedOptions);
+                                mPowerOptions);
                     }
                 });
             }
@@ -662,7 +663,7 @@
                     @Override
                     public void run() {
                         mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL, null,
-                                mBatteryLowOptions);
+                                mBatteryOptions);
                     }
                 });
             } else if (mSentLowBatteryBroadcast &&
@@ -675,7 +676,7 @@
                     @Override
                     public void run() {
                         mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL, null,
-                                mBatteryOkayOptions);
+                                mBatteryOptions);
                     }
                 });
             }
diff --git a/services/core/java/com/android/server/BinaryTransparencyService.java b/services/core/java/com/android/server/BinaryTransparencyService.java
index 2992bf9..3ecf933 100644
--- a/services/core/java/com/android/server/BinaryTransparencyService.java
+++ b/services/core/java/com/android/server/BinaryTransparencyService.java
@@ -34,7 +34,6 @@
 import android.content.IntentFilter;
 import android.content.pm.ApexStagedEvent;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.Checksum;
 import android.content.pm.IBackgroundInstallControlService;
 import android.content.pm.IPackageManagerNative;
 import android.content.pm.IStagedApexObserver;
@@ -117,14 +116,17 @@
     @VisibleForTesting
     static final String BINARY_HASH_ERROR = "SHA256HashError";
 
-    static final int MEASURE_APEX_AND_MODULES = 1;
-    static final int MEASURE_PRELOADS = 2;
-    static final int MEASURE_NEW_MBAS = 3;
-
     static final long RECORD_MEASUREMENTS_COOLDOWN_MS = 24 * 60 * 60 * 1000;
 
     static final String APEX_PRELOAD_LOCATION_ERROR = "could-not-be-determined";
 
+    // Copy from the atom. Consistent for both ApexInfoGathered and MobileBundledAppInfoGathered.
+    static final int DIGEST_ALGORITHM_UNKNOWN = 0;
+    static final int DIGEST_ALGORITHM_CHUNKED_SHA256 = 1;
+    static final int DIGEST_ALGORITHM_CHUNKED_SHA512 = 2;
+    static final int DIGEST_ALGORITHM_VERITY_CHUNKED_SHA256 = 3;
+    static final int DIGEST_ALGORITHM_SHA256 = 4;
+
     // used for indicating any type of error during MBA measurement
     static final int MBA_STATUS_ERROR = 0;
     // used for indicating factory condition preloads
@@ -226,9 +228,9 @@
                 appInfo.mbaStatus = mbaStatus;
 
                 // Only digest and split name are different between splits.
-                Checksum checksum = measureApk(split.getPath());
-                appInfo.digest = checksum.getValue();
-                appInfo.digestAlgorithm = checksum.getType();
+                Digest digest = measureApk(split.getPath());
+                appInfo.digest = digest.value;
+                appInfo.digestAlgorithm = digest.algorithm;
 
                 results.add(appInfo);
             }
@@ -260,10 +262,9 @@
          * Perform basic measurement (i.e. content digest) on a given APK.
          *
          * @param apkPath The APK (or APEX, since it's also an APK) file to be measured.
-         * @return a {@link android.content.pm.Checksum} with preferred digest algorithm type and
-         *         the checksum.
+         * @return a {@link #Digest} with preferred digest algorithm type and the value.
          */
-        private @Nullable Checksum measureApk(@NonNull String apkPath) {
+        private @Nullable Digest measureApk(@NonNull String apkPath) {
             // compute content digest
             Map<Integer, byte[]> contentDigests = computeApkContentDigest(apkPath);
             if (contentDigests == null) {
@@ -274,20 +275,20 @@
                 // And only one of them will be available per package.
                 if (contentDigests.containsKey(
                             ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA256)) {
-                    return new Checksum(
-                            Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256,
+                    return new Digest(
+                            DIGEST_ALGORITHM_CHUNKED_SHA256,
                             contentDigests.get(ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA256));
                 } else if (contentDigests.containsKey(
                         ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA512)) {
-                    return new Checksum(
-                            Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512,
+                    return new Digest(
+                            DIGEST_ALGORITHM_CHUNKED_SHA512,
                             contentDigests.get(ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA512));
                 }
             }
             // When something went wrong, fall back to simple sha256.
             byte[] digest = PackageUtils.computeSha256DigestForLargeFileAsBytes(apkPath,
                     PackageUtils.createLargeFileBuffer());
-            return new Checksum(Checksum.TYPE_WHOLE_SHA256, digest);
+            return new Digest(DIGEST_ALGORITHM_SHA256, digest);
         }
 
 
@@ -350,7 +351,7 @@
                 // lastly measure all newly installed MBAs
                 List<IBinaryTransparencyService.AppInfo> allMbaInfo =
                         collectAllSilentInstalledMbaInfo(packagesMeasured);
-                for (IBinaryTransparencyService.AppInfo appInfo : allUpdatedPreloadInfo) {
+                for (IBinaryTransparencyService.AppInfo appInfo : allMbaInfo) {
                     packagesMeasured.putBoolean(appInfo.packageName, true);
                     writeAppInfoToLog(appInfo);
                 }
@@ -381,7 +382,7 @@
                     Slog.w(TAG, "Skipping the missing APK in " + pkg.getPath());
                     continue;
                 }
-                Checksum apexChecksum = measureApk(pkg.getPath());
+                Digest apexChecksum = measureApk(pkg.getPath());
                 if (apexChecksum == null) {
                     Slog.w(TAG, "Skipping the missing APEX in " + pkg.getPath());
                     continue;
@@ -390,8 +391,8 @@
                 var apexInfo = new IBinaryTransparencyService.ApexInfo();
                 apexInfo.packageName = packageState.getPackageName();
                 apexInfo.longVersion = packageState.getVersionCode();
-                apexInfo.digest = apexChecksum.getValue();
-                apexInfo.digestAlgorithm = apexChecksum.getType();
+                apexInfo.digest = apexChecksum.value;
+                apexInfo.digestAlgorithm = apexChecksum.algorithm;
                 apexInfo.signerDigests =
                         computePackageSignerSha256Digests(packageState.getSigningInfo());
 
@@ -1691,4 +1692,14 @@
         }
         return slice.getList();
     }
+
+    private static class Digest {
+        public int algorithm;
+        public byte[] value;
+
+        Digest(int algorithm, byte[] value) {
+            this.algorithm = algorithm;
+            this.value = value;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/DropBoxManagerService.java b/services/core/java/com/android/server/DropBoxManagerService.java
index 725ea5c..19e5cb1 100644
--- a/services/core/java/com/android/server/DropBoxManagerService.java
+++ b/services/core/java/com/android/server/DropBoxManagerService.java
@@ -79,6 +79,7 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 import java.util.SortedSet;
 import java.util.TreeSet;
 import java.util.zip.GZIPOutputStream;
@@ -105,6 +106,10 @@
     // Size beyond which to force-compress newly added entries.
     private static final long COMPRESS_THRESHOLD_BYTES = 16_384;
 
+    // Tags that we should drop by default.
+    private static final List<String> DISABLED_BY_DEFAULT_TAGS =
+            List.of("data_app_wtf", "system_app_wtf", "system_server_wtf");
+
     // TODO: This implementation currently uses one file per entry, which is
     // inefficient for smallish entries -- consider using a single queue file
     // per tag (or even globally) instead.
@@ -549,8 +554,13 @@
     public boolean isTagEnabled(String tag) {
         final long token = Binder.clearCallingIdentity();
         try {
-            return !"disabled".equals(Settings.Global.getString(
+            if (DISABLED_BY_DEFAULT_TAGS.contains(tag)) {
+                return "enabled".equals(Settings.Global.getString(
                     mContentResolver, Settings.Global.DROPBOX_TAG_PREFIX + tag));
+            } else {
+                return !"disabled".equals(Settings.Global.getString(
+                    mContentResolver, Settings.Global.DROPBOX_TAG_PREFIX + tag));
+            }
         } finally {
             Binder.restoreCallingIdentity(token);
         }
diff --git a/services/core/java/com/android/server/IntentResolver.java b/services/core/java/com/android/server/IntentResolver.java
index 3f1ad3a..2a46d86 100644
--- a/services/core/java/com/android/server/IntentResolver.java
+++ b/services/core/java/com/android/server/IntentResolver.java
@@ -16,18 +16,12 @@
 
 package com.android.server;
 
-import static android.content.IntentFilter.BLOCK_NULL_ACTION_INTENTS;
-
-import static com.android.internal.util.FrameworkStatsLog.UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__NULL_ACTION_MATCH;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.net.Uri;
-import android.os.Binder;
-import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.FastImmutableArraySet;
@@ -40,7 +34,6 @@
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.util.FastPrintWriter;
-import com.android.server.am.ActivityManagerUtils;
 import com.android.server.pm.Computer;
 import com.android.server.pm.snapshot.PackageDataSnapshot;
 
@@ -88,7 +81,7 @@
      * Returns whether an intent matches the IntentFilter with a pre-resolved type.
      */
     public static boolean intentMatchesFilter(
-            IntentFilter filter, Intent intent, String resolvedType, boolean blockNullAction) {
+            IntentFilter filter, Intent intent, String resolvedType) {
         final boolean debug = localLOGV
                 || ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
 
@@ -102,8 +95,7 @@
         }
 
         final int match = filter.match(intent.getAction(), resolvedType, intent.getScheme(),
-                intent.getData(), intent.getCategories(), TAG, /* supportWildcards */ false,
-                blockNullAction, null, null);
+                intent.getData(), intent.getCategories(), TAG);
 
         if (match >= 0) {
             if (debug) {
@@ -358,32 +350,14 @@
         return Collections.unmodifiableSet(mFilters);
     }
 
-    private boolean blockNullAction(Computer computer, Intent intent,
-            String resolvedType, int callingUid, boolean debug) {
-        if (intent.getAction() == null) {
-            final boolean blockNullAction = UserHandle.isCore(callingUid)
-                    || computer.isChangeEnabled(BLOCK_NULL_ACTION_INTENTS, callingUid);
-            ActivityManagerUtils.logUnsafeIntentEvent(
-                    UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__NULL_ACTION_MATCH,
-                    callingUid, intent, resolvedType, blockNullAction);
-            if (blockNullAction) {
-                if (debug) Slog.v(TAG, "Skip matching filters: action is null");
-                return true;
-            }
-        }
-        return false;
-    }
-
     public List<R> queryIntentFromList(@NonNull Computer computer, Intent intent,
-            String resolvedType, boolean defaultOnly, ArrayList<F[]> listCut,
-            int callingUid, @UserIdInt int userId, long customFlags) {
+            String resolvedType, boolean defaultOnly, ArrayList<F[]> listCut, int userId,
+            long customFlags) {
         ArrayList<R> resultList = new ArrayList<R>();
 
         final boolean debug = localLOGV ||
                 ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
 
-        if (blockNullAction(computer, intent, resolvedType, callingUid, debug)) return resultList;
-
         FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
         final String scheme = intent.getScheme();
         int N = listCut.size();
@@ -391,26 +365,18 @@
             buildResolveList(computer, intent, categories, debug, defaultOnly, resolvedType, scheme,
                     listCut.get(i), resultList, userId, customFlags);
         }
-        filterResults(computer, intent, resultList);
+        filterResults(resultList);
         sortResults(resultList);
         return resultList;
     }
 
-    public final List<R> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
-            String resolvedType, boolean defaultOnly, @UserIdInt int userId) {
-        return queryIntent(snapshot, intent, resolvedType, defaultOnly,
-                Binder.getCallingUid(), userId, 0);
-    }
-
     public List<R> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
-            String resolvedType, boolean defaultOnly, int callingUid, @UserIdInt int userId) {
-        return queryIntent(snapshot, intent, resolvedType, defaultOnly, callingUid, userId, 0);
+            String resolvedType, boolean defaultOnly, @UserIdInt int userId) {
+        return queryIntent(snapshot, intent, resolvedType, defaultOnly, userId, 0);
     }
 
     protected final List<R> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
-            String resolvedType, boolean defaultOnly, int callingUid, @UserIdInt int userId,
-            long customFlags) {
-        final Computer computer = (Computer) snapshot;
+            String resolvedType, boolean defaultOnly, @UserIdInt int userId, long customFlags) {
         String scheme = intent.getScheme();
 
         ArrayList<R> finalList = new ArrayList<R>();
@@ -422,8 +388,6 @@
             TAG, "Resolving type=" + resolvedType + " scheme=" + scheme
             + " defaultOnly=" + defaultOnly + " userId=" + userId + " of " + intent);
 
-        if (blockNullAction(computer, intent, resolvedType, callingUid, debug)) return finalList;
-
         F[] firstTypeCut = null;
         F[] secondTypeCut = null;
         F[] thirdTypeCut = null;
@@ -484,6 +448,7 @@
         }
 
         FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
+        Computer computer = (Computer) snapshot;
         if (firstTypeCut != null) {
             buildResolveList(computer, intent, categories, debug, defaultOnly, resolvedType,
                     scheme, firstTypeCut, finalList, userId, customFlags);
@@ -500,7 +465,7 @@
             buildResolveList(computer, intent, categories, debug, defaultOnly, resolvedType,
                     scheme, schemeCut, finalList, userId, customFlags);
         }
-        filterResults(computer, intent, finalList);
+        filterResults(finalList);
         sortResults(finalList);
 
         if (debug) {
@@ -569,8 +534,7 @@
     /**
      * Apply filtering to the results. This happens before the results are sorted.
      */
-    protected void filterResults(@NonNull Computer computer, @NonNull Intent intent,
-            List<R> results) {
+    protected void filterResults(List<R> results) {
     }
 
     protected void dumpFilter(PrintWriter out, String prefix, F filter) {
@@ -802,11 +766,7 @@
                 continue;
             }
 
-            match = intentFilter.match(action, resolvedType, scheme, data, categories, TAG,
-                    false /*supportWildcards*/,
-                    false /*blockNullAction: already handled*/,
-                    null /*ignoreActions*/,
-                    null /*extras*/);
+            match = intentFilter.match(action, resolvedType, scheme, data, categories, TAG);
             if (match >= 0) {
                 if (debug) Slog.v(TAG, "  Filter matched!  match=0x" +
                         Integer.toHexString(match) + " hasDefault="
diff --git a/services/core/java/com/android/server/LogMteState.java b/services/core/java/com/android/server/LogMteState.java
new file mode 100644
index 0000000..410dd83
--- /dev/null
+++ b/services/core/java/com/android/server/LogMteState.java
@@ -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.server;
+
+import android.app.StatsManager;
+import android.content.Context;
+import android.util.StatsEvent;
+
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.os.Zygote;
+import com.android.internal.util.FrameworkStatsLog;
+
+import java.util.List;
+
+public class LogMteState {
+    public static void register(Context context) {
+        context.getSystemService(StatsManager.class)
+                .setPullAtomCallback(
+                        FrameworkStatsLog.MTE_STATE,
+                        null, // use default PullAtomMetadata values
+                        BackgroundThread.getExecutor(),
+                        new StatsManager.StatsPullAtomCallback() {
+                            @Override
+                            public int onPullAtom(int atomTag, List<StatsEvent> data) {
+                                if (atomTag != FrameworkStatsLog.MTE_STATE) {
+                                    throw new UnsupportedOperationException(
+                                            "Unknown tagId=" + atomTag);
+                                }
+                                data.add(
+                                        FrameworkStatsLog.buildStatsEvent(
+                                                FrameworkStatsLog.MTE_STATE,
+                                                Zygote.nativeSupportsMemoryTagging()
+                                                        ? FrameworkStatsLog.MTE_STATE__STATE__ON
+                                                        : FrameworkStatsLog.MTE_STATE__STATE__OFF));
+                                return StatsManager.PULL_SUCCESS;
+                            }
+                        });
+    }
+}
diff --git a/services/core/java/com/android/server/TEST_MAPPING b/services/core/java/com/android/server/TEST_MAPPING
index c5b0f05..c3dda71 100644
--- a/services/core/java/com/android/server/TEST_MAPPING
+++ b/services/core/java/com/android/server/TEST_MAPPING
@@ -23,6 +23,18 @@
             "file_patterns": ["NotificationManagerService\\.java"]
         },
         {
+            "name": "CtsScopedStorageCoreHostTest",
+            "file_patterns": ["StorageManagerService\\.java"]
+        },
+        {
+            "name": "CtsScopedStorageHostTest",
+            "file_patterns": ["StorageManagerService\\.java"]
+        },
+        {
+            "name": "CtsScopedStorageDeviceOnlyTest",
+            "file_patterns": ["StorageManagerService\\.java"]
+        },
+        {
             "name": "FrameworksMockingServicesTests",
             "options": [
                 {
@@ -63,18 +75,6 @@
     ],
     "presubmit-large": [
         {
-            "name": "CtsScopedStorageCoreHostTest",
-            "file_patterns": ["StorageManagerService\\.java"]
-        },
-        {
-            "name": "CtsScopedStorageHostTest",
-            "file_patterns": ["StorageManagerService\\.java"]
-        },
-        {
-            "name": "CtsScopedStorageDeviceOnlyTest",
-            "file_patterns": ["StorageManagerService\\.java"]
-        },
-        {
             "name": "CtsContentTestCases",
             "options": [
                 {
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index aaa376a..e76b628 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -28,6 +28,7 @@
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
+import android.app.BroadcastOptions;
 import android.app.compat.CompatChanges;
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledSince;
@@ -1672,57 +1673,62 @@
             return;
         }
 
-        synchronized (mRecords) {
-            String str = "notifyServiceStateForSubscriber: subId=" + subId + " phoneId=" + phoneId
-                    + " state=" + state;
-            if (VDBG) {
-                log(str);
-            }
-            mLocalLog.log(str);
-            // for service state updates, don't notify clients when subId is invalid. This prevents
-            // us from sending incorrect notifications like b/133140128
-            // In the future, we can remove this logic for every notification here and add a
-            // callback so listeners know when their PhoneStateListener's subId becomes invalid, but
-            // for now we use the simplest fix.
-            if (validatePhoneId(phoneId) && SubscriptionManager.isValidSubscriptionId(subId)) {
-                mServiceState[phoneId] = state;
+        final long callingIdentity = Binder.clearCallingIdentity();
+        try {
+            synchronized (mRecords) {
+                String str = "notifyServiceStateForSubscriber: subId=" + subId + " phoneId="
+                        + phoneId + " state=" + state;
+                if (VDBG) {
+                    log(str);
+                }
+                mLocalLog.log(str);
+                // for service state updates, don't notify clients when subId is invalid. This
+                // prevents us from sending incorrect notifications like b/133140128
+                // In the future, we can remove this logic for every notification here and add a
+                // callback so listeners know when their PhoneStateListener's subId becomes invalid,
+                // but for now we use the simplest fix.
+                if (validatePhoneId(phoneId) && SubscriptionManager.isValidSubscriptionId(subId)) {
+                    mServiceState[phoneId] = state;
 
-                for (Record r : mRecords) {
-                    if (VDBG) {
-                        log("notifyServiceStateForSubscriber: r=" + r + " subId=" + subId
-                                + " phoneId=" + phoneId + " state=" + state);
-                    }
-                    if (r.matchTelephonyCallbackEvent(
-                            TelephonyCallback.EVENT_SERVICE_STATE_CHANGED)
-                            && idMatch(r, subId, phoneId)) {
+                    for (Record r : mRecords) {
+                        if (VDBG) {
+                            log("notifyServiceStateForSubscriber: r=" + r + " subId=" + subId
+                                    + " phoneId=" + phoneId + " state=" + state);
+                        }
+                        if (r.matchTelephonyCallbackEvent(
+                                TelephonyCallback.EVENT_SERVICE_STATE_CHANGED)
+                                && idMatch(r, subId, phoneId)) {
 
-                        try {
-                            ServiceState stateToSend;
-                            if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
-                                stateToSend = new ServiceState(state);
-                            } else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
-                                stateToSend = state.createLocationInfoSanitizedCopy(false);
-                            } else {
-                                stateToSend = state.createLocationInfoSanitizedCopy(true);
+                            try {
+                                ServiceState stateToSend;
+                                if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+                                    stateToSend = new ServiceState(state);
+                                } else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
+                                    stateToSend = state.createLocationInfoSanitizedCopy(false);
+                                } else {
+                                    stateToSend = state.createLocationInfoSanitizedCopy(true);
+                                }
+                                if (DBG) {
+                                    log("notifyServiceStateForSubscriber: callback.onSSC r=" + r
+                                            + " subId=" + subId + " phoneId=" + phoneId
+                                            + " state=" + stateToSend);
+                                }
+                                r.callback.onServiceStateChanged(stateToSend);
+                            } catch (RemoteException ex) {
+                                mRemoveList.add(r.binder);
                             }
-                            if (DBG) {
-                                log("notifyServiceStateForSubscriber: callback.onSSC r=" + r
-                                        + " subId=" + subId + " phoneId=" + phoneId
-                                        + " state=" + stateToSend);
-                            }
-                            r.callback.onServiceStateChanged(stateToSend);
-                        } catch (RemoteException ex) {
-                            mRemoveList.add(r.binder);
                         }
                     }
+                } else {
+                    log("notifyServiceStateForSubscriber: INVALID phoneId=" + phoneId
+                            + " or subId=" + subId);
                 }
-            } else {
-                log("notifyServiceStateForSubscriber: INVALID phoneId=" + phoneId
-                        + " or subId=" + subId);
+                handleRemoveListLocked();
             }
-            handleRemoveListLocked();
+            broadcastServiceStateChanged(state, phoneId, subId);
+        } finally {
+            Binder.restoreCallingIdentity(callingIdentity);
         }
-        broadcastServiceStateChanged(state, phoneId, subId);
     }
 
     public void notifySimActivationStateChangedForPhoneId(int phoneId, int subId,
@@ -3508,13 +3514,10 @@
     public static final String ACTION_SIGNAL_STRENGTH_CHANGED = "android.intent.action.SIG_STR";
 
     private void broadcastServiceStateChanged(ServiceState state, int phoneId, int subId) {
-        final long ident = Binder.clearCallingIdentity();
         try {
             mBatteryStats.notePhoneState(state.getState());
         } catch (RemoteException re) {
             // Can't do much
-        } finally {
-            Binder.restoreCallingIdentity(ident);
         }
 
         // Send the broadcast exactly once to all possible disjoint sets of apps.
@@ -3531,29 +3534,36 @@
         // - Sanitized ServiceState sent to all other apps with READ_PHONE_STATE
         // - Sanitized ServiceState sent to all other apps with READ_PRIVILEGED_PHONE_STATE but not
         //   READ_PHONE_STATE
-        if (Binder.withCleanCallingIdentity(() ->
-                LocationAccessPolicy.isLocationModeEnabled(mContext, mContext.getUserId()))) {
+        BroadcastOptions options = createServiceStateBroadcastOptions(subId, phoneId);
+        if (LocationAccessPolicy.isLocationModeEnabled(mContext, mContext.getUserId())) {
             Intent fullIntent = createServiceStateIntent(state, subId, phoneId, false);
             mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(
                     fullIntent,
                     new String[]{Manifest.permission.READ_PHONE_STATE,
-                            Manifest.permission.ACCESS_FINE_LOCATION});
+                            Manifest.permission.ACCESS_FINE_LOCATION},
+                    options);
             mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(
                     fullIntent,
                     new String[]{Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
                             Manifest.permission.ACCESS_FINE_LOCATION},
-                    new String[]{Manifest.permission.READ_PHONE_STATE});
+                    new String[]{Manifest.permission.READ_PHONE_STATE},
+                    null,
+                    options);
 
             Intent sanitizedIntent = createServiceStateIntent(state, subId, phoneId, true);
             mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(
                     sanitizedIntent,
                     new String[]{Manifest.permission.READ_PHONE_STATE},
-                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION});
+                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
+                    null,
+                    options);
             mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(
                     sanitizedIntent,
                     new String[]{Manifest.permission.READ_PRIVILEGED_PHONE_STATE},
                     new String[]{Manifest.permission.READ_PHONE_STATE,
-                            Manifest.permission.ACCESS_FINE_LOCATION});
+                            Manifest.permission.ACCESS_FINE_LOCATION},
+                    null,
+                    options);
         } else {
             String[] locationBypassPackages = Binder.withCleanCallingIdentity(() ->
                     LocationAccessPolicy.getLocationBypassPackages(mContext));
@@ -3562,11 +3572,14 @@
                 fullIntent.setPackage(locationBypassPackage);
                 mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(
                         fullIntent,
-                        new String[]{Manifest.permission.READ_PHONE_STATE});
+                        new String[]{Manifest.permission.READ_PHONE_STATE},
+                        options);
                 mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(
                         fullIntent,
                         new String[]{Manifest.permission.READ_PRIVILEGED_PHONE_STATE},
-                        new String[]{Manifest.permission.READ_PHONE_STATE});
+                        new String[]{Manifest.permission.READ_PHONE_STATE},
+                        null,
+                        options);
             }
 
             Intent sanitizedIntent = createServiceStateIntent(state, subId, phoneId, true);
@@ -3574,12 +3587,14 @@
                     sanitizedIntent,
                     new String[]{Manifest.permission.READ_PHONE_STATE},
                     new String[]{/* no excluded permissions */},
-                    locationBypassPackages);
+                    locationBypassPackages,
+                    options);
             mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(
                     sanitizedIntent,
                     new String[]{Manifest.permission.READ_PRIVILEGED_PHONE_STATE},
                     new String[]{Manifest.permission.READ_PHONE_STATE},
-                    locationBypassPackages);
+                    locationBypassPackages,
+                    options);
         }
     }
 
@@ -3601,6 +3616,15 @@
         return intent;
     }
 
+    private BroadcastOptions createServiceStateBroadcastOptions(int subId, int phoneId) {
+        return new BroadcastOptions()
+                .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
+                // Use a combination of subId and phoneId as the key so that older broadcasts
+                // with same subId and phoneId will get discarded.
+                .setDeliveryGroupMatchingKey(Intent.ACTION_SERVICE_STATE, subId + "-" + phoneId)
+                .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE);
+    }
+
     private void broadcastSignalStrengthChanged(SignalStrength signalStrength, int phoneId,
             int subId) {
         final long ident = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 5d46de3..7c32627 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import static android.app.UiModeManager.ContrastUtils.CONTRAST_DEFAULT_VALUE;
 import static android.app.UiModeManager.DEFAULT_PRIORITY;
 import static android.app.UiModeManager.MODE_NIGHT_AUTO;
 import static android.app.UiModeManager.MODE_NIGHT_CUSTOM;
@@ -27,8 +28,11 @@
 import static android.app.UiModeManager.PROJECTION_TYPE_AUTOMOTIVE;
 import static android.app.UiModeManager.PROJECTION_TYPE_NONE;
 import static android.os.UserHandle.USER_SYSTEM;
+import static android.provider.Settings.Secure.CONTRAST_LEVEL;
 import static android.util.TimeUtils.isTimeBetween;
 
+import static com.android.internal.util.FunctionalUtils.ignoreRemoteException;
+
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -38,6 +42,7 @@
 import android.app.AlarmManager;
 import android.app.IOnProjectionStateChangedListener;
 import android.app.IUiModeManager;
+import android.app.IUiModeManagerCallback;
 import android.app.KeyguardManager;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -71,6 +76,7 @@
 import android.os.ShellCommand;
 import android.os.SystemProperties;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.provider.Settings.Secure;
 import android.service.dreams.Sandman;
 import android.service.vr.IVrManager;
@@ -193,12 +199,19 @@
     private PowerManagerInternal mLocalPowerManager;
 
     @GuardedBy("mLock")
+    private final RemoteCallbackList<IUiModeManagerCallback> mUiModeManagerCallbacks =
+            new RemoteCallbackList<IUiModeManagerCallback>();
+
+    @GuardedBy("mLock")
     @Nullable
     private SparseArray<List<ProjectionHolder>> mProjectionHolders;
     @GuardedBy("mLock")
     @Nullable
     private SparseArray<RemoteCallbackList<IOnProjectionStateChangedListener>> mProjectionListeners;
 
+    @GuardedBy("mLock")
+    private final SparseArray<Float> mContrasts = new SparseArray<>();
+
     public UiModeManagerService(Context context) {
         this(context, /* setupWizardComplete= */ false, /* tm= */ null, new Injector());
     }
@@ -352,6 +365,19 @@
         }
     };
 
+    private final ContentObserver mContrastObserver = new ContentObserver(mHandler) {
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            synchronized (mLock) {
+                if (updateContrastLocked()) {
+                    float contrast = getContrastLocked();
+                    mUiModeManagerCallbacks.broadcast(ignoreRemoteException(callback ->
+                            callback.notifyContrastChanged(contrast)));
+                }
+            }
+        }
+    };
+
     private void updateSystemProperties() {
         int mode = Secure.getIntForUser(getContext().getContentResolver(), Secure.UI_NIGHT_MODE,
                 mNightMode, 0);
@@ -407,6 +433,9 @@
                 context.getContentResolver()
                         .registerContentObserver(Secure.getUriFor(Secure.UI_NIGHT_MODE),
                                 false, mDarkThemeObserver, 0);
+                context.getContentResolver().registerContentObserver(
+                        Secure.getUriFor(Secure.CONTRAST_LEVEL), false,
+                        mContrastObserver, UserHandle.USER_ALL);
                 context.registerReceiver(mDockModeReceiver,
                         new IntentFilter(Intent.ACTION_DOCK_EVENT));
                 IntentFilter batteryFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
@@ -634,6 +663,13 @@
 
     private final IUiModeManager.Stub mService = new IUiModeManager.Stub() {
         @Override
+        public void addCallback(IUiModeManagerCallback callback) {
+            synchronized (mLock) {
+                mUiModeManagerCallbacks.register(callback);
+            }
+        }
+
+        @Override
         public void enableCarMode(@UiModeManager.EnableCarMode int flags,
                 @IntRange(from = 0) int priority, String callingPackage) {
             if (isUiModeLocked()) {
@@ -1132,6 +1168,13 @@
                 }
             }
         }
+
+        @Override
+        public float getContrast() {
+            synchronized (mLock) {
+                return getContrastLocked();
+            }
+        }
     };
 
     private void enforceProjectionTypePermissions(@UiModeManager.ProjectionType int p) {
@@ -1214,6 +1257,30 @@
         }
     }
 
+    /**
+     * Return the contrast for the current user. If not cached, fetch it from the settings.
+     */
+    @GuardedBy("mLock")
+    private float getContrastLocked() {
+        if (!mContrasts.contains(mCurrentUser)) updateContrastLocked();
+        return mContrasts.get(mCurrentUser);
+    }
+
+    /**
+     * Read the contrast setting for the current user and update {@link #mContrasts}
+     * if the contrast changed. Returns true if {@link #mContrasts} was updated.
+     */
+    @GuardedBy("mLock")
+    private boolean updateContrastLocked() {
+        float contrast = Settings.Secure.getFloatForUser(getContext().getContentResolver(),
+                CONTRAST_LEVEL, CONTRAST_DEFAULT_VALUE, mCurrentUser);
+        if (Math.abs(mContrasts.get(mCurrentUser, Float.MAX_VALUE) - contrast) >= 1e-10) {
+            mContrasts.put(mCurrentUser, contrast);
+            return true;
+        }
+        return false;
+    }
+
     private static class ProjectionHolder implements IBinder.DeathRecipient {
         private final String mPackageName;
         private final @UiModeManager.ProjectionType int mProjectionType;
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index c16314b..225afea 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -38,6 +38,7 @@
 import android.app.ActivityManager;
 import android.app.ActivityThread;
 import android.app.AppOpsManager;
+import android.app.BroadcastOptions;
 import android.app.INotificationManager;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -195,6 +196,9 @@
     private final IAccountAuthenticatorCache mAuthenticatorCache;
     private static final String PRE_N_DATABASE_NAME = "accounts.db";
     private static final Intent ACCOUNTS_CHANGED_INTENT;
+    private static final Bundle ACCOUNTS_CHANGED_OPTIONS = new BroadcastOptions()
+            .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
+            .toBundle();
 
     private static final int SIGNATURE_CHECK_MISMATCH = 0;
     private static final int SIGNATURE_CHECK_MATCH = 1;
@@ -1075,7 +1079,8 @@
         Log.i(TAG, "the accountType= " + (accountType == null ? "" : accountType)
                 + " changed with useCase=" + useCase + " for userId=" + userId
                 + ", sending broadcast of " + ACCOUNTS_CHANGED_INTENT.getAction());
-        mContext.sendBroadcastAsUser(ACCOUNTS_CHANGED_INTENT, new UserHandle(userId));
+        mContext.sendBroadcastAsUser(ACCOUNTS_CHANGED_INTENT, new UserHandle(userId),
+                null /* receiverPermission */, ACCOUNTS_CHANGED_OPTIONS);
     }
 
     private void sendAccountRemovedBroadcast(
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 70304c5..9bde039 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -137,6 +137,7 @@
 import android.app.RemoteServiceException.ForegroundServiceDidNotStartInTimeException;
 import android.app.Service;
 import android.app.ServiceStartArgs;
+import android.app.StartForegroundCalledOnStoppedServiceException;
 import android.app.admin.DevicePolicyEventLogger;
 import android.app.compat.CompatChanges;
 import android.app.usage.UsageEvents;
@@ -336,6 +337,13 @@
     final ArrayMap<ForegroundServiceDelegation, ServiceRecord> mFgsDelegations = new ArrayMap<>();
 
     /**
+     * A global counter for generating sequence numbers to uniquely identify bindService requests.
+     * It is purely for logging purposes.
+     */
+    @GuardedBy("mAm")
+    private long mBindServiceSeqCounter = 0;
+
+    /**
      * Whether there is a rate limit that suppresses immediate re-deferral of new FGS
      * notifications from each app.  On by default, disabled only by shell command for
      * test-suite purposes.  To disable the behavior more generally, use the usual
@@ -639,6 +647,7 @@
         mAppWidgetManagerInternal = LocalServices.getService(AppWidgetManagerInternal.class);
         setAllowListWhileInUsePermissionInFgs();
         initSystemExemptedFgsTypePermission();
+        initMediaProjectFgsTypeCustomPermission();
     }
 
     private AppStateTracker getAppStateTracker() {
@@ -800,13 +809,17 @@
                     ? res.permission : "private to package");
         }
 
-
-        // TODO(short-service): This is inside startService() / startForegroundService().
-        // Consider if there's anything special we have to do if these are called on an already-
-        // running short-FGS... But given these APIs shouldn't change the FGS type, we likely
-        // don't need to do anything. (If they would change the FGS type, we'd have to stop
-        // the timeout)
         ServiceRecord r = res.record;
+        // Note, when startService() or startForegroundService() is called on an already
+        // running SHORT_SERVICE FGS, the call will succeed (i.e. we won't throw
+        // ForegroundServiceStartNotAllowedException), even when the service is alerady timed
+        // out. This is because these APIs will essnetially only change the "started" state
+        // of the service, and it won't afect "the foreground-ness" of the service, or the type
+        // of the FGS.
+        // However, this call will still _not_ extend the SHORT_SERVICE timeout either.
+        // Also, if the app tries to change the type of the FGS later (using
+        // Service.startForeground()), at that point we will consult the BFSL check and the timeout
+        // and make the necessary decisions.
         setFgsRestrictionLocked(callingPackage, callingPid, callingUid, service, r, userId,
                 backgroundStartPrivileges, false /* isBindService */);
 
@@ -2035,8 +2048,7 @@
                         // suddenly disallow it.
                         // However, this would be very problematic if used with a short-FGS, so we
                         // explicitly disallow this combination.
-                        // TODO(short-service): Change to another exception type?
-                        throw new IllegalStateException(
+                        throw new StartForegroundCalledOnStoppedServiceException(
                                 "startForeground(SHORT_SERVICE) called on a service that's not"
                                 + " started.");
                     }
@@ -2062,7 +2074,9 @@
                     final boolean isOldTypeShortFgs = r.isShortFgs();
                     final boolean isNewTypeShortFgs =
                             foregroundServiceType == FOREGROUND_SERVICE_TYPE_SHORT_SERVICE;
-                    final boolean isOldTypeShortFgsAndTimedOut = r.shouldTriggerShortFgsTimeout();
+                    final long nowUptime = SystemClock.uptimeMillis();
+                    final boolean isOldTypeShortFgsAndTimedOut =
+                            r.shouldTriggerShortFgsTimeout(nowUptime);
 
                     // If true, we skip the BFSL check.
                     boolean bypassBfslCheck = false;
@@ -2088,6 +2102,17 @@
                                 r.appInfo.uid, r.intent.getIntent(), r, r.userId,
                                 BackgroundStartPrivileges.NONE,
                                 false /* isBindService */);
+                        if (r.mAllowStartForeground == REASON_DENIED) {
+                            Slog.w(TAG_SERVICE, "FGS type change to/from SHORT_SERVICE: "
+                                    + " BFSL DENIED.");
+                        } else {
+                            if (DEBUG_SHORT_SERVICE) {
+                                Slog.w(TAG_SERVICE, "FGS type change to/from SHORT_SERVICE: "
+                                        + " BFSL Allowed: "
+                                        + PowerExemptionManager.reasonCodeToString(
+                                                r.mAllowStartForeground));
+                            }
+                        }
 
                         final boolean fgsStartAllowed =
                                 !isBgFgsRestrictionEnabledForService
@@ -2241,10 +2266,6 @@
                         cancelForegroundNotificationLocked(r);
                         r.foregroundId = id;
                     }
-
-                    // TODO(short-service): Stop the short service timeout, if the type is changing
-                    // from short to non-short. (should we do it earlier?)
-
                     notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
                     r.foregroundNoti = notification;
                     r.foregroundServiceType = foregroundServiceType;
@@ -2569,6 +2590,39 @@
         }
     }
 
+    /**
+     * A custom permission checker for the "mediaProjection" FGS type:
+     * if the app has been granted the permission to start a media projection via
+     * the {@link android.media.project.MediaProjectionManager#createScreenCaptureIntent()},
+     * it'll get the permission to start a foreground service with type "mediaProjection".
+     */
+    private class MediaProjectionFgsTypeCustomPermission extends ForegroundServiceTypePermission {
+        MediaProjectionFgsTypeCustomPermission() {
+            super("Media projection screen capture permission");
+        }
+
+        @Override
+        public int checkPermission(@NonNull Context context, int callerUid, int callerPid,
+                @NonNull String packageName, boolean allowWhileInUse) {
+            return mAm.isAllowedMediaProjectionNoOpCheck(callerUid)
+                    ? PERMISSION_GRANTED : PERMISSION_DENIED;
+        }
+    }
+
+    /**
+     * Set a custom permission checker for the "mediaProjection" FGS type.
+     */
+    private void initMediaProjectFgsTypeCustomPermission() {
+        final ForegroundServiceTypePolicy policy = ForegroundServiceTypePolicy.getDefaultPolicy();
+        final ForegroundServiceTypePolicyInfo policyInfo =
+                policy.getForegroundServiceTypePolicyInfo(
+                       ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION,
+                       ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE);
+        if (policyInfo != null) {
+            policyInfo.setCustomPermission(new MediaProjectionFgsTypeCustomPermission());
+        }
+    }
+
     ServiceNotificationPolicy applyForegroundServiceNotificationLocked(Notification notification,
             final String tag, final int id, final String pkg, final int userId) {
         // By nature of the FGS API, all FGS notifications have a null tag
@@ -3180,9 +3234,11 @@
 
     void onShortFgsTimeout(ServiceRecord sr) {
         synchronized (mAm) {
-            if (!sr.shouldTriggerShortFgsTimeout()) {
+            final long nowUptime = SystemClock.uptimeMillis();
+            if (!sr.shouldTriggerShortFgsTimeout(nowUptime)) {
                 if (DEBUG_SHORT_SERVICE) {
-                    Slog.d(TAG_SERVICE, "[STALE] Short FGS timed out: " + sr);
+                    Slog.d(TAG_SERVICE, "[STALE] Short FGS timed out: " + sr
+                            + " " + sr.getShortFgsTimedEventDescription(nowUptime));
                 }
                 return;
             }
@@ -3190,7 +3246,7 @@
             try {
                 sr.app.getThread().scheduleTimeoutService(sr, sr.getShortFgsInfo().getStartId());
             } catch (RemoteException e) {
-                // TODO(short-service): Anything to do here?
+                Slog.w(TAG_SERVICE, "Exception from scheduleTimeoutService: " + e.toString());
             }
             // Schedule the procstate demotion timeout and ANR timeout.
             {
@@ -3216,7 +3272,8 @@
             if (sr == null) {
                 return false;
             }
-            return sr.shouldTriggerShortFgsTimeout();
+            final long nowUptime = SystemClock.uptimeMillis();
+            return sr.shouldTriggerShortFgsTimeout(nowUptime);
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
@@ -3224,9 +3281,11 @@
 
     void onShortFgsProcstateTimeout(ServiceRecord sr) {
         synchronized (mAm) {
-            if (!sr.shouldDemoteShortFgsProcState()) {
+            final long nowUptime = SystemClock.uptimeMillis();
+            if (!sr.shouldDemoteShortFgsProcState(nowUptime)) {
                 if (DEBUG_SHORT_SERVICE) {
-                    Slog.d(TAG_SERVICE, "[STALE] Short FGS procstate demotion: " + sr);
+                    Slog.d(TAG_SERVICE, "[STALE] Short FGS procstate demotion: " + sr
+                            + " " + sr.getShortFgsTimedEventDescription(nowUptime));
                 }
                 return;
             }
@@ -3247,9 +3306,11 @@
         synchronized (mAm) {
             tr.mLatencyTracker.waitingOnAMSLockEnded();
 
-            if (!sr.shouldTriggerShortFgsAnr()) {
+            final long nowUptime = SystemClock.uptimeMillis();
+            if (!sr.shouldTriggerShortFgsAnr(nowUptime)) {
                 if (DEBUG_SHORT_SERVICE) {
-                    Slog.d(TAG_SERVICE, "[STALE] Short FGS ANR'ed: " + sr);
+                    Slog.d(TAG_SERVICE, "[STALE] Short FGS ANR'ed: " + sr
+                            + " " + sr.getShortFgsTimedEventDescription(nowUptime));
                 }
                 return;
             }
@@ -3262,8 +3323,9 @@
             }
             mAm.appNotResponding(sr.app, tr);
 
-            // TODO(short-service): Make sure, if the FGS stops after this, the ANR dialog
-            // disappears.
+            // TODO: Can we close the ANR dialog here, if it's still shown? Currently, the ANR
+            // dialog really doesn't remember the "cause" (especially if there have been multiple
+            // ANRs), so it's not doable.
         }
     }
 
@@ -3278,8 +3340,8 @@
         }
     }
 
-    // TODO(short-service): Hmm what is it? Should we stop the timeout here?
     private void stopServiceAndUpdateAllowlistManagerLocked(ServiceRecord service) {
+        maybeStopShortFgsTimeoutLocked(service);
         final ProcessServiceRecord psr = service.app.mServices;
         psr.stopService(service);
         psr.updateBoundClientUids();
@@ -4374,8 +4436,12 @@
             try {
                 bumpServiceExecutingLocked(r, execInFg, "bind",
                         OomAdjuster.OOM_ADJ_REASON_BIND_SERVICE);
+                if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
+                    Trace.instant(Trace.TRACE_TAG_ACTIVITY_MANAGER, "requestServiceBinding="
+                            + i.intent.getIntent() + ". bindSeq=" + mBindServiceSeqCounter);
+                }
                 r.app.getThread().scheduleBindService(r, i.intent.getIntent(), rebind,
-                        r.app.mState.getReportedProcState());
+                        r.app.mState.getReportedProcState(), mBindServiceSeqCounter++);
                 if (!rebind) {
                     i.requested = true;
                 }
@@ -5406,8 +5472,6 @@
 
         // Check to see if the service had been started as foreground, but being
         // brought down before actually showing a notification.  That is not allowed.
-        // TODO(short-service): This is unlikely related to short-FGS, but I'm curious why it's
-        // not allowed. Look into it.
         if (r.fgRequired) {
             Slog.w(TAG_SERVICE, "Bringing down service while still waiting for start foreground: "
                     + r);
@@ -5478,6 +5542,7 @@
         cancelForegroundNotificationLocked(r);
         final boolean exitingFg = r.isForeground;
         if (exitingFg) {
+            maybeStopShortFgsTimeoutLocked(r);
             decActiveForegroundAppLocked(smap, r);
             synchronized (mAm.mProcessStats.mLock) {
                 ServiceState stracker = r.getTracker();
@@ -5501,8 +5566,6 @@
                 mFGSLogger.logForegroundServiceStop(r.appInfo.uid, r);
             }
             mAm.updateForegroundServiceUsageStats(r.name, r.userId, false);
-
-            // TODO(short-service): Make sure we stop the timeout by here.
         }
 
         r.isForeground = false;
@@ -7822,7 +7885,7 @@
         final int callerTargetSdkVersion = r.mRecentCallerApplicationInfo != null
                 ? r.mRecentCallerApplicationInfo.targetSdkVersion : 0;
 
-        // TODO(short-service): Log BFSL too.
+        // TODO(short-service): Log the UID capabilities (for BFSL) too, and also the procstate?
         FrameworkStatsLog.write(FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
                 r.appInfo.uid,
                 r.shortInstanceName,
@@ -7872,7 +7935,8 @@
                 r.mFgsNotificationShown ? 1 : 0,
                 durationMs,
                 r.mStartForegroundCount,
-                fgsStopReasonToString(fgsStopReason));
+                fgsStopReasonToString(fgsStopReason),
+                r.foregroundServiceType);
     }
 
     private void updateNumForegroundServicesLocked() {
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 9e95e5f..5696004 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -25,6 +25,7 @@
 
 import android.annotation.NonNull;
 import android.app.ActivityThread;
+import android.app.ForegroundServiceTypePolicy;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -1196,6 +1197,7 @@
                                 updateUseTieredCachedAdj();
                                 break;
                             default:
+                                updateFGSPermissionEnforcementFlagsIfNecessary(name);
                                 break;
                         }
                     }
@@ -1951,6 +1953,11 @@
             DEFAULT_TIERED_CACHED_ADJ_DECAY_TIME);
     }
 
+    private void updateFGSPermissionEnforcementFlagsIfNecessary(@NonNull String name) {
+        ForegroundServiceTypePolicy.getDefaultPolicy()
+                .updatePermissionEnforcementFlagIfNecessary(name);
+    }
+
     @NeverCompile // Avoid size overhead of debugging code.
     void dump(PrintWriter pw) {
         pw.println("ACTIVITY MANAGER SETTINGS (dumpsys activity settings) "
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 4a134ee..2a1e860 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -32,13 +32,14 @@
 import static android.app.ActivityManager.INSTR_FLAG_NO_RESTART;
 import static android.app.ActivityManager.INTENT_SENDER_ACTIVITY;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
-import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
 import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
 import static android.app.ActivityManager.PROCESS_STATE_TOP;
 import static android.app.ActivityManager.StopUserOnSwitch;
 import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
 import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
+import static android.app.ActivityManagerInternal.MEDIA_PROJECTION_TOKEN_EVENT_CREATED;
+import static android.app.ActivityManagerInternal.MEDIA_PROJECTION_TOKEN_EVENT_DESTROYED;
 import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.AppOpsManager.OP_NONE;
 import static android.content.pm.ApplicationInfo.HIDDEN_API_ENFORCEMENT_DEFAULT;
@@ -100,9 +101,10 @@
 import static android.provider.Settings.Global.WAIT_FOR_DEBUGGER;
 import static android.text.format.DateUtils.DAY_IN_MILLIS;
 import static android.util.FeatureFlagUtils.SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS;
+import static android.view.Display.INVALID_DISPLAY;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;
-import static com.android.internal.util.FrameworkStatsLog.UNSAFE_INTENT_EVENT_REPORTED;
+import static com.android.internal.util.FrameworkStatsLog.UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__INTERNAL_NON_EXPORTED_COMPONENT_MATCH;
 import static com.android.internal.util.FrameworkStatsLog.UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__NEW_MUTABLE_IMPLICIT_PENDING_INTENT_RETRIEVED;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALLOWLISTS;
@@ -178,6 +180,7 @@
 import android.app.ActivityManagerInternal.BindServiceEventListener;
 import android.app.ActivityManagerInternal.BroadcastEventListener;
 import android.app.ActivityManagerInternal.ForegroundServiceStateListener;
+import android.app.ActivityManagerInternal.MediaProjectionTokenEvent;
 import android.app.ActivityTaskManager.RootTaskInfo;
 import android.app.ActivityThread;
 import android.app.AnrController;
@@ -345,6 +348,7 @@
 import android.util.IndentingPrintWriter;
 import android.util.IntArray;
 import android.util.Log;
+import android.util.LogWriter;
 import android.util.Pair;
 import android.util.PrintWriterPrinter;
 import android.util.Slog;
@@ -485,9 +489,11 @@
 import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.BiFunction;
@@ -1128,19 +1134,6 @@
         }
 
         @Override
-        protected void filterResults(@NonNull Computer computer,
-                @NonNull Intent intent, List<BroadcastFilter> results) {
-            if (intent.getAction() != null) return;
-            // When the resolved component is targeting U+, block null action intents
-            for (int i = results.size() - 1; i >= 0; --i) {
-                if (computer.isChangeEnabled(
-                        IntentFilter.BLOCK_NULL_ACTION_INTENTS, results.get(i).owningUid)) {
-                    results.remove(i);
-                }
-            }
-        }
-
-        @Override
         protected IntentFilter getIntentFilter(@NonNull BroadcastFilter input) {
             return input;
         }
@@ -1518,6 +1511,17 @@
 
     final AppRestrictionController mAppRestrictionController;
 
+    /**
+     * The collection of the MediaProjection tokens per UID, for the apps that are allowed to
+     * start FGS with the type "mediaProjection"; this permission is granted via the request over
+     * the call to {@link android.media.project.MediaProjectionManager#createScreenCaptureIntent()}.
+     *
+     * <p>Note, the "token" here is actually an instance of
+     * {@link android.media.projection.IMediaProjection}.</p>
+     */
+    @GuardedBy("mMediaProjectionTokenMap")
+    private final SparseArray<ArraySet<IBinder>> mMediaProjectionTokenMap = new SparseArray();
+
     private final class AppDeathRecipient implements IBinder.DeathRecipient {
         final ProcessRecord mApp;
         final int mPid;
@@ -3341,7 +3345,6 @@
         }
 
         mBatteryStatsService.noteProcessDied(app.info.uid, pid);
-        mOomAdjuster.updateShortFgsOwner(app.info.uid, pid, false);
 
         if (!app.isKilled()) {
             if (!fromBinderDied) {
@@ -3537,7 +3540,7 @@
 
         // We'll take the stack crawls of just the top apps using CPU.
         final int workingStatsNumber = processCpuTracker.countWorkingStats();
-        for (int i = 0; i < workingStatsNumber && extraPids.size() < 5; i++) {
+        for (int i = 0; i < workingStatsNumber && extraPids.size() < 2; i++) {
             ProcessCpuTracker.Stats stats = processCpuTracker.getWorkingStats(i);
             if (lastPids.indexOfKey(stats.pid) >= 0) {
                 if (DEBUG_ANR) {
@@ -5602,8 +5605,11 @@
                         boolean isChangeEnabled = CompatChanges.isChangeEnabled(
                                         PendingIntent.BLOCK_MUTABLE_IMPLICIT_PENDING_INTENT,
                                         owningUid);
-                        logUnsafeMutableImplicitPi(packageName, resolvedTypes, owningUid, i, intent,
-                                isChangeEnabled);
+                        String resolvedType = resolvedTypes == null
+                                || i >= resolvedTypes.length ? null : resolvedTypes[i];
+                        ActivityManagerUtils.logUnsafeIntentEvent(
+                                UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__NEW_MUTABLE_IMPLICIT_PENDING_INTENT_RETRIEVED,
+                                owningUid, intent, resolvedType, isChangeEnabled);
                         if (isChangeEnabled) {
                             String msg = packageName + ": Targeting U+ (version "
                                     + Build.VERSION_CODES.UPSIDE_DOWN_CAKE + " and above) disallows"
@@ -5669,24 +5675,6 @@
         }
     }
 
-    private void logUnsafeMutableImplicitPi(String packageName, String[] resolvedTypes,
-            int owningUid, int i, Intent intent, boolean isChangeEnabled) {
-        String[] categories = intent.getCategories() == null ? new String[0]
-                : intent.getCategories().toArray(String[]::new);
-        String resolvedType = resolvedTypes == null || i >= resolvedTypes.length ? null
-                : resolvedTypes[i];
-        FrameworkStatsLog.write(UNSAFE_INTENT_EVENT_REPORTED,
-                UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__NEW_MUTABLE_IMPLICIT_PENDING_INTENT_RETRIEVED,
-                owningUid,
-                null,
-                packageName,
-                intent.getAction(),
-                categories,
-                resolvedType,
-                intent.getScheme(),
-                isChangeEnabled);
-    }
-
     @Override
     public int sendIntentSender(IApplicationThread caller, IIntentSender target,
             IBinder allowlistToken, int code, Intent intent, String resolvedType,
@@ -7015,36 +7003,6 @@
     }
 
     /**
-     * Allows apps to retrieve the MIME type of a URI.
-     * If an app is in the same user as the ContentProvider, or if it is allowed to interact across
-     * users, then it does not need permission to access the ContentProvider.
-     * Either, it needs cross-user uri grants.
-     *
-     * CTS tests for this functionality can be run with "runtest cts-appsecurity".
-     *
-     * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
-     *     src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
-     *
-     * @deprecated -- use getProviderMimeTypeAsync.
-     */
-    @Deprecated
-    @Override
-    public String getProviderMimeType(Uri uri, int userId) {
-        return mCpHelper.getProviderMimeType(uri, userId);
-    }
-
-    /**
-     * Allows apps to retrieve the MIME type of a URI.
-     * If an app is in the same user as the ContentProvider, or if it is allowed to interact across
-     * users, then it does not need permission to access the ContentProvider.
-     * Either way, it needs cross-user uri grants.
-     */
-    @Override
-    public void getProviderMimeTypeAsync(Uri uri, int userId, RemoteCallback resultCallback) {
-        mCpHelper.getProviderMimeTypeAsync(uri, userId, resultCallback);
-    }
-
-    /**
      * Filters calls to getType based on permission. If the caller has required permission,
      * then it returns the contentProvider#getType.
      * Else, it returns the contentProvider#getTypeAnonymous, which does not
@@ -9740,8 +9698,8 @@
     }
 
     private void dumpEverything(FileDescriptor fd, PrintWriter pw, String[] args, int opti,
-            boolean dumpAll, String dumpPackage, boolean dumpClient, boolean dumpNormalPriority,
-            int dumpAppId, boolean dumpProxies) {
+            boolean dumpAll, String dumpPackage, int displayIdFilter, boolean dumpClient,
+            boolean dumpNormalPriority, int dumpAppId, boolean dumpProxies) {
 
         ActiveServices.ServiceDumper sdumper;
 
@@ -9821,27 +9779,27 @@
             if (dumpAll) {
                 pw.println("-------------------------------------------------------------------------------");
             }
-            mAtmInternal.dump(
-                    DUMP_RECENTS_CMD, fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
+            mAtmInternal.dump(DUMP_RECENTS_CMD, fd, pw, args, opti, dumpAll, dumpClient,
+                    dumpPackage, displayIdFilter);
             pw.println();
             if (dumpAll) {
                 pw.println("-------------------------------------------------------------------------------");
             }
-            mAtmInternal.dump(
-                    DUMP_LASTANR_CMD, fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
+            mAtmInternal.dump(DUMP_LASTANR_CMD, fd, pw, args, opti, dumpAll, dumpClient,
+                    dumpPackage, displayIdFilter);
             pw.println();
             if (dumpAll) {
                 pw.println("-------------------------------------------------------------------------------");
             }
-            mAtmInternal.dump(
-                    DUMP_STARTER_CMD, fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
+            mAtmInternal.dump(DUMP_STARTER_CMD, fd, pw, args, opti, dumpAll, dumpClient,
+                    dumpPackage, displayIdFilter);
             if (dumpPackage == null) {
                 pw.println();
                 if (dumpAll) {
                     pw.println("-------------------------------------------------------------------------------");
                 }
-                mAtmInternal.dump(
-                        DUMP_CONTAINERS_CMD, fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
+                mAtmInternal.dump(DUMP_CONTAINERS_CMD, fd, pw, args, opti, dumpAll, dumpClient,
+                        dumpPackage, displayIdFilter);
             }
             // Activities section is dumped as part of the Critical priority dump. Exclude the
             // section if priority is Normal.
@@ -9850,8 +9808,8 @@
                 if (dumpAll) {
                     pw.println("-------------------------------------------------------------------------------");
                 }
-                mAtmInternal.dump(
-                        DUMP_ACTIVITIES_CMD, fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
+                mAtmInternal.dump(DUMP_ACTIVITIES_CMD, fd, pw, args, opti, dumpAll, dumpClient,
+                        dumpPackage, displayIdFilter);
             }
             if (mAssociations.size() > 0) {
                 pw.println();
@@ -9924,6 +9882,7 @@
         boolean dumpNormalPriority = false;
         boolean dumpVisibleStacksOnly = false;
         boolean dumpFocusedStackOnly = false;
+        int dumpDisplayId = INVALID_DISPLAY;
         String dumpPackage = null;
         int dumpUserId = UserHandle.USER_ALL;
 
@@ -9968,11 +9927,25 @@
                     pw.println("Error: --user option requires user id argument");
                     return;
                 }
+            } else if ("-d".equals(opt)) {
+                if (opti < args.length) {
+                    dumpDisplayId = Integer.parseInt(args[opti]);
+                    if (dumpDisplayId == INVALID_DISPLAY) {
+                        pw.println("Error: -d cannot be used with INVALID_DISPLAY");
+                        return;
+                    }
+                    opti++;
+                } else {
+                    pw.println("Error: -d option requires display argument");
+                    return;
+                }
+                dumpClient = true;
             } else if ("-h".equals(opt)) {
                 ActivityManagerShellCommand.dumpHelp(pw, true);
                 return;
             } else {
                 pw.println("Unknown argument: " + opt + "; use -h for help");
+                return;
             }
         }
 
@@ -10085,8 +10058,8 @@
                     || DUMP_RECENTS_CMD.equals(cmd) || DUMP_RECENTS_SHORT_CMD.equals(cmd)
                     || DUMP_TOP_RESUMED_ACTIVITY.equals(cmd)
                     || DUMP_VISIBLE_ACTIVITIES.equals(cmd)) {
-                mAtmInternal.dump(
-                        cmd, fd, pw, args, opti, true /* dumpAll */, dumpClient, dumpPackage);
+                mAtmInternal.dump(cmd, fd, pw, args, opti, /* dumpAll= */ true , dumpClient,
+                        dumpPackage, dumpDisplayId);
             } else if ("binder-proxies".equals(cmd)) {
                 if (opti >= args.length) {
                     dumpBinderProxies(pw, 0 /* minToDump */);
@@ -10253,7 +10226,7 @@
             } else {
                 // Dumping a single activity?
                 if (!mAtmInternal.dumpActivity(fd, pw, cmd, args, opti, dumpAll,
-                        dumpVisibleStacksOnly, dumpFocusedStackOnly, dumpUserId)) {
+                        dumpVisibleStacksOnly, dumpFocusedStackOnly, dumpDisplayId, dumpUserId)) {
                     ActivityManagerShellCommand shell = new ActivityManagerShellCommand(this, true);
                     int res = shell.exec(this, null, fd, null, args, null,
                             new ResultReceiver(null));
@@ -10276,15 +10249,15 @@
             if (dumpClient) {
                 // dumpEverything() will take the lock when needed, and momentarily drop
                 // it for dumping client state.
-                dumpEverything(fd, pw, args, opti, dumpAll, dumpPackage, dumpClient,
-                        dumpNormalPriority, dumpAppId, true /* dumpProxies */);
+                dumpEverything(fd, pw, args, opti, dumpAll, dumpPackage, dumpDisplayId,
+                        dumpClient, dumpNormalPriority, dumpAppId, /* dumpProxies= */ true);
             } else {
                 // Take the lock here, so we get a consistent state for the entire dump;
                 // dumpEverything() will take the lock as well, which is fine for everything
                 // except dumping proxies, which can take a long time; exclude them.
                 synchronized(this) {
-                    dumpEverything(fd, pw, args, opti, dumpAll, dumpPackage, dumpClient,
-                            dumpNormalPriority, dumpAppId, false /* dumpProxies */);
+                    dumpEverything(fd, pw, args, opti, dumpAll, dumpPackage, dumpDisplayId,
+                            dumpClient, dumpNormalPriority, dumpAppId, /* dumpProxies= */ false);
                 }
             }
             if (dumpAll) {
@@ -12956,18 +12929,9 @@
             boolean hasToBeExportedToMatch = platformCompat.isChangeEnabledByUid(
                     ActivityManagerService.IMPLICIT_INTENTS_ONLY_MATCH_EXPORTED_COMPONENTS,
                     callingUid);
-            String[] categories = intent.getCategories() == null ? new String[0]
-                    : intent.getCategories().toArray(String[]::new);
-            FrameworkStatsLog.write(UNSAFE_INTENT_EVENT_REPORTED,
-                    FrameworkStatsLog.UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__INTERNAL_NON_EXPORTED_COMPONENT_MATCH,
-                    callingUid,
-                    componentInfo,
-                    callerPackage,
-                    intent.getAction(),
-                    categories,
-                    resolvedType,
-                    intent.getScheme(),
-                    hasToBeExportedToMatch);
+            ActivityManagerUtils.logUnsafeIntentEvent(
+                    UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__INTERNAL_NON_EXPORTED_COMPONENT_MATCH,
+                    callingUid, intent, resolvedType, hasToBeExportedToMatch);
             if (!hasToBeExportedToMatch) {
                 return;
             }
@@ -13138,8 +13102,8 @@
     @Override
     public void logFgsApiBegin(@ForegroundServiceApiType int apiType,
             int uid, int pid) {
-        enforceCallingPermission(android.Manifest.permission.LOG_PROCESS_ACTIVITIES,
-                "logFgsApiStart");
+        enforceCallingPermission(android.Manifest.permission.LOG_FOREGROUND_RESOURCE_USE,
+                "logFgsApiBegin");
         synchronized (this) {
             mServices.logFgsApiBeginLocked(apiType, uid, pid);
         }
@@ -13148,8 +13112,8 @@
     @Override
     public void logFgsApiEnd(@ForegroundServiceApiType int apiType,
             int uid, int pid) {
-        enforceCallingPermission(android.Manifest.permission.LOG_PROCESS_ACTIVITIES,
-                "logFgsApiStart");
+        enforceCallingPermission(android.Manifest.permission.LOG_FOREGROUND_RESOURCE_USE,
+                "logFgsApiEnd");
         synchronized (this) {
             mServices.logFgsApiEndLocked(apiType, uid, pid);
         }
@@ -13158,8 +13122,8 @@
     @Override
     public void logFgsApiStateChanged(@ForegroundServiceApiType int apiType,
             int state, int uid, int pid) {
-        enforceCallingPermission(android.Manifest.permission.LOG_PROCESS_ACTIVITIES,
-                "logFgsApiStart");
+        enforceCallingPermission(android.Manifest.permission.LOG_FOREGROUND_RESOURCE_USE,
+                "logFgsApiEvent");
         synchronized (this) {
             mServices.logFgsApiStateChangedLocked(apiType, uid, pid, state);
         }
@@ -13978,19 +13942,11 @@
                         (intent.getFlags() & Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) == 0) {
                     continue;
                 }
-
-                final boolean blockNullAction = mPlatformCompat.isChangeEnabledInternal(
-                        IntentFilter.BLOCK_NULL_ACTION_INTENTS, callerApp.info);
                 // If intent has scheme "content", it will need to access
                 // provider that needs to lock mProviderMap in ActivityThread
                 // and also it may need to wait application response, so we
                 // cannot lock ActivityManagerService here.
-                if (filter.match(intent.getAction(), intent.resolveType(resolver),
-                        intent.getScheme(), intent.getData(), intent.getCategories(), TAG,
-                        false /* supportWildcards */,
-                        blockNullAction,
-                        null /* ignoreActions */,
-                        intent.getExtras()) >= 0) {
+                if (filter.match(resolver, intent, true, TAG) >= 0) {
                     if (allSticky == null) {
                         allSticky = new ArrayList<Intent>();
                     }
@@ -14337,7 +14293,8 @@
     // Apply permission policy around the use of specific broadcast options
     void enforceBroadcastOptionPermissionsInternal(
             @Nullable Bundle options, int callingUid) {
-        enforceBroadcastOptionPermissionsInternal(BroadcastOptions.fromBundle(options), callingUid);
+        enforceBroadcastOptionPermissionsInternal(BroadcastOptions.fromBundleNullable(options),
+                callingUid);
     }
 
     void enforceBroadcastOptionPermissionsInternal(
@@ -14353,7 +14310,7 @@
             }
             if (options.isInteractive()) {
                 enforceCallingPermission(
-                        android.Manifest.permission.COMPONENT_OPTION_INTERACTIVE,
+                        android.Manifest.permission.BROADCAST_OPTION_INTERACTIVE,
                         "setInteractive");
             }
         }
@@ -14390,9 +14347,9 @@
         final int res = broadcastIntentLockedTraced(callerApp, callerPackage, callerFeatureId,
                 intent, resolvedType, resultToApp, resultTo, resultCode, resultData, resultExtras,
                 requiredPermissions, excludedPermissions, excludedPackages, appOp,
-                BroadcastOptions.fromBundle(bOptions), ordered, sticky, callingPid, callingUid,
-                realCallingUid, realCallingPid, userId, backgroundStartPrivileges,
-                broadcastAllowList, filterExtrasForReceiver);
+                BroadcastOptions.fromBundleNullable(bOptions), ordered, sticky,
+                callingPid, callingUid, realCallingUid, realCallingPid, userId,
+                backgroundStartPrivileges, broadcastAllowList, filterExtrasForReceiver);
         BroadcastQueue.traceEnd(cookie);
         return res;
     }
@@ -14558,7 +14515,7 @@
             brOptions.setDeferUntilActive(true);
         }
 
-        if (ordered && brOptions != null && brOptions.isDeferUntilActive()) {
+        if (mEnableModernQueue && ordered && brOptions != null && brOptions.isDeferUntilActive()) {
             throw new IllegalArgumentException("Ordered broadcasts can't be deferred until active");
         }
 
@@ -15009,7 +14966,7 @@
                     }
                     List<BroadcastFilter> registeredReceiversForUser =
                             mReceiverResolver.queryIntent(snapshot, intent,
-                                    resolvedType, false /*defaultOnly*/, callingUid, users[i]);
+                                    resolvedType, false /*defaultOnly*/, users[i]);
                     if (registeredReceivers == null) {
                         registeredReceivers = registeredReceiversForUser;
                     } else if (registeredReceiversForUser != null) {
@@ -15018,7 +14975,7 @@
                 }
             } else {
                 registeredReceivers = mReceiverResolver.queryIntent(snapshot, intent,
-                        resolvedType, false /*defaultOnly*/, callingUid, userId);
+                        resolvedType, false /*defaultOnly*/, userId);
             }
         }
         BroadcastQueue.traceEnd(cookie);
@@ -17322,6 +17279,9 @@
         public ComponentName startSdkSandboxService(Intent service, int clientAppUid,
                 String clientAppPackage, String processName) throws RemoteException {
             validateSdkSandboxParams(service, clientAppUid, clientAppPackage, processName);
+            if (mAppOpsService.checkPackage(clientAppUid, clientAppPackage) != MODE_ALLOWED) {
+                throw new IllegalArgumentException("uid does not belong to provided package");
+            }
             // TODO(b/269598719): Is passing the application thread of the system_server alright?
             // e.g. the sandbox getting privileged access due to this.
             ComponentName cn = ActivityManagerService.this.startService(
@@ -17388,6 +17348,9 @@
                 String processName, long flags)
                 throws RemoteException {
             validateSdkSandboxParams(service, clientAppUid, clientAppPackage, processName);
+            if (mAppOpsService.checkPackage(clientAppUid, clientAppPackage) != MODE_ALLOWED) {
+                throw new IllegalArgumentException("uid does not belong to provided package");
+            }
             if (conn == null) {
                 throw new IllegalArgumentException("connection is null");
             }
@@ -17440,9 +17403,6 @@
             if (!UserHandle.isApp(clientAppUid)) {
                 throw new IllegalArgumentException("uid is not within application range");
             }
-            if (mAppOpsService.checkPackage(clientAppUid, clientAppPackage) != MODE_ALLOWED) {
-                throw new IllegalArgumentException("uid does not belong to provided package");
-            }
         }
 
         @Override
@@ -18194,8 +18154,12 @@
                         | Intent.FLAG_RECEIVER_REPLACE_PENDING
                         | Intent.FLAG_RECEIVER_FOREGROUND
                         | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
+                final Bundle configChangedOptions = new BroadcastOptions()
+                        .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
+                        .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE)
+                        .toBundle();
                 broadcastIntentLocked(null, null, null, intent, null, null, 0, null, null, null,
-                        null, null, OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
+                        null, null, OP_NONE, configChangedOptions, false, false, MY_PID, SYSTEM_UID,
                         Binder.getCallingUid(), Binder.getCallingPid(), UserHandle.USER_ALL);
                 if ((changes & ActivityInfo.CONFIG_LOCALE) != 0) {
                     intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
@@ -18209,8 +18173,9 @@
                     bOptions.setTemporaryAppAllowlist(mInternal.getBootTimeTempAllowListDuration(),
                             TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
                             PowerExemptionManager.REASON_LOCALE_CHANGED, "");
-                    bOptions.setRemoveMatchingFilter(
-                            new IntentFilter(Intent.ACTION_LOCALE_CHANGED));
+                    bOptions.setDeliveryGroupPolicy(
+                            BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT);
+                    bOptions.setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE);
                     broadcastIntentLocked(null, null, null, intent, null, null, 0, null, null, null,
                             null, null, OP_NONE, bOptions.toBundle(), false, false, MY_PID,
                             SYSTEM_UID, Binder.getCallingUid(), Binder.getCallingPid(),
@@ -18253,8 +18218,14 @@
                     intent.putExtra("reason", reason);
                 }
 
+                final BroadcastOptions options = new BroadcastOptions()
+                        .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
+                        .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE);
+                if (reason != null) {
+                    options.setDeliveryGroupMatchingKey(Intent.ACTION_CLOSE_SYSTEM_DIALOGS, reason);
+                }
                 broadcastIntentLocked(null, null, null, intent, null, null, 0, null, null, null,
-                        null, null, OP_NONE, null, false, false, -1, SYSTEM_UID,
+                        null, null, OP_NONE, options.toBundle(), false, false, -1, SYSTEM_UID,
                         Binder.getCallingUid(), Binder.getCallingPid(), UserHandle.USER_ALL);
             }
         }
@@ -18769,23 +18740,6 @@
         }
 
         @Override
-        public boolean canHoldWakeLocksInDeepDoze(int uid, int procstate) {
-            // This method is called with the PowerManager lock held. Do not hold AM here.
-
-            // If the procstate is high enough, it's always allowed.
-            if (procstate <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
-                return true;
-            }
-            // IF it's too low, it's not allowed.
-            if (procstate > PROCESS_STATE_IMPORTANT_FOREGROUND) {
-                return false;
-            }
-            // If it's PROCESS_STATE_IMPORTANT_FOREGROUND, then we allow it only wheen the UID
-            // has a SHORT_FGS.
-            return mOomAdjuster.hasUidShortForegroundService(uid);
-        }
-
-        @Override
         public boolean startProfileEvenWhenDisabled(@UserIdInt int userId) {
             return mUserController.startProfile(userId, /* evenWhenDisabled= */ true,
                     /* unlockListener= */ null);
@@ -18802,6 +18756,12 @@
                 int uid, int pid) {
             ActivityManagerService.this.logFgsApiEnd(apiType, uid, pid);
         }
+
+        @Override
+        public void notifyMediaProjectionEvent(int uid, @NonNull IBinder projectionToken,
+                @MediaProjectionTokenEvent int event) {
+            ActivityManagerService.this.notifyMediaProjectionEvent(uid, projectionToken, event);
+        }
     }
 
     long inputDispatchingTimedOut(int pid, final boolean aboveSystem, TimeoutRecord timeoutRecord) {
@@ -18936,10 +18896,11 @@
 
     @Override
     public void waitForBroadcastBarrier() {
-        waitForBroadcastBarrier(/* printWriter= */ null, false);
+        waitForBroadcastBarrier(/* printWriter= */ null, false, false);
     }
 
-    public void waitForBroadcastBarrier(@Nullable PrintWriter pw, boolean flushBroadcastLoopers) {
+    public void waitForBroadcastBarrier(@Nullable PrintWriter pw,
+            boolean flushBroadcastLoopers, boolean flushApplicationThreads) {
         enforceCallingPermission(permission.DUMP, "waitForBroadcastBarrier()");
         if (flushBroadcastLoopers) {
             BroadcastLoopers.waitForBarrier(pw);
@@ -18947,6 +18908,76 @@
         for (BroadcastQueue queue : mBroadcastQueues) {
             queue.waitForBarrier(pw);
         }
+        if (flushApplicationThreads) {
+            waitForApplicationBarrier(pw);
+        }
+    }
+
+    /**
+     * Wait for all pending {@link IApplicationThread} events to be processed in
+     * all currently running apps.
+     */
+    public void waitForApplicationBarrier(@Nullable PrintWriter pw) {
+        if (pw == null) {
+            pw = new PrintWriter(new LogWriter(Log.VERBOSE, TAG));
+        }
+
+        final CountDownLatch finishedLatch = new CountDownLatch(1);
+        final AtomicInteger pingCount = new AtomicInteger(0);
+        final AtomicInteger pongCount = new AtomicInteger(0);
+        final RemoteCallback pongCallback = new RemoteCallback((result) -> {
+            if (pongCount.incrementAndGet() == pingCount.get()) {
+                finishedLatch.countDown();
+            }
+        });
+
+        // Insert an extra "ping" as a sentinel value to guard us from finishing
+        // too quickly in parallel below
+        pingCount.incrementAndGet();
+
+        synchronized (mProcLock) {
+            final ArrayMap<String, SparseArray<ProcessRecord>> pmap =
+                    mProcessList.getProcessNamesLOSP().getMap();
+            final int numProc = pmap.size();
+            for (int iProc = 0; iProc < numProc; iProc++) {
+                final SparseArray<ProcessRecord> apps = pmap.valueAt(iProc);
+                for (int iApp = 0, numApps = apps.size(); iApp < numApps; iApp++) {
+                    final ProcessRecord app = apps.valueAt(iApp);
+                    final IApplicationThread thread = app.getOnewayThread();
+                    if (thread != null) {
+                        mOomAdjuster.mCachedAppOptimizer.unfreezeTemporarily(app,
+                                OomAdjuster.OOM_ADJ_REASON_NONE);
+                        pingCount.incrementAndGet();
+                        try {
+                            thread.schedulePing(pongCallback);
+                        } catch (RemoteException ignored) {
+                            // When we failed to ping remote process, pretend as
+                            // if we received the expected pong
+                            pongCallback.sendResult(null);
+                        }
+                    }
+                }
+            }
+        }
+
+        // Now that we've dispatched all "ping" events above, we can send our
+        // "pong" sentinel value
+        pongCallback.sendResult(null);
+
+        // Wait for any remaining "pong" events to trickle in
+        for (int i = 0; i < 30; i++) {
+            try {
+                if (finishedLatch.await(1, TimeUnit.SECONDS)) {
+                    pw.println("Finished application barriers!");
+                    return;
+                } else {
+                    pw.println("Waiting for application barriers, at " + pongCount.get() + " of "
+                            + pingCount.get() + "...");
+                }
+            } catch (InterruptedException ignored) {
+            }
+        }
+        pw.println("Gave up waiting for application barriers!");
     }
 
     void setIgnoreDeliveryGroupPolicy(@NonNull String broadcastAction) {
@@ -19698,8 +19729,9 @@
                 final long identity = Binder.clearCallingIdentity();
                 try {
                     return superImpl.apply(code, new AttributionSource(shellUid,
-                            "com.android.shell", attributionSource.getAttributionTag(),
-                            attributionSource.getToken(), attributionSource.getNext()),
+                            Process.INVALID_PID, "com.android.shell",
+                            attributionSource.getAttributionTag(), attributionSource.getToken(),
+                            /*renouncedPermissions*/ null, attributionSource.getNext()),
                             shouldCollectAsyncNotedOp, message, shouldCollectMessage,
                             skiProxyOperation);
                 } finally {
@@ -19750,8 +19782,9 @@
                 final long identity = Binder.clearCallingIdentity();
                 try {
                     return superImpl.apply(clientId, code, new AttributionSource(shellUid,
-                            "com.android.shell", attributionSource.getAttributionTag(),
-                            attributionSource.getToken(), attributionSource.getNext()),
+                            Process.INVALID_PID, "com.android.shell",
+                            attributionSource.getAttributionTag(), attributionSource.getToken(),
+                            /*renouncedPermissions*/ null, attributionSource.getNext()),
                             startIfModeDefault, shouldCollectAsyncNotedOp, message,
                             shouldCollectMessage, skipProxyOperation, proxyAttributionFlags,
                             proxiedAttributionFlags, attributionChainId);
@@ -19775,8 +19808,9 @@
                 final long identity = Binder.clearCallingIdentity();
                 try {
                     superImpl.apply(clientId, code, new AttributionSource(shellUid,
-                            "com.android.shell", attributionSource.getAttributionTag(),
-                            attributionSource.getToken(), attributionSource.getNext()),
+                            Process.INVALID_PID, "com.android.shell",
+                            attributionSource.getAttributionTag(), attributionSource.getToken(),
+                            /*renouncedPermissions*/ null, attributionSource.getNext()),
                             skipProxyOperation);
                 } finally {
                     Binder.restoreCallingIdentity(identity);
@@ -19964,4 +19998,41 @@
             return invalidValue;
         }
     }
+
+    private void notifyMediaProjectionEvent(int uid, @NonNull IBinder projectionToken,
+            @MediaProjectionTokenEvent int event) {
+        synchronized (mMediaProjectionTokenMap) {
+            final int index = mMediaProjectionTokenMap.indexOfKey(uid);
+            ArraySet<IBinder> tokens;
+            if (event == MEDIA_PROJECTION_TOKEN_EVENT_CREATED) {
+                if (index < 0) {
+                    tokens = new ArraySet();
+                    mMediaProjectionTokenMap.put(uid, tokens);
+                } else {
+                    tokens = mMediaProjectionTokenMap.valueAt(index);
+                }
+                tokens.add(projectionToken);
+            } else if (event == MEDIA_PROJECTION_TOKEN_EVENT_DESTROYED && index >= 0) {
+                tokens = mMediaProjectionTokenMap.valueAt(index);
+                tokens.remove(projectionToken);
+                if (tokens.isEmpty()) {
+                    mMediaProjectionTokenMap.removeAt(index);
+                }
+            }
+        }
+    }
+
+    /**
+     * @return {@code true} if the MediaProjectionManagerService has created a media projection
+     *         for the given {@code uid} because the user has granted the permission;
+     *         it doesn't necessarily mean it has started the projection.
+     *
+     * <p>It doesn't check the {@link AppOpsManager#OP_PROJECT_MEDIA}.</p>
+     */
+    boolean isAllowedMediaProjectionNoOpCheck(int uid) {
+        synchronized (mMediaProjectionTokenMap) {
+            final int index = mMediaProjectionTokenMap.indexOfKey(uid);
+            return index >= 0 && !mMediaProjectionTokenMap.valueAt(index).isEmpty();
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 72d6ca9..94d08bf 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -19,7 +19,7 @@
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
-import static android.app.ActivityManager.PROCESS_CAPABILITY_NETWORK;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
 import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM;
@@ -46,6 +46,7 @@
 import android.annotation.UserIdInt;
 import android.app.Activity;
 import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
 import android.app.ActivityOptions;
 import android.app.ActivityTaskManager;
 import android.app.ActivityTaskManager.RootTaskInfo;
@@ -146,6 +147,7 @@
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
 
 import javax.microedition.khronos.egl.EGL10;
 import javax.microedition.khronos.egl.EGLConfig;
@@ -358,6 +360,8 @@
                     return runWaitForBroadcastIdle(pw);
                 case "wait-for-broadcast-barrier":
                     return runWaitForBroadcastBarrier(pw);
+                case "wait-for-application-barrier":
+                    return runWaitForApplicationBarrier(pw);
                 case "set-ignore-delivery-group-policy":
                     return runSetIgnoreDeliveryGroupPolicy(pw);
                 case "clear-ignore-delivery-group-policy":
@@ -595,10 +599,14 @@
             return 1;
         }
 
-        String mimeType = intent.getType();
-        if (mimeType == null && intent.getData() != null
+        AtomicReference<String> mimeType = new AtomicReference<>(intent.getType());
+
+        if (mimeType.get() == null && intent.getData() != null
                 && "content".equals(intent.getData().getScheme())) {
-            mimeType = mInterface.getProviderMimeType(intent.getData(), mUserId);
+            mInterface.getMimeTypeFilterAsync(intent.getData(), mUserId,
+                    new RemoteCallback(result -> {
+                        mimeType.set(result.getPairValue());
+                    }));
         }
 
         do {
@@ -611,8 +619,8 @@
                     int userIdForQuery = mInternal.mUserController.handleIncomingUser(
                             Binder.getCallingPid(), Binder.getCallingUid(), mUserId, false,
                             ALLOW_NON_FULL, "ActivityManagerShellCommand", null);
-                    List<ResolveInfo> activities = mPm.queryIntentActivities(intent, mimeType, 0,
-                            userIdForQuery).getList();
+                    List<ResolveInfo> activities = mPm.queryIntentActivities(intent, mimeType.get(),
+                            0, userIdForQuery).getList();
                     if (activities == null || activities.size() <= 0) {
                         getErrPrintWriter().println("Error: Intent does not match any activities: "
                                 + intent);
@@ -708,12 +716,12 @@
             }
             if (mWaitOption) {
                 result = mInternal.startActivityAndWait(null, SHELL_PACKAGE_NAME, null, intent,
-                        mimeType, null, null, 0, mStartFlags, profilerInfo,
+                        mimeType.get(), null, null, 0, mStartFlags, profilerInfo,
                         options != null ? options.toBundle() : null, mUserId);
                 res = result.result;
             } else {
                 res = mInternal.startActivityAsUserWithFeature(null, SHELL_PACKAGE_NAME, null,
-                        intent, mimeType, null, null, 0, mStartFlags, profilerInfo,
+                        intent, mimeType.get(), null, null, 0, mStartFlags, profilerInfo,
                         options != null ? options.toBundle() : null, mUserId);
             }
             final long endTime = SystemClock.uptimeMillis();
@@ -2009,7 +2017,7 @@
         int mask = PROCESS_CAPABILITY_FOREGROUND_LOCATION
                 | PROCESS_CAPABILITY_FOREGROUND_CAMERA
                 | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
-                | PROCESS_CAPABILITY_NETWORK;
+                | PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
 
         while ((opt=getNextOption()) != null) {
             if (opt.equals("--oom")) {
@@ -2215,7 +2223,6 @@
         boolean wait = false;
         String opt;
         int displayId = Display.INVALID_DISPLAY;
-        boolean forceInvisible = false;
         while ((opt = getNextOption()) != null) {
             switch(opt) {
                 case "-w":
@@ -2224,27 +2231,31 @@
                 case "--display":
                     displayId = getDisplayIdFromNextArg();
                     break;
-                case "--force-invisible":
-                    forceInvisible = true;
-                    break;
                 default:
                     getErrPrintWriter().println("Error: unknown option: " + opt);
                     return -1;
             }
         }
         final int userId = Integer.parseInt(getNextArgRequired());
-        final boolean callStartProfile = !forceInvisible && isProfile(userId);
         final ProgressWaiter waiter = wait ? new ProgressWaiter(userId) : null;
-        Slogf.d(TAG, "runStartUser(): userId=%d, display=%d, waiter=%s, callStartProfile=%b, "
-                + "forceInvisible=%b", userId,  displayId, waiter, callStartProfile,
-                forceInvisible);
+
+        // For backwards compatibility, if the user is a profile, we need to define whether it
+        // should be started visible (when its parent is the current user) or not (when it isn't)
+        final UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class);
+        final ActivityManagerInternal ami = LocalServices.getService(ActivityManagerInternal.class);
+        final int parentUserId = umi.getProfileParentId(userId);
+        final int currentUserId = ami.getCurrentUserId();
+        final boolean isProfile = parentUserId != userId;
+        final boolean isVisibleProfile = isProfile && parentUserId == currentUserId;
+        Slogf.d(TAG, "runStartUser(): userId=%d, parentUserId=%d, currentUserId=%d, isProfile=%b, "
+                + "isVisibleProfile=%b, display=%d, waiter=%s", userId, parentUserId, currentUserId,
+                isProfile, isVisibleProfile, displayId, waiter);
 
         boolean success;
         String displaySuffix = "";
-
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "shell_runStartUser" + userId);
         try {
-            if (callStartProfile) {
+            if (isVisibleProfile) {
                 Slogf.d(TAG, "calling startProfileWithListener(%d, %s)", userId, waiter);
                 // startProfileWithListener() will start the profile visible (as long its parent is
                 // the current user), while startUserInBackgroundWithListener() will always start
@@ -3327,16 +3338,24 @@
 
     int runWaitForBroadcastBarrier(PrintWriter pw) throws RemoteException {
         boolean flushBroadcastLoopers = false;
+        boolean flushApplicationThreads = false;
         String opt;
         while ((opt = getNextOption()) != null) {
             if (opt.equals("--flush-broadcast-loopers")) {
                 flushBroadcastLoopers = true;
+            } else if (opt.equals("--flush-application-threads")) {
+                flushApplicationThreads = true;
             } else {
                 getErrPrintWriter().println("Error: Unknown option: " + opt);
                 return -1;
             }
         }
-        mInternal.waitForBroadcastBarrier(pw, flushBroadcastLoopers);
+        mInternal.waitForBroadcastBarrier(pw, flushBroadcastLoopers, flushApplicationThreads);
+        return 0;
+    }
+
+    int runWaitForApplicationBarrier(PrintWriter pw) throws RemoteException {
+        mInternal.waitForApplicationBarrier(pw);
         return 0;
     }
 
@@ -3891,11 +3910,6 @@
         return new Resources(AssetManager.getSystem(), metrics, config);
     }
 
-    private boolean isProfile(@UserIdInt int userId) {
-        final UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class);
-        return umi.getProfileParentId(userId) != userId;
-    }
-
     @Override
     public void onHelp() {
         PrintWriter pw = getOutPrintWriter();
@@ -3930,6 +3944,7 @@
             pw.println("    package [PACKAGE_NAME]: all state related to given package");
             pw.println("    all: dump all activities");
             pw.println("    top: dump the top activity");
+            pw.println("    users: user state");
             pw.println("  WHAT may also be a COMP_SPEC to dump activities.");
             pw.println("  COMP_SPEC may be a component name (com.foo/.myApp),");
             pw.println("    a partial substring in a component name, a");
@@ -3937,6 +3952,7 @@
             pw.println("  -a: include all available server state.");
             pw.println("  -c: include client state.");
             pw.println("  -p: limit output to given package.");
+            pw.println("  -d: limit output to given display.");
             pw.println("  --checkin: output checkin format, resetting data.");
             pw.println("  --C: output checkin format, not resetting data.");
             pw.println("  --proto: output dump in protocol buffer format.");
@@ -4140,7 +4156,7 @@
             pw.println("      execution of that user if it is currently stopped.");
             pw.println("  get-current-user");
             pw.println("      Returns id of the current foreground user.");
-            pw.println("  start-user [-w] [--display DISPLAY_ID] [--force-invisible] <USER_ID>");
+            pw.println("  start-user [-w] [--display DISPLAY_ID] <USER_ID>");
             pw.println("      Start USER_ID in background if it is currently stopped;");
             pw.println("      use switch-user if you want to start the user in foreground.");
             pw.println("      -w: wait for start-user to complete and the user to be unlocked.");
@@ -4148,10 +4164,6 @@
                     + "which allows the user to launch activities on it.");
             pw.println("        (not supported on all devices; typically only on automotive builds "
                     + "where the vehicle has passenger displays)");
-            pw.println("      --force-invisible: always start the user invisible, even if it's a "
-                    + "profile.");
-            pw.println("        (by default, a profile is visible in the default display when its "
-                    + "parent is the current foreground user)");
             pw.println("  unlock-user <USER_ID>");
             pw.println("      Unlock the given user.  This will only work if the user doesn't");
             pw.println("      have an LSKF (PIN/pattern/password).");
diff --git a/services/core/java/com/android/server/am/AppExitInfoTracker.java b/services/core/java/com/android/server/am/AppExitInfoTracker.java
index 32d2071..1ba3266 100644
--- a/services/core/java/com/android/server/am/AppExitInfoTracker.java
+++ b/services/core/java/com/android/server/am/AppExitInfoTracker.java
@@ -674,7 +674,7 @@
                         break;
                 }
             }
-        } catch (IOException | IllegalArgumentException | WireTypeMismatchException e) {
+        } catch (Exception e) {
             Slog.w(TAG, "Error in loading historical app exit info from persistent storage: " + e);
         } finally {
             if (fin != null) {
diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java
index 050ac19..dd6598f 100644
--- a/services/core/java/com/android/server/am/AppProfiler.java
+++ b/services/core/java/com/android/server/am/AppProfiler.java
@@ -20,6 +20,7 @@
 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
 import static android.os.Process.FIRST_APPLICATION_UID;
 import static android.util.FeatureFlagUtils.SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS;
+import static android.view.Display.INVALID_DISPLAY;
 
 import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
 import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_LOW;
@@ -1604,8 +1605,8 @@
             mService.mServices.newServiceDumperLocked(null, catPw, emptyArgs, 0,
                     false, null).dumpLocked();
             catPw.println();
-            mService.mAtmInternal.dump(
-                    DUMP_ACTIVITIES_CMD, null, catPw, emptyArgs, 0, false, false, null);
+            mService.mAtmInternal.dump(DUMP_ACTIVITIES_CMD, null, catPw, emptyArgs, 0, false, false,
+                    null, INVALID_DISPLAY);
             catPw.flush();
         }
         dropBuilder.append(catSw.toString());
@@ -1892,15 +1893,11 @@
     }
 
     long getCpuTimeForPid(int pid) {
-        synchronized (mProcessCpuTracker) {
-            return mProcessCpuTracker.getCpuTimeForPid(pid);
-        }
+        return mProcessCpuTracker.getCpuTimeForPid(pid);
     }
 
     long getCpuDelayTimeForPid(int pid) {
-        synchronized (mProcessCpuTracker) {
-            return mProcessCpuTracker.getCpuDelayTimeForPid(pid);
-        }
+        return mProcessCpuTracker.getCpuDelayTimeForPid(pid);
     }
 
     List<ProcessCpuTracker.Stats> getCpuStats(Predicate<ProcessCpuTracker.Stats> predicate) {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 1607566..d09ca5c 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -23,13 +23,13 @@
 import static android.Manifest.permission.POWER_SAVER;
 import static android.Manifest.permission.UPDATE_DEVICE_STATS;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
 import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
 import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
 
 import android.annotation.EnforcePermission;
 import android.annotation.NonNull;
 import android.annotation.RequiresNoPermission;
-import android.app.AlarmManager;
 import android.app.StatsManager;
 import android.app.usage.NetworkStatsManager;
 import android.bluetooth.BluetoothActivityEnergyInfo;
@@ -401,6 +401,7 @@
 
     public void systemServicesReady() {
         mStats.systemServicesReady(mContext);
+        mCpuWakeupStats.systemServicesReady();
         mWorker.systemServicesReady();
         final INetworkManagementService nms = INetworkManagementService.Stub.asInterface(
                 ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
@@ -412,18 +413,6 @@
             Slog.e(TAG, "Could not register INetworkManagement event observer " + e);
         }
 
-        final AlarmManager am = mContext.getSystemService(AlarmManager.class);
-        mHandler.post(() -> {
-            synchronized (mStats) {
-                mStats.setLongPlugInAlarmInterface(new AlarmInterface(am, () -> {
-                    synchronized (mStats) {
-                        if (mStats.isOnBattery()) return;
-                        mStats.maybeResetWhilePluggedInLocked();
-                    }
-                }));
-            }
-        });
-
         synchronized (mPowerStatsLock) {
             mPowerStatsInternal = LocalServices.getService(PowerStatsInternal.class);
             if (mPowerStatsInternal != null) {
@@ -479,9 +468,29 @@
             BatteryStatsService.this.noteJobsDeferred(uid, numDeferred, sinceLast);
         }
 
+        private int transportToSubsystem(NetworkCapabilities nc) {
+            if (nc.hasTransport(TRANSPORT_WIFI)) {
+                return CPU_WAKEUP_SUBSYSTEM_WIFI;
+            }
+            return CPU_WAKEUP_SUBSYSTEM_UNKNOWN;
+        }
+
         @Override
         public void noteCpuWakingNetworkPacket(Network network, long elapsedMillis, int uid) {
-            Slog.d(TAG, "Wakeup due to incoming packet on network " + network + " to uid " + uid);
+            if (uid < 0) {
+                Slog.e(TAG, "Invalid uid for waking network packet: " + uid);
+                return;
+            }
+            final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
+            final NetworkCapabilities nc = cm.getNetworkCapabilities(network);
+            final int subsystem = transportToSubsystem(nc);
+
+            if (subsystem == CPU_WAKEUP_SUBSYSTEM_UNKNOWN) {
+                Slog.wtf(TAG, "Could not map transport for network: " + network
+                        + " while attributing wakeup by packet sent to uid: " + uid);
+                return;
+            }
+            noteCpuWakingActivity(subsystem, elapsedMillis, uid);
         }
 
         @Override
@@ -2507,32 +2516,6 @@
         }
     }
 
-    final class AlarmInterface implements BatteryStatsImpl.AlarmInterface,
-            AlarmManager.OnAlarmListener {
-        private AlarmManager mAm;
-        private Runnable mOnAlarm;
-
-        AlarmInterface(AlarmManager am, Runnable onAlarm) {
-            mAm = am;
-            mOnAlarm = onAlarm;
-        }
-
-        @Override
-        public void schedule(long rtcTimeMs, long windowLengthMs) {
-            mAm.setWindow(AlarmManager.RTC, rtcTimeMs, windowLengthMs, TAG, this, mHandler);
-        }
-
-        @Override
-        public void cancel() {
-            mAm.cancel(this);
-        }
-
-        @Override
-        public void onAlarm() {
-            mOnAlarm.run();
-        }
-    }
-
     private static native int nativeWaitWakeup(ByteBuffer outBuffer);
 
     private void dumpHelp(PrintWriter pw) {
diff --git a/services/core/java/com/android/server/am/BroadcastHistory.java b/services/core/java/com/android/server/am/BroadcastHistory.java
index 6ac0e8b..34658ca 100644
--- a/services/core/java/com/android/server/am/BroadcastHistory.java
+++ b/services/core/java/com/android/server/am/BroadcastHistory.java
@@ -17,6 +17,7 @@
 package com.android.server.am;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Intent;
 import android.os.Bundle;
 import android.util.TimeUtils;
@@ -26,6 +27,7 @@
 
 import java.io.PrintWriter;
 import java.text.SimpleDateFormat;
+import java.util.ArrayList;
 import java.util.Date;
 
 /**
@@ -48,6 +50,11 @@
     }
 
     /**
+     * List of broadcasts which are being delivered or yet to be delivered.
+     */
+    private final ArrayList<BroadcastRecord> mPendingBroadcasts = new ArrayList<>();
+
+    /**
      * Historical data of past broadcasts, for debugging.  This is a ring buffer
      * whose last element is at mHistoryNext.
      */
@@ -70,7 +77,16 @@
     final long[] mSummaryHistoryDispatchTime;
     final long[] mSummaryHistoryFinishTime;
 
-    public void addBroadcastToHistoryLocked(BroadcastRecord original) {
+    void onBroadcastEnqueuedLocked(@NonNull BroadcastRecord r) {
+        mPendingBroadcasts.add(r);
+    }
+
+    void onBroadcastFinishedLocked(@NonNull BroadcastRecord r) {
+        mPendingBroadcasts.remove(r);
+        addBroadcastToHistoryLocked(r);
+    }
+
+    public void addBroadcastToHistoryLocked(@NonNull BroadcastRecord original) {
         // Note sometimes (only for sticky broadcasts?) we reuse BroadcastRecords,
         // So don't change the incoming record directly.
         final BroadcastRecord historyRecord = original.maybeStripForHistory();
@@ -93,7 +109,12 @@
     }
 
     @NeverCompile
-    public void dumpDebug(ProtoOutputStream proto) {
+    public void dumpDebug(@NonNull ProtoOutputStream proto) {
+        for (int i = 0; i < mPendingBroadcasts.size(); ++i) {
+            final BroadcastRecord r = mPendingBroadcasts.get(i);
+            r.dumpDebug(proto, BroadcastQueueProto.PENDING_BROADCASTS);
+        }
+
         int lastIndex = mHistoryNext;
         int ringIndex = lastIndex;
         do {
@@ -127,8 +148,20 @@
     }
 
     @NeverCompile
-    public boolean dumpLocked(PrintWriter pw, String dumpPackage, String queueName,
-            SimpleDateFormat sdf, boolean dumpAll, boolean needSep) {
+    public boolean dumpLocked(@NonNull PrintWriter pw, @Nullable String dumpPackage,
+            @NonNull String queueName, @NonNull SimpleDateFormat sdf,
+            boolean dumpAll, boolean needSep) {
+        pw.println("  Pending broadcasts:");
+        if (mPendingBroadcasts.isEmpty()) {
+            pw.println("    <empty>");
+        } else {
+            for (int idx = mPendingBroadcasts.size() - 1; idx >= 0; --idx) {
+                final BroadcastRecord r = mPendingBroadcasts.get(idx);
+                pw.print("  Broadcast #"); pw.print(idx); pw.println(":");
+                r.dump(pw, "    ", sdf);
+            }
+        }
+
         int i;
         boolean printed = false;
 
diff --git a/services/core/java/com/android/server/am/BroadcastProcessQueue.java b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
index 84c03e5..7591057 100644
--- a/services/core/java/com/android/server/am/BroadcastProcessQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
@@ -25,6 +25,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UptimeMillisLong;
+import android.content.Intent;
 import android.content.pm.ResolveInfo;
 import android.os.SystemClock;
 import android.os.Trace;
@@ -42,7 +43,6 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayDeque;
 import java.util.Iterator;
-import java.util.List;
 import java.util.Objects;
 
 /**
@@ -126,12 +126,6 @@
     private final ArrayDeque<SomeArgs> mPendingOffload = new ArrayDeque<>(4);
 
     /**
-     * List of all queues holding broadcasts that are waiting to be dispatched.
-     */
-    private final List<ArrayDeque<SomeArgs>> mPendingQueues = List.of(
-            mPendingUrgent, mPending, mPendingOffload);
-
-    /**
      * Broadcast actively being dispatched to this process.
      */
     private @Nullable BroadcastRecord mActive;
@@ -1043,14 +1037,28 @@
      * that we're not wedged.
      */
     public void checkHealthLocked() {
-        if (mRunnableAtReason == REASON_BLOCKED) {
-            final SomeArgs next = peekNextBroadcast();
-            Objects.requireNonNull(next, "peekNextBroadcast");
+        checkHealthLocked(mPending);
+        checkHealthLocked(mPendingUrgent);
+        checkHealthLocked(mPendingOffload);
+    }
 
-            // If blocked more than 10 minutes, we're likely wedged
-            final BroadcastRecord r = (BroadcastRecord) next.arg1;
-            final long waitingTime = SystemClock.uptimeMillis() - r.enqueueTime;
-            checkState(waitingTime < (10 * DateUtils.MINUTE_IN_MILLIS), "waitingTime");
+    private void checkHealthLocked(@NonNull ArrayDeque<SomeArgs> queue) {
+        if (queue.isEmpty()) return;
+
+        final Iterator<SomeArgs> it = queue.descendingIterator();
+        while (it.hasNext()) {
+            final SomeArgs args = it.next();
+            final BroadcastRecord record = (BroadcastRecord) args.arg1;
+            final int recordIndex = args.argi1;
+
+            if (BroadcastRecord.isDeliveryStateTerminal(record.getDeliveryState(recordIndex))
+                    || record.isDeferUntilActive()) {
+                continue;
+            } else {
+                // If waiting more than 10 minutes, we're likely wedged
+                final long waitingTime = SystemClock.uptimeMillis() - record.enqueueTime;
+                checkState(waitingTime < (10 * DateUtils.MINUTE_IN_MILLIS), "waitingTime");
+            }
         }
     }
 
@@ -1145,8 +1153,11 @@
         pw.print(" because ");
         pw.print(reasonToString(mRunnableAtReason));
         pw.println();
-        pw.print("mProcessCached="); pw.println(mProcessCached);
+
         pw.increaseIndent();
+        dumpProcessState(pw);
+        dumpBroadcastCounts(pw);
+
         if (mActive != null) {
             dumpRecord("ACTIVE", now, pw, mActive, mActiveIndex);
         }
@@ -1167,6 +1178,49 @@
     }
 
     @NeverCompile
+    private void dumpProcessState(@NonNull IndentingPrintWriter pw) {
+        final StringBuilder sb = new StringBuilder();
+        if (mProcessCached) {
+            sb.append("CACHED");
+        }
+        if (mProcessInstrumented) {
+            if (sb.length() > 0) sb.append("|");
+            sb.append("INSTR");
+        }
+        if (mProcessPersistent) {
+            if (sb.length() > 0) sb.append("|");
+            sb.append("PER");
+        }
+        if (sb.length() > 0) {
+            pw.print("state:"); pw.println(sb);
+        }
+        if (runningOomAdjusted) {
+            pw.print("runningOomAdjusted:"); pw.println(runningOomAdjusted);
+        }
+    }
+
+    @NeverCompile
+    private void dumpBroadcastCounts(@NonNull IndentingPrintWriter pw) {
+        pw.print("e:"); pw.print(mCountEnqueued);
+        pw.print(" d:"); pw.print(mCountDeferred);
+        pw.print(" f:"); pw.print(mCountForeground);
+        pw.print(" fd:"); pw.print(mCountForegroundDeferred);
+        pw.print(" o:"); pw.print(mCountOrdered);
+        pw.print(" a:"); pw.print(mCountAlarm);
+        pw.print(" p:"); pw.print(mCountPrioritized);
+        pw.print(" pd:"); pw.print(mCountPrioritizedDeferred);
+        pw.print(" int:"); pw.print(mCountInteractive);
+        pw.print(" rt:"); pw.print(mCountResultTo);
+        pw.print(" ins:"); pw.print(mCountInstrumented);
+        pw.print(" m:"); pw.print(mCountManifest);
+
+        pw.print(" csi:"); pw.print(mActiveCountSinceIdle);
+        pw.print(" ccu:"); pw.print(mActiveCountConsecutiveUrgent);
+        pw.print(" ccn:"); pw.print(mActiveCountConsecutiveNormal);
+        pw.println();
+    }
+
+    @NeverCompile
     private void dumpRecord(@Nullable String flavor, @UptimeMillisLong long now,
             @NonNull IndentingPrintWriter pw, @NonNull BroadcastRecord record, int recordIndex) {
         TimeUtils.formatDuration(record.enqueueTime, now, pw);
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index b942f4b..bef16b6 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -52,7 +52,6 @@
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -90,7 +89,6 @@
 import java.io.PrintWriter;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
@@ -225,22 +223,12 @@
     private static final int MSG_DELIVERY_TIMEOUT_HARD = 3;
     private static final int MSG_BG_ACTIVITY_START_TIMEOUT = 4;
     private static final int MSG_CHECK_HEALTH = 5;
-    private static final int MSG_FINISH_RECEIVER = 6;
 
     private void enqueueUpdateRunningList() {
         mLocalHandler.removeMessages(MSG_UPDATE_RUNNING_LIST);
         mLocalHandler.sendEmptyMessage(MSG_UPDATE_RUNNING_LIST);
     }
 
-    private void enqueueFinishReceiver(@NonNull BroadcastProcessQueue queue,
-            @DeliveryState int deliveryState, @NonNull String reason) {
-        final SomeArgs args = SomeArgs.obtain();
-        args.arg1 = queue;
-        args.argi1 = deliveryState;
-        args.arg2 = reason;
-        mLocalHandler.sendMessage(Message.obtain(mLocalHandler, MSG_FINISH_RECEIVER, args));
-    }
-
     private final Handler mLocalHandler;
 
     private final Handler.Callback mLocalCallback = (msg) -> {
@@ -279,17 +267,6 @@
                 }
                 return true;
             }
-            case MSG_FINISH_RECEIVER: {
-                synchronized (mService) {
-                    final SomeArgs args = (SomeArgs) msg.obj;
-                    final BroadcastProcessQueue queue = (BroadcastProcessQueue) args.arg1;
-                    final int deliveryState = args.argi1;
-                    final String reason = (String) args.arg2;
-                    args.recycle();
-                    finishReceiverActiveLocked(queue, deliveryState, reason);
-                }
-                return true;
-            }
         }
         return false;
     };
@@ -597,23 +574,12 @@
         final int cookie = traceBegin("enqueueBroadcast");
         r.applySingletonPolicy(mService);
 
-        final IntentFilter removeMatchingFilter = (r.options != null)
-                ? r.options.getRemoveMatchingFilter() : null;
-        if (removeMatchingFilter != null) {
-            final Predicate<Intent> removeMatching = removeMatchingFilter.asPredicate();
-            forEachMatchingBroadcast(QUEUE_PREDICATE_ANY, (testRecord, testIndex) -> {
-                // We only allow caller to remove broadcasts they enqueued
-                return (r.callingUid == testRecord.callingUid)
-                        && (r.userId == testRecord.userId)
-                        && removeMatching.test(testRecord.intent);
-            }, mBroadcastConsumerSkipAndCanceled, true);
-        }
-
         applyDeliveryGroupPolicy(r);
 
         r.enqueueTime = SystemClock.uptimeMillis();
         r.enqueueRealTime = SystemClock.elapsedRealtime();
         r.enqueueClockTime = System.currentTimeMillis();
+        mHistory.onBroadcastEnqueuedLocked(r);
 
         ArraySet<BroadcastRecord> replacedBroadcasts = mReplacedBroadcastsCache.getAndSet(null);
         if (replacedBroadcasts == null) {
@@ -739,7 +705,7 @@
         // Ignore registered receivers from a previous PID
         if (receiver instanceof BroadcastFilter) {
             mRunningColdStart = null;
-            enqueueFinishReceiver(queue, BroadcastRecord.DELIVERY_SKIPPED,
+            finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_SKIPPED,
                     "BroadcastFilter for cold app");
             return;
         }
@@ -770,7 +736,7 @@
                 hostingRecord, zygotePolicyFlags, allowWhileBooting, false);
         if (queue.app == null) {
             mRunningColdStart = null;
-            enqueueFinishReceiver(queue, BroadcastRecord.DELIVERY_FAILURE,
+            finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_FAILURE,
                     "startProcessLocked failed");
             return;
         }
@@ -812,7 +778,7 @@
             @NonNull BroadcastRecord r, int index) {
         final String reason = shouldSkipReceiver(queue, r, index);
         if (reason != null) {
-            enqueueFinishReceiver(queue, BroadcastRecord.DELIVERY_SKIPPED, reason);
+            finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_SKIPPED, reason);
             return true;
         }
         return false;
@@ -837,8 +803,9 @@
         if (app != null && app.isInFullBackup()) {
             return "isInFullBackup";
         }
-        if (mSkipPolicy.shouldSkip(r, receiver)) {
-            return "mSkipPolicy";
+        final String skipReason = mSkipPolicy.shouldSkipMessage(r, receiver);
+        if (skipReason != null) {
+            return skipReason;
         }
         final Intent receiverIntent = r.getReceiverIntent(receiver);
         if (receiverIntent == null) {
@@ -909,6 +876,10 @@
         final IApplicationThread thread = app.getOnewayThread();
         if (thread != null) {
             try {
+                if (r.shareIdentity) {
+                    mService.mPackageManagerInt.grantImplicitAccess(r.userId, r.intent,
+                            UserHandle.getAppId(app.uid), r.callingUid, true);
+                }
                 if (receiver instanceof BroadcastFilter) {
                     notifyScheduleRegisteredReceiver(app, r, (BroadcastFilter) receiver);
                     thread.scheduleRegisteredReceiver(
@@ -921,7 +892,7 @@
                     // TODO: consider making registered receivers of unordered
                     // broadcasts report results to detect ANRs
                     if (assumeDelivered) {
-                        enqueueFinishReceiver(queue, BroadcastRecord.DELIVERY_DELIVERED,
+                        finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_DELIVERED,
                                 "assuming delivered");
                     }
                 } else {
@@ -939,10 +910,10 @@
                 logw(msg);
                 app.killLocked("Can't deliver broadcast", ApplicationExitInfo.REASON_OTHER,
                         ApplicationExitInfo.SUBREASON_UNDELIVERED_BROADCAST, true);
-                enqueueFinishReceiver(queue, BroadcastRecord.DELIVERY_FAILURE, "remote app");
+                finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_FAILURE, "remote app");
             }
         } else {
-            enqueueFinishReceiver(queue, BroadcastRecord.DELIVERY_FAILURE,
+            finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_FAILURE,
                     "missing IApplicationThread");
         }
     }
@@ -1108,7 +1079,8 @@
      */
     private void setDeliveryState(@Nullable BroadcastProcessQueue queue,
             @Nullable ProcessRecord app, @NonNull BroadcastRecord r, int index,
-            @NonNull Object receiver, @DeliveryState int newDeliveryState, String reason) {
+            @NonNull Object receiver, @DeliveryState int newDeliveryState,
+            @NonNull String reason) {
         final int cookie = traceBegin("setDeliveryState");
         final int oldDeliveryState = getDeliveryState(r, index);
         boolean checkFinished = false;
@@ -1116,7 +1088,7 @@
         // Only apply state when we haven't already reached a terminal state;
         // this is how we ignore racing timeout messages
         if (!isDeliveryStateTerminal(oldDeliveryState)) {
-            r.setDeliveryState(index, newDeliveryState);
+            r.setDeliveryState(index, newDeliveryState, reason);
             if (oldDeliveryState == BroadcastRecord.DELIVERY_DEFERRED) {
                 r.deferredCount--;
             } else if (newDeliveryState == BroadcastRecord.DELIVERY_DEFERRED) {
@@ -1667,7 +1639,7 @@
         mService.notifyBroadcastFinishedLocked(r);
         r.finishTime = SystemClock.uptimeMillis();
         r.nextReceiver = r.receivers.size();
-        mHistory.addBroadcastToHistoryLocked(r);
+        mHistory.onBroadcastFinishedLocked(r);
 
         BroadcastQueueImpl.logBootCompletedBroadcastCompletionLatencyIfPossible(r);
 
@@ -1841,8 +1813,9 @@
         if (dumpConstants) {
             mConstants.dump(ipw);
         }
+
         if (dumpHistory) {
-            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+            final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
             needSep = mHistory.dumpLocked(ipw, dumpPackage, mQueueName, sdf, dumpAll, needSep);
         }
         return needSep;
diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java
index f793c50..59f33dd 100644
--- a/services/core/java/com/android/server/am/BroadcastRecord.java
+++ b/services/core/java/com/android/server/am/BroadcastRecord.java
@@ -99,6 +99,7 @@
     final @Nullable BroadcastOptions options; // BroadcastOptions supplied by caller
     final @NonNull List<Object> receivers;   // contains BroadcastFilter and ResolveInfo
     final @DeliveryState int[] delivery;   // delivery state of each receiver
+    final @NonNull String[] deliveryReasons; // reasons for delivery state of each receiver
     final boolean[] deferredUntilActive; // whether each receiver is infinitely deferred
     final int[] blockedUntilTerminalCount; // blocked until count of each receiver
     @Nullable ProcessRecord resultToApp; // who receives final result if non-null
@@ -298,7 +299,7 @@
                     pw.print(" initialSticky="); pw.println(initialSticky);
         }
         if (nextReceiver != 0) {
-            pw.print(prefix); pw.print("nextReceiver="); pw.print(nextReceiver);
+            pw.print(prefix); pw.print("nextReceiver="); pw.println(nextReceiver);
         }
         if (curFilter != null) {
             pw.print(prefix); pw.print("curFilter="); pw.println(curFilter);
@@ -328,6 +329,7 @@
             }
             pw.print(prefix); pw.print("state="); pw.print(state); pw.println(stateStr);
         }
+        pw.print(prefix); pw.print("terminalCount="); pw.println(terminalCount);
         final int N = receivers != null ? receivers.size() : 0;
         String p2 = prefix + "  ";
         PrintWriterPrinter printer = new PrintWriterPrinter(pw);
@@ -346,6 +348,7 @@
                 TimeUtils.formatDuration(terminalTime[i] - scheduledTime[i], pw);
                 pw.print(' ');
             }
+            pw.print("("); pw.print(blockedUntilTerminalCount[i]); pw.print(") ");
             pw.print("#"); pw.print(i); pw.print(": ");
             if (o instanceof BroadcastFilter) {
                 pw.println(o);
@@ -356,6 +359,9 @@
             } else {
                 pw.println(o);
             }
+            if (deliveryReasons[i] != null) {
+                pw.print(p2); pw.print("reason: "); pw.println(deliveryReasons[i]);
+            }
         }
     }
 
@@ -393,6 +399,7 @@
         options = _options;
         receivers = (_receivers != null) ? _receivers : EMPTY_RECEIVERS;
         delivery = new int[_receivers != null ? _receivers.size() : 0];
+        deliveryReasons = new String[delivery.length];
         deferUntilActive = options != null ? options.isDeferUntilActive() : false;
         deferredUntilActive = new boolean[deferUntilActive ? delivery.length : 0];
         blockedUntilTerminalCount = calculateBlockedUntilTerminalCount(receivers, _serialized);
@@ -448,6 +455,7 @@
         options = from.options;
         receivers = from.receivers;
         delivery = from.delivery;
+        deliveryReasons = from.deliveryReasons;
         deferUntilActive = from.deferUntilActive;
         deferredUntilActive = from.deferredUntilActive;
         blockedUntilTerminalCount = from.blockedUntilTerminalCount;
@@ -609,8 +617,10 @@
      * Update the delivery state of the given {@link #receivers} index.
      * Automatically updates any time measurements related to state changes.
      */
-    void setDeliveryState(int index, @DeliveryState int deliveryState) {
+    void setDeliveryState(int index, @DeliveryState int deliveryState,
+            @NonNull String reason) {
         delivery[index] = deliveryState;
+        deliveryReasons[index] = reason;
         if (deferUntilActive) deferredUntilActive[index] = false;
         switch (deliveryState) {
             case DELIVERY_DELIVERED:
@@ -977,7 +987,8 @@
             if (label == null) {
                 label = intent.toString();
             }
-            mCachedToShortString = label + "/u" + userId;
+            mCachedToShortString = Integer.toHexString(System.identityHashCode(this))
+                    + ":" + label + "/u" + userId;
         }
         return mCachedToShortString;
     }
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index f721d69..48df1494 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -969,122 +969,6 @@
     }
 
     /**
-     * Allows apps to retrieve the MIME type of a URI.
-     * If an app is in the same user as the ContentProvider, or if it is allowed to interact across
-     * users, then it does not need permission to access the ContentProvider.
-     * Either, it needs cross-user uri grants.
-     *
-     * CTS tests for this functionality can be run with "runtest cts-appsecurity".
-     *
-     * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
-     *     src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
-     *
-     * @deprecated -- use getProviderMimeTypeAsync.
-     */
-    @Deprecated
-    String getProviderMimeType(Uri uri, int userId) {
-        mService.enforceNotIsolatedCaller("getProviderMimeType");
-        final String name = uri.getAuthority();
-        final int callingUid = Binder.getCallingUid();
-        final int callingPid = Binder.getCallingPid();
-        final int safeUserId = mService.mUserController.unsafeConvertIncomingUser(userId);
-        final long ident = canClearIdentity(callingPid, callingUid, safeUserId)
-                ? Binder.clearCallingIdentity() : 0;
-        final ContentProviderHolder holder;
-        try {
-            holder = getContentProviderExternalUnchecked(name, null /* token */, callingUid,
-                    "*getmimetype*", safeUserId);
-        } finally {
-            if (ident != 0) {
-                Binder.restoreCallingIdentity(ident);
-            }
-        }
-        try {
-            if (isHolderVisibleToCaller(holder, callingUid, safeUserId)) {
-                final IBinder providerConnection = holder.connection;
-                final ComponentName providerName = holder.info.getComponentName();
-                // Note: creating a new Runnable instead of using a lambda here since lambdas in
-                // java provide no guarantee that there will be a new instance returned every call.
-                // Hence, it's possible that a cached copy is returned and the ANR is executed on
-                // the incorrect provider.
-                final Runnable providerNotResponding = new Runnable() {
-                    @Override
-                    public void run() {
-                        Log.w(TAG, "Provider " + providerName + " didn't return from getType().");
-                        appNotRespondingViaProvider(providerConnection);
-                    }
-                };
-                mService.mHandler.postDelayed(providerNotResponding, 1000);
-                try {
-                    final String type = holder.provider.getType(uri);
-                    return type;
-                } finally {
-                    mService.mHandler.removeCallbacks(providerNotResponding);
-                    // We need to clear the identity to call removeContentProviderExternalUnchecked
-                    final long token = Binder.clearCallingIdentity();
-                    try {
-                        removeContentProviderExternalUnchecked(name, null /* token */, safeUserId);
-                    } finally {
-                        Binder.restoreCallingIdentity(token);
-                    }
-                }
-            }
-        } catch (RemoteException e) {
-            Log.w(TAG, "Content provider dead retrieving " + uri, e);
-            return null;
-        } catch (Exception e) {
-            Log.w(TAG, "Exception while determining type of " + uri, e);
-            return null;
-        }
-
-        return null;
-    }
-
-    /**
-     * Allows apps to retrieve the MIME type of a URI.
-     * If an app is in the same user as the ContentProvider, or if it is allowed to interact across
-     * users, then it does not need permission to access the ContentProvider.
-     * Either way, it needs cross-user uri grants.
-     */
-    void getProviderMimeTypeAsync(Uri uri, int userId, RemoteCallback resultCallback) {
-        mService.enforceNotIsolatedCaller("getProviderMimeTypeAsync");
-        final String name = uri.getAuthority();
-        final int callingUid = Binder.getCallingUid();
-        final int callingPid = Binder.getCallingPid();
-        final int safeUserId = mService.mUserController.unsafeConvertIncomingUser(userId);
-        final long ident = canClearIdentity(callingPid, callingUid, safeUserId)
-                ? Binder.clearCallingIdentity() : 0;
-        final ContentProviderHolder holder;
-        try {
-            holder = getContentProviderExternalUnchecked(name, null /* token */, callingUid,
-                    "*getmimetype*", safeUserId);
-        } finally {
-            if (ident != 0) {
-                Binder.restoreCallingIdentity(ident);
-            }
-        }
-
-        try {
-            if (isHolderVisibleToCaller(holder, callingUid, safeUserId)) {
-                holder.provider.getTypeAsync(uri, new RemoteCallback(result -> {
-                    final long identity = Binder.clearCallingIdentity();
-                    try {
-                        removeContentProviderExternalUnchecked(name, null, safeUserId);
-                    } finally {
-                        Binder.restoreCallingIdentity(identity);
-                    }
-                    resultCallback.sendResult(result);
-                }));
-            } else {
-                resultCallback.sendResult(Bundle.EMPTY);
-            }
-        } catch (RemoteException e) {
-            Log.w(TAG, "Content provider dead retrieving " + uri, e);
-            resultCallback.sendResult(Bundle.EMPTY);
-        }
-    }
-
-    /**
      * Filters calls to getType based on permission. If the caller has required permission,
      * then it returns the contentProvider#getType.
      * Else, it returns the contentProvider#getTypeAnonymous, which does not
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 2e3e635..ddc9e91 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -96,6 +96,10 @@
         sGlobalSettingToTypeMap.put(
                 Settings.Global.ANGLE_EGL_FEATURES, String.class);
         sGlobalSettingToTypeMap.put(
+                Settings.Global.ANGLE_DEFERLIST, String.class);
+        sGlobalSettingToTypeMap.put(
+                Settings.Global.ANGLE_DEFERLIST_MODE, String.class);
+        sGlobalSettingToTypeMap.put(
                 Settings.Global.SHOW_ANGLE_IN_USE_DIALOG_BOX, String.class);
         sGlobalSettingToTypeMap.put(Settings.Global.ENABLE_GPU_DEBUG_LAYERS, int.class);
         sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_APP, String.class);
diff --git a/services/core/java/com/android/server/am/DropboxRateLimiter.java b/services/core/java/com/android/server/am/DropboxRateLimiter.java
index 3792625..9ff2cd0 100644
--- a/services/core/java/com/android/server/am/DropboxRateLimiter.java
+++ b/services/core/java/com/android/server/am/DropboxRateLimiter.java
@@ -31,11 +31,17 @@
     // process/eventType) further entries will be rejected until RATE_LIMIT_BUFFER_DURATION has
     // elapsed, after which the current count for this breakdown will be reset.
     private static final long RATE_LIMIT_BUFFER_DURATION = 10 * DateUtils.MINUTE_IN_MILLIS;
-    // The time duration after which the rate limit buffer will be cleared.
-    private static final long RATE_LIMIT_BUFFER_EXPIRY = 3 * RATE_LIMIT_BUFFER_DURATION;
+    // Indicated how many buffer durations to wait before the rate limit buffer will be cleared.
+    // E.g. if set to 3 will wait 3xRATE_LIMIT_BUFFER_DURATION before clearing the buffer.
+    private static final long RATE_LIMIT_BUFFER_EXPIRY_FACTOR = 3;
     // The number of entries to keep per breakdown of process/eventType.
     private static final int RATE_LIMIT_ALLOWED_ENTRIES = 6;
 
+    // If a process is rate limited twice in a row we consider it crash-looping and rate limit it
+    // more aggressively.
+    private static final int STRICT_RATE_LIMIT_ALLOWED_ENTRIES = 1;
+    private static final long STRICT_RATE_LIMIT_BUFFER_DURATION = 60 * DateUtils.MINUTE_IN_MILLIS;
+
     @GuardedBy("mErrorClusterRecords")
     private final ArrayMap<String, ErrorRecord> mErrorClusterRecords = new ArrayMap<>();
     private final Clock mClock;
@@ -71,15 +77,27 @@
                 return new RateLimitResult(false, 0);
             }
 
-            if (now - errRecord.getStartTime() > RATE_LIMIT_BUFFER_DURATION) {
+            final long timeSinceFirstError = now - errRecord.getStartTime();
+            if (timeSinceFirstError > errRecord.getBufferDuration()) {
                 final int errCount = recentlyDroppedCount(errRecord);
                 errRecord.setStartTime(now);
                 errRecord.setCount(1);
+
+                // If this error happened exactly the next "rate limiting cycle" after the last
+                // error and the previous cycle was rate limiting then increment the successive
+                // rate limiting cycle counter. If a full "cycle" has passed since the last error
+                // then this is no longer a continuous occurrence and will be rate limited normally.
+                if (errCount > 0 && timeSinceFirstError < 2 * errRecord.getBufferDuration()) {
+                    errRecord.incrementSuccessiveRateLimitCycles();
+                } else {
+                    errRecord.setSuccessiveRateLimitCycles(0);
+                }
+
                 return new RateLimitResult(false, errCount);
             }
 
             errRecord.incrementCount();
-            if (errRecord.getCount() > RATE_LIMIT_ALLOWED_ENTRIES) {
+            if (errRecord.getCount() > errRecord.getAllowedEntries()) {
                 return new RateLimitResult(true, recentlyDroppedCount(errRecord));
             }
         }
@@ -91,16 +109,19 @@
      * dropped. Resets every RATE_LIMIT_BUFFER_DURATION if events are still actively created or
      * RATE_LIMIT_BUFFER_EXPIRY if not. */
     private int recentlyDroppedCount(ErrorRecord errRecord) {
-        if (errRecord == null || errRecord.getCount() < RATE_LIMIT_ALLOWED_ENTRIES) return 0;
-        return errRecord.getCount() - RATE_LIMIT_ALLOWED_ENTRIES;
+        if (errRecord == null || errRecord.getCount() < errRecord.getAllowedEntries()) return 0;
+        return errRecord.getCount() - errRecord.getAllowedEntries();
     }
 
 
-    private void maybeRemoveExpiredRecords(long now) {
-        if (now - mLastMapCleanUp <= RATE_LIMIT_BUFFER_EXPIRY) return;
+    private void maybeRemoveExpiredRecords(long currentTime) {
+        if (currentTime - mLastMapCleanUp
+                <= RATE_LIMIT_BUFFER_EXPIRY_FACTOR * RATE_LIMIT_BUFFER_DURATION) {
+            return;
+        }
 
         for (int i = mErrorClusterRecords.size() - 1; i >= 0; i--) {
-            if (now - mErrorClusterRecords.valueAt(i).getStartTime() > RATE_LIMIT_BUFFER_EXPIRY) {
+            if (mErrorClusterRecords.valueAt(i).hasExpired(currentTime)) {
                 Counter.logIncrement(
                         "stability_errors.value_dropbox_buffer_expired_count",
                         mErrorClusterRecords.valueAt(i).getCount());
@@ -108,7 +129,7 @@
             }
         }
 
-        mLastMapCleanUp = now;
+        mLastMapCleanUp = currentTime;
     }
 
     /** Resets the rate limiter memory. */
@@ -153,10 +174,12 @@
     private class ErrorRecord {
         long mStartTime;
         int mCount;
+        int mSuccessiveRateLimitCycles;
 
         ErrorRecord(long startTime, int count) {
             mStartTime = startTime;
             mCount = count;
+            mSuccessiveRateLimitCycles = 0;
         }
 
         public void setStartTime(long startTime) {
@@ -171,6 +194,14 @@
             mCount++;
         }
 
+        public void setSuccessiveRateLimitCycles(int successiveRateLimitCycles) {
+            mSuccessiveRateLimitCycles = successiveRateLimitCycles;
+        }
+
+        public void incrementSuccessiveRateLimitCycles() {
+            mSuccessiveRateLimitCycles++;
+        }
+
         public long getStartTime() {
             return mStartTime;
         }
@@ -178,6 +209,27 @@
         public int getCount() {
             return mCount;
         }
+
+        public int getSuccessiveRateLimitCycles() {
+            return mSuccessiveRateLimitCycles;
+        }
+
+        public boolean isRepeated() {
+            return mSuccessiveRateLimitCycles >= 2;
+        }
+
+        public int getAllowedEntries() {
+            return isRepeated() ? STRICT_RATE_LIMIT_ALLOWED_ENTRIES : RATE_LIMIT_ALLOWED_ENTRIES;
+        }
+
+        public long getBufferDuration() {
+            return isRepeated() ? STRICT_RATE_LIMIT_BUFFER_DURATION : RATE_LIMIT_BUFFER_DURATION;
+        }
+
+        public boolean hasExpired(long currentTime) {
+            long bufferExpiry = RATE_LIMIT_BUFFER_EXPIRY_FACTOR * getBufferDuration();
+            return currentTime - mStartTime > bufferExpiry;
+        }
     }
 
     private static class DefaultClock implements Clock {
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index 1534ff5..50841ae 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -122,9 +122,9 @@
 30091 um_user_visibility_changed (userId|1|5),(visible|1)
 
 # Foreground service start/stop events.
-30100 am_foreground_service_start (User|1|5),(Component Name|3),(allowWhileInUse|1),(startReasonCode|3),(targetSdk|1|1),(callerTargetSdk|1|1),(notificationWasDeferred|1),(notificationShown|1),(durationMs|1|3),(startForegroundCount|1|1),(stopReason|3)
-30101 am_foreground_service_denied (User|1|5),(Component Name|3),(allowWhileInUse|1),(startReasonCode|3),(targetSdk|1|1),(callerTargetSdk|1|1),(notificationWasDeferred|1),(notificationShown|1),(durationMs|1|3),(startForegroundCount|1|1),(stopReason|3)
-30102 am_foreground_service_stop (User|1|5),(Component Name|3),(allowWhileInUse|1),(startReasonCode|3),(targetSdk|1|1),(callerTargetSdk|1|1),(notificationWasDeferred|1),(notificationShown|1),(durationMs|1|3),(startForegroundCount|1|1),(stopReason|3)
+30100 am_foreground_service_start (User|1|5),(Component Name|3),(allowWhileInUse|1),(startReasonCode|3),(targetSdk|1|1),(callerTargetSdk|1|1),(notificationWasDeferred|1),(notificationShown|1),(durationMs|1|3),(startForegroundCount|1|1),(stopReason|3),(fgsType|1)
+30101 am_foreground_service_denied (User|1|5),(Component Name|3),(allowWhileInUse|1),(startReasonCode|3),(targetSdk|1|1),(callerTargetSdk|1|1),(notificationWasDeferred|1),(notificationShown|1),(durationMs|1|3),(startForegroundCount|1|1),(stopReason|3),(fgsType|1)
+30102 am_foreground_service_stop (User|1|5),(Component Name|3),(allowWhileInUse|1),(startReasonCode|3),(targetSdk|1|1),(callerTargetSdk|1|1),(notificationWasDeferred|1),(notificationShown|1),(durationMs|1|3),(startForegroundCount|1|1),(stopReason|3),(fgsType|1)
 
 # Intent Sender redirect for UserHandle.USER_CURRENT
 30110 am_intent_sender_redirect_user (userId|1|5)
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 0c36626..a944f6f 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -22,8 +22,8 @@
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
-import static android.app.ActivityManager.PROCESS_CAPABILITY_NETWORK;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
 import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
 import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
 import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
@@ -117,6 +117,7 @@
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ServiceInfo;
+import android.net.NetworkPolicyManager;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.PowerManagerInternal;
@@ -127,7 +128,6 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Slog;
-import android.util.SparseSetArray;
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.CompositeRWLock;
@@ -207,7 +207,8 @@
                 return AppProtoEnums.OOM_ADJ_REASON_PROCESS_BEGIN;
             case OOM_ADJ_REASON_PROCESS_END:
                 return AppProtoEnums.OOM_ADJ_REASON_PROCESS_END;
-            case OOM_ADJ_REASON_SHORT_FGS_TIMEOUT: // TODO(short-service) add value to AppProtoEnums
+            case OOM_ADJ_REASON_SHORT_FGS_TIMEOUT:
+                return AppProtoEnums.OOM_ADJ_REASON_SHORT_FGS_TIMEOUT;
             default:
                 return AppProtoEnums.OOM_ADJ_REASON_UNKNOWN_TO_PROTO;
         }
@@ -366,19 +367,6 @@
     @GuardedBy("mService")
     private boolean mPendingFullOomAdjUpdate = false;
 
-    /**
-     * PIDs that has a SHORT_SERVICE. We need to access it with the PowerManager lock held,
-     * so we use a fine-grained lock here.
-     */
-    @GuardedBy("mPidsWithShortFgs")
-    private final ArraySet<Integer> mPidsWithShortFgs = new ArraySet<>();
-
-    /**
-     * UIDs -> PIDs map, used with mPidsWithShortFgs.
-     */
-    @GuardedBy("mPidsWithShortFgs")
-    private final SparseSetArray<Integer> mUidsToPidsWithShortFgs = new SparseSetArray<>();
-
     /** Overrideable by a test */
     @VisibleForTesting
     protected boolean isChangeEnabled(@CachedCompatChangeId int cachedCompatChangeId,
@@ -1955,7 +1943,6 @@
                 }
             }
         }
-        updateShortFgsOwner(psr.mApp.uid, psr.mApp.mPid, hasShortForegroundServices);
 
         // If the app was recently in the foreground and moved to a foreground service status,
         // allow it to get a higher rank in memory for some time, compared to other foreground
@@ -2184,8 +2171,6 @@
                 }
             }
 
-            // TODO(short-service): While-in-user permissions. Do we need any change here for
-            // short-FGS? (Likely not)
             if (s.isForeground) {
                 final int fgsType = s.foregroundServiceType;
                 if (s.mAllowWhileInUsePermissionInFgs) {
@@ -2276,14 +2261,15 @@
                         // elevated to a high enough procstate anyway to get network unless they
                         // request otherwise, so don't propagate the network capability by default
                         // in this case unless they explicitly request it.
-                        if ((cstate.getCurCapability() & PROCESS_CAPABILITY_NETWORK) != 0) {
+                        if ((cstate.getCurCapability()
+                                & PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0) {
                             if (clientProcState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
                                 // This is used to grant network access to Expedited Jobs.
                                 if (cr.hasFlag(Context.BIND_BYPASS_POWER_NETWORK_RESTRICTIONS)) {
-                                    capability |= PROCESS_CAPABILITY_NETWORK;
+                                    capability |= PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
                                 }
                             } else {
-                                capability |= PROCESS_CAPABILITY_NETWORK;
+                                capability |= PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
                             }
                         }
 
@@ -2794,27 +2780,33 @@
     }
 
     private int getDefaultCapability(ProcessRecord app, int procState) {
+        final int networkCapabilities =
+                NetworkPolicyManager.getDefaultProcessNetworkCapabilities(procState);
+        final int baseCapabilities;
         switch (procState) {
             case PROCESS_STATE_PERSISTENT:
             case PROCESS_STATE_PERSISTENT_UI:
             case PROCESS_STATE_TOP:
-                return PROCESS_CAPABILITY_ALL; // BFSL allowed
+                baseCapabilities = PROCESS_CAPABILITY_ALL; // BFSL allowed
+                break;
             case PROCESS_STATE_BOUND_TOP:
-                return PROCESS_CAPABILITY_NETWORK | PROCESS_CAPABILITY_BFSL;
+                baseCapabilities = PROCESS_CAPABILITY_BFSL;
+                break;
             case PROCESS_STATE_FOREGROUND_SERVICE:
                 if (app.getActiveInstrumentation() != null) {
-                    return PROCESS_CAPABILITY_ALL_IMPLICIT | PROCESS_CAPABILITY_NETWORK ;
+                    baseCapabilities = PROCESS_CAPABILITY_ALL_IMPLICIT;
                 } else {
                     // Capability from foreground service is conditional depending on
                     // foregroundServiceType in the manifest file and the
                     // mAllowWhileInUsePermissionInFgs flag.
-                    return PROCESS_CAPABILITY_NETWORK;
+                    baseCapabilities = PROCESS_CAPABILITY_NONE;
                 }
-            case PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
-                return PROCESS_CAPABILITY_NETWORK;
+                break;
             default:
-                return PROCESS_CAPABILITY_NONE;
+                baseCapabilities = PROCESS_CAPABILITY_NONE;
+                break;
         }
+        return baseCapabilities | networkCapabilities;
     }
 
     /**
@@ -3467,40 +3459,4 @@
             mCachedAppOptimizer.unfreezeAppLSP(app, oomAdjReason);
         }
     }
-
-    /**
-     * Update {@link #mPidsWithShortFgs} and {@link #mUidsToPidsWithShortFgs} to keep track
-     * of which UID/PID has a short FGS.
-     *
-     * TODO(short-FGS): Remove it and all the relevant code once SHORT_FGS use the FGS procstate.
-     */
-    void updateShortFgsOwner(int uid, int pid, boolean add) {
-        synchronized (mPidsWithShortFgs) {
-            if (add) {
-                mUidsToPidsWithShortFgs.add(uid, pid);
-                mPidsWithShortFgs.add(pid);
-            } else {
-                mUidsToPidsWithShortFgs.remove(uid, pid);
-                mPidsWithShortFgs.remove(pid);
-            }
-        }
-    }
-
-    /**
-     * Whether a UID has a (non-timed-out) short FGS or not.
-     * It's indirectly called by PowerManager, so we can't hold the AM lock in it.
-     */
-    boolean hasUidShortForegroundService(int uid) {
-        synchronized (mPidsWithShortFgs) {
-            final ArraySet<Integer> pids = mUidsToPidsWithShortFgs.get(uid);
-            if (pids == null || pids.size() == 0) {
-                return false;
-            }
-            for (int i = pids.size() - 1; i >= 0; i--) {
-                final int pid = pids.valueAt(i);
-                return mPidsWithShortFgs.contains(pid);
-            }
-        }
-        return false;
-    }
 }
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index f4e2b0f..35f71f7 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -3100,9 +3100,10 @@
                 hostingRecord.getDefiningUid(), hostingRecord.getDefiningProcessName());
         final ProcessStateRecord state = r.mState;
 
-        if (!mService.mBooted && !mService.mBooting
+        if (!isolated && !isSdkSandbox
                 && userId == UserHandle.USER_SYSTEM
-                && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
+                && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK
+                && (TextUtils.equals(proc, info.processName))) {
             // The system process is initialized to SCHED_GROUP_DEFAULT in init.rc.
             state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT);
             state.setSetSchedGroup(ProcessList.SCHED_GROUP_DEFAULT);
diff --git a/services/core/java/com/android/server/am/SameProcessApplicationThread.java b/services/core/java/com/android/server/am/SameProcessApplicationThread.java
index 82dd5c2..6deaf7b 100644
--- a/services/core/java/com/android/server/am/SameProcessApplicationThread.java
+++ b/services/core/java/com/android/server/am/SameProcessApplicationThread.java
@@ -25,6 +25,7 @@
 import android.content.res.CompatibilityInfo;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.RemoteCallback;
 import android.os.RemoteException;
 
 import java.util.List;
@@ -77,17 +78,23 @@
 
     @Override
     public void scheduleReceiverList(List<ReceiverInfo> info) {
-        for (int i = 0; i < info.size(); i++) {
-            ReceiverInfo r = info.get(i);
-            if (r.registered) {
-                scheduleRegisteredReceiver(r.receiver, r.intent,
-                        r.resultCode, r.data, r.extras, r.ordered, r.sticky, r.assumeDelivered,
-                        r.sendingUser, r.processState, r.sendingUid, r.sendingPackage);
-            } else {
-                scheduleReceiver(r.intent, r.activityInfo, r.compatInfo,
-                        r.resultCode, r.data, r.extras, r.sync, r.assumeDelivered,
-                        r.sendingUser, r.processState, r.sendingUid, r.sendingPackage);
+        mHandler.post(() -> {
+            try {
+                mWrapped.scheduleReceiverList(info);
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
             }
-        }
+        });
+    }
+
+    @Override
+    public void schedulePing(RemoteCallback pong) {
+        mHandler.post(() -> {
+            try {
+                mWrapped.schedulePing(pong);
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+        });
     }
 }
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index ae8ceab..663121e 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -392,6 +392,15 @@
             return mStartTime + ams.mConstants.mShortFgsTimeoutDuration
                     + ams.mConstants.mShortFgsAnrExtraWaitDuration;
         }
+
+        String getDescription() {
+            return "sfc=" + this.mStartForegroundCount
+                    + " sid=" + this.mStartId
+                    + " stime=" + this.mStartTime
+                    + " tt=" + this.getTimeoutTime()
+                    + " dt=" + this.getProcStateDemoteTime()
+                    + " at=" + this.getAnrTime();
+        }
     }
 
     /**
@@ -468,6 +477,8 @@
             long fgToken = proto.start(ServiceRecordProto.FOREGROUND);
             proto.write(ServiceRecordProto.Foreground.ID, foregroundId);
             foregroundNoti.dumpDebug(proto, ServiceRecordProto.Foreground.NOTIFICATION);
+            proto.write(ServiceRecordProto.Foreground.FOREGROUND_SERVICE_TYPE,
+                    foregroundServiceType);
             proto.end(fgToken);
         }
         ProtoUtils.toDuration(proto, ServiceRecordProto.CREATE_REAL_TIME, createRealTime, nowReal);
@@ -1411,10 +1422,7 @@
         this.mShortFgsInfo = null;
     }
 
-    /**
-     * @return true if it's a short FGS that's still up and running, and should be timed out.
-     */
-    public boolean shouldTriggerShortFgsTimeout() {
+    private boolean shouldTriggerShortFgsTimedEvent(long targetTime, long nowUptime) {
         if (!isAppAlive()) {
             return false;
         }
@@ -1422,36 +1430,48 @@
                 || !mShortFgsInfo.isCurrent()) {
             return false;
         }
-        return mShortFgsInfo.getTimeoutTime() <= SystemClock.uptimeMillis();
+        return targetTime <= nowUptime;
+    }
+
+    /**
+     * @return true if it's a short FGS that's still up and running, and should be timed out.
+     */
+    public boolean shouldTriggerShortFgsTimeout(long nowUptime) {
+        return shouldTriggerShortFgsTimedEvent(
+                (mShortFgsInfo == null ? 0 : mShortFgsInfo.getTimeoutTime()),
+                nowUptime);
     }
 
     /**
      * @return true if it's a short FGS's procstate should be demoted.
      */
-    public boolean shouldDemoteShortFgsProcState() {
-        if (!isAppAlive()) {
-            return false;
-        }
-        if (!this.startRequested || !isShortFgs() || mShortFgsInfo == null
-                || !mShortFgsInfo.isCurrent()) {
-            return false;
-        }
-        return mShortFgsInfo.getProcStateDemoteTime() <= SystemClock.uptimeMillis();
+    public boolean shouldDemoteShortFgsProcState(long nowUptime) {
+        return shouldTriggerShortFgsTimedEvent(
+                (mShortFgsInfo == null ? 0 : mShortFgsInfo.getProcStateDemoteTime()),
+                nowUptime);
     }
 
     /**
      * @return true if it's a short FGS that's still up and running, and should be declared
      * an ANR.
      */
-    public boolean shouldTriggerShortFgsAnr() {
-        if (!isAppAlive()) {
-            return false;
-        }
-        if (!this.startRequested || !isShortFgs() || mShortFgsInfo == null
-                || !mShortFgsInfo.isCurrent()) {
-            return false;
-        }
-        return mShortFgsInfo.getAnrTime() <= SystemClock.uptimeMillis();
+    public boolean shouldTriggerShortFgsAnr(long nowUptime) {
+        return shouldTriggerShortFgsTimedEvent(
+                (mShortFgsInfo == null ? 0 : mShortFgsInfo.getAnrTime()),
+                nowUptime);
+    }
+
+    /**
+     * Human readable description about short-FGS internal states.
+     */
+    public String getShortFgsTimedEventDescription(long nowUptime) {
+        return "aa=" + isAppAlive()
+                + " sreq=" + this.startRequested
+                + " isfg=" + this.isForeground
+                + " type=" + Integer.toHexString(this.foregroundServiceType)
+                + " sfc=" + this.mStartForegroundCount
+                + " now=" + nowUptime
+                + " " + (mShortFgsInfo == null ? "" : mShortFgsInfo.getDescription());
     }
 
     private boolean isAppAlive() {
diff --git a/services/core/java/com/android/server/am/TEST_MAPPING b/services/core/java/com/android/server/am/TEST_MAPPING
index c6a8bcd..97d4879 100644
--- a/services/core/java/com/android/server/am/TEST_MAPPING
+++ b/services/core/java/com/android/server/am/TEST_MAPPING
@@ -3,9 +3,11 @@
     {
       "name": "CtsAppTestCases",
       "options": [
-        {
-          "include-filter": "android.app.cts.TaskDescriptionTest"
-        },
+        { "include-filter": "android.app.cts.TaskDescriptionTest" },
+        { "include-filter": "android.app.cts.ActivityManagerTest" },
+        { "include-filter": "android.app.cts.ActivityManagerProcessStateTest" },
+        { "include-filter": "android.app.cts.ServiceTest" },
+        { "include-filter": "android.app.cts.ActivityManagerFgsBgStartTest" },
         {
           "include-annotation": "android.platform.test.annotations.Presubmit"
         },
@@ -14,7 +16,8 @@
         },
         {
           "exclude-annotation": "androidx.test.filters.FlakyTest"
-        }
+        },
+        { "exclude-annotation": "org.junit.Ignore" }
       ]
     },
     {
@@ -106,9 +109,7 @@
         { "exclude-annotation": "androidx.test.filters.FlakyTest" },
         { "exclude-annotation": "org.junit.Ignore" }
       ]
-    }
-  ],
-  "presubmit-large": [
+    },
     {
       "name": "CtsUsageStatsTestCases",
       "file_patterns": [
@@ -150,6 +151,16 @@
           "include-filter": "android.appsecurity.cts.AppDataIsolationTests"
         }
       ]
+    },
+    {
+      "name": "CtsAppTestCases",
+      "options": [
+        { "include-filter": "android.app.cts.TaskDescriptionTest" },
+        { "include-filter": "android.app.cts.ActivityManagerTest" },
+        { "include-filter": "android.app.cts.ActivityManagerProcessStateTest" },
+        { "include-filter": "android.app.cts.ServiceTest" },
+        { "include-filter": "android.app.cts.ActivityManagerFgsBgStartTest" }
+      ]
     }
   ]
 }
diff --git a/services/core/java/com/android/server/appop/AppOpsCheckingServiceTracingDecorator.java b/services/core/java/com/android/server/appop/AppOpsCheckingServiceTracingDecorator.java
index dd06464..a028ae1 100644
--- a/services/core/java/com/android/server/appop/AppOpsCheckingServiceTracingDecorator.java
+++ b/services/core/java/com/android/server/appop/AppOpsCheckingServiceTracingDecorator.java
@@ -32,7 +32,7 @@
  * Trace.traceEnd. These traces are used for performance testing.
  */
 public class AppOpsCheckingServiceTracingDecorator implements AppOpsCheckingServiceInterface {
-    private static final long TRACE_TAG = Trace.TRACE_TAG_SYSTEM_SERVER;
+    private static final long TRACE_TAG = Trace.TRACE_TAG_ACTIVITY_MANAGER;
     private final AppOpsCheckingServiceInterface mService;
 
     AppOpsCheckingServiceTracingDecorator(
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 5bea614..fc22935 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -2096,7 +2096,9 @@
                         final int code = opModes.keyAt(j);
                         if (AppOpsManager.opAllowsReset(code)) {
                             int previousMode = opModes.valueAt(j);
-                            uidState.setUidMode(code, AppOpsManager.opToDefaultMode(code));
+                            int newMode = isUidOpGrantedByRole(uidState.uid, code) ? MODE_ALLOWED :
+                                    AppOpsManager.opToDefaultMode(code);
+                            uidState.setUidMode(code, newMode);
                             for (String packageName : getPackagesForUid(uidState.uid)) {
                                 callbacks = addCallbacks(callbacks, code, uidState.uid, packageName,
                                         previousMode,
@@ -2139,10 +2141,15 @@
                             deferResetOpToDpm(curOp.op, reqPackageName, reqUserId);
                             continue;
                         }
-                        if (AppOpsManager.opAllowsReset(curOp.op)
-                                && curOp.getMode() != AppOpsManager.opToDefaultMode(curOp.op)) {
+                        if (AppOpsManager.opAllowsReset(curOp.op)) {
                             int previousMode = curOp.getMode();
-                            curOp.setMode(AppOpsManager.opToDefaultMode(curOp.op));
+                            int newMode = isPackageOpGrantedByRole(packageName, uidState.uid,
+                                    curOp.op) ? MODE_ALLOWED : AppOpsManager.opToDefaultMode(
+                                    curOp.op);
+                            if (previousMode == newMode) {
+                                continue;
+                            }
+                            curOp.setMode(newMode);
                             changed = true;
                             uidChanged = true;
                             final int uid = curOp.uidState.uid;
@@ -2198,6 +2205,41 @@
         }
     }
 
+    private boolean isUidOpGrantedByRole(int uid, int code) {
+        if (!AppOpsManager.opIsUidAppOpPermission(code)) {
+            return false;
+        }
+        PackageManager packageManager = mContext.getPackageManager();
+        long token = Binder.clearCallingIdentity();
+        try {
+            // Permissions are managed by UIDs, but unfortunately a package name is required in API.
+            String packageName = ArrayUtils.firstOrNull(packageManager.getPackagesForUid(uid));
+            if (packageName == null) {
+                return false;
+            }
+            int permissionFlags = packageManager.getPermissionFlags(AppOpsManager.opToPermission(
+                    code), packageName, UserHandle.getUserHandleForUid(uid));
+            return (permissionFlags & PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE) != 0;
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    private boolean isPackageOpGrantedByRole(@NonNull String packageName, int uid, int code) {
+        if (!AppOpsManager.opIsPackageAppOpPermission(code)) {
+            return false;
+        }
+        PackageManager packageManager = mContext.getPackageManager();
+        long token = Binder.clearCallingIdentity();
+        try {
+            int permissionFlags = packageManager.getPermissionFlags(AppOpsManager.opToPermission(
+                    code), packageName, UserHandle.getUserHandleForUid(uid));
+            return (permissionFlags & PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE) != 0;
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
     private boolean shouldDeferResetOpToDpm(int op) {
         // TODO(b/174582385): avoid special-casing app-op resets by migrating app-op permission
         //  pre-grants to a role-based mechanism or another general-purpose mechanism.
diff --git a/services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java b/services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java
index 49279d4..23a384f 100644
--- a/services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java
+++ b/services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java
@@ -67,8 +67,8 @@
     private SparseIntArray mPendingUidStates = new SparseIntArray();
     private SparseIntArray mCapability = new SparseIntArray();
     private SparseIntArray mPendingCapability = new SparseIntArray();
-    private SparseBooleanArray mVisibleAppWidget = new SparseBooleanArray();
-    private SparseBooleanArray mPendingVisibleAppWidget = new SparseBooleanArray();
+    private SparseBooleanArray mAppWidgetVisible = new SparseBooleanArray();
+    private SparseBooleanArray mPendingAppWidgetVisible = new SparseBooleanArray();
     private SparseLongArray mPendingCommitTime = new SparseLongArray();
     private SparseBooleanArray mPendingGone = new SparseBooleanArray();
 
@@ -140,7 +140,7 @@
 
     private int evalModeInternal(int uid, int code, int uidState, int uidCapability) {
 
-        if (getUidVisibleAppWidget(uid) || mActivityManagerInternal.isPendingTopUid(uid)
+        if (getUidAppWidgetVisible(uid) || mActivityManagerInternal.isPendingTopUid(uid)
                 || mActivityManagerInternal.isTempAllowlistedForFgsWhileInUse(uid)) {
             return MODE_ALLOWED;
         }
@@ -205,7 +205,7 @@
         int numUids = uidPackageNames.size();
         for (int i = 0; i < numUids; i++) {
             int uid = uidPackageNames.keyAt(i);
-            mPendingVisibleAppWidget.put(uid, visible);
+            mPendingAppWidgetVisible.put(uid, visible);
 
             commitUidPendingState(uid);
         }
@@ -213,8 +213,6 @@
 
     @Override
     public void updateUidProcState(int uid, int procState, int capability) {
-        mEventLog.logUpdateUidProcState(uid, procState, capability);
-
         int uidState = processStateToUidState(procState);
 
         int prevUidState = mUidStates.get(uid, AppOpsManager.MIN_PRIORITY_UID_STATE);
@@ -226,6 +224,10 @@
                 && (uidState != prevUidState || capability != prevCapability))
                 || (pendingStateCommitTime != 0
                 && (uidState != pendingUidState || capability != pendingCapability))) {
+
+            // If this process update results in a capability or uid state change, log it. It's
+            // not interesting otherwise.
+            mEventLog.logUpdateUidProcState(uid, procState, capability);
             mPendingUidStates.put(uid, uidState);
             mPendingCapability.put(uid, capability);
 
@@ -289,9 +291,9 @@
             ActivityManager.printCapabilitiesFull(pw, pendingCapability);
             pw.println();
         }
-        boolean appWidgetVisible = mVisibleAppWidget.get(uid, false);
+        boolean appWidgetVisible = mAppWidgetVisible.get(uid, false);
         // if no pendingAppWidgetVisible set to appWidgetVisible to suppress output
-        boolean pendingAppWidgetVisible = mPendingVisibleAppWidget.get(uid, appWidgetVisible);
+        boolean pendingAppWidgetVisible = mPendingAppWidgetVisible.get(uid, appWidgetVisible);
         pw.print("    appWidgetVisible=");
         pw.println(appWidgetVisible);
         if (appWidgetVisible != pendingAppWidgetVisible) {
@@ -327,26 +329,29 @@
     }
 
     private void commitUidPendingState(int uid) {
-        int pendingUidState = mPendingUidStates.get(uid, MIN_PRIORITY_UID_STATE);
-        int pendingCapability = mPendingCapability.get(uid, PROCESS_CAPABILITY_NONE);
-        boolean pendingVisibleAppWidget = mPendingVisibleAppWidget.get(uid, false);
+        int pendingUidState = mPendingUidStates.get(uid,
+                mUidStates.get(uid, MIN_PRIORITY_UID_STATE));
+        int pendingCapability = mPendingCapability.get(uid,
+                mCapability.get(uid, PROCESS_CAPABILITY_NONE));
+        boolean pendingAppWidgetVisible = mPendingAppWidgetVisible.get(uid,
+                mAppWidgetVisible.get(uid, false));
 
         int uidState = mUidStates.get(uid, MIN_PRIORITY_UID_STATE);
         int capability = mCapability.get(uid, PROCESS_CAPABILITY_NONE);
-        boolean visibleAppWidget = mVisibleAppWidget.get(uid, false);
+        boolean appWidgetVisible = mAppWidgetVisible.get(uid, false);
 
         if (uidState != pendingUidState
                 || capability != pendingCapability
-                || visibleAppWidget != pendingVisibleAppWidget) {
+                || appWidgetVisible != pendingAppWidgetVisible) {
             boolean foregroundChange = uidState <= UID_STATE_MAX_LAST_NON_RESTRICTED
                     != pendingUidState <= UID_STATE_MAX_LAST_NON_RESTRICTED
                     || capability != pendingCapability
-                    || visibleAppWidget != pendingVisibleAppWidget;
+                    || appWidgetVisible != pendingAppWidgetVisible;
 
             if (foregroundChange) {
                 // To save on memory usage, log only interesting changes.
                 mEventLog.logCommitUidState(uid, pendingUidState, pendingCapability,
-                        pendingVisibleAppWidget);
+                        pendingAppWidgetVisible, appWidgetVisible != pendingAppWidgetVisible);
             }
 
             for (int i = 0; i < mUidStateChangedCallbacks.size(); i++) {
@@ -362,17 +367,17 @@
         if (mPendingGone.get(uid, false)) {
             mUidStates.delete(uid);
             mCapability.delete(uid);
-            mVisibleAppWidget.delete(uid);
+            mAppWidgetVisible.delete(uid);
             mPendingGone.delete(uid);
         } else {
             mUidStates.put(uid, pendingUidState);
             mCapability.put(uid, pendingCapability);
-            mVisibleAppWidget.put(uid, pendingVisibleAppWidget);
+            mAppWidgetVisible.put(uid, pendingAppWidgetVisible);
         }
 
         mPendingUidStates.delete(uid);
         mPendingCapability.delete(uid);
-        mPendingVisibleAppWidget.delete(uid);
+        mPendingAppWidgetVisible.delete(uid);
         mPendingCommitTime.delete(uid);
     }
 
@@ -380,21 +385,22 @@
         return mCapability.get(uid, ActivityManager.PROCESS_CAPABILITY_NONE);
     }
 
-    private boolean getUidVisibleAppWidget(int uid) {
-        return mVisibleAppWidget.get(uid, false);
+    private boolean getUidAppWidgetVisible(int uid) {
+        return mAppWidgetVisible.get(uid, false);
     }
 
     private static class EventLog {
 
-        // These seems a bit too verbose and not as useful, turning off for now.
-        // DCE should be able to remove most associated code.
         // Memory usage: 16 * size bytes
-        private static final int UPDATE_UID_PROC_STATE_LOG_MAX_SIZE = 0;
+        private static final int UPDATE_UID_PROC_STATE_LOG_MAX_SIZE = 200;
         // Memory usage: 20 * size bytes
         private static final int COMMIT_UID_STATE_LOG_MAX_SIZE = 200;
         // Memory usage: 24 * size bytes
         private static final int EVAL_FOREGROUND_MODE_MAX_SIZE = 200;
 
+        private static final int APP_WIDGET_VISIBLE = 1 << 0;
+        private static final int APP_WIDGET_VISIBLE_CHANGED = 1 << 1;
+
         private final DelayableExecutor mExecutor;
         private final Thread mExecutorThread;
 
@@ -443,16 +449,18 @@
             mUpdateUidProcStateLogTimestamps[idx] = timestamp;
         }
 
-        void logCommitUidState(int uid, int uidState, int capability, boolean visible) {
+        void logCommitUidState(int uid, int uidState, int capability, boolean appWidgetVisible,
+                boolean appWidgetVisibleChanged) {
             if (COMMIT_UID_STATE_LOG_MAX_SIZE == 0) {
                 return;
             }
             mExecutor.execute(PooledLambda.obtainRunnable(EventLog::logCommitUidStateAsync,
-                    this, System.currentTimeMillis(), uid, uidState, capability, visible));
+                    this, System.currentTimeMillis(), uid, uidState, capability, appWidgetVisible,
+                    appWidgetVisibleChanged));
         }
 
         void logCommitUidStateAsync(long timestamp, int uid, int uidState, int capability,
-                boolean visible) {
+                boolean appWidgetVisible, boolean appWidgetVisibleChanged) {
             int idx = (mCommitUidStateLogHead + mCommitUidStateLogSize)
                     % COMMIT_UID_STATE_LOG_MAX_SIZE;
             if (mCommitUidStateLogSize == COMMIT_UID_STATE_LOG_MAX_SIZE) {
@@ -465,7 +473,13 @@
             mCommitUidStateLog[idx][0] = uid;
             mCommitUidStateLog[idx][1] = uidState;
             mCommitUidStateLog[idx][2] = capability;
-            mCommitUidStateLog[idx][3] = visible ? 1 : 0;
+            mCommitUidStateLog[idx][3] = 0;
+            if (appWidgetVisible) {
+                mCommitUidStateLog[idx][3] += APP_WIDGET_VISIBLE;
+            }
+            if (appWidgetVisibleChanged) {
+                mCommitUidStateLog[idx][3] += APP_WIDGET_VISIBLE_CHANGED;
+            }
             mCommitUidStateLogTimestamps[idx] = timestamp;
         }
 
@@ -567,7 +581,9 @@
             int uid = mCommitUidStateLog[idx][0];
             int uidState = mCommitUidStateLog[idx][1];
             int capability = mCommitUidStateLog[idx][2];
-            boolean visibleAppWidget = mCommitUidStateLog[idx][3] != 0;
+            boolean appWidgetVisible = (mCommitUidStateLog[idx][3] & APP_WIDGET_VISIBLE) != 0;
+            boolean appWidgetVisibleChanged =
+                    (mCommitUidStateLog[idx][3] & APP_WIDGET_VISIBLE_CHANGED) != 0;
 
             TimeUtils.dumpTime(pw, timestamp);
 
@@ -582,8 +598,12 @@
             pw.print(" capability=");
             pw.print(ActivityManager.getCapabilitiesSummary(capability) + " ");
 
-            pw.print(" visibleAppWidget=");
-            pw.print(visibleAppWidget);
+            pw.print(" appWidgetVisible=");
+            pw.print(appWidgetVisible);
+
+            if (appWidgetVisibleChanged) {
+                pw.print(" (changed)");
+            }
 
             pw.println();
         }
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 45181e8..490a33e 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1315,7 +1315,7 @@
         // persistent data
         initVolumeGroupStates();
 
-        mSoundDoseHelper.initSafeUsbMediaVolumeIndex();
+        mSoundDoseHelper.initSafeMediaVolumeIndex();
         // Link VGS on VSS
         initVolumeStreamStates();
 
@@ -3928,8 +3928,10 @@
     }
 
     @Override
-    @android.annotation.EnforcePermission(anyOf =
-            {"MODIFY_AUDIO_ROUTING", "MODIFY_AUDIO_SETTINGS_PRIVILEGED"})
+    @android.annotation.EnforcePermission(anyOf = {
+            android.Manifest.permission.MODIFY_AUDIO_ROUTING,
+            android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED
+    })
     /** @see AudioDeviceVolumeManager#setDeviceVolume(VolumeInfo, AudioDeviceAttributes)
      * Part of service interface, check permissions and parameters here
      * Note calling package is for logging purposes only, not to be trusted
@@ -4945,8 +4947,10 @@
     }
 
     @Override
-    @android.annotation.EnforcePermission(anyOf =
-            {"MODIFY_AUDIO_ROUTING", "MODIFY_AUDIO_SETTINGS_PRIVILEGED"})
+    @android.annotation.EnforcePermission(anyOf = {
+            android.Manifest.permission.MODIFY_AUDIO_ROUTING,
+            android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED
+    })
     /**
      * @see AudioDeviceVolumeManager#getDeviceVolume(VolumeInfo, AudioDeviceAttributes)
      */
@@ -7214,8 +7218,10 @@
      * @param device the audio device to be affected
      * @param deviceVolumeBehavior one of the device behaviors
      */
-    @android.annotation.EnforcePermission(anyOf =
-            {"MODIFY_AUDIO_ROUTING", "MODIFY_AUDIO_SETTINGS_PRIVILEGED"})
+    @android.annotation.EnforcePermission(anyOf = {
+            android.Manifest.permission.MODIFY_AUDIO_ROUTING,
+            android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED
+    })
     public void setDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device,
             @AudioManager.DeviceVolumeBehavior int deviceVolumeBehavior, @Nullable String pkgName) {
         // verify permissions
@@ -7295,8 +7301,11 @@
      * @param device the audio output device type
      * @return the volume behavior for the device
      */
-    @android.annotation.EnforcePermission(anyOf =
-            {"MODIFY_AUDIO_ROUTING", "QUERY_AUDIO_STATE", "MODIFY_AUDIO_SETTINGS_PRIVILEGED"})
+    @android.annotation.EnforcePermission(anyOf = {
+            android.Manifest.permission.MODIFY_AUDIO_ROUTING,
+            android.Manifest.permission.QUERY_AUDIO_STATE,
+            android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED
+    })
     public @AudioManager.DeviceVolumeBehavior
     int getDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device) {
         // verify permissions
@@ -8588,7 +8597,9 @@
                     if (isMutable()) {
                         // For call stream, align mute only when muted, not when index is set to 0
                         mVolumeGroupState.mute(
-                                forceMuteState ? mIsMuted : groupIndex == 0 || mIsMuted);
+                                forceMuteState ? mIsMuted :
+                                        (groupIndex == 0 && !isCallStream(mStreamType))
+                                                || mIsMuted);
                     }
                 }
             }
@@ -8837,7 +8848,7 @@
         final VolumeStreamState streamState = mStreamStates[update.mStreamType];
         if (update.hasVolumeIndex()) {
             int index = update.getVolumeIndex();
-            if (!mSoundDoseHelper.checkSafeMediaVolume(update.mStreamType, index, update.mDevice)) {
+            if (mSoundDoseHelper.checkSafeMediaVolume(update.mStreamType, index, update.mDevice)) {
                 index = mSoundDoseHelper.safeMediaVolumeIndex(update.mDevice);
             }
             streamState.setIndex(index, update.mDevice, update.mCaller,
diff --git a/services/core/java/com/android/server/audio/SoundDoseHelper.java b/services/core/java/com/android/server/audio/SoundDoseHelper.java
index 4b30234..3dac04c 100644
--- a/services/core/java/com/android/server/audio/SoundDoseHelper.java
+++ b/services/core/java/com/android/server/audio/SoundDoseHelper.java
@@ -52,10 +52,9 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashSet;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Objects;
-import java.util.Set;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Collectors;
 
@@ -80,7 +79,6 @@
     // SAFE_MEDIA_VOLUME_DISABLED according to country option. If not SAFE_MEDIA_VOLUME_DISABLED, it
     // can be set to SAFE_MEDIA_VOLUME_INACTIVE by calling AudioService.disableSafeMediaVolume()
     // (when user opts out).
-    // Note: when CSD calculation is enabled the state is set to SAFE_MEDIA_VOLUME_DISABLED
     private static final int SAFE_MEDIA_VOLUME_NOT_CONFIGURED = 0;
     private static final int SAFE_MEDIA_VOLUME_DISABLED = 1;
     private static final int SAFE_MEDIA_VOLUME_INACTIVE = 2;  // confirmed
@@ -94,6 +92,8 @@
 
     private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours
 
+    private static final int MOMENTARY_EXPOSURE_TIMEOUT_MS = (20 * 3600 * 1000); // 20 hours
+
     // 30s after boot completed
     private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000;
 
@@ -127,30 +127,50 @@
 
     // mSafeMediaVolumeIndex is the cached value of config_safe_media_volume_index property
     private int mSafeMediaVolumeIndex;
-    // mSafeUsbMediaVolumeDbfs is the cached value of the config_safe_media_volume_usb_mB
+    // mSafeMediaVolumeDbfs is the cached value of the config_safe_media_volume_usb_mB
     // property, divided by 100.0.
-    private float mSafeUsbMediaVolumeDbfs;
+    // For now using the same value for CSD supported devices
+    private float mSafeMediaVolumeDbfs;
 
-    // mSafeUsbMediaVolumeIndex is used for USB Headsets and is the music volume UI index
-    // corresponding to a gain of mSafeUsbMediaVolumeDbfs (defaulting to -37dB) in audio
-    // flinger mixer.
-    // We remove -22 dBs from the theoretical -15dB to account for the EQ + bass boost
-    // amplification when both effects are on with all band gains at maximum.
-    // This level corresponds to a loudness of 85 dB SPL for the warning to be displayed when
-    // the headset is compliant to EN 60950 with a max loudness of 100dB SPL.
-    private int mSafeUsbMediaVolumeIndex;
-    // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced,
-    private final Set<Integer> mSafeMediaVolumeDevices = new HashSet<>(
-            Arrays.asList(AudioSystem.DEVICE_OUT_WIRED_HEADSET,
-                    AudioSystem.DEVICE_OUT_WIRED_HEADPHONE, AudioSystem.DEVICE_OUT_USB_HEADSET));
+    private static class SafeDeviceVolumeInfo {
+        int mDeviceType;
+        int mSafeVolumeIndex = -1;
 
-    private final Set<Integer> mSafeMediaCsdDevices = new HashSet<>(
-            Arrays.asList(AudioSystem.DEVICE_OUT_WIRED_HEADSET,
-                    AudioSystem.DEVICE_OUT_WIRED_HEADPHONE, AudioSystem.DEVICE_OUT_USB_HEADSET,
-                    AudioSystem.DEVICE_OUT_BLE_HEADSET, AudioSystem.DEVICE_OUT_BLE_BROADCAST,
-                    AudioSystem.DEVICE_OUT_HEARING_AID,
-                    AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES,
-                    AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP));
+        SafeDeviceVolumeInfo(int deviceType) {
+            mDeviceType = deviceType;
+        }
+    }
+
+    /**
+     * mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced.
+     * Contains a safe volume index for a given device type.
+     * Indexes are used for headsets and is the music volume UI index
+     * corresponding to a gain of mSafeMediaVolumeDbfs (defaulting to -37dB) in audio
+     * flinger mixer.
+     * We remove -22 dBs from the theoretical -15dB to account for the EQ + bass boost
+     * amplification when both effects are on with all band gains at maximum.
+     * This level corresponds to a loudness of 85 dB SPL for the warning to be displayed when
+     * the headset is compliant to EN 60950 with a max loudness of 100dB SPL.
+     */
+    private final HashMap<Integer, SafeDeviceVolumeInfo> mSafeMediaVolumeDevices =
+            new HashMap<>() {{
+                put(AudioSystem.DEVICE_OUT_WIRED_HEADSET,
+                        new SafeDeviceVolumeInfo(AudioSystem.DEVICE_OUT_WIRED_HEADSET));
+                put(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE,
+                        new SafeDeviceVolumeInfo(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE));
+                put(AudioSystem.DEVICE_OUT_USB_HEADSET,
+                        new SafeDeviceVolumeInfo(AudioSystem.DEVICE_OUT_USB_HEADSET));
+                put(AudioSystem.DEVICE_OUT_BLE_HEADSET,
+                        new SafeDeviceVolumeInfo(AudioSystem.DEVICE_OUT_BLE_HEADSET));
+                put(AudioSystem.DEVICE_OUT_BLE_BROADCAST,
+                        new SafeDeviceVolumeInfo(AudioSystem.DEVICE_OUT_BLE_BROADCAST));
+                put(AudioSystem.DEVICE_OUT_HEARING_AID,
+                        new SafeDeviceVolumeInfo(AudioSystem.DEVICE_OUT_HEARING_AID));
+                put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES,
+                        new SafeDeviceVolumeInfo(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES));
+                put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
+                        new SafeDeviceVolumeInfo(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP));
+            }};
 
     // mMusicActiveMs is the cumulative time of music activity since safe volume was disabled.
     // When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled
@@ -173,6 +193,10 @@
 
     @GuardedBy("mCsdStateLock")
     private float mCurrentCsd = 0.f;
+
+    @GuardedBy("mCsdStateLock")
+    private long mLastMomentaryExposureTimeMs = -1;
+
     // dose at which the next dose reached warning occurs
     @GuardedBy("mCsdStateLock")
     private float mNextCsdWarning = 1.0f;
@@ -188,10 +212,26 @@
 
     private final ISoundDoseCallback.Stub mSoundDoseCallback = new ISoundDoseCallback.Stub() {
         public void onMomentaryExposure(float currentMel, int deviceId) {
+            if (!mEnableCsd) {
+                Log.w(TAG, "onMomentaryExposure: csd not supported, ignoring callback");
+                return;
+            }
+
             Log.w(TAG, "DeviceId " + deviceId + " triggered momentary exposure with value: "
                     + currentMel);
             mLogger.enqueue(SoundDoseEvent.getMomentaryExposureEvent(currentMel));
-            if (mEnableCsd) {
+
+            boolean postWarning = false;
+            synchronized (mCsdStateLock) {
+                if (mLastMomentaryExposureTimeMs < 0
+                        || (System.currentTimeMillis() - mLastMomentaryExposureTimeMs)
+                        >= MOMENTARY_EXPOSURE_TIMEOUT_MS) {
+                    mLastMomentaryExposureTimeMs = System.currentTimeMillis();
+                    postWarning = true;
+                }
+            }
+
+            if (postWarning) {
                 mVolumeController.postDisplayCsdWarning(
                         AudioManager.CSD_WARNING_MOMENTARY_EXPOSURE,
                         getTimeoutMsForWarning(AudioManager.CSD_WARNING_MOMENTARY_EXPOSURE));
@@ -250,15 +290,11 @@
         mContext = context;
 
         mEnableCsd = mContext.getResources().getBoolean(R.bool.config_audio_csd_enabled_default);
-        if (mEnableCsd) {
-            mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED;
-        } else {
-            mSafeMediaVolumeState = mSettings.getGlobalInt(audioService.getContentResolver(),
-                    Settings.Global.AUDIO_SAFE_VOLUME_STATE, SAFE_MEDIA_VOLUME_NOT_CONFIGURED);
-        }
-
         initCsd();
 
+        mSafeMediaVolumeState = mSettings.getGlobalInt(audioService.getContentResolver(),
+                Settings.Global.AUDIO_SAFE_VOLUME_STATE, SAFE_MEDIA_VOLUME_NOT_CONFIGURED);
+
         // The default safe volume index read here will be replaced by the actual value when
         // the mcc is read by onConfigureSafeMedia()
         // For now we use the same index for RS2 initial warning with CSD
@@ -330,6 +366,21 @@
             return;
         }
 
+        SoundDoseRecord[] doseRecordsArray;
+        synchronized (mCsdStateLock) {
+            mCurrentCsd = csd;
+
+            mDoseRecords.clear();
+
+            if (mCurrentCsd > 0.0f) {
+                final SoundDoseRecord record = new SoundDoseRecord();
+                record.timestamp = SystemClock.elapsedRealtime();
+                record.value = csd;
+                mDoseRecords.add(record);
+            }
+            doseRecordsArray = mDoseRecords.toArray(new SoundDoseRecord[0]);
+        }
+
         final ISoundDose soundDose = mSoundDose.get();
         if (soundDose == null) {
             Log.w(TAG, "Sound dose interface not initialized");
@@ -337,11 +388,7 @@
         }
 
         try {
-            final SoundDoseRecord record = new SoundDoseRecord();
-            record.timestamp = System.currentTimeMillis();
-            record.value = csd;
-            final SoundDoseRecord[] recordArray = new SoundDoseRecord[] { record };
-            soundDose.resetCsd(csd, recordArray);
+            soundDose.resetCsd(csd, doseRecordsArray);
         } catch (RemoteException e) {
             Log.e(TAG, "Exception while setting the CSD value", e);
         }
@@ -388,14 +435,12 @@
     }
 
     /*package*/ int safeMediaVolumeIndex(int device) {
-        if (!mSafeMediaVolumeDevices.contains(device)) {
+        final SafeDeviceVolumeInfo vi = mSafeMediaVolumeDevices.get(device);
+        if (vi == null) {
             return MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
         }
-        if (device == AudioSystem.DEVICE_OUT_USB_HEADSET) {
-            return mSafeUsbMediaVolumeIndex;
-        } else {
-            return mSafeMediaVolumeIndex;
-        }
+
+        return vi.mSafeVolumeIndex;
     }
 
     /*package*/ void restoreMusicActiveMs() {
@@ -419,20 +464,24 @@
     /*package*/ void enforceSafeMediaVolume(String caller) {
         AudioService.VolumeStreamState streamState = mAudioService.getVssVolumeForStream(
                 AudioSystem.STREAM_MUSIC);
-        Set<Integer> devices = mSafeMediaVolumeDevices;
 
-        for (int device : devices) {
-            int index = streamState.getIndex(device);
-            int safeIndex = safeMediaVolumeIndex(device);
+        for (SafeDeviceVolumeInfo vi : mSafeMediaVolumeDevices.values()) {
+            int index = streamState.getIndex(vi.mDeviceType);
+            int safeIndex = safeMediaVolumeIndex(vi.mDeviceType);
             if (index > safeIndex) {
-                streamState.setIndex(safeIndex, device, caller, true /*hasModifyAudioSettings*/);
+                streamState.setIndex(safeIndex, vi.mDeviceType, caller,
+                        true /*hasModifyAudioSettings*/);
                 mAudioHandler.sendMessageAtTime(
-                        mAudioHandler.obtainMessage(MSG_SET_DEVICE_VOLUME, device, /*arg2=*/0,
-                                streamState), /*delay=*/0);
+                        mAudioHandler.obtainMessage(MSG_SET_DEVICE_VOLUME, vi.mDeviceType,
+                                /*arg2=*/0, streamState), /*delay=*/0);
             }
         }
     }
 
+    /**
+     * Returns {@code true} if the safe media actions can be applied for the given stream type,
+     * volume index and device.
+     **/
     /*package*/ boolean checkSafeMediaVolume(int streamType, int index, int device) {
         boolean result;
         synchronized (mSafeMediaVolumeStateLock) {
@@ -443,17 +492,16 @@
 
     @GuardedBy("mSafeMediaVolumeStateLock")
     private boolean checkSafeMediaVolume_l(int streamType, int index, int device) {
-        return (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_ACTIVE)
-                    || (AudioService.mStreamVolumeAlias[streamType] != AudioSystem.STREAM_MUSIC)
-                    || (!mSafeMediaVolumeDevices.contains(device))
-                    || (index <= safeMediaVolumeIndex(device))
-                    || mEnableCsd;
+        return (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)
+                    && (AudioService.mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC)
+                    && (mSafeMediaVolumeDevices.containsKey(device))
+                    && (index > safeMediaVolumeIndex(device));
     }
 
     /*package*/ boolean willDisplayWarningAfterCheckVolume(int streamType, int index, int device,
             int flags) {
         synchronized (mSafeMediaVolumeStateLock) {
-            if (!checkSafeMediaVolume_l(streamType, index, device)) {
+            if (checkSafeMediaVolume_l(streamType, index, device)) {
                 mVolumeController.postDisplaySafeVolumeWarning(flags);
                 mPendingVolumeCommand = new StreamVolumeCommand(
                         streamType, index, flags, device);
@@ -484,15 +532,13 @@
     /*package*/ void scheduleMusicActiveCheck() {
         synchronized (mSafeMediaVolumeStateLock) {
             cancelMusicActiveCheck();
-            if (!mEnableCsd) {
-                mMusicActiveIntent = PendingIntent.getBroadcast(mContext,
-                        REQUEST_CODE_CHECK_MUSIC_ACTIVE,
-                        new Intent(ACTION_CHECK_MUSIC_ACTIVE),
-                        PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
-                mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
-                        SystemClock.elapsedRealtime()
-                                + MUSIC_ACTIVE_POLL_PERIOD_MS, mMusicActiveIntent);
-            }
+            mMusicActiveIntent = PendingIntent.getBroadcast(mContext,
+                    REQUEST_CODE_CHECK_MUSIC_ACTIVE,
+                    new Intent(ACTION_CHECK_MUSIC_ACTIVE),
+                    PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
+            mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+                    SystemClock.elapsedRealtime()
+                            + MUSIC_ACTIVE_POLL_PERIOD_MS, mMusicActiveIntent);
         }
     }
 
@@ -500,7 +546,7 @@
         synchronized (mSafeMediaVolumeStateLock) {
             if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) {
                 int device = mAudioService.getDeviceForStream(AudioSystem.STREAM_MUSIC);
-                if (mSafeMediaVolumeDevices.contains(device) && isStreamActive) {
+                if (mSafeMediaVolumeDevices.containsKey(device) && isStreamActive) {
                     scheduleMusicActiveCheck();
                     int index = mAudioService.getVssVolumeForDevice(AudioSystem.STREAM_MUSIC,
                             device);
@@ -528,6 +574,7 @@
 
     /*package*/ void configureSafeMedia(boolean forced, String caller) {
         int msg = MSG_CONFIGURE_SAFE_MEDIA;
+
         mAudioHandler.removeMessages(msg);
 
         long time = 0;
@@ -535,20 +582,21 @@
             time = (SystemClock.uptimeMillis() + (SystemProperties.getBoolean(
                     "audio.safemedia.bypass", false) ? 0 : SAFE_VOLUME_CONFIGURE_TIMEOUT_MS));
         }
+
         mAudioHandler.sendMessageAtTime(
                 mAudioHandler.obtainMessage(msg, /*arg1=*/forced ? 1 : 0, /*arg2=*/0, caller),
                 time);
     }
 
-    /*package*/ void initSafeUsbMediaVolumeIndex() {
-        // mSafeUsbMediaVolumeIndex must be initialized after createStreamStates() because it
-        // relies on audio policy having correct ranges for volume indexes.
-        mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();
+    /*package*/ void initSafeMediaVolumeIndex() {
+        for (SafeDeviceVolumeInfo vi : mSafeMediaVolumeDevices.values()) {
+            vi.mSafeVolumeIndex = getSafeDeviceMediaVolumeIndex(vi.mDeviceType);
+        }
     }
 
     /*package*/ int getSafeMediaVolumeIndex(int device) {
-        if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE && mSafeMediaVolumeDevices.contains(
-                device)) {
+        if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE
+                && mSafeMediaVolumeDevices.containsKey(device)) {
             return safeMediaVolumeIndex(device);
         } else {
             return -1;
@@ -557,7 +605,7 @@
 
     /*package*/ boolean raiseVolumeDisplaySafeMediaVolume(int streamType, int index, int device,
             int flags) {
-        if (checkSafeMediaVolume(streamType, index, device)) {
+        if (!checkSafeMediaVolume(streamType, index, device)) {
             return false;
         }
 
@@ -566,7 +614,7 @@
     }
 
     /*package*/ boolean safeDevicesContains(int device) {
-        return mSafeMediaVolumeDevices.contains(device);
+        return mSafeMediaVolumeDevices.containsKey(device);
     }
 
     /*package*/ void invalidatPendingVolumeCommand() {
@@ -609,11 +657,19 @@
 
     /*package*/ void dump(PrintWriter pw) {
         pw.print("  mEnableCsd="); pw.println(mEnableCsd);
+        if (mEnableCsd) {
+            synchronized (mCsdStateLock) {
+                pw.print("  mCurrentCsd="); pw.println(mCurrentCsd);
+            }
+        }
         pw.print("  mSafeMediaVolumeState=");
         pw.println(safeMediaVolumeStateToString(mSafeMediaVolumeState));
         pw.print("  mSafeMediaVolumeIndex="); pw.println(mSafeMediaVolumeIndex);
-        pw.print("  mSafeUsbMediaVolumeIndex="); pw.println(mSafeUsbMediaVolumeIndex);
-        pw.print("  mSafeUsbMediaVolumeDbfs="); pw.println(mSafeUsbMediaVolumeDbfs);
+        for (SafeDeviceVolumeInfo vi : mSafeMediaVolumeDevices.values()) {
+            pw.print("  mSafeMediaVolumeIndex["); pw.print(vi.mDeviceType);
+            pw.print("]="); pw.println(vi.mSafeVolumeIndex);
+        }
+        pw.print("  mSafeMediaVolumeDbfs="); pw.println(mSafeMediaVolumeDbfs);
         pw.print("  mMusicActiveMs="); pw.println(mMusicActiveMs);
         pw.print("  mMcc="); pw.println(mMcc);
         pw.print("  mPendingVolumeCommand="); pw.println(mPendingVolumeCommand);
@@ -660,11 +716,12 @@
             if (!isAbsoluteVolume) {
                 // remove any possible previous attenuation
                 soundDose.updateAttenuation(/* attenuationDB= */0.f, device);
+
                 return;
             }
 
             if (AudioService.mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC
-                    && mSafeMediaCsdDevices.contains(device)) {
+                    && mSafeMediaVolumeDevices.containsKey(device)) {
                 soundDose.updateAttenuation(
                         AudioSystem.getStreamVolumeDB(AudioSystem.STREAM_MUSIC,
                                 (newIndex + 5) / 10,
@@ -715,7 +772,7 @@
                 mSafeMediaVolumeIndex = mContext.getResources().getInteger(
                         com.android.internal.R.integer.config_safe_media_volume_index) * 10;
 
-                mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();
+                initSafeMediaVolumeIndex();
 
                 boolean safeMediaVolumeEnabled =
                         SystemProperties.getBoolean("audio.safemedia.force", false)
@@ -728,7 +785,7 @@
                 // The persisted state is either "disabled" or "active": this is the state applied
                 // next time we boot and cannot be "inactive"
                 int persistedState;
-                if (safeMediaVolumeEnabled && !safeMediaVolumeBypass && !mEnableCsd) {
+                if (safeMediaVolumeEnabled && !safeMediaVolumeBypass) {
                     persistedState = SAFE_MEDIA_VOLUME_ACTIVE;
                     // The state can already be "inactive" here if the user has forced it before
                     // the 30 seconds timeout for forced configuration. In this case we don't reset
@@ -801,25 +858,32 @@
         mAudioHandler.obtainMessage(MSG_PERSIST_MUSIC_ACTIVE_MS, mMusicActiveMs, 0).sendToTarget();
     }
 
-    private int getSafeUsbMediaVolumeIndex() {
+    private int getSafeDeviceMediaVolumeIndex(int deviceType) {
+        // legacy implementation uses mSafeMediaVolumeIndex for wired HS/HP
+        // instead of computing it from the volume curves
+        if ((deviceType == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE
+                || deviceType == AudioSystem.DEVICE_OUT_WIRED_HEADSET) && !mEnableCsd) {
+            return mSafeMediaVolumeIndex;
+        }
+
         // determine UI volume index corresponding to the wanted safe gain in dBFS
         int min = MIN_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
         int max = MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
 
-        mSafeUsbMediaVolumeDbfs = mContext.getResources().getInteger(
+        mSafeMediaVolumeDbfs = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_safe_media_volume_usb_mB) / 100.0f;
 
         while (Math.abs(max - min) > 1) {
             int index = (max + min) / 2;
-            float gainDB = AudioSystem.getStreamVolumeDB(
-                    AudioSystem.STREAM_MUSIC, index, AudioSystem.DEVICE_OUT_USB_HEADSET);
+            float gainDB = AudioSystem.getStreamVolumeDB(AudioSystem.STREAM_MUSIC, index,
+                    deviceType);
             if (Float.isNaN(gainDB)) {
                 //keep last min in case of read error
                 break;
-            } else if (gainDB == mSafeUsbMediaVolumeDbfs) {
+            } else if (gainDB == mSafeMediaVolumeDbfs) {
                 min = index;
                 break;
-            } else if (gainDB < mSafeUsbMediaVolumeDbfs) {
+            } else if (gainDB < mSafeMediaVolumeDbfs) {
                 min = index;
             } else {
                 max = index;
diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java
index 2b525f1..3ea4f4f 100644
--- a/services/core/java/com/android/server/audio/SpatializerHelper.java
+++ b/services/core/java/com/android/server/audio/SpatializerHelper.java
@@ -107,12 +107,12 @@
     };
 
     // Spatializer state machine
-    private static final int STATE_UNINITIALIZED = 0;
-    private static final int STATE_NOT_SUPPORTED = 1;
-    private static final int STATE_DISABLED_UNAVAILABLE = 3;
-    private static final int STATE_ENABLED_UNAVAILABLE = 4;
-    private static final int STATE_ENABLED_AVAILABLE = 5;
-    private static final int STATE_DISABLED_AVAILABLE = 6;
+    /*package*/ static final int STATE_UNINITIALIZED = 0;
+    /*package*/ static final int STATE_NOT_SUPPORTED = 1;
+    /*package*/ static final int STATE_DISABLED_UNAVAILABLE = 3;
+    /*package*/ static final int STATE_ENABLED_UNAVAILABLE = 4;
+    /*package*/ static final int STATE_ENABLED_AVAILABLE = 5;
+    /*package*/ static final int STATE_DISABLED_AVAILABLE = 6;
     private int mState = STATE_UNINITIALIZED;
 
     private boolean mFeatureEnabled = false;
@@ -148,9 +148,9 @@
             .setSampleRate(48000)
             .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1)
             .build();
-    // device array to store the routing for the default attributes and format, size 1 because
-    // media is never expected to be duplicated
-    private static final AudioDeviceAttributes[] ROUTING_DEVICES = new AudioDeviceAttributes[1];
+    // device array to store the routing for the default attributes and format, initialized to
+    // an empty list as routing hasn't been established yet
+    private static ArrayList<AudioDeviceAttributes> sRoutingDevices = new ArrayList<>(0);
 
     //---------------------------------------------------------------
     // audio device compatibility / enabled
@@ -181,11 +181,6 @@
         SADeviceState.sHeadTrackingEnabledDefault = headTrackingEnabledByDefault;
     }
 
-    synchronized void initForTest(boolean hasBinaural, boolean hasTransaural) {
-        mBinauralSupported = hasBinaural;
-        mTransauralSupported = hasTransaural;
-    }
-
     synchronized void init(boolean effectExpected, @Nullable String settings) {
         loglogi("init effectExpected=" + effectExpected);
         if (!effectExpected) {
@@ -319,8 +314,7 @@
             return;
         }
         mState = STATE_DISABLED_UNAVAILABLE;
-        mASA.getDevicesForAttributes(
-                DEFAULT_ATTRIBUTES, false /* forVolume */).toArray(ROUTING_DEVICES);
+        sRoutingDevices = getRoutingDevices(DEFAULT_ATTRIBUTES);
         // note at this point mSpat is still not instantiated
     }
 
@@ -362,34 +356,35 @@
             case STATE_DISABLED_AVAILABLE:
                 break;
         }
-        mASA.getDevicesForAttributes(
-                DEFAULT_ATTRIBUTES, false /* forVolume */).toArray(ROUTING_DEVICES);
+
+        sRoutingDevices = getRoutingDevices(DEFAULT_ATTRIBUTES);
 
         // check validity of routing information
-        if (ROUTING_DEVICES[0] == null) {
-            logloge("onRoutingUpdated: device is null, no Spatial Audio");
+        if (sRoutingDevices.isEmpty()) {
+            logloge("onRoutingUpdated: no device, no Spatial Audio");
             setDispatchAvailableState(false);
             // not changing the spatializer level as this is likely a transient state
             return;
         }
+        final AudioDeviceAttributes currentDevice = sRoutingDevices.get(0);
 
         // is media routed to a new device?
-        if (isWireless(ROUTING_DEVICES[0].getType())) {
-            addWirelessDeviceIfNew(ROUTING_DEVICES[0]);
+        if (isWireless(currentDevice.getType())) {
+            addWirelessDeviceIfNew(currentDevice);
         }
 
         // find if media device enabled / available
-        final Pair<Boolean, Boolean> enabledAvailable = evaluateState(ROUTING_DEVICES[0]);
+        final Pair<Boolean, Boolean> enabledAvailable = evaluateState(currentDevice);
 
         boolean able = false;
         if (enabledAvailable.second) {
             // available for Spatial audio, check w/ effect
-            able = canBeSpatializedOnDevice(DEFAULT_ATTRIBUTES, DEFAULT_FORMAT, ROUTING_DEVICES);
+            able = canBeSpatializedOnDevice(DEFAULT_ATTRIBUTES, DEFAULT_FORMAT, sRoutingDevices);
             loglogi("onRoutingUpdated: can spatialize media 5.1:" + able
-                    + " on device:" + ROUTING_DEVICES[0]);
+                    + " on device:" + currentDevice);
             setDispatchAvailableState(able);
         } else {
-            loglogi("onRoutingUpdated: device:" + ROUTING_DEVICES[0]
+            loglogi("onRoutingUpdated: device:" + currentDevice
                     + " not available for Spatial Audio");
             setDispatchAvailableState(false);
         }
@@ -397,10 +392,10 @@
         boolean enabled = able && enabledAvailable.first;
         if (enabled) {
             loglogi("Enabling Spatial Audio since enabled for media device:"
-                    + ROUTING_DEVICES[0]);
+                    + currentDevice);
         } else {
             loglogi("Disabling Spatial Audio since disabled for media device:"
-                    + ROUTING_DEVICES[0]);
+                    + currentDevice);
         }
         if (mSpat != null) {
             byte level = enabled ? (byte) Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL
@@ -733,9 +728,13 @@
     }
 
     private synchronized boolean canBeSpatializedOnDevice(@NonNull AudioAttributes attributes,
-            @NonNull AudioFormat format, @NonNull AudioDeviceAttributes[] devices) {
-        if (isDeviceCompatibleWithSpatializationModes(devices[0])) {
-            return AudioSystem.canBeSpatialized(attributes, format, devices);
+            @NonNull AudioFormat format, @NonNull ArrayList<AudioDeviceAttributes> devices) {
+        if (devices.isEmpty()) {
+            return false;
+        }
+        if (isDeviceCompatibleWithSpatializationModes(devices.get(0))) {
+            AudioDeviceAttributes[] devArray = new AudioDeviceAttributes[devices.size()];
+            return AudioSystem.canBeSpatialized(attributes, format, devices.toArray(devArray));
         }
         return false;
     }
@@ -1011,10 +1010,13 @@
                 logd("canBeSpatialized false due to usage:" + attributes.getUsage());
                 return false;
         }
-        AudioDeviceAttributes[] devices = new AudioDeviceAttributes[1];
+
         // going through adapter to take advantage of routing cache
-        mASA.getDevicesForAttributes(
-                attributes, false /* forVolume */).toArray(devices);
+        final ArrayList<AudioDeviceAttributes> devices = getRoutingDevices(attributes);
+        if (devices.isEmpty()) {
+            logloge("canBeSpatialized got no device for " + attributes);
+            return false;
+        }
         final boolean able = canBeSpatializedOnDevice(attributes, format, devices);
         logd("canBeSpatialized usage:" + attributes.getUsage()
                 + " format:" + format.toLogFriendlyString() + " returning " + able);
@@ -1123,8 +1125,13 @@
         logDeviceState(deviceState, "setHeadTrackerEnabled");
 
         // check current routing to see if it affects the headtracking mode
-        if (ROUTING_DEVICES[0] != null && ROUTING_DEVICES[0].getType() == ada.getType()
-                && ROUTING_DEVICES[0].getAddress().equals(ada.getAddress())) {
+        if (sRoutingDevices.isEmpty()) {
+            logloge("setHeadTrackerEnabled: no device, bailing");
+            return;
+        }
+        final AudioDeviceAttributes currentDevice = sRoutingDevices.get(0);
+        if (currentDevice.getType() == ada.getType()
+                && currentDevice.getAddress().equals(ada.getAddress())) {
             setDesiredHeadTrackingMode(enabled ? mDesiredHeadTrackingModeWhenEnabled
                     : Spatializer.HEAD_TRACKING_MODE_DISABLED);
             if (enabled && !mHeadTrackerAvailable) {
@@ -1669,10 +1676,11 @@
 
     private int getHeadSensorHandleUpdateTracker() {
         int headHandle = -1;
-        final AudioDeviceAttributes currentDevice = ROUTING_DEVICES[0];
-        if (currentDevice == null) {
+        if (sRoutingDevices.isEmpty()) {
+            logloge("getHeadSensorHandleUpdateTracker: no device, no head tracker");
             return headHandle;
         }
+        final AudioDeviceAttributes currentDevice = sRoutingDevices.get(0);
         UUID routingDeviceUuid = mAudioService.getDeviceSensorUuid(currentDevice);
         // We limit only to Sensor.TYPE_HEAD_TRACKER here to avoid confusion
         // with gaming sensors. (Note that Sensor.TYPE_ROTATION_VECTOR
@@ -1706,6 +1714,23 @@
         return screenHandle;
     }
 
+    /**
+     * Returns routing for the given attributes
+     * @param aa AudioAttributes whose routing is being queried
+     * @return a non-null never-empty list of devices. If the routing query failed, the list
+     *     will contain null.
+     */
+    private @NonNull ArrayList<AudioDeviceAttributes> getRoutingDevices(AudioAttributes aa) {
+        final ArrayList<AudioDeviceAttributes> devices = mASA.getDevicesForAttributes(
+                aa, false /* forVolume */);
+        for (AudioDeviceAttributes ada : devices) {
+            if (ada == null) {
+                // invalid entry, reject this routing query by returning an empty list
+                return new ArrayList<>(0);
+            }
+        }
+        return devices;
+    }
 
     private static void loglogi(String msg) {
         AudioService.sSpatialLogger.enqueueAndLog(msg, EventLogger.Event.ALOGI, TAG);
@@ -1722,4 +1747,13 @@
     /*package*/ void clearSADevices() {
         mSADevices.clear();
     }
+
+    /*package*/ synchronized void forceStateForTest(int state) {
+        mState = state;
+    }
+
+    /*package*/ synchronized void initForTest(boolean hasBinaural, boolean hasTransaural) {
+        mBinauralSupported = hasBinaural;
+        mTransauralSupported = hasTransaural;
+    }
 }
diff --git a/services/core/java/com/android/server/audio/TEST_MAPPING b/services/core/java/com/android/server/audio/TEST_MAPPING
index 300a2c8..2cea32a 100644
--- a/services/core/java/com/android/server/audio/TEST_MAPPING
+++ b/services/core/java/com/android/server/audio/TEST_MAPPING
@@ -1,5 +1,5 @@
 {
-    "presubmit-large": [
+    "presubmit": [
         {
             "name": "CtsMediaAudioTestCases",
             "options": [
@@ -24,9 +24,7 @@
                     "include-annotation": "android.platform.test.annotations.Presubmit"
                 }
             ]
-        }
-    ],
-    "presubmit": [
+        },
         {
             "name": "FrameworksServicesTests",
             "options": [
diff --git a/services/core/java/com/android/server/biometrics/log/OperationContextExt.java b/services/core/java/com/android/server/biometrics/log/OperationContextExt.java
index 42be95b..ecb7e7c 100644
--- a/services/core/java/com/android/server/biometrics/log/OperationContextExt.java
+++ b/services/core/java/com/android/server/biometrics/log/OperationContextExt.java
@@ -20,8 +20,13 @@
 import android.annotation.Nullable;
 import android.content.Intent;
 import android.hardware.biometrics.IBiometricContextListener;
+import android.hardware.biometrics.common.AuthenticateReason;
 import android.hardware.biometrics.common.OperationContext;
 import android.hardware.biometrics.common.OperationReason;
+import android.hardware.biometrics.common.WakeReason;
+import android.hardware.face.FaceAuthenticateOptions;
+import android.hardware.fingerprint.FingerprintAuthenticateOptions;
+import android.os.PowerManager;
 import android.view.Surface;
 
 /**
@@ -50,12 +55,127 @@
         mAidlContext = context;
     }
 
-    /** Gets the subset of the context that can be shared with the HAL. */
+    /**
+     * Gets the subset of the context that can be shared with the HAL.
+     *
+     * When starting a new operation use methods like to update & fetch the context:
+     * <ul>
+     *     <li>{@link #toAidlContext(FaceAuthenticateOptions)}
+     *     <li>{@link #toAidlContext(FingerprintAuthenticateOptions)}
+     * </ul>
+     *
+     * Use this method for any subsequent calls to the HAL or for operations that do
+     * not accept any options.
+     *
+     * @return the underlying AIDL context
+     */
     @NonNull
     public OperationContext toAidlContext() {
         return mAidlContext;
     }
 
+    /**
+     * Gets the subset of the context that can be shared with the HAL and updates
+     * it with the given options.
+     *
+     * @param options authenticate options
+     * @return the underlying AIDL context
+     */
+    @NonNull
+    public OperationContext toAidlContext(@NonNull FaceAuthenticateOptions options) {
+        mAidlContext.authenticateReason = AuthenticateReason
+                .faceAuthenticateReason(getAuthReason(options));
+        mAidlContext.wakeReason = getWakeReason(options);
+
+        return mAidlContext;
+    }
+
+    /**
+     * Gets the subset of the context that can be shared with the HAL and updates
+     * it with the given options.
+     *
+     * @param options authenticate options
+     * @return the underlying AIDL context
+     */
+    @NonNull
+    public OperationContext toAidlContext(@NonNull FingerprintAuthenticateOptions options) {
+        mAidlContext.authenticateReason = AuthenticateReason
+                .fingerprintAuthenticateReason(getAuthReason(options));
+        mAidlContext.wakeReason = getWakeReason(options);
+
+        return mAidlContext;
+    }
+
+    @AuthenticateReason.Face
+    private int getAuthReason(@NonNull FaceAuthenticateOptions options) {
+        switch (options.getAuthenticateReason()) {
+            case FaceAuthenticateOptions.AUTHENTICATE_REASON_STARTED_WAKING_UP:
+                return AuthenticateReason.Face.STARTED_WAKING_UP;
+            case FaceAuthenticateOptions.AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN:
+                return AuthenticateReason.Face.PRIMARY_BOUNCER_SHOWN;
+            case FaceAuthenticateOptions.AUTHENTICATE_REASON_ASSISTANT_VISIBLE:
+                return AuthenticateReason.Face.ASSISTANT_VISIBLE;
+            case FaceAuthenticateOptions.AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN:
+                return AuthenticateReason.Face.ALTERNATE_BIOMETRIC_BOUNCER_SHOWN;
+            case FaceAuthenticateOptions.AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED:
+                return AuthenticateReason.Face.NOTIFICATION_PANEL_CLICKED;
+            case FaceAuthenticateOptions.AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED:
+                return AuthenticateReason.Face.OCCLUDING_APP_REQUESTED;
+            case FaceAuthenticateOptions.AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED:
+                return AuthenticateReason.Face.PICK_UP_GESTURE_TRIGGERED;
+            case FaceAuthenticateOptions.AUTHENTICATE_REASON_QS_EXPANDED:
+                return AuthenticateReason.Face.QS_EXPANDED;
+            case FaceAuthenticateOptions.AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER:
+                return AuthenticateReason.Face.SWIPE_UP_ON_BOUNCER;
+            case FaceAuthenticateOptions.AUTHENTICATE_REASON_UDFPS_POINTER_DOWN:
+                return AuthenticateReason.Face.UDFPS_POINTER_DOWN;
+            default:
+                return AuthenticateReason.Face.UNKNOWN;
+        }
+    }
+
+    @WakeReason
+    private int getWakeReason(@NonNull FaceAuthenticateOptions options) {
+        switch (options.getWakeReason()) {
+            case PowerManager.WAKE_REASON_POWER_BUTTON:
+                return WakeReason.POWER_BUTTON;
+            case PowerManager.WAKE_REASON_GESTURE:
+                return WakeReason.GESTURE;
+            case PowerManager.WAKE_REASON_WAKE_KEY:
+                return WakeReason.WAKE_KEY;
+            case PowerManager.WAKE_REASON_WAKE_MOTION:
+                return WakeReason.WAKE_MOTION;
+            case PowerManager.WAKE_REASON_DISPLAY_GROUP_ADDED:
+                return WakeReason.DISPLAY_GROUP_ADDED;
+            case PowerManager.WAKE_REASON_TAP:
+                return WakeReason.TAP;
+            case PowerManager.WAKE_REASON_LIFT:
+                return WakeReason.LIFT;
+            case PowerManager.WAKE_REASON_BIOMETRIC:
+                return WakeReason.BIOMETRIC;
+            case PowerManager.WAKE_REASON_CAMERA_LAUNCH:
+            case PowerManager.WAKE_REASON_HDMI:
+            case PowerManager.WAKE_REASON_DISPLAY_GROUP_TURNED_ON:
+            case PowerManager.WAKE_REASON_UNFOLD_DEVICE:
+            case PowerManager.WAKE_REASON_DREAM_FINISHED:
+            case PowerManager.WAKE_REASON_TILT:
+            case PowerManager.WAKE_REASON_APPLICATION:
+            case PowerManager.WAKE_REASON_PLUGGED_IN:
+            default:
+                return WakeReason.UNKNOWN;
+        }
+    }
+
+    @AuthenticateReason.Fingerprint
+    private int getAuthReason(@NonNull FingerprintAuthenticateOptions options) {
+        return AuthenticateReason.Fingerprint.UNKNOWN;
+    }
+
+    @WakeReason
+    private int getWakeReason(@NonNull FingerprintAuthenticateOptions options) {
+        return WakeReason.UNKNOWN;
+    }
+
     /** {@link OperationContext#id}. */
     public int getId() {
         return mAidlContext.id;
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 005ad20..7b9fc36 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -74,6 +74,7 @@
     @Nullable
     private final TaskStackListener mTaskStackListener;
     private final LockoutTracker mLockoutTracker;
+    private final O mOptions;
     private final boolean mIsRestricted;
     private final boolean mAllowBackgroundAuthentication;
     // TODO: This is currently hard to maintain, as each AuthenticationClient subclass must update
@@ -110,6 +111,7 @@
         mAllowBackgroundAuthentication = allowBackgroundAuthentication;
         mShouldUseLockoutTracker = lockoutTracker != null;
         mSensorStrength = sensorStrength;
+        mOptions = options;
     }
 
     @LockoutTracker.LockoutMode
@@ -151,6 +153,11 @@
         return Utils.isSettings(getContext(), getOwnerString());
     }
 
+    /** The options requested at the start of the operation. */
+    protected O getOptions() {
+        return mOptions;
+    }
+
     @Override
     protected boolean isCryptoOperation() {
         return mOperationId != 0;
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java b/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java
index 7b8f824..f516a49 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java
@@ -37,6 +37,7 @@
     private static final String TAG = "BiometricNotificationUtils";
     private static final String RE_ENROLL_NOTIFICATION_TAG = "FaceService";
     private static final String BAD_CALIBRATION_NOTIFICATION_TAG = "FingerprintService";
+    private static final String KEY_RE_ENROLL_FACE = "re_enroll_face_unlock";
     private static final int NOTIFICATION_ID = 1;
     private static final long NOTIFICATION_INTERVAL_MS = 24 * 60 * 60 * 1000;
     private static long sLastAlertTime = 0;
@@ -57,6 +58,7 @@
 
         final Intent intent = new Intent("android.settings.FACE_SETTINGS");
         intent.setPackage("com.android.settings");
+        intent.putExtra(KEY_RE_ENROLL_FACE, true);
 
         final PendingIntent pendingIntent = PendingIntent.getActivityAsUser(context,
                 0 /* requestCode */, intent, PendingIntent.FLAG_IMMUTABLE /* flags */,
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 6d7b2cb..c2994a9 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
@@ -260,9 +260,8 @@
             if (provider == null) {
                 Slog.w(TAG, "Null provider for authenticate");
                 return -1;
-            } else {
-                options.setSensorId(provider.first);
             }
+            options.setSensorId(provider.first);
 
             return provider.second.scheduleAuthenticate(token, operationId,
                     0 /* cookie */, new ClientMonitorCallbackConverter(receiver), options,
@@ -286,6 +285,7 @@
                 Slog.w(TAG, "Null provider for detectFace");
                 return -1;
             }
+            options.setSensorId(provider.first);
 
             return provider.second.scheduleFaceDetect(token,
                     new ClientMonitorCallbackConverter(receiver), options,
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
index 976f1cb..84e2fb4 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
@@ -166,7 +166,7 @@
 
         if (session.hasContextMethods()) {
             return session.getSession().authenticateWithContext(
-                    mOperationId, getOperationContext().toAidlContext());
+                    mOperationId, getOperationContext().toAidlContext(getOptions()));
         } else {
             return session.getSession().authenticate(mOperationId);
         }
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java
index e65202d..fa23ccd 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java
@@ -47,6 +47,7 @@
     private static final String TAG = "FaceDetectClient";
 
     private final boolean mIsStrongBiometric;
+    private final FaceAuthenticateOptions mOptions;
     @Nullable private ICancellationSignal mCancellationSignal;
     @Nullable private SensorPrivacyManager mSensorPrivacyManager;
 
@@ -74,6 +75,7 @@
         setRequestId(requestId);
         mIsStrongBiometric = isStrongBiometric;
         mSensorPrivacyManager = sensorPrivacyManager;
+        mOptions = options;
     }
 
     @Override
@@ -118,7 +120,7 @@
 
         if (session.hasContextMethods()) {
             return session.getSession().detectInteractionWithContext(
-                    getOperationContext().toAidlContext());
+                    getOperationContext().toAidlContext(mOptions));
         } else {
             return session.getSession().detectInteraction();
         }
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 8a33f22..dc00ffc 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
@@ -261,7 +261,6 @@
             final String opPackageName = options.getOpPackageName();
             final String attributionTag = options.getAttributionTag();
             final int userId = options.getUserId();
-            final int sensorId = options.getSensorId();
 
             if (!canUseFingerprint(
                     opPackageName,
@@ -298,21 +297,22 @@
                     : BiometricsProtoEnums.CLIENT_FINGERPRINT_MANAGER;
 
             final Pair<Integer, ServiceProvider> provider;
-            if (sensorId == FingerprintManager.SENSOR_ID_ANY) {
+            if (options.getSensorId() == FingerprintManager.SENSOR_ID_ANY) {
                 provider = mRegistry.getSingleProvider();
             } else {
                 Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
-                provider = new Pair<>(sensorId, mRegistry.getProviderForSensor(sensorId));
+                provider = new Pair<>(options.getSensorId(),
+                        mRegistry.getProviderForSensor(options.getSensorId()));
             }
+
             if (provider == null) {
                 Slog.w(TAG, "Null provider for authenticate");
                 return -1;
-            } else {
-                options.setSensorId(provider.first);
             }
+            options.setSensorId(provider.first);
 
             final FingerprintSensorPropertiesInternal sensorProps =
-                    provider.second.getSensorProperties(sensorId);
+                    provider.second.getSensorProperties(options.getSensorId());
             if (!isKeyguard && !Utils.isSettings(getContext(), opPackageName)
                     && sensorProps != null && sensorProps.isAnyUdfpsType()) {
                 try {
@@ -427,20 +427,12 @@
                 return -1;
             }
 
-            if (!Utils.isUserEncryptedOrLockdown(mLockPatternUtils, options.getUserId())) {
-                // If this happens, something in KeyguardUpdateMonitor is wrong. This should only
-                // ever be invoked when the user is encrypted or lockdown.
-                Slog.e(TAG, "detectFingerprint invoked when user is not encrypted or lockdown");
-                return -1;
-            }
-
             final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
             if (provider == null) {
                 Slog.w(TAG, "Null provider for detectFingerprint");
                 return -1;
-            } else {
-                options.setSensorId(provider.first);
             }
+            options.setSensorId(provider.first);
 
             return provider.second.scheduleFingerDetect(token,
                     new ClientMonitorCallbackConverter(receiver), options,
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlConversionUtils.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlConversionUtils.java
index 1630be7..bae84bd 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlConversionUtils.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlConversionUtils.java
@@ -48,6 +48,8 @@
             return BiometricFingerprintConstants.FINGERPRINT_ERROR_VENDOR;
         } else if (aidlError == Error.BAD_CALIBRATION) {
             return BiometricFingerprintConstants.FINGERPRINT_ERROR_BAD_CALIBRATION;
+        } else if (aidlError == Error.POWER_PRESS) {
+            return BiometricFingerprintConstants.BIOMETRIC_ERROR_POWER_PRESSED;
         } else {
             return BiometricFingerprintConstants.FINGERPRINT_ERROR_UNKNOWN;
         }
@@ -84,6 +86,8 @@
         } else if (aidlAcquiredInfo == AcquiredInfo.RETRYING_CAPTURE) {
             // No framework constant available
             return BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_UNKNOWN;
+        } else if (aidlAcquiredInfo == AcquiredInfo.POWER_PRESS) {
+            return BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_POWER_PRESSED;
         } else {
             return BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_UNKNOWN;
         }
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 0f81f9f..435e81d 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
@@ -285,7 +285,7 @@
 
         if (session.hasContextMethods()) {
             return session.getSession().authenticateWithContext(
-                    mOperationId, opContext.toAidlContext());
+                    mOperationId, opContext.toAidlContext(getOptions()));
         } else {
             return session.getSession().authenticate(mOperationId);
         }
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 376d231..16d16fc 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
@@ -48,6 +48,7 @@
     private static final String TAG = "FingerprintDetectClient";
 
     private final boolean mIsStrongBiometric;
+    private final FingerprintAuthenticateOptions mOptions;
     @NonNull private final SensorOverlays mSensorOverlays;
     @Nullable private ICancellationSignal mCancellationSignal;
 
@@ -66,6 +67,7 @@
         mIsStrongBiometric = isStrongBiometric;
         mSensorOverlays = new SensorOverlays(udfpsOverlayController,
                 null /* sideFpsController*/, udfpsOverlay);
+        mOptions = options;
     }
 
     @Override
@@ -105,7 +107,7 @@
 
         if (session.hasContextMethods()) {
             return session.getSession().detectInteractionWithContext(
-                    getOperationContext().toAidlContext());
+                    getOperationContext().toAidlContext(mOptions));
         } else {
             return session.getSession().detectInteraction();
         }
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 513b3e3..c2ca78e 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
@@ -274,8 +274,5 @@
     }
 
     @Override
-    public void onPowerPressed() {
-        onAcquired(BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_POWER_PRESSED,
-                0 /* vendorCode */);
-    }
+    public void onPowerPressed() {}
 }
diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java
index 12134f7..4e3de3c 100644
--- a/services/core/java/com/android/server/camera/CameraServiceProxy.java
+++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java
@@ -499,7 +499,8 @@
 
             if ((recentTasks != null) && (!recentTasks.getList().isEmpty())) {
                 for (ActivityManager.RecentTaskInfo task : recentTasks.getList()) {
-                    if (packageName.equals(task.topActivityInfo.packageName)) {
+                    if (task.topActivityInfo != null && packageName.equals(
+                            task.topActivityInfo.packageName)) {
                         taskInfo = new TaskInfo();
                         taskInfo.frontTaskId = task.taskId;
                         taskInfo.isResizeable =
diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index 3a4aaa7..1f82961 100644
--- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -31,7 +31,9 @@
 import android.net.metrics.NetworkMetrics;
 import android.net.metrics.WakeupEvent;
 import android.net.metrics.WakeupStats;
+import android.os.BatteryStatsInternal;
 import android.os.RemoteException;
+import android.os.SystemClock;
 import android.text.format.DateUtils;
 import android.util.ArrayMap;
 import android.util.Log;
@@ -44,6 +46,7 @@
 import com.android.internal.util.RingBuffer;
 import com.android.internal.util.TokenBucket;
 import com.android.net.module.util.BaseNetdEventListener;
+import com.android.server.LocalServices;
 import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
 
 import java.io.PrintWriter;
@@ -74,7 +77,7 @@
     // TODO: dedup this String constant with the one used in
     // ConnectivityService#wakeupModifyInterface().
     @VisibleForTesting
-    static final String WAKEUP_EVENT_IFACE_PREFIX = "iface:";
+    static final String WAKEUP_EVENT_PREFIX_DELIM = ":";
 
     // Array of aggregated DNS and connect events sent by netd, grouped by net id.
     @GuardedBy("this")
@@ -278,17 +281,14 @@
     @Override
     public synchronized void onWakeupEvent(String prefix, int uid, int ethertype, int ipNextHeader,
             byte[] dstHw, String srcIp, String dstIp, int srcPort, int dstPort, long timestampNs) {
-        String iface = prefix.replaceFirst(WAKEUP_EVENT_IFACE_PREFIX, "");
-        final long timestampMs;
-        if (timestampNs > 0) {
-            timestampMs = timestampNs / NANOS_PER_MS;
-        } else {
-            timestampMs = System.currentTimeMillis();
+        final String[] prefixParts = prefix.split(WAKEUP_EVENT_PREFIX_DELIM);
+        if (prefixParts.length != 2) {
+            throw new IllegalArgumentException("Prefix " + prefix
+                    + " required in format <nethandle>:<interface>");
         }
 
-        WakeupEvent event = new WakeupEvent();
-        event.iface = iface;
-        event.timestampMs = timestampMs;
+        final WakeupEvent event = new WakeupEvent();
+        event.iface = prefixParts[1];
         event.uid = uid;
         event.ethertype = ethertype;
         event.dstHwAddr = MacAddress.fromBytes(dstHw);
@@ -297,11 +297,25 @@
         event.ipNextHeader = ipNextHeader;
         event.srcPort = srcPort;
         event.dstPort = dstPort;
+        if (timestampNs > 0) {
+            event.timestampMs = timestampNs / NANOS_PER_MS;
+        } else {
+            event.timestampMs = System.currentTimeMillis();
+        }
         addWakeupEvent(event);
 
-        String dstMac = event.dstHwAddr.toString();
+        final BatteryStatsInternal bsi = LocalServices.getService(BatteryStatsInternal.class);
+        if (bsi != null) {
+            final long netHandle = Long.parseLong(prefixParts[0]);
+            final long elapsedMs = SystemClock.elapsedRealtime() + event.timestampMs
+                    - System.currentTimeMillis();
+            bsi.noteCpuWakingNetworkPacket(Network.fromNetworkHandle(netHandle), elapsedMs,
+                    event.uid);
+        }
+
+        final String dstMac = event.dstHwAddr.toString();
         FrameworkStatsLog.write(FrameworkStatsLog.PACKET_WAKEUP_OCCURRED,
-                uid, iface, ethertype, dstMac, srcIp, dstIp, ipNextHeader, srcPort, dstPort);
+                uid, event.iface, ethertype, dstMac, srcIp, dstIp, ipNextHeader, srcPort, dstPort);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 1ce917c..6d3f8fd 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -21,6 +21,7 @@
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.NetworkCapabilities.TRANSPORT_VPN;
 import static android.net.RouteInfo.RTN_THROW;
 import static android.net.RouteInfo.RTN_UNREACHABLE;
@@ -29,6 +30,7 @@
 import static android.net.ipsec.ike.IkeSessionParams.ESP_IP_VERSION_AUTO;
 import static android.os.PowerWhitelistManager.REASON_VPN;
 import static android.os.UserHandle.PER_USER_RANGE;
+import static android.telephony.CarrierConfigManager.KEY_MIN_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT;
 
 import static com.android.net.module.util.NetworkStackConstants.IPV6_MIN_MTU;
 import static com.android.server.vcn.util.PersistableBundleUtils.STRING_DESERIALIZER;
@@ -79,7 +81,9 @@
 import android.net.NetworkProvider;
 import android.net.NetworkRequest;
 import android.net.NetworkScore;
+import android.net.NetworkSpecifier;
 import android.net.RouteInfo;
+import android.net.TelephonyNetworkSpecifier;
 import android.net.UidRangeParcel;
 import android.net.UnderlyingNetworkInfo;
 import android.net.Uri;
@@ -127,12 +131,16 @@
 import android.system.keystore2.Domain;
 import android.system.keystore2.KeyDescriptor;
 import android.system.keystore2.KeyPermission;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.IndentingPrintWriter;
 import android.util.LocalLog;
 import android.util.Log;
 import android.util.Range;
+import android.util.SparseArray;
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
@@ -268,6 +276,10 @@
     private final ConnectivityManager mConnectivityManager;
     private final AppOpsManager mAppOpsManager;
     private final ConnectivityDiagnosticsManager mConnectivityDiagnosticsManager;
+    private final TelephonyManager mTelephonyManager;
+    private final CarrierConfigManager mCarrierConfigManager;
+    private final SubscriptionManager mSubscriptionManager;
+
     // The context is for specific user which is created from mUserId
     private final Context mUserIdContext;
     @VisibleForTesting final Dependencies mDeps;
@@ -314,6 +326,14 @@
     private final LocalLog mVpnManagerEvents = new LocalLog(MAX_EVENTS_LOGS);
 
     /**
+     * Cached Map of <subscription ID, keepalive delay ms> since retrieving the PersistableBundle
+     * and the target value from CarrierConfigManager is somewhat expensive as it has hundreds of
+     * fields. This cache is cleared when the carrier config changes to ensure data freshness.
+     */
+    @GuardedBy("this")
+    private final SparseArray<Integer> mCachedKeepalivePerSubId = new SparseArray<>();
+
+    /**
      * Whether to keep the connection active after rebooting, or upgrading or reinstalling. This
      * only applies to {@link VpnService} connections.
      */
@@ -626,6 +646,10 @@
         mUserIdContext = context.createContextAsUser(UserHandle.of(userId), 0 /* flags */);
         mConnectivityDiagnosticsManager =
                 mContext.getSystemService(ConnectivityDiagnosticsManager.class);
+        mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
+        mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
+        mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
+
         mDeps = deps;
         mNms = netService;
         mNetd = netd;
@@ -2893,6 +2917,24 @@
          */
         private int mRetryCount = 0;
 
+        private CarrierConfigManager.CarrierConfigChangeListener mCarrierConfigChangeListener =
+                new CarrierConfigManager.CarrierConfigChangeListener() {
+                    @Override
+                    public void onCarrierConfigChanged(int slotIndex, int subId, int carrierId,
+                            int specificCarrierId) {
+                        synchronized (Vpn.this) {
+                            mCachedKeepalivePerSubId.remove(subId);
+
+                            // Ignore stale runner.
+                            if (mVpnRunner != Vpn.IkeV2VpnRunner.this) return;
+
+                            maybeMigrateIkeSession(mActiveNetwork);
+                        }
+                        // TODO: update the longLivedTcpConnectionsExpensive value in the
+                        //  networkcapabilities of the VPN network.
+                    }
+        };
+
         IkeV2VpnRunner(
                 @NonNull Ikev2VpnProfile profile, @NonNull ScheduledThreadPoolExecutor executor) {
             super(TAG);
@@ -2918,6 +2960,9 @@
             setVpnNetworkPreference(mSessionKey,
                     createUserAndRestrictedProfilesRanges(mUserId,
                             mConfig.allowedApplications, mConfig.disallowedApplications));
+
+            mCarrierConfigManager.registerCarrierConfigChangeListener(mExecutor,
+                    mCarrierConfigChangeListener);
         }
 
         @Override
@@ -3257,8 +3302,6 @@
             mUnderlyingLinkProperties = null;
             mUnderlyingNetworkCapabilities = null;
             mRetryCount = 0;
-
-            startOrMigrateIkeSession(network);
         }
 
         @NonNull
@@ -3356,9 +3399,36 @@
         }
 
         private int guessNattKeepaliveTimerForNetwork() {
-            // TODO : guess the keepalive delay based on carrier if auto keepalive timer is
-            // enabled
-            return AUTOMATIC_KEEPALIVE_DELAY_SECONDS;
+            final int subId = getCellSubIdForNetworkCapabilities(mUnderlyingNetworkCapabilities);
+            if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+                Log.d(TAG, "Underlying network is not a cellular network");
+                return AUTOMATIC_KEEPALIVE_DELAY_SECONDS;
+            }
+
+            synchronized (Vpn.this) {
+                if (mCachedKeepalivePerSubId.contains(subId)) {
+                    Log.d(TAG, "Get cached keepalive config");
+                    return mCachedKeepalivePerSubId.get(subId);
+                }
+
+                final TelephonyManager perSubTm = mTelephonyManager.createForSubscriptionId(subId);
+                if (perSubTm.getSimApplicationState() != TelephonyManager.SIM_STATE_LOADED) {
+                    Log.d(TAG, "SIM card is not ready on sub " + subId);
+                    return AUTOMATIC_KEEPALIVE_DELAY_SECONDS;
+                }
+
+                final PersistableBundle carrierConfig =
+                        mCarrierConfigManager.getConfigForSubId(subId);
+                if (!CarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfig)) {
+                    return AUTOMATIC_KEEPALIVE_DELAY_SECONDS;
+                }
+
+                final int natKeepalive =
+                        carrierConfig.getInt(KEY_MIN_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT);
+                mCachedKeepalivePerSubId.put(subId, natKeepalive);
+                Log.d(TAG, "Get customized keepalive=" + natKeepalive);
+                return natKeepalive;
+            }
         }
 
         boolean maybeMigrateIkeSession(@NonNull Network underlyingNetwork) {
@@ -3456,7 +3526,15 @@
 
         /** Called when the NetworkCapabilities of underlying network is changed */
         public void onDefaultNetworkCapabilitiesChanged(@NonNull NetworkCapabilities nc) {
+            final NetworkCapabilities oldNc = mUnderlyingNetworkCapabilities;
             mUnderlyingNetworkCapabilities = nc;
+            if (oldNc == null) {
+                // A new default network is available.
+                startOrMigrateIkeSession(mActiveNetwork);
+            } else if (!nc.getSubscriptionIds().equals(oldNc.getSubscriptionIds())) {
+                // Renew carrierConfig values.
+                maybeMigrateIkeSession(mActiveNetwork);
+            }
         }
 
         /** Called when the LinkProperties of underlying network is changed */
@@ -3812,6 +3890,8 @@
 
             resetIkeState();
 
+            mCarrierConfigManager.unregisterCarrierConfigChangeListener(
+                    mCarrierConfigChangeListener);
             mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
             mConnectivityDiagnosticsManager.unregisterConnectivityDiagnosticsCallback(
                     mDiagnosticsCallback);
@@ -4804,6 +4884,8 @@
                     pw.println("Reset session scheduled");
                 }
             }
+            pw.println("mCachedKeepalivePerSubId=" + mCachedKeepalivePerSubId);
+
             pw.println("mUnderlyNetworkChanges (most recent first):");
             pw.increaseIndent();
             mUnderlyNetworkChanges.reverseDump(pw);
@@ -4815,4 +4897,19 @@
             pw.decreaseIndent();
         }
     }
+
+    private static int getCellSubIdForNetworkCapabilities(@Nullable NetworkCapabilities nc) {
+        if (nc == null) return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
+        if (!nc.hasTransport(TRANSPORT_CELLULAR)) {
+            return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+        }
+
+        final NetworkSpecifier specifier = nc.getNetworkSpecifier();
+        if (specifier instanceof TelephonyNetworkSpecifier) {
+            return ((TelephonyNetworkSpecifier) specifier).getSubscriptionId();
+        }
+
+        return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+    }
 }
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 592daa6..720ea99 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -50,7 +50,12 @@
 
 import java.io.PrintWriter;
 
-class AutomaticBrightnessController {
+/**
+ * Manages the associated display brightness when in auto-brightness mode. This is also
+ * responsible for managing the brightness lux-nits mapping strategies. Internally also listens to
+ * the LightSensor and adjusts the system brightness in case of changes in the surrounding lux.
+ */
+public class AutomaticBrightnessController {
     private static final String TAG = "AutomaticBrightnessController";
 
     private static final boolean DEBUG_PRETEND_LIGHT_SENSOR_ABSENT = false;
@@ -1140,7 +1145,7 @@
         if (mCurrentBrightnessMapper != null) {
             return mCurrentBrightnessMapper.convertToFloatScale(nits);
         } else {
-            return -1.0f;
+            return PowerManager.BRIGHTNESS_INVALID_FLOAT;
         }
     }
 
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index d7c1529..d047183 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -322,9 +322,10 @@
     public abstract float convertToNits(float brightness);
 
     /**
-     * Converts the provided nits value to a float value if possible.
+     * Converts the provided nit value to a float scale value if possible.
      *
-     * Returns -1.0f if there's no available mapping for the nits to float.
+     * Returns {@link PowerManager.BRIGHTNESS_INVALID_FLOAT} if there's no available mapping for
+     * the nits to float scale.
      */
     public abstract float convertToFloatScale(float nits);
 
@@ -679,7 +680,7 @@
 
         @Override
         public float convertToFloatScale(float nits) {
-            return -1.0f;
+            return PowerManager.BRIGHTNESS_INVALID_FLOAT;
         }
 
         @Override
diff --git a/services/core/java/com/android/server/display/BrightnessSetting.java b/services/core/java/com/android/server/display/BrightnessSetting.java
index 4a9b562..de42370 100644
--- a/services/core/java/com/android/server/display/BrightnessSetting.java
+++ b/services/core/java/com/android/server/display/BrightnessSetting.java
@@ -121,6 +121,23 @@
         }
     }
 
+    /**
+     * @return The brightness for the default display in nits. Used when the underlying display
+     * device has changed but we want to persist the nit value.
+     */
+    public float getBrightnessNitsForDefaultDisplay() {
+        return mPersistentDataStore.getBrightnessNitsForDefaultDisplay();
+    }
+
+    /**
+     * Set brightness in nits for the default display. Used when we want to persist the nit value
+     * even if the underlying display device changes.
+     * @param nits The brightness value in nits
+     */
+    public void setBrightnessNitsForDefaultDisplay(float nits) {
+        mPersistentDataStore.setBrightnessNitsForDefaultDisplay(nits);
+    }
+
     private void notifyListeners(float brightness) {
         for (BrightnessSettingListener l : mListeners) {
             l.onBrightnessChanged(brightness);
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index 6e1640d..22b6a53 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -35,7 +35,6 @@
 import android.hardware.SensorManager;
 import android.hardware.display.AmbientBrightnessDayStats;
 import android.hardware.display.BrightnessChangeEvent;
-import android.hardware.display.BrightnessConfiguration;
 import android.hardware.display.ColorDisplayManager;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManagerInternal;
@@ -126,7 +125,7 @@
     private static final int MSG_BRIGHTNESS_CHANGED = 1;
     private static final int MSG_STOP_SENSOR_LISTENER = 2;
     private static final int MSG_START_SENSOR_LISTENER = 3;
-    private static final int MSG_BRIGHTNESS_CONFIG_CHANGED = 4;
+    private static final int MSG_SHOULD_COLLECT_COLOR_SAMPLE_CHANGED = 4;
     private static final int MSG_SENSOR_CHANGED = 5;
 
     private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
@@ -162,7 +161,7 @@
     private boolean mColorSamplingEnabled;
     private int mNoFramesToSample;
     private float mFrameRate;
-    private BrightnessConfiguration mBrightnessConfiguration;
+    private boolean mShouldCollectColorSample = false;
     // End of block of members that should only be accessed on the mBgHandler thread.
 
     private @UserIdInt int mCurrentUserId = UserHandle.USER_NULL;
@@ -208,9 +207,9 @@
     /**
      * Update tracker with new brightness configuration.
      */
-    public void setBrightnessConfiguration(BrightnessConfiguration brightnessConfiguration) {
-        mBgHandler.obtainMessage(MSG_BRIGHTNESS_CONFIG_CHANGED,
-                brightnessConfiguration).sendToTarget();
+    public void setShouldCollectColorSample(boolean shouldCollectColorSample) {
+        mBgHandler.obtainMessage(MSG_SHOULD_COLLECT_COLOR_SAMPLE_CHANGED,
+                shouldCollectColorSample).sendToTarget();
     }
 
     private void backgroundStart(float initialBrightness) {
@@ -320,7 +319,7 @@
      * Notify the BrightnessTracker that the user has changed the brightness of the display.
      */
     public void notifyBrightnessChanged(float brightness, boolean userInitiated,
-            float powerBrightnessFactor, boolean isUserSetBrightness,
+            float powerBrightnessFactor, boolean wasShortTermModelActive,
             boolean isDefaultBrightnessConfig, String uniqueDisplayId, float[] luxValues,
             long[] luxTimestamps) {
         if (DEBUG) {
@@ -329,7 +328,7 @@
         }
         Message m = mBgHandler.obtainMessage(MSG_BRIGHTNESS_CHANGED,
                 userInitiated ? 1 : 0, 0 /*unused*/, new BrightnessChangeValues(brightness,
-                        powerBrightnessFactor, isUserSetBrightness, isDefaultBrightnessConfig,
+                        powerBrightnessFactor, wasShortTermModelActive, isDefaultBrightnessConfig,
                         mInjector.currentTimeMillis(), uniqueDisplayId, luxValues, luxTimestamps));
         m.sendToTarget();
     }
@@ -343,7 +342,7 @@
     }
 
     private void handleBrightnessChanged(float brightness, boolean userInitiated,
-            float powerBrightnessFactor, boolean isUserSetBrightness,
+            float powerBrightnessFactor, boolean wasShortTermModelActive,
             boolean isDefaultBrightnessConfig, long timestamp, String uniqueDisplayId,
             float[] luxValues, long[] luxTimestamps) {
         BrightnessChangeEvent.Builder builder;
@@ -368,7 +367,7 @@
             builder.setBrightness(brightness);
             builder.setTimeStamp(timestamp);
             builder.setPowerBrightnessFactor(powerBrightnessFactor);
-            builder.setUserBrightnessPoint(isUserSetBrightness);
+            builder.setUserBrightnessPoint(wasShortTermModelActive);
             builder.setIsDefaultBrightnessConfig(isDefaultBrightnessConfig);
             builder.setUniqueDisplayId(uniqueDisplayId);
 
@@ -827,8 +826,7 @@
         if (!mInjector.isBrightnessModeAutomatic(mContentResolver)
                 || !mInjector.isInteractive(mContext)
                 || mColorSamplingEnabled
-                || mBrightnessConfiguration == null
-                || !mBrightnessConfiguration.shouldCollectColorSamples()) {
+                || !mShouldCollectColorSample) {
             return;
         }
 
@@ -997,7 +995,7 @@
                     BrightnessChangeValues values = (BrightnessChangeValues) msg.obj;
                     boolean userInitiatedChange = (msg.arg1 == 1);
                     handleBrightnessChanged(values.brightness, userInitiatedChange,
-                            values.powerBrightnessFactor, values.isUserSetBrightness,
+                            values.powerBrightnessFactor, values.wasShortTermModelActive,
                             values.isDefaultBrightnessConfig, values.timestamp,
                             values.uniqueDisplayId, values.luxValues, values.luxTimestamps);
                     break;
@@ -1009,14 +1007,11 @@
                     stopSensorListener();
                     disableColorSampling();
                     break;
-                case MSG_BRIGHTNESS_CONFIG_CHANGED:
-                    mBrightnessConfiguration = (BrightnessConfiguration) msg.obj;
-                    boolean shouldCollectColorSamples =
-                            mBrightnessConfiguration != null
-                                    && mBrightnessConfiguration.shouldCollectColorSamples();
-                    if (shouldCollectColorSamples && !mColorSamplingEnabled) {
+                case MSG_SHOULD_COLLECT_COLOR_SAMPLE_CHANGED:
+                    mShouldCollectColorSample = (boolean) msg.obj;
+                    if (mShouldCollectColorSample && !mColorSamplingEnabled) {
                         enableColorSampling();
-                    } else if (!shouldCollectColorSamples && mColorSamplingEnabled) {
+                    } else if (!mShouldCollectColorSample && mColorSamplingEnabled) {
                         disableColorSampling();
                     }
                     break;
@@ -1031,7 +1026,7 @@
     private static class BrightnessChangeValues {
         public final float brightness;
         public final float powerBrightnessFactor;
-        public final boolean isUserSetBrightness;
+        public final boolean wasShortTermModelActive;
         public final boolean isDefaultBrightnessConfig;
         public final long timestamp;
         public final String uniqueDisplayId;
@@ -1039,11 +1034,11 @@
         public final long[] luxTimestamps;
 
         BrightnessChangeValues(float brightness, float powerBrightnessFactor,
-                boolean isUserSetBrightness, boolean isDefaultBrightnessConfig,
+                boolean wasShortTermModelActive, boolean isDefaultBrightnessConfig,
                 long timestamp, String uniqueDisplayId, float[] luxValues, long[] luxTimestamps) {
             this.brightness = brightness;
             this.powerBrightnessFactor = powerBrightnessFactor;
-            this.isUserSetBrightness = isUserSetBrightness;
+            this.wasShortTermModelActive = wasShortTermModelActive;
             this.isDefaultBrightnessConfig = isDefaultBrightnessConfig;
             this.timestamp = timestamp;
             this.uniqueDisplayId = uniqueDisplayId;
diff --git a/services/core/java/com/android/server/display/DeviceStateToLayoutMap.java b/services/core/java/com/android/server/display/DeviceStateToLayoutMap.java
index ce29013..f84a58c 100644
--- a/services/core/java/com/android/server/display/DeviceStateToLayoutMap.java
+++ b/services/core/java/com/android/server/display/DeviceStateToLayoutMap.java
@@ -121,23 +121,18 @@
                 final Layout layout = createLayout(state);
                 for (com.android.server.display.config.layout.Display d: l.getDisplay()) {
                     assert layout != null;
-                    Layout.Display display = layout.createDisplayLocked(
+                    int position = getPosition(d.getPosition());
+                    layout.createDisplayLocked(
                             DisplayAddress.fromPhysicalDisplayId(d.getAddress().longValue()),
                             d.isDefaultDisplay(),
                             d.isEnabled(),
                             d.getDisplayGroup(),
                             mIdProducer,
+                            position,
+                            leadDisplayId,
                             d.getBrightnessThrottlingMapId(),
-                            leadDisplayId);
-
-                    if (FRONT_STRING.equals(d.getPosition())) {
-                        display.setPosition(POSITION_FRONT);
-                    } else if (REAR_STRING.equals(d.getPosition())) {
-                        display.setPosition(POSITION_REAR);
-                    } else {
-                        display.setPosition(POSITION_UNKNOWN);
-                    }
-                    display.setRefreshRateZoneId(d.getRefreshRateZoneId());
+                            d.getRefreshRateZoneId(),
+                            d.getRefreshRateThermalThrottlingMapId());
                 }
             }
         } catch (IOException | DatatypeConfigurationException | XmlPullParserException e) {
@@ -146,6 +141,16 @@
         }
     }
 
+    private int getPosition(@NonNull String position) {
+        int positionInt = POSITION_UNKNOWN;
+        if (FRONT_STRING.equals(position)) {
+            positionInt = POSITION_FRONT;
+        } else if (REAR_STRING.equals(position)) {
+            positionInt = POSITION_REAR;
+        }
+        return positionInt;
+    }
+
     private Layout createLayout(int state) {
         if (mLayoutMap.contains(state)) {
             Slog.e(TAG, "Attempted to create a second layout for state " + state);
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 99e709e..d57dc47 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -22,11 +22,14 @@
 import android.graphics.Rect;
 import android.hardware.display.DisplayViewport;
 import android.os.IBinder;
+import android.util.Slog;
 import android.view.Display;
 import android.view.DisplayAddress;
 import android.view.Surface;
 import android.view.SurfaceControl;
 
+import com.android.server.display.mode.DisplayModeDirector;
+
 import java.io.PrintWriter;
 
 /**
@@ -37,6 +40,7 @@
  * </p>
  */
 abstract class DisplayDevice {
+    private static final String TAG = "DisplayDevice";
     private static final Display.Mode EMPTY_DISPLAY_MODE = new Display.Mode.Builder().build();
 
     private final DisplayAdapter mDisplayAdapter;
@@ -267,10 +271,13 @@
     /**
      * Sets the display layer stack while in a transaction.
      */
-    public final void setLayerStackLocked(SurfaceControl.Transaction t, int layerStack) {
+    public final void setLayerStackLocked(SurfaceControl.Transaction t, int layerStack,
+            int layerStackTag) {
         if (mCurrentLayerStack != layerStack) {
             mCurrentLayerStack = layerStack;
             t.setDisplayLayerStack(mDisplayToken, layerStack);
+            Slog.i(TAG, "[" + layerStackTag + "] Layerstack set to " + layerStack + " for "
+                    + mUniqueId);
         }
     }
 
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index d9b3501..f4b3f1a 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -31,6 +31,7 @@
 import android.util.MathUtils;
 import android.util.Pair;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.util.Spline;
 import android.view.DisplayAddress;
 import android.view.SurfaceControl;
@@ -54,6 +55,8 @@
 import com.android.server.display.config.Point;
 import com.android.server.display.config.RefreshRateConfigs;
 import com.android.server.display.config.RefreshRateRange;
+import com.android.server.display.config.RefreshRateThrottlingMap;
+import com.android.server.display.config.RefreshRateThrottlingPoint;
 import com.android.server.display.config.RefreshRateZone;
 import com.android.server.display.config.SdrHdrRatioMap;
 import com.android.server.display.config.SdrHdrRatioPoint;
@@ -88,6 +91,7 @@
  * <pre>
  *  {@code
  *    <displayConfiguration>
+ *      <name>Built-In Display</name>
  *      <densityMapping>
  *        <density>
  *          <height>480</height>
@@ -149,9 +153,26 @@
  *            <brightness>0.005</brightness>
  *          </brightnessThrottlingPoint>
  *        </concurrentDisplaysBrightnessThrottlingMap>
+ *        <refreshRateThrottlingMap>
+ *            <refreshRateThrottlingPoint>
+ *                <thermalStatus>critical</thermalStatus>
+ *                <refreshRateRange>
+ *                     <minimum>0</minimum>
+ *                     <maximum>60</maximum>
+ *                 </refreshRateRange>
+ *            </refreshRateThrottlingPoint>
+ *        </refreshRateThrottlingMap>
  *      </thermalThrottling>
  *
  *      <refreshRate>
+ *       <refreshRateZoneProfiles>
+ *         <refreshRateZoneProfile id="concurrent">
+ *           <refreshRateRange>
+ *             <minimum>60</minimum>
+ *             <maximum>60</maximum>
+ *            </refreshRateRange>
+ *          </refreshRateZoneProfile>
+ *        </refreshRateZoneProfiles>
  *        <defaultRefreshRateInHbmHdr>75</defaultRefreshRateInHbmHdr>
  *        <defaultRefreshRateInHbmSunlight>75</defaultRefreshRateInHbmSunlight>
  *        <lowerBlockingZoneConfigs>
@@ -417,7 +438,7 @@
 
     public static final String QUIRK_CAN_SET_BRIGHTNESS_VIA_HWC = "canSetBrightnessViaHwc";
 
-    static final String DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID = "default";
+    static final String DEFAULT_ID = "default";
 
     private static final float BRIGHTNESS_DEFAULT = 0.5f;
     private static final String ETC_DIR = "etc";
@@ -479,6 +500,10 @@
     private final List<RefreshRateLimitation> mRefreshRateLimitations =
             new ArrayList<>(2 /*initialCapacity*/);
 
+    // Name of the display, if configured.
+    @Nullable
+    private String mName;
+
     // Nits and backlight values that are loaded from either the display device config file, or
     // config.xml. These are the raw values and just used for the dumpsys
     private float[] mRawNits;
@@ -662,7 +687,11 @@
     private int[] mHighDisplayBrightnessThresholds = DEFAULT_BRIGHTNESS_THRESHOLDS;
     private int[] mHighAmbientBrightnessThresholds = DEFAULT_BRIGHTNESS_THRESHOLDS;
 
-    private Map<String, BrightnessThrottlingData> mBrightnessThrottlingDataMap = new HashMap();
+    private final Map<String, BrightnessThrottlingData> mBrightnessThrottlingDataMap =
+            new HashMap<>();
+
+    private final Map<String, SparseArray<SurfaceControl.RefreshRateRange>>
+            mRefreshRateThrottlingMap = new HashMap<>();
 
     @Nullable
     private HostUsiVersion mHostUsiVersion;
@@ -808,6 +837,15 @@
         return config;
     }
 
+    /** The name of the display.
+     *
+     * @return The name of the display.
+     */
+    @Nullable
+    public String getName() {
+        return mName;
+    }
+
     /**
      * Return the brightness mapping nits array.
      *
@@ -851,11 +889,12 @@
     }
 
     /**
-     * Calculate the HDR brightness for the specified SDR brightenss.
+     * Calculate the HDR brightness for the specified SDR brightenss, restricted by the
+     * maxDesiredHdrSdrRatio (the ratio between the HDR luminance and SDR luminance)
      *
      * @return the HDR brightness or BRIGHTNESS_INVALID when no mapping exists.
      */
-    public float getHdrBrightnessFromSdr(float brightness) {
+    public float getHdrBrightnessFromSdr(float brightness, float maxDesiredHdrSdrRatio) {
         if (mSdrToHdrRatioSpline == null) {
             return PowerManager.BRIGHTNESS_INVALID;
         }
@@ -866,7 +905,7 @@
             return PowerManager.BRIGHTNESS_INVALID;
         }
 
-        float ratio = mSdrToHdrRatioSpline.interpolate(nits);
+        float ratio = Math.min(mSdrToHdrRatioSpline.interpolate(nits), maxDesiredHdrSdrRatio);
         float hdrNits = nits * ratio;
         if (mNitsToBacklightSpline == null) {
             return PowerManager.BRIGHTNESS_INVALID;
@@ -1260,7 +1299,7 @@
         return mAmbientDarkeningPercentagesIdle;
     }
 
-    SensorData getAmbientLightSensor() {
+    public SensorData getAmbientLightSensor() {
         return mAmbientLightSensor;
     }
 
@@ -1315,6 +1354,17 @@
     }
 
     /**
+     * @param id - throttling data id or null for default
+     * @return refresh rate throttling configuration
+     */
+    @Nullable
+    public SparseArray<SurfaceControl.RefreshRateRange> getRefreshRateThrottlingData(
+            @Nullable String id) {
+        String key = id == null ? DEFAULT_ID : id;
+        return mRefreshRateThrottlingMap.get(key);
+    }
+
+    /**
      * @return Auto brightness darkening light debounce
      */
     public long getAutoBrightnessDarkeningLightDebounce() {
@@ -1552,6 +1602,8 @@
                 + ", mRefreshRateZoneProfiles= " + mRefreshRateZoneProfiles
                 + ", mDefaultRefreshRateInHbmHdr= " + mDefaultRefreshRateInHbmHdr
                 + ", mDefaultRefreshRateInHbmSunlight= " + mDefaultRefreshRateInHbmSunlight
+                + ", mRefreshRateThrottlingMap= " + mRefreshRateThrottlingMap
+                + "\n"
                 + ", mLowDisplayBrightnessThresholds= "
                 + Arrays.toString(mLowDisplayBrightnessThresholds)
                 + ", mLowAmbientBrightnessThresholds= "
@@ -1609,11 +1661,12 @@
         try (InputStream in = new BufferedInputStream(new FileInputStream(configFile))) {
             final DisplayConfiguration config = XmlParser.read(in);
             if (config != null) {
+                loadName(config);
                 loadDensityMapping(config);
                 loadBrightnessDefaultFromDdcXml(config);
                 loadBrightnessConstraintsFromConfigXml();
                 loadBrightnessMap(config);
-                loadBrightnessThrottlingMaps(config);
+                loadThermalThrottlingConfig(config);
                 loadHighBrightnessModeData(config);
                 loadQuirks(config);
                 loadBrightnessRamps(config);
@@ -1680,6 +1733,10 @@
         }
     }
 
+    private void loadName(DisplayConfiguration config) {
+        mName = config.getName();
+    }
+
     private void loadDensityMapping(DisplayConfiguration config) {
         if (config.getDensityMapping() == null) {
             return;
@@ -1823,13 +1880,17 @@
         return Spline.createSpline(nits, ratios);
     }
 
-    private void loadBrightnessThrottlingMaps(DisplayConfiguration config) {
+    private void loadThermalThrottlingConfig(DisplayConfiguration config) {
         final ThermalThrottling throttlingConfig = config.getThermalThrottling();
         if (throttlingConfig == null) {
             Slog.i(TAG, "No thermal throttling config found");
             return;
         }
+        loadBrightnessThrottlingMaps(throttlingConfig);
+        loadRefreshRateThermalThrottlingMap(throttlingConfig);
+    }
 
+    private void loadBrightnessThrottlingMaps(ThermalThrottling throttlingConfig) {
         final List<BrightnessThrottlingMap> maps = throttlingConfig.getBrightnessThrottlingMap();
         if (maps == null || maps.isEmpty()) {
             Slog.i(TAG, "No brightness throttling map found");
@@ -1855,7 +1916,7 @@
             }
 
             if (!badConfig) {
-                String id = map.getId() == null ? DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID
+                String id = map.getId() == null ? DEFAULT_ID
                         : map.getId();
                 if (mBrightnessThrottlingDataMap.containsKey(id)) {
                     throw new RuntimeException("Brightness throttling data with ID " + id
@@ -1867,6 +1928,57 @@
         }
     }
 
+    private void loadRefreshRateThermalThrottlingMap(ThermalThrottling throttlingConfig) {
+        List<RefreshRateThrottlingMap> maps = throttlingConfig.getRefreshRateThrottlingMap();
+        if (maps == null || maps.isEmpty()) {
+            Slog.w(TAG, "RefreshRateThrottling: map not found");
+            return;
+        }
+
+        for (RefreshRateThrottlingMap map : maps) {
+            List<RefreshRateThrottlingPoint> points = map.getRefreshRateThrottlingPoint();
+            String id = map.getId() == null ? DEFAULT_ID : map.getId();
+
+            if (points == null || points.isEmpty()) {
+                // Expected at lease 1 throttling point for each map
+                Slog.w(TAG, "RefreshRateThrottling: points not found for mapId=" + id);
+                continue;
+            }
+            if (mRefreshRateThrottlingMap.containsKey(id)) {
+                Slog.wtf(TAG, "RefreshRateThrottling: map already exists, mapId=" + id);
+                continue;
+            }
+
+            SparseArray<SurfaceControl.RefreshRateRange> refreshRates = new SparseArray<>();
+            for (RefreshRateThrottlingPoint point : points) {
+                ThermalStatus status = point.getThermalStatus();
+                if (!thermalStatusIsValid(status)) {
+                    Slog.wtf(TAG,
+                            "RefreshRateThrottling: Invalid thermalStatus=" + status.getRawName()
+                                    + ",mapId=" + id);
+                    continue;
+                }
+                int thermalStatusInt = convertThermalStatus(status);
+                if (refreshRates.contains(thermalStatusInt)) {
+                    Slog.wtf(TAG, "RefreshRateThrottling: thermalStatus=" + status.getRawName()
+                            + " is already in the map, mapId=" + id);
+                    continue;
+                }
+
+                refreshRates.put(thermalStatusInt, new SurfaceControl.RefreshRateRange(
+                        point.getRefreshRateRange().getMinimum().floatValue(),
+                        point.getRefreshRateRange().getMaximum().floatValue()
+                ));
+            }
+            if (refreshRates.size() == 0) {
+                Slog.w(TAG, "RefreshRateThrottling: no valid throttling points fond for map, mapId="
+                        + id);
+                continue;
+            }
+            mRefreshRateThrottlingMap.put(id, refreshRates);
+        }
+    }
+
     private void loadRefreshRateSetting(DisplayConfiguration config) {
         final RefreshRateConfigs refreshRateConfigs =
                 (config == null) ? null : config.getRefreshRate();
@@ -2821,7 +2933,7 @@
     /**
      * Uniquely identifies a Sensor, with the combination of Type and Name.
      */
-    static class SensorData {
+    public static class SensorData {
         public String type;
         public String name;
         public float minRefreshRate = 0.0f;
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 6eb465e..ea157c8 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -128,6 +128,7 @@
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 import android.util.Spline;
+import android.view.ContentRecordingSession;
 import android.view.Display;
 import android.view.DisplayEventReceiver;
 import android.view.DisplayInfo;
@@ -152,6 +153,7 @@
 import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
 import com.android.server.display.DisplayDeviceConfig.SensorData;
 import com.android.server.display.layout.Layout;
+import com.android.server.display.mode.DisplayModeDirector;
 import com.android.server.display.utils.SensorUtils;
 import com.android.server.input.InputManagerInternal;
 import com.android.server.wm.SurfaceAnimationThread;
@@ -249,6 +251,7 @@
     private ActivityManagerInternal mActivityManagerInternal;
     private ActivityManager mActivityManager;
     private UidImportanceListener mUidImportanceListener = new UidImportanceListener();
+    @Nullable
     private IMediaProjectionManager mProjectionService;
     private DeviceStateManagerInternal mDeviceStateManager;
     @GuardedBy("mSyncRoot")
@@ -1493,8 +1496,9 @@
 
         final long token = Binder.clearCallingIdentity();
         try {
+            final int displayId;
             synchronized (mSyncRoot) {
-                final int displayId =
+                displayId =
                         createVirtualDisplayLocked(
                                 callback,
                                 projection,
@@ -1508,8 +1512,39 @@
                     mDisplayWindowPolicyControllers.put(
                             displayId, Pair.create(virtualDevice, dwpc));
                 }
-                return displayId;
             }
+
+            // When calling setContentRecordingSession into the WindowManagerService, the WMS
+            // attempts to acquire a lock before executing its main body. Due to this, we need
+            // to be sure that it isn't called while the DisplayManagerService is also holding
+            // a lock, to avoid a deadlock scenario.
+            final ContentRecordingSession session =
+                    virtualDisplayConfig.getContentRecordingSession();
+
+            if (displayId != Display.INVALID_DISPLAY && session != null) {
+                // Only attempt to set content recording session if there are details to set and a
+                // VirtualDisplay has been successfully constructed.
+                session.setDisplayId(displayId);
+
+                // We set the content recording session here on the server side instead of using
+                // a second AIDL call in MediaProjection. By ensuring that a virtual display has
+                // been constructed before calling setContentRecordingSession, we avoid a race
+                // condition between the DMS & WMS which could lead to the MediaProjection
+                // being pre-emptively torn down.
+                if (!mWindowManagerInternal.setContentRecordingSession(session)) {
+                    // Unable to start mirroring, so tear down projection & release VirtualDisplay.
+                    try {
+                        getProjectionService().stopActiveProjection();
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "Unable to tell MediaProjectionManagerService to stop the "
+                                + "active projection", e);
+                    }
+                    releaseVirtualDisplayInternal(callback.asBinder());
+                    return Display.INVALID_DISPLAY;
+                }
+            }
+
+            return displayId;
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -2104,8 +2139,7 @@
         }
     }
 
-    // TODO (b/264979880) - Add unit test for HDR output control methods.
-    private void setHdrConversionModeInternal(HdrConversionMode hdrConversionMode) {
+    void setHdrConversionModeInternal(HdrConversionMode hdrConversionMode) {
         if (!mInjector.getHdrOutputConversionSupport()) {
             return;
         }
@@ -2126,20 +2160,28 @@
                 autoHdrOutputTypes = getEnabledAutoHdrTypesLocked();
             }
 
+            int conversionMode = hdrConversionMode.getConversionMode();
+            int preferredHdrType = hdrConversionMode.getPreferredHdrOutputType();
             // If the HDR conversion is disabled by an app through WindowManager.LayoutParams, then
             // set HDR conversion mode to HDR_CONVERSION_PASSTHROUGH.
             if (mOverrideHdrConversionMode == null) {
-                mSystemPreferredHdrOutputType =
-                        mInjector.setHdrConversionMode(hdrConversionMode.getConversionMode(),
-                        hdrConversionMode.getPreferredHdrOutputType(), autoHdrOutputTypes);
+                // HDR_CONVERSION_FORCE with HDR_TYPE_INVALID is used to represent forcing SDR type.
+                // But, internally SDR is selected by using passthrough mode.
+                if (conversionMode == HdrConversionMode.HDR_CONVERSION_FORCE
+                        && preferredHdrType == Display.HdrCapabilities.HDR_TYPE_INVALID) {
+                    conversionMode = HdrConversionMode.HDR_CONVERSION_PASSTHROUGH;
+                }
             } else {
-                mInjector.setHdrConversionMode(mOverrideHdrConversionMode.getConversionMode(),
-                        mOverrideHdrConversionMode.getPreferredHdrOutputType(), null);
+                conversionMode = mOverrideHdrConversionMode.getConversionMode();
+                preferredHdrType = mOverrideHdrConversionMode.getPreferredHdrOutputType();
+                autoHdrOutputTypes = null;
             }
+            mSystemPreferredHdrOutputType = mInjector.setHdrConversionMode(
+                    conversionMode, preferredHdrType, autoHdrOutputTypes);
         }
     }
 
-    private HdrConversionMode getHdrConversionModeSettingInternal() {
+    HdrConversionMode getHdrConversionModeSettingInternal() {
         if (!mInjector.getHdrOutputConversionSupport()) {
             return HDR_CONVERSION_MODE_UNSUPPORTED;
         }
@@ -2796,8 +2838,7 @@
 
     private IMediaProjectionManager getProjectionService() {
         if (mProjectionService == null) {
-            IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE);
-            mProjectionService = IMediaProjectionManager.Stub.asInterface(b);
+            mProjectionService = mInjector.getProjectionService();
         }
         return mProjectionService;
     }
@@ -2956,6 +2997,11 @@
         boolean getHdrOutputConversionSupport() {
             return DisplayControl.getHdrOutputConversionSupport();
         }
+
+        IMediaProjectionManager getProjectionService() {
+            IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE);
+            return  IMediaProjectionManager.Stub.asInterface(b);
+        }
     }
 
     @VisibleForTesting
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 9917bfc..e12cd8c 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -233,6 +233,10 @@
     // True if should use light sensor to automatically determine doze screen brightness.
     private final boolean mAllowAutoBrightnessWhileDozingConfig;
 
+    // True if we want to persist the brightness value in nits even if the underlying display
+    // device changes.
+    private final boolean mPersistBrightnessNitsForDefaultDisplay;
+
     // True if the brightness config has changed and the short-term model needs to be reset
     private boolean mShouldResetShortTermModel;
 
@@ -590,6 +594,9 @@
         mAllowAutoBrightnessWhileDozingConfig = resources.getBoolean(
                 com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing);
 
+        mPersistBrightnessNitsForDefaultDisplay = resources.getBoolean(
+                com.android.internal.R.bool.config_persistBrightnessNitsForDefaultDisplay);
+
         mDisplayDeviceConfig = logicalDisplay.getPrimaryDisplayDeviceLocked()
                 .getDisplayDeviceConfig();
 
@@ -658,7 +665,7 @@
 
         loadProximitySensor();
 
-        mCurrentScreenBrightnessSetting = getScreenBrightnessSetting();
+        loadNitBasedBrightnessSetting();
         mBrightnessToFollow = PowerManager.BRIGHTNESS_INVALID_FLOAT;
         mAutoBrightnessAdjustment = getAutoBrightnessAdjustmentSetting();
         mTemporaryScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
@@ -745,10 +752,10 @@
     @Override
     public void setBrightnessToFollow(float leadDisplayBrightness, float nits, float ambientLux) {
         mHbmController.onAmbientLuxChange(ambientLux);
-        if (mAutomaticBrightnessController == null || nits < 0) {
+        if (nits < 0) {
             mBrightnessToFollow = leadDisplayBrightness;
         } else {
-            float brightness = mAutomaticBrightnessController.convertToFloatScale(nits);
+            float brightness = convertToFloatScale(nits);
             if (isValidBrightnessValue(brightness)) {
                 mBrightnessToFollow = brightness;
             } else {
@@ -885,7 +892,7 @@
         final boolean isInTransition = mLogicalDisplay.isInTransitionLocked();
         final String brightnessThrottlingDataId =
                 mLogicalDisplay.getBrightnessThrottlingDataIdLocked();
-        mHandler.post(() -> {
+        mHandler.postAtTime(() -> {
             boolean changed = false;
             if (mDisplayDevice != device) {
                 changed = true;
@@ -895,6 +902,7 @@
                 mDisplayDeviceConfig = config;
                 mBrightnessThrottlingDataId = brightnessThrottlingDataId;
                 loadFromDisplayDeviceConfig(token, info, hbmMetadata);
+                loadNitBasedBrightnessSetting();
 
                 /// Since the underlying display-device changed, we really don't know the
                 // last command that was sent to change it's state. Lets assume it is unknown so
@@ -916,7 +924,7 @@
             if (changed) {
                 updatePowerState();
             }
-        });
+        }, mClock.uptimeMillis());
     }
 
     /**
@@ -940,10 +948,6 @@
                 mAutomaticBrightnessController.stop();
             }
 
-            if (mScreenOffBrightnessSensorController != null) {
-                mScreenOffBrightnessSensorController.stop();
-            }
-
             if (mBrightnessSetting != null) {
                 mBrightnessSetting.unregisterListener(mBrightnessSettingListener);
             }
@@ -971,8 +975,10 @@
                 mDisplayDeviceConfig.getHighBrightnessModeData(),
                 new HighBrightnessModeController.HdrBrightnessDeviceConfig() {
                     @Override
-                    public float getHdrBrightnessFromSdr(float sdrBrightness) {
-                        return mDisplayDeviceConfig.getHdrBrightnessFromSdr(sdrBrightness);
+                    public float getHdrBrightnessFromSdr(
+                            float sdrBrightness, float maxDesiredHdrSdrRatio) {
+                        return mDisplayDeviceConfig.getHdrBrightnessFromSdr(
+                                sdrBrightness, maxDesiredHdrSdrRatio);
                     }
                 });
         mBrightnessThrottler.resetThrottlingData(
@@ -1190,6 +1196,7 @@
 
             if (mScreenOffBrightnessSensorController != null) {
                 mScreenOffBrightnessSensorController.stop();
+                mScreenOffBrightnessSensorController = null;
             }
             loadScreenOffBrightnessSensor();
             int[] sensorValueToLux = mDisplayDeviceConfig.getScreenOffBrightnessSensorValueToLux();
@@ -1311,6 +1318,10 @@
             mPowerState.stop();
             mPowerState = null;
         }
+
+        if (mScreenOffBrightnessSensorController != null) {
+            mScreenOffBrightnessSensorController.stop();
+        }
     }
 
     private void updatePowerState() {
@@ -1440,8 +1451,17 @@
                 sendOnProximityNegativeWithWakelock();
             }
         } else {
+            setProximitySensorEnabled(false);
             mWaitingForNegativeProximity = false;
             mIgnoreProximityUntilChanged = false;
+
+            if (mScreenOffBecauseOfProximity) {
+                // The screen *was* off due to prox being near, but now there's no prox sensor, so
+                // let's turn the screen back on.
+                mScreenOffBecauseOfProximity = false;
+                skipRampBecauseOfProximityChangeToNegative = true;
+                sendOnProximityNegativeWithWakelock();
+            }
         }
 
         if (!mIsEnabled
@@ -1538,10 +1558,10 @@
         // user, or is a temporary adjustment.
         boolean userInitiatedChange = (Float.isNaN(brightnessState))
                 && (autoBrightnessAdjustmentChanged || userSetBrightnessChanged);
-        boolean hadUserBrightnessPoint = false;
+        boolean wasShortTermModelActive = false;
         // Configure auto-brightness.
         if (mAutomaticBrightnessController != null) {
-            hadUserBrightnessPoint = mAutomaticBrightnessController.hasUserDataPoints();
+            wasShortTermModelActive = mAutomaticBrightnessController.hasUserDataPoints();
             mAutomaticBrightnessController.configure(autoBrightnessState,
                     mBrightnessConfiguration,
                     mLastUserSetScreenBrightness,
@@ -1555,7 +1575,8 @@
                 : AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED);
 
         if (mBrightnessTracker != null) {
-            mBrightnessTracker.setBrightnessConfiguration(mBrightnessConfiguration);
+            mBrightnessTracker.setShouldCollectColorSample(mBrightnessConfiguration != null
+                    && mBrightnessConfiguration.shouldCollectColorSamples());
         }
 
         boolean updateScreenBrightnessSetting = false;
@@ -1823,7 +1844,7 @@
                     userInitiatedChange = false;
                 }
                 notifyBrightnessTrackerChanged(brightnessState, userInitiatedChange,
-                        hadUserBrightnessPoint);
+                        wasShortTermModelActive);
             }
 
             // We save the brightness info *after* the brightness setting has been changed and
@@ -1865,7 +1886,8 @@
         mTempBrightnessEvent.setRbcStrength(mCdsi != null
                 ? mCdsi.getReduceBrightColorsStrength() : -1);
         mTempBrightnessEvent.setPowerFactor(mPowerRequest.screenLowPowerBrightnessFactor);
-        mTempBrightnessEvent.setWasShortTermModelActive(hadUserBrightnessPoint);
+        mTempBrightnessEvent.setWasShortTermModelActive(wasShortTermModelActive);
+        mTempBrightnessEvent.setAutomaticBrightnessEnabled(mUseAutoBrightness);
         // Temporary is what we use during slider interactions. We avoid logging those so that
         // we don't spam logcat when the slider is being used.
         boolean tempToTempTransition =
@@ -1874,9 +1896,7 @@
                         == BrightnessReason.REASON_TEMPORARY;
         if ((!mTempBrightnessEvent.equalsMainData(mLastBrightnessEvent) && !tempToTempTransition)
                 || brightnessAdjustmentFlags != 0) {
-            float lastBrightness = mLastBrightnessEvent.getBrightness();
-            mTempBrightnessEvent.setInitialBrightness(lastBrightness);
-            mTempBrightnessEvent.setAutomaticBrightnessEnabled(mUseAutoBrightness);
+            mTempBrightnessEvent.setInitialBrightness(mLastBrightnessEvent.getBrightness());
             mLastBrightnessEvent.copyFrom(mTempBrightnessEvent);
             BrightnessEvent newEvent = new BrightnessEvent(mTempBrightnessEvent);
             // Adjustment flags (and user-set flag) only get added after the equality checks since
@@ -2069,8 +2089,10 @@
                 displayUniqueId, PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, hbmData,
                 new HighBrightnessModeController.HdrBrightnessDeviceConfig() {
                     @Override
-                    public float getHdrBrightnessFromSdr(float sdrBrightness) {
-                        return mDisplayDeviceConfig.getHdrBrightnessFromSdr(sdrBrightness);
+                    public float getHdrBrightnessFromSdr(
+                            float sdrBrightness, float maxDesiredHdrSdrRatio) {
+                        return mDisplayDeviceConfig.getHdrBrightnessFromSdr(
+                                sdrBrightness, maxDesiredHdrSdrRatio);
                     }
                 },
                 () -> {
@@ -2561,11 +2583,34 @@
         return clampAbsoluteBrightness(brightness);
     }
 
+    private void loadNitBasedBrightnessSetting() {
+        if (mDisplayId == Display.DEFAULT_DISPLAY && mPersistBrightnessNitsForDefaultDisplay) {
+            float brightnessNitsForDefaultDisplay =
+                    mBrightnessSetting.getBrightnessNitsForDefaultDisplay();
+            if (brightnessNitsForDefaultDisplay >= 0) {
+                float brightnessForDefaultDisplay = convertToFloatScale(
+                        brightnessNitsForDefaultDisplay);
+                if (isValidBrightnessValue(brightnessForDefaultDisplay)) {
+                    mBrightnessSetting.setBrightness(brightnessForDefaultDisplay);
+                    mCurrentScreenBrightnessSetting = brightnessForDefaultDisplay;
+                    return;
+                }
+            }
+        }
+        mCurrentScreenBrightnessSetting = getScreenBrightnessSetting();
+    }
+
     @Override
     public void setBrightness(float brightnessValue) {
         // Update the setting, which will eventually call back into DPC to have us actually update
         // the display with the new value.
         mBrightnessSetting.setBrightness(brightnessValue);
+        if (mDisplayId == Display.DEFAULT_DISPLAY && mPersistBrightnessNitsForDefaultDisplay) {
+            float nits = convertToNits(brightnessValue);
+            if (nits >= 0) {
+                mBrightnessSetting.setBrightnessNitsForDefaultDisplay(nits);
+            }
+        }
     }
 
     @Override
@@ -2580,7 +2625,7 @@
             return;
         }
         setCurrentScreenBrightness(brightnessValue);
-        mBrightnessSetting.setBrightness(brightnessValue);
+        setBrightness(brightnessValue);
     }
 
     private void setCurrentScreenBrightness(float brightnessValue) {
@@ -2634,7 +2679,7 @@
     }
 
     private void notifyBrightnessTrackerChanged(float brightness, boolean userInitiated,
-            boolean hadUserDataPoint) {
+            boolean wasShortTermModelActive) {
         final float brightnessInNits = convertToNits(brightness);
         if (mUseAutoBrightness && brightnessInNits >= 0.0f
                 && mAutomaticBrightnessController != null && mBrightnessTracker != null) {
@@ -2645,7 +2690,7 @@
                     ? mPowerRequest.screenLowPowerBrightnessFactor
                     : 1.0f;
             mBrightnessTracker.notifyBrightnessChanged(brightnessInNits, userInitiated,
-                    powerFactor, hadUserDataPoint,
+                    powerFactor, wasShortTermModelActive,
                     mAutomaticBrightnessController.isDefaultConfig(), mUniqueDisplayId,
                     mAutomaticBrightnessController.getLastSensorValues(),
                     mAutomaticBrightnessController.getLastSensorTimestamps());
@@ -2659,6 +2704,13 @@
         return mAutomaticBrightnessController.convertToNits(brightness);
     }
 
+    private float convertToFloatScale(float nits) {
+        if (mAutomaticBrightnessController == null) {
+            return PowerManager.BRIGHTNESS_INVALID_FLOAT;
+        }
+        return mAutomaticBrightnessController.convertToFloatScale(nits);
+    }
+
     @GuardedBy("mLock")
     private void updatePendingProximityRequestsLocked() {
         mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
@@ -2757,6 +2809,8 @@
         pw.println("  mUseSoftwareAutoBrightnessConfig=" + mUseSoftwareAutoBrightnessConfig);
         pw.println("  mAllowAutoBrightnessWhileDozingConfig="
                 + mAllowAutoBrightnessWhileDozingConfig);
+        pw.println("  mPersistBrightnessNitsForDefaultDisplay="
+                + mPersistBrightnessNitsForDefaultDisplay);
         pw.println("  mSkipScreenOnBrightnessRamp=" + mSkipScreenOnBrightnessRamp);
         pw.println("  mColorFadeFadesConfig=" + mColorFadeFadesConfig);
         pw.println("  mColorFadeEnabled=" + mColorFadeEnabled);
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java
index f49419cf..fbc354e 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController2.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController2.java
@@ -729,7 +729,7 @@
         final String brightnessThrottlingDataId =
                 mLogicalDisplay.getBrightnessThrottlingDataIdLocked();
 
-        mHandler.post(() -> {
+        mHandler.postAtTime(() -> {
             boolean changed = false;
             if (mDisplayDevice != device) {
                 changed = true;
@@ -761,7 +761,7 @@
             if (changed) {
                 updatePowerState();
             }
-        });
+        }, mClock.uptimeMillis());
     }
 
     /**
@@ -809,8 +809,10 @@
                 mDisplayDeviceConfig.getHighBrightnessModeData(),
                 new HighBrightnessModeController.HdrBrightnessDeviceConfig() {
                     @Override
-                    public float getHdrBrightnessFromSdr(float sdrBrightness) {
-                        return mDisplayDeviceConfig.getHdrBrightnessFromSdr(sdrBrightness);
+                    public float getHdrBrightnessFromSdr(
+                            float sdrBrightness, float maxDesiredHdrSdrRatio) {
+                        return mDisplayDeviceConfig.getHdrBrightnessFromSdr(
+                                sdrBrightness, maxDesiredHdrSdrRatio);
                     }
                 });
         mBrightnessThrottler.resetThrottlingData(
@@ -861,7 +863,8 @@
         noteScreenBrightness(mPowerState.getScreenBrightness());
 
         // Initialize all of the brightness tracking state
-        final float brightness = convertToNits(mPowerState.getScreenBrightness());
+        final float brightness = mDisplayBrightnessController.convertToNits(
+                mPowerState.getScreenBrightness());
         if (mBrightnessTracker != null && brightness >= PowerManager.BRIGHTNESS_MIN) {
             mBrightnessTracker.start(brightness);
         }
@@ -1024,10 +1027,16 @@
                     mHbmController, mBrightnessThrottler, mIdleModeBrightnessMapper,
                     mDisplayDeviceConfig.getAmbientHorizonShort(),
                     mDisplayDeviceConfig.getAmbientHorizonLong(), userLux, userBrightness);
+            mDisplayBrightnessController.setAutomaticBrightnessController(
+                    mAutomaticBrightnessController);
 
             mBrightnessEventRingBuffer =
                     new RingBuffer<>(BrightnessEvent.class, RINGBUFFER_MAX);
 
+            if (mScreenOffBrightnessSensorController != null) {
+                mScreenOffBrightnessSensorController.stop();
+                mScreenOffBrightnessSensorController = null;
+            }
             loadScreenOffBrightnessSensor();
             int[] sensorValueToLux = mDisplayDeviceConfig.getScreenOffBrightnessSensorValueToLux();
             if (mScreenOffBrightnessSensor != null && sensorValueToLux != null) {
@@ -1133,6 +1142,10 @@
             mPowerState.stop();
             mPowerState = null;
         }
+
+        if (mScreenOffBrightnessSensorController != null) {
+            mScreenOffBrightnessSensorController.stop();
+        }
     }
 
     private void updatePowerState() {
@@ -1250,10 +1263,10 @@
         // user, or is a temporary adjustment.
         boolean userInitiatedChange = (Float.isNaN(brightnessState))
                 && (autoBrightnessAdjustmentChanged || userSetBrightnessChanged);
-        boolean hadUserBrightnessPoint = false;
+        boolean wasShortTermModelActive = false;
         // Configure auto-brightness.
         if (mAutomaticBrightnessController != null) {
-            hadUserBrightnessPoint = mAutomaticBrightnessController.hasUserDataPoints();
+            wasShortTermModelActive = mAutomaticBrightnessController.hasUserDataPoints();
             mAutomaticBrightnessController.configure(autoBrightnessState,
                     mBrightnessConfiguration,
                     mDisplayBrightnessController.getLastUserSetScreenBrightness(),
@@ -1267,7 +1280,8 @@
                 : AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED);
 
         if (mBrightnessTracker != null) {
-            mBrightnessTracker.setBrightnessConfiguration(mBrightnessConfiguration);
+            mBrightnessTracker.setShouldCollectColorSample(mBrightnessConfiguration != null
+                    && mBrightnessConfiguration.shouldCollectColorSamples());
         }
 
         boolean updateScreenBrightnessSetting = false;
@@ -1380,7 +1394,8 @@
                 : mAutomaticBrightnessController.getAmbientLux();
         for (int i = 0; i < displayBrightnessFollowers.size(); i++) {
             DisplayPowerControllerInterface follower = displayBrightnessFollowers.valueAt(i);
-            follower.setBrightnessToFollow(rawBrightnessState, convertToNits(rawBrightnessState),
+            follower.setBrightnessToFollow(rawBrightnessState,
+                    mDisplayBrightnessController.convertToNits(rawBrightnessState),
                     ambientLux);
         }
 
@@ -1537,7 +1552,7 @@
                     userInitiatedChange = false;
                 }
                 notifyBrightnessTrackerChanged(brightnessState, userInitiatedChange,
-                        hadUserBrightnessPoint);
+                        wasShortTermModelActive);
             }
 
             // We save the brightness info *after* the brightness setting has been changed and
@@ -1579,9 +1594,10 @@
         mTempBrightnessEvent.setRbcStrength(mCdsi != null
                 ? mCdsi.getReduceBrightColorsStrength() : -1);
         mTempBrightnessEvent.setPowerFactor(mPowerRequest.screenLowPowerBrightnessFactor);
-        mTempBrightnessEvent.setWasShortTermModelActive(hadUserBrightnessPoint);
+        mTempBrightnessEvent.setWasShortTermModelActive(wasShortTermModelActive);
         mTempBrightnessEvent.setDisplayBrightnessStrategyName(displayBrightnessState
                 .getDisplayBrightnessStrategyName());
+        mTempBrightnessEvent.setAutomaticBrightnessEnabled(mUseAutoBrightness);
         // Temporary is what we use during slider interactions. We avoid logging those so that
         // we don't spam logcat when the slider is being used.
         boolean tempToTempTransition =
@@ -1590,9 +1606,7 @@
                         == BrightnessReason.REASON_TEMPORARY;
         if ((!mTempBrightnessEvent.equalsMainData(mLastBrightnessEvent) && !tempToTempTransition)
                 || brightnessAdjustmentFlags != 0) {
-            float lastBrightness = mLastBrightnessEvent.getBrightness();
-            mTempBrightnessEvent.setInitialBrightness(lastBrightness);
-            mTempBrightnessEvent.setAutomaticBrightnessEnabled(mUseAutoBrightness);
+            mTempBrightnessEvent.setInitialBrightness(mLastBrightnessEvent.getBrightness());
             mLastBrightnessEvent.copyFrom(mTempBrightnessEvent);
             BrightnessEvent newEvent = new BrightnessEvent(mTempBrightnessEvent);
             // Adjustment flags (and user-set flag) only get added after the equality checks since
@@ -1783,8 +1797,10 @@
                 displayUniqueId, PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, hbmData,
                 new HighBrightnessModeController.HdrBrightnessDeviceConfig() {
                     @Override
-                    public float getHdrBrightnessFromSdr(float sdrBrightness) {
-                        return mDisplayDeviceConfig.getHdrBrightnessFromSdr(sdrBrightness);
+                    public float getHdrBrightnessFromSdr(
+                            float sdrBrightness, float maxDesiredHdrSdrRatio) {
+                        return mDisplayDeviceConfig.getHdrBrightnessFromSdr(
+                                sdrBrightness, maxDesiredHdrSdrRatio);
                     }
                 },
                 () -> {
@@ -2182,10 +2198,10 @@
     @Override
     public void setBrightnessToFollow(float leadDisplayBrightness, float nits, float ambientLux) {
         mHbmController.onAmbientLuxChange(ambientLux);
-        if (mAutomaticBrightnessController == null || nits < 0) {
+        if (nits < 0) {
             mDisplayBrightnessController.setBrightnessToFollow(leadDisplayBrightness);
         } else {
-            float brightness = mAutomaticBrightnessController.convertToFloatScale(nits);
+            float brightness = mDisplayBrightnessController.convertToFloatScale(nits);
             if (BrightnessUtils.isValidBrightnessValue(brightness)) {
                 mDisplayBrightnessController.setBrightnessToFollow(brightness);
             } else {
@@ -2220,8 +2236,8 @@
     }
 
     private void notifyBrightnessTrackerChanged(float brightness, boolean userInitiated,
-            boolean hadUserDataPoint) {
-        final float brightnessInNits = convertToNits(brightness);
+            boolean wasShortTermModelActive) {
+        final float brightnessInNits = mDisplayBrightnessController.convertToNits(brightness);
         if (mUseAutoBrightness && brightnessInNits >= 0.0f
                 && mAutomaticBrightnessController != null && mBrightnessTracker != null) {
             // We only want to track changes on devices that can actually map the display backlight
@@ -2231,20 +2247,13 @@
                     ? mPowerRequest.screenLowPowerBrightnessFactor
                     : 1.0f;
             mBrightnessTracker.notifyBrightnessChanged(brightnessInNits, userInitiated,
-                    powerFactor, hadUserDataPoint,
+                    powerFactor, wasShortTermModelActive,
                     mAutomaticBrightnessController.isDefaultConfig(), mUniqueDisplayId,
                     mAutomaticBrightnessController.getLastSensorValues(),
                     mAutomaticBrightnessController.getLastSensorTimestamps());
         }
     }
 
-    private float convertToNits(float brightness) {
-        if (mAutomaticBrightnessController == null) {
-            return -1f;
-        }
-        return mAutomaticBrightnessController.convertToNits(brightness);
-    }
-
     @Override
     public void addDisplayBrightnessFollower(DisplayPowerControllerInterface follower) {
         synchronized (mLock) {
@@ -2504,17 +2513,17 @@
         int appliedRbcStrength  = event.isRbcEnabled() ? event.getRbcStrength() : -1;
         float appliedHbmMaxNits =
                 event.getHbmMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF
-                ? -1f : convertToNits(event.getHbmMax());
+                ? -1f : mDisplayBrightnessController.convertToNits(event.getHbmMax());
         // thermalCapNits set to -1 if not currently capping max brightness
         float appliedThermalCapNits =
                 event.getThermalMax() == PowerManager.BRIGHTNESS_MAX
-                ? -1f : convertToNits(event.getThermalMax());
+                ? -1f : mDisplayBrightnessController.convertToNits(event.getThermalMax());
         if (mLogicalDisplay.getPrimaryDisplayDeviceLocked() != null
                 && mLogicalDisplay.getPrimaryDisplayDeviceLocked()
                 .getDisplayDeviceInfoLocked().type == Display.TYPE_INTERNAL) {
             FrameworkStatsLog.write(FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED,
-                    convertToNits(event.getInitialBrightness()),
-                    convertToNits(event.getBrightness()),
+                    mDisplayBrightnessController.convertToNits(event.getInitialBrightness()),
+                    mDisplayBrightnessController.convertToNits(event.getBrightness()),
                     event.getLux(),
                     event.getPhysicalDisplayId(),
                     event.wasShortTermModelActive(),
diff --git a/services/core/java/com/android/server/display/DisplayPowerProximityStateController.java b/services/core/java/com/android/server/display/DisplayPowerProximityStateController.java
index 5bb3e6b..c074786 100644
--- a/services/core/java/com/android/server/display/DisplayPowerProximityStateController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerProximityStateController.java
@@ -262,8 +262,17 @@
                 sendOnProximityNegativeWithWakelock();
             }
         } else {
+            setProximitySensorEnabled(false);
             mWaitingForNegativeProximity = false;
             mIgnoreProximityUntilChanged = false;
+
+            if (mScreenOffBecauseOfProximity) {
+                // The screen *was* off due to prox being near, but now there's no prox sensor, so
+                // let's turn the screen back on.
+                mScreenOffBecauseOfProximity = false;
+                mSkipRampBecauseOfProximityChangeToNegative = true;
+                sendOnProximityNegativeWithWakelock();
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/display/HighBrightnessModeController.java b/services/core/java/com/android/server/display/HighBrightnessModeController.java
index 2c843a4..ca208ac 100644
--- a/services/core/java/com/android/server/display/HighBrightnessModeController.java
+++ b/services/core/java/com/android/server/display/HighBrightnessModeController.java
@@ -61,8 +61,12 @@
     @VisibleForTesting
     static final float HBM_TRANSITION_POINT_INVALID = Float.POSITIVE_INFINITY;
 
+    private static final float DEFAULT_MAX_DESIRED_HDR_SDR_RATIO = 1.0f;
+
     public interface HdrBrightnessDeviceConfig {
-        float getHdrBrightnessFromSdr(float sdrBrightness);
+        // maxDesiredHdrSdrRatio will restrict the HDR brightness if the ratio is less than
+        // Float.POSITIVE_INFINITY
+        float getHdrBrightnessFromSdr(float sdrBrightness, float maxDesiredHdrSdrRatio);
     }
 
     private final float mBrightnessMin;
@@ -96,6 +100,9 @@
 
     private int mHbmMode = BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
     private boolean mIsHdrLayerPresent = false;
+
+    // mMaxDesiredHdrSdrRatio should only be applied when there is a valid backlight->nits mapping
+    private float mMaxDesiredHdrSdrRatio = DEFAULT_MAX_DESIRED_HDR_SDR_RATIO;
     private boolean mIsThermalStatusWithinLimit = true;
     private boolean mIsBlockedByLowPowerMode = false;
     private int mWidth;
@@ -177,7 +184,8 @@
 
     float getHdrBrightnessValue() {
         if (mHdrBrightnessCfg != null) {
-            float hdrBrightness = mHdrBrightnessCfg.getHdrBrightnessFromSdr(mBrightness);
+            float hdrBrightness = mHdrBrightnessCfg.getHdrBrightnessFromSdr(
+                    mBrightness, mMaxDesiredHdrSdrRatio);
             if (hdrBrightness != PowerManager.BRIGHTNESS_INVALID) {
                 return hdrBrightness;
             }
@@ -457,6 +465,7 @@
                     + ", isLuxHigh: " + mIsInAllowedAmbientRange
                     + ", isHBMCurrentlyAllowed: " + isCurrentlyAllowed()
                     + ", isHdrLayerPresent: " + mIsHdrLayerPresent
+                    + ", mMaxDesiredHdrSdrRatio: " + mMaxDesiredHdrSdrRatio
                     + ", isAutoBrightnessEnabled: " +  mIsAutoBrightnessEnabled
                     + ", mIsTimeAvailable: " + mIsTimeAvailable
                     + ", mIsInAllowedAmbientRange: " + mIsInAllowedAmbientRange
@@ -600,11 +609,25 @@
     class HdrListener extends SurfaceControlHdrLayerInfoListener {
         @Override
         public void onHdrInfoChanged(IBinder displayToken, int numberOfHdrLayers,
-                int maxW, int maxH, int flags) {
+                int maxW, int maxH, int flags, float maxDesiredHdrSdrRatio) {
             mHandler.post(() -> {
                 mIsHdrLayerPresent = numberOfHdrLayers > 0
                         && (float) (maxW * maxH) >= ((float) (mWidth * mHeight)
                                    * mHbmData.minimumHdrPercentOfScreen);
+
+                final float candidateDesiredHdrSdrRatio =
+                        mIsHdrLayerPresent && mHdrBrightnessCfg != null
+                                ? maxDesiredHdrSdrRatio
+                                : DEFAULT_MAX_DESIRED_HDR_SDR_RATIO;
+
+                if (candidateDesiredHdrSdrRatio >= 1.0f) {
+                    mMaxDesiredHdrSdrRatio = candidateDesiredHdrSdrRatio;
+                } else {
+                    Slog.w(TAG, "Ignoring invalid desired HDR/SDR Ratio: "
+                            + candidateDesiredHdrSdrRatio);
+                    mMaxDesiredHdrSdrRatio = DEFAULT_MAX_DESIRED_HDR_SDR_RATIO;
+                }
+
                 // Calling the brightness update so that we can recalculate
                 // brightness with HDR in mind.
                 onBrightnessChanged(mBrightness, mUnthrottledBrightness, mThrottlingReason);
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 8f52c97..8d0689f 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -42,10 +42,12 @@
 import android.view.RoundedCorners;
 import android.view.SurfaceControl;
 
+import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.display.BrightnessSynchronizer;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.LocalServices;
+import com.android.server.display.mode.DisplayModeDirector;
 import com.android.server.lights.LightsManager;
 import com.android.server.lights.LogicalLight;
 
@@ -674,14 +676,13 @@
                 mInfo.flags |= DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY;
 
                 if (mIsFirstDisplay) {
-                    if (res.getBoolean(com.android.internal.R.bool.config_mainBuiltInDisplayIsRound)
+                    if (res.getBoolean(R.bool.config_mainBuiltInDisplayIsRound)
                             || (Build.IS_EMULATOR
                             && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false))) {
                         mInfo.flags |= DisplayDeviceInfo.FLAG_ROUND;
                     }
                 } else {
-                    if (!res.getBoolean(
-                                com.android.internal.R.bool.config_localDisplaysMirrorContent)) {
+                    if (!res.getBoolean(R.bool.config_localDisplaysMirrorContent)) {
                         mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY;
                     }
 
@@ -710,18 +711,23 @@
                 mInfo.displayShape = DisplayShape.fromResources(
                         res, mInfo.uniqueId, maxWidth, maxHeight, mInfo.width, mInfo.height);
 
+                mInfo.name = getDisplayDeviceConfig().getName();
+
                 if (mStaticDisplayInfo.isInternal) {
                     mInfo.type = Display.TYPE_INTERNAL;
                     mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL;
                     mInfo.flags |= DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
-                    mInfo.name = res.getString(
-                            com.android.internal.R.string.display_manager_built_in_display_name);
+                    if (mInfo.name == null) {
+                        mInfo.name = res.getString(R.string.display_manager_built_in_display_name);
+                    }
                 } else {
                     mInfo.type = Display.TYPE_EXTERNAL;
                     mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
                     mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION;
-                    mInfo.name = getContext().getResources().getString(
-                            com.android.internal.R.string.display_manager_hdmi_display_name);
+                    if (mInfo.name == null) {
+                        mInfo.name = getContext().getResources().getString(
+                                R.string.display_manager_hdmi_display_name);
+                    }
                 }
                 mInfo.frameRateOverrides = mFrameRateOverrides;
 
@@ -1254,8 +1260,7 @@
                 return false;
             }
             final Resources res = getOverlayContext().getResources();
-            int[] ports = res.getIntArray(
-                    com.android.internal.R.array.config_localPrivateDisplayPorts);
+            int[] ports = res.getIntArray(R.array.config_localPrivateDisplayPorts);
             if (ports != null) {
                 int port = physicalAddress.getPort();
                 for (int p : ports) {
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index fc90db6..dee4cde 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -33,6 +33,7 @@
 import android.view.SurfaceControl;
 
 import com.android.server.display.layout.Layout;
+import com.android.server.display.mode.DisplayModeDirector;
 import com.android.server.wm.utils.InsetUtils;
 
 import java.io.PrintWriter;
@@ -188,7 +189,7 @@
         mTempFrameRateOverride = new SparseArray<>();
         mIsEnabled = true;
         mIsInTransition = false;
-        mBrightnessThrottlingDataId = DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID;
+        mBrightnessThrottlingDataId = DisplayDeviceConfig.DEFAULT_ID;
     }
 
     public void setDevicePositionLocked(int position) {
@@ -343,6 +344,21 @@
             mInfo.set(null);
         }
     }
+    /**
+     * Updates refreshRateThermalThrottling
+     *
+     * @param refreshRanges new refreshRateThermalThrottling ranges limited by layout or default
+     */
+    public void updateRefreshRateThermalThrottling(
+            @Nullable SparseArray<SurfaceControl.RefreshRateRange> refreshRanges) {
+        if (refreshRanges == null) {
+            refreshRanges = new SparseArray<>();
+        }
+        if (!mBaseDisplayInfo.refreshRateThermalThrottling.contentEquals(refreshRanges)) {
+            mBaseDisplayInfo.refreshRateThermalThrottling = refreshRanges;
+            mInfo.set(null);
+        }
+    }
 
     /**
      * Updates the state of the logical display based on the available display devices.
@@ -571,7 +587,7 @@
             DisplayDevice device,
             boolean isBlanked) {
         // Set the layer stack.
-        device.setLayerStackLocked(t, isBlanked ? BLANK_LAYER_STACK : mLayerStack);
+        device.setLayerStackLocked(t, isBlanked ? BLANK_LAYER_STACK : mLayerStack, mDisplayId);
         // Also inform whether the device is the same one sent to inputflinger for its layerstack.
         // Prevent displays that are disabled from receiving input.
         // TODO(b/188914255): Remove once input can dispatch against device vs layerstack.
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index 2ac7d9d..250ba43 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -18,8 +18,6 @@
 
 import static android.view.Display.DEFAULT_DISPLAY;
 
-import static com.android.server.display.layout.Layout.NO_LEAD_DISPLAY;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -646,10 +644,7 @@
                 if ((nextDeviceInfo.flags
                         & DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY) != 0
                         && !nextDeviceInfo.address.equals(deviceInfo.address)) {
-                    layout.createDisplayLocked(nextDeviceInfo.address,
-                            /* isDefault= */ true, /* isEnabled= */ true,
-                            Layout.DEFAULT_DISPLAY_GROUP_NAME, mIdProducer,
-                            /* brightnessThrottlingMapId= */ null, DEFAULT_DISPLAY);
+                    layout.createDefaultDisplayLocked(nextDeviceInfo.address, mIdProducer);
                     applyLayoutLocked();
                     return;
                 }
@@ -1013,19 +1008,23 @@
             if (newDisplay != oldDisplay) {
                 newDisplay.swapDisplaysLocked(oldDisplay);
             }
+            DisplayDeviceConfig config = device.getDisplayDeviceConfig();
 
             newDisplay.setDevicePositionLocked(displayLayout.getPosition());
             newDisplay.setLeadDisplayLocked(displayLayout.getLeadDisplayId());
             newDisplay.updateLayoutLimitedRefreshRateLocked(
-                    device.getDisplayDeviceConfig().getRefreshRange(
-                            displayLayout.getRefreshRateZoneId()
+                    config.getRefreshRange(displayLayout.getRefreshRateZoneId())
+            );
+            newDisplay.updateRefreshRateThermalThrottling(
+                    config.getRefreshRateThrottlingData(
+                            displayLayout.getRefreshRateThermalThrottlingMapId()
                     )
             );
 
             setEnabledLocked(newDisplay, displayLayout.isEnabled());
             newDisplay.setBrightnessThrottlingDataIdLocked(
                     displayLayout.getBrightnessThrottlingMapId() == null
-                            ? DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID
+                            ? DisplayDeviceConfig.DEFAULT_ID
                             : displayLayout.getBrightnessThrottlingMapId());
 
             newDisplay.setDisplayGroupNameLocked(displayLayout.getDisplayGroupName());
@@ -1106,9 +1105,7 @@
             return;
         }
         final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
-        layout.createDisplayLocked(info.address, /* isDefault= */ true, /* isEnabled= */ true,
-                Layout.DEFAULT_DISPLAY_GROUP_NAME, mIdProducer,
-                /* brightnessThrottlingMapId= */ null, NO_LEAD_DISPLAY);
+        layout.createDefaultDisplayLocked(info.address, mIdProducer);
     }
 
     private int assignLayerStackLocked(int displayId) {
diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
index 3e67f0a..2ce7690 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -36,6 +36,7 @@
 
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.display.mode.DisplayModeDirector;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java
index e7601bc..ec70c89 100644
--- a/services/core/java/com/android/server/display/PersistentDataStore.java
+++ b/services/core/java/com/android/server/display/PersistentDataStore.java
@@ -94,6 +94,7 @@
  *          &lt;/brightness-curve>
  *      &lt;/brightness-configuration>
  *  &lt;/brightness-configurations>
+ *  &lt;brightness-nits-for-default-display>600&lt;/brightness-nits-for-default-display>
  * &lt;/display-manager-state>
  * </code>
  *
@@ -130,6 +131,9 @@
     private static final String TAG_RESOLUTION_HEIGHT = "resolution-height";
     private static final String TAG_REFRESH_RATE = "refresh-rate";
 
+    private static final String TAG_BRIGHTNESS_NITS_FOR_DEFAULT_DISPLAY =
+            "brightness-nits-for-default-display";
+
     // Remembered Wifi display devices.
     private ArrayList<WifiDisplay> mRememberedWifiDisplays = new ArrayList<WifiDisplay>();
 
@@ -137,6 +141,8 @@
     private final HashMap<String, DisplayState> mDisplayStates =
             new HashMap<String, DisplayState>();
 
+    private float mBrightnessNitsForDefaultDisplay = -1;
+
     // Display values which should be stable across the device's lifetime.
     private final StableDeviceValues mStableDeviceValues = new StableDeviceValues();
 
@@ -312,6 +318,19 @@
         return false;
     }
 
+    public float getBrightnessNitsForDefaultDisplay() {
+        return mBrightnessNitsForDefaultDisplay;
+    }
+
+    public boolean setBrightnessNitsForDefaultDisplay(float nits) {
+        if (nits != mBrightnessNitsForDefaultDisplay) {
+            mBrightnessNitsForDefaultDisplay = nits;
+            setDirty();
+            return true;
+        }
+        return false;
+    }
+
     public boolean setUserPreferredRefreshRate(DisplayDevice displayDevice, float refreshRate) {
         final String displayDeviceUniqueId = displayDevice.getUniqueId();
         if (!displayDevice.hasStableUniqueId() || displayDeviceUniqueId == null) {
@@ -513,6 +532,10 @@
             if (parser.getName().equals(TAG_BRIGHTNESS_CONFIGURATIONS)) {
                 mGlobalBrightnessConfigurations.loadFromXml(parser);
             }
+            if (parser.getName().equals(TAG_BRIGHTNESS_NITS_FOR_DEFAULT_DISPLAY)) {
+                String value = parser.nextText();
+                mBrightnessNitsForDefaultDisplay = Float.parseFloat(value);
+            }
         }
     }
 
@@ -592,6 +615,9 @@
         serializer.startTag(null, TAG_BRIGHTNESS_CONFIGURATIONS);
         mGlobalBrightnessConfigurations.saveToXml(serializer);
         serializer.endTag(null, TAG_BRIGHTNESS_CONFIGURATIONS);
+        serializer.startTag(null, TAG_BRIGHTNESS_NITS_FOR_DEFAULT_DISPLAY);
+        serializer.text(Float.toString(mBrightnessNitsForDefaultDisplay));
+        serializer.endTag(null, TAG_BRIGHTNESS_NITS_FOR_DEFAULT_DISPLAY);
         serializer.endTag(null, TAG_DISPLAY_MANAGER_STATE);
         serializer.endDocument();
     }
@@ -615,6 +641,7 @@
         mStableDeviceValues.dump(pw, "      ");
         pw.println("  GlobalBrightnessConfigurations:");
         mGlobalBrightnessConfigurations.dump(pw, "      ");
+        pw.println("  mBrightnessNitsForDefaultDisplay=" + mBrightnessNitsForDefaultDisplay);
     }
 
     private static final class DisplayState {
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index 364d53b..4f7a2ba 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -88,7 +88,17 @@
     // Called with SyncRoot lock held.
     public VirtualDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
             Context context, Handler handler, Listener listener) {
-        this(syncRoot, context, handler, listener, DisplayControl::createDisplay);
+        this(syncRoot, context, handler, listener, new SurfaceControlDisplayFactory() {
+            @Override
+            public IBinder createDisplay(String name, boolean secure, float requestedRefreshRate) {
+                return DisplayControl.createDisplay(name, secure, requestedRefreshRate);
+            }
+
+            @Override
+            public void destroyDisplay(IBinder displayToken) {
+                DisplayControl.destroyDisplay(displayToken);
+            }
+        });
     }
 
     @VisibleForTesting
@@ -285,7 +295,7 @@
             mUniqueIndex = uniqueIndex;
             mIsDisplayOn = surface != null;
             mDisplayIdToMirror = virtualDisplayConfig.getDisplayIdToMirror();
-            mIsWindowManagerMirroring = virtualDisplayConfig.isWindowManagerMirroring();
+            mIsWindowManagerMirroring = virtualDisplayConfig.isWindowManagerMirroringEnabled();
         }
 
         @Override
@@ -311,7 +321,7 @@
                 mSurface.release();
                 mSurface = null;
             }
-            DisplayControl.destroyDisplay(getDisplayTokenLocked());
+            mSurfaceControlDisplayFactory.destroyDisplay(getDisplayTokenLocked());
             if (mProjection != null && mMediaProjectionCallback != null) {
                 try {
                     mProjection.unregisterCallback(mMediaProjectionCallback);
@@ -653,5 +663,12 @@
          * @return The token reference for the display in SurfaceFlinger.
          */
         IBinder createDisplay(String name, boolean secure, float requestedRefreshRate);
+        
+        /**
+         * Destroy a display in SurfaceFlinger.
+         *
+         * @param displayToken The display token for the display to be destroyed.
+         */
+        void destroyDisplay(IBinder displayToken);
     }
 }
diff --git a/services/core/java/com/android/server/display/brightness/BrightnessEvent.java b/services/core/java/com/android/server/display/brightness/BrightnessEvent.java
index aff80de..a3bca9a 100644
--- a/services/core/java/com/android/server/display/brightness/BrightnessEvent.java
+++ b/services/core/java/com/android/server/display/brightness/BrightnessEvent.java
@@ -142,8 +142,6 @@
                 && Float.floatToRawIntBits(mLux) == Float.floatToRawIntBits(that.mLux)
                 && Float.floatToRawIntBits(mPreThresholdLux)
                 == Float.floatToRawIntBits(that.mPreThresholdLux)
-                && Float.floatToRawIntBits(mInitialBrightness)
-                == Float.floatToRawIntBits(that.mInitialBrightness)
                 && Float.floatToRawIntBits(mBrightness)
                 == Float.floatToRawIntBits(that.mBrightness)
                 && Float.floatToRawIntBits(mRecommendedBrightness)
diff --git a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
index 68758ca..2916fef 100644
--- a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
+++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
@@ -16,14 +16,17 @@
 
 package com.android.server.display.brightness;
 
+import android.annotation.Nullable;
 import android.content.Context;
 import android.hardware.display.DisplayManagerInternal;
 import android.os.HandlerExecutor;
 import android.os.PowerManager;
 import android.util.IndentingPrintWriter;
+import android.view.Display;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.display.AutomaticBrightnessController;
 import com.android.server.display.BrightnessSetting;
 import com.android.server.display.DisplayBrightnessState;
 import com.android.server.display.brightness.strategy.DisplayBrightnessStrategy;
@@ -84,6 +87,15 @@
     // callback is not executed in sync and is not blocking the thread from which it is called.
     private final HandlerExecutor mBrightnessChangeExecutor;
 
+    // True if we want to persist the brightness value in nits even if the underlying display
+    // device changes.
+    private final boolean mPersistBrightnessNitsForDefaultDisplay;
+
+    // The controller for the automatic brightness level.
+    // TODO(b/265415257): Move to the automatic brightness strategy
+    @Nullable
+    private AutomaticBrightnessController mAutomaticBrightnessController;
+
     /**
      * The constructor of DisplayBrightnessController.
      */
@@ -103,6 +115,8 @@
         mDisplayBrightnessStrategySelector = injector.getDisplayBrightnessStrategySelector(context,
                 displayId);
         mBrightnessChangeExecutor = brightnessChangeExecutor;
+        mPersistBrightnessNitsForDefaultDisplay = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_persistBrightnessNitsForDefaultDisplay);
     }
 
     /**
@@ -263,6 +277,12 @@
         // Update the setting, which will eventually call back into DPC to have us actually
         // update the display with the new value.
         mBrightnessSetting.setBrightness(brightnessValue);
+        if (mDisplayId == Display.DEFAULT_DISPLAY && mPersistBrightnessNitsForDefaultDisplay) {
+            float nits = convertToNits(brightnessValue);
+            if (nits >= 0) {
+                mBrightnessSetting.setBrightnessNitsForDefaultDisplay(nits);
+            }
+        }
     }
 
     /**
@@ -281,6 +301,42 @@
     }
 
     /**
+     * Set the {@link AutomaticBrightnessController} which is needed to perform nit-to-float-scale
+     * conversion.
+     * @param automaticBrightnessController The ABC
+     */
+    public void setAutomaticBrightnessController(
+            AutomaticBrightnessController automaticBrightnessController) {
+        mAutomaticBrightnessController = automaticBrightnessController;
+        loadNitBasedBrightnessSetting();
+    }
+
+    /**
+     * Convert a brightness float scale value to a nit value.
+     * @param brightness The float scale value
+     * @return The nit value or -1f if no conversion is possible.
+     */
+    public float convertToNits(float brightness) {
+        if (mAutomaticBrightnessController == null) {
+            return -1f;
+        }
+        return mAutomaticBrightnessController.convertToNits(brightness);
+    }
+
+    /**
+     * Convert a brightness nit value to a float scale value.
+     * @param nits The nit value
+     * @return The float scale value or {@link PowerManager.BRIGHTNESS_INVALID_FLOAT} if no
+     * conversion is possible.
+     */
+    public float convertToFloatScale(float nits) {
+        if (mAutomaticBrightnessController == null) {
+            return PowerManager.BRIGHTNESS_INVALID_FLOAT;
+        }
+        return mAutomaticBrightnessController.convertToFloatScale(nits);
+    }
+
+    /**
      * Stops the associated listeners when the display is stopped. Invoked when the {@link
      * #mDisplayId} is being removed.
      */
@@ -300,6 +356,8 @@
         writer.println("DisplayBrightnessController:");
         writer.println("  mDisplayId=: " + mDisplayId);
         writer.println("  mScreenBrightnessDefault=" + mScreenBrightnessDefault);
+        writer.println("  mPersistBrightnessNitsForDefaultDisplay="
+                + mPersistBrightnessNitsForDefaultDisplay);
         synchronized (mLock) {
             writer.println("  mPendingScreenBrightness=" + mPendingScreenBrightness);
             writer.println("  mCurrentScreenBrightness=" + mCurrentScreenBrightness);
@@ -353,4 +411,29 @@
     private void notifyCurrentScreenBrightness() {
         mBrightnessChangeExecutor.execute(mOnBrightnessChangeRunnable);
     }
+
+    /**
+     * Loads the brightness value. If this is the default display and the config says that we should
+     * persist the nit value, the nit value for the default display will be loaded.
+     */
+    private void loadNitBasedBrightnessSetting() {
+        if (mDisplayId == Display.DEFAULT_DISPLAY && mPersistBrightnessNitsForDefaultDisplay) {
+            float brightnessNitsForDefaultDisplay =
+                    mBrightnessSetting.getBrightnessNitsForDefaultDisplay();
+            if (brightnessNitsForDefaultDisplay >= 0) {
+                float brightnessForDefaultDisplay = convertToFloatScale(
+                        brightnessNitsForDefaultDisplay);
+                if (BrightnessUtils.isValidBrightnessValue(brightnessForDefaultDisplay)) {
+                    mBrightnessSetting.setBrightness(brightnessForDefaultDisplay);
+                    synchronized (mLock) {
+                        mCurrentScreenBrightness = brightnessForDefaultDisplay;
+                    }
+                    return;
+                }
+            }
+        }
+        synchronized (mLock) {
+            mCurrentScreenBrightness = getScreenBrightnessSetting();
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/display/layout/Layout.java b/services/core/java/com/android/server/display/layout/Layout.java
index f1e885e..f86ee24 100644
--- a/services/core/java/com/android/server/display/layout/Layout.java
+++ b/services/core/java/com/android/server/display/layout/Layout.java
@@ -39,7 +39,6 @@
     public static final String DEFAULT_DISPLAY_GROUP_NAME = "";
 
     private static final String TAG = "Layout";
-    private static int sNextNonDefaultDisplayId = DEFAULT_DISPLAY + 1;
 
     // Lead display Id is set to this if this is not a follower display, and therefore
     // has no lead.
@@ -47,13 +46,6 @@
 
     private final List<Display> mDisplays = new ArrayList<>(2);
 
-    /**
-     *  @return The default display ID, or a new unique one to use.
-     */
-    public static int assignDisplayIdLocked(boolean isDefault) {
-        return isDefault ? DEFAULT_DISPLAY : sNextNonDefaultDisplayId++;
-    }
-
     @Override
     public String toString() {
         return mDisplays.toString();
@@ -76,25 +68,17 @@
     }
 
     /**
-     * Creates a simple 1:1 LogicalDisplay mapping for the specified DisplayDevice.
+     * Creates the default 1:1 LogicalDisplay mapping for the specified DisplayDevice.
      *
      * @param address Address of the device.
-     * @param isDefault Indicates if the device is meant to be the default display.
-     * @param isEnabled Indicates if this display is usable and can be switched on
-     * @param displayGroupName Name of the display group to which the display is assigned.
      * @param idProducer Produces the logical display id.
-     * @param brightnessThrottlingMapId Name of which throttling policy should be used.
-     * @param leadDisplayId Display that this one follows (-1 if none).
-     * @exception IllegalArgumentException When a default display owns a display group other than
-     *            DEFAULT_DISPLAY_GROUP.
-     * @return The new Display.
      */
-    public Display createDisplayLocked(
-            @NonNull DisplayAddress address, boolean isDefault, boolean isEnabled,
-            String displayGroupName, DisplayIdProducer idProducer, String brightnessThrottlingMapId,
-            int leadDisplayId) {
-        return createDisplayLocked(address, isDefault, isEnabled, displayGroupName, idProducer,
-                brightnessThrottlingMapId, POSITION_UNKNOWN, leadDisplayId);
+    public void createDefaultDisplayLocked(@NonNull DisplayAddress address,
+            DisplayIdProducer idProducer) {
+        createDisplayLocked(address, /* isDefault= */ true, /* isEnabled= */ true,
+                DEFAULT_DISPLAY_GROUP_NAME, idProducer, POSITION_UNKNOWN,
+                NO_LEAD_DISPLAY, /* brightnessThrottlingMapId= */ null,
+                /* refreshRateZoneId= */ null, /* refreshRateThermalThrottlingMapId= */ null);
     }
 
     /**
@@ -105,26 +89,30 @@
      * @param isEnabled Indicates if this display is usable and can be switched on
      * @param displayGroupName Name of the display group to which the display is assigned.
      * @param idProducer Produces the logical display id.
-     * @param brightnessThrottlingMapId Name of which throttling policy should be used.
      * @param position Indicates the position this display is facing in this layout.
      * @param leadDisplayId Display that this one follows (-1 if none).
+     * @param brightnessThrottlingMapId Name of which brightness throttling policy should be used.
+     * @param refreshRateZoneId Layout limited refresh rate zone name.
+     * @param refreshRateThermalThrottlingMapId Name of which refresh rate throttling
+     *                                          policy should be used.
+
      * @exception IllegalArgumentException When a default display owns a display group other than
      *            DEFAULT_DISPLAY_GROUP.
-     * @return The new Display.
      */
-    public Display createDisplayLocked(
+    public void createDisplayLocked(
             @NonNull DisplayAddress address, boolean isDefault, boolean isEnabled,
-            String displayGroupName, DisplayIdProducer idProducer, String brightnessThrottlingMapId,
-            int position, int leadDisplayId) {
+            String displayGroupName, DisplayIdProducer idProducer, int position, int leadDisplayId,
+            String brightnessThrottlingMapId, @Nullable String refreshRateZoneId,
+            @Nullable String refreshRateThermalThrottlingMapId) {
         if (contains(address)) {
             Slog.w(TAG, "Attempting to add second definition for display-device: " + address);
-            return null;
+            return;
         }
 
         // See if we're dealing with the "default" display
         if (isDefault && getById(DEFAULT_DISPLAY) != null) {
             Slog.w(TAG, "Ignoring attempt to add a second default display: " + address);
-            return null;
+            return;
         }
 
         // Assign a logical display ID and create the new display.
@@ -138,11 +126,13 @@
             throw new IllegalArgumentException("Default display should own DEFAULT_DISPLAY_GROUP");
         }
         final int logicalDisplayId = idProducer.getId(isDefault);
+        leadDisplayId = isDefault ? NO_LEAD_DISPLAY : leadDisplayId;
+
         final Display display = new Display(address, logicalDisplayId, isEnabled, displayGroupName,
-                brightnessThrottlingMapId, position, leadDisplayId);
+                brightnessThrottlingMapId, position, leadDisplayId, refreshRateZoneId,
+                refreshRateThermalThrottlingMapId);
 
         mDisplays.add(display);
-        return display;
     }
 
     /**
@@ -242,7 +232,7 @@
         // {@link DeviceStateToLayoutMap.POSITION_FRONT} or
         // {@link DeviceStateToLayoutMap.POSITION_REAR}.
         // {@link DeviceStateToLayoutMap.POSITION_UNKNOWN} is unspecified.
-        private int mPosition;
+        private final int mPosition;
 
         // The ID of the brightness throttling map that should be used. This can change e.g. in
         // concurrent displays mode in which a stricter brightness throttling policy might need to
@@ -251,28 +241,28 @@
         private final String mBrightnessThrottlingMapId;
 
         // The ID of the lead display that this display will follow in a layout. -1 means no lead.
-        private int mLeadDisplayId;
+        private final int mLeadDisplayId;
 
         // Refresh rate zone id for specific layout
         @Nullable
-        private String mRefreshRateZoneId;
+        private final String mRefreshRateZoneId;
 
-        Display(@NonNull DisplayAddress address, int logicalDisplayId, boolean isEnabled,
+        @Nullable
+        private final String mRefreshRateThermalThrottlingMapId;
+
+        private Display(@NonNull DisplayAddress address, int logicalDisplayId, boolean isEnabled,
                 @NonNull String displayGroupName, String brightnessThrottlingMapId, int position,
-                int leadDisplayId) {
+                int leadDisplayId, @Nullable String refreshRateZoneId,
+                @Nullable String refreshRateThermalThrottlingMapId) {
             mAddress = address;
             mLogicalDisplayId = logicalDisplayId;
             mIsEnabled = isEnabled;
             mDisplayGroupName = displayGroupName;
             mPosition = position;
             mBrightnessThrottlingMapId = brightnessThrottlingMapId;
-
-            if (leadDisplayId == mLogicalDisplayId) {
-                mLeadDisplayId = NO_LEAD_DISPLAY;
-            } else {
-                mLeadDisplayId = leadDisplayId;
-            }
-
+            mRefreshRateZoneId = refreshRateZoneId;
+            mRefreshRateThermalThrottlingMapId = refreshRateThermalThrottlingMapId;
+            mLeadDisplayId = leadDisplayId;
         }
 
         @Override
@@ -286,6 +276,7 @@
                     + ", brightnessThrottlingMapId: " + mBrightnessThrottlingMapId
                     + ", mRefreshRateZoneId: " + mRefreshRateZoneId
                     + ", mLeadDisplayId: " + mLeadDisplayId
+                    + ", mRefreshRateThermalThrottlingMapId: " + mRefreshRateThermalThrottlingMapId
                     + "}";
         }
 
@@ -305,7 +296,9 @@
                     && Objects.equals(mBrightnessThrottlingMapId,
                     otherDisplay.mBrightnessThrottlingMapId)
                     && Objects.equals(otherDisplay.mRefreshRateZoneId, this.mRefreshRateZoneId)
-                    && this.mLeadDisplayId == otherDisplay.mLeadDisplayId;
+                    && this.mLeadDisplayId == otherDisplay.mLeadDisplayId
+                    && Objects.equals(mRefreshRateThermalThrottlingMapId,
+                    otherDisplay.mRefreshRateThermalThrottlingMapId);
         }
 
         @Override
@@ -319,6 +312,7 @@
             result = 31 * result + mBrightnessThrottlingMapId.hashCode();
             result = 31 * result + Objects.hashCode(mRefreshRateZoneId);
             result = 31 * result + mLeadDisplayId;
+            result = 31 * result + Objects.hashCode(mRefreshRateThermalThrottlingMapId);
             return result;
         }
 
@@ -338,24 +332,12 @@
             return mDisplayGroupName;
         }
 
-        public void setRefreshRateZoneId(@Nullable String refreshRateZoneId) {
-            mRefreshRateZoneId = refreshRateZoneId;
-        }
-
         @Nullable
         public String getRefreshRateZoneId() {
             return mRefreshRateZoneId;
         }
 
         /**
-         * Sets the position that this display is facing.
-         * @param position the display is facing.
-         */
-        public void setPosition(int position) {
-            mPosition = position;
-        }
-
-        /**
          * @return The ID of the brightness throttling map that this display should use.
          */
         public String getBrightnessThrottlingMapId() {
@@ -363,7 +345,6 @@
         }
 
         /**
-         *
          * @return the position that this display is facing.
          */
         public int getPosition() {
@@ -371,22 +352,14 @@
         }
 
         /**
-         * Set the display that this display should follow certain properties of, for example,
-         * brightness
-         * @param displayId of the lead display.
-         */
-        public void setLeadDisplay(int displayId) {
-            if (displayId != mLogicalDisplayId) {
-                mLeadDisplayId = displayId;
-            }
-        }
-
-        /**
-         *
          * @return logical displayId of the display that this one follows.
          */
         public int getLeadDisplayId() {
             return mLeadDisplayId;
         }
+
+        public String getRefreshRateThermalThrottlingMapId() {
+            return mRefreshRateThermalThrottlingMapId;
+        }
     }
 }
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
similarity index 97%
rename from services/core/java/com/android/server/display/DisplayModeDirector.java
rename to services/core/java/com/android/server/display/mode/DisplayModeDirector.java
index 31f5ab7..3864200 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.display;
+package com.android.server.display.mode;
 
 import static android.hardware.display.DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED;
 import static android.hardware.display.DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE;
@@ -67,6 +67,7 @@
 import com.android.internal.display.BrightnessSynchronizer;
 import com.android.internal.os.BackgroundThread;
 import com.android.server.LocalServices;
+import com.android.server.display.DisplayDeviceConfig;
 import com.android.server.display.utils.AmbientFilter;
 import com.android.server.display.utils.AmbientFilterFactory;
 import com.android.server.display.utils.SensorUtils;
@@ -214,12 +215,16 @@
         mUdfpsObserver.observe();
     }
 
+    /**
+    * Enables or disables component logging
+    */
     public void setLoggingEnabled(boolean loggingEnabled) {
         if (mLoggingEnabled == loggingEnabled) {
             return;
         }
         mLoggingEnabled = loggingEnabled;
         mBrightnessObserver.setLoggingEnabled(loggingEnabled);
+        mSkinThermalStatusObserver.setLoggingEnabled(loggingEnabled);
     }
 
     @NonNull
@@ -1574,7 +1579,10 @@
         }
     }
 
-    final class AppRequestObserver {
+    /**
+     *  Responsible for keeping track of app requested refresh rates per display
+     */
+    public final class AppRequestObserver {
         private final SparseArray<Display.Mode> mAppRequestedModeByDisplay;
         private final SparseArray<RefreshRateRange> mAppPreferredRefreshRateRangeByDisplay;
 
@@ -1583,6 +1591,9 @@
             mAppPreferredRefreshRateRangeByDisplay = new SparseArray<>();
         }
 
+        /**
+         * Sets refresh rates from app request
+         */
         public void setAppRequest(int displayId, int modeId, float requestedMinRefreshRateRange,
                 float requestedMaxRefreshRateRange) {
             synchronized (mLock) {
@@ -1665,7 +1676,7 @@
             return null;
         }
 
-        public void dumpLocked(PrintWriter pw) {
+        private void dumpLocked(PrintWriter pw) {
             pw.println("  AppRequestObserver");
             pw.println("    mAppRequestedModeByDisplay:");
             for (int i = 0; i < mAppRequestedModeByDisplay.size(); i++) {
@@ -1794,7 +1805,7 @@
      */
     @VisibleForTesting
     public class BrightnessObserver implements DisplayManager.DisplayListener {
-        private final static int LIGHT_SENSOR_RATE_MS = 250;
+        private static final int LIGHT_SENSOR_RATE_MS = 250;
         private int[] mLowDisplayBrightnessThresholds;
         private int[] mLowAmbientBrightnessThresholds;
         private int[] mHighDisplayBrightnessThresholds;
@@ -2019,7 +2030,7 @@
             return mLowAmbientBrightnessThresholds;
         }
 
-        public void observe(SensorManager sensorManager) {
+        private void observe(SensorManager sensorManager) {
             mSensorManager = sensorManager;
             mBrightness = getBrightness(Display.DEFAULT_DISPLAY);
 
@@ -2064,11 +2075,11 @@
             mDeviceConfigDisplaySettings.startListening();
 
             mInjector.registerDisplayListener(this, mHandler,
-                    DisplayManager.EVENT_FLAG_DISPLAY_CHANGED |
-                    DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS);
+                    DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
+                            | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS);
         }
 
-        public void setLoggingEnabled(boolean loggingEnabled) {
+        private void setLoggingEnabled(boolean loggingEnabled) {
             if (mLoggingEnabled == loggingEnabled) {
                 return;
             }
@@ -2076,6 +2087,7 @@
             mLightSensorListener.setLoggingEnabled(loggingEnabled);
         }
 
+        @VisibleForTesting
         public void onRefreshRateSettingChangedLocked(float min, float max) {
             boolean changeable = (max - min > 1f && max > 60f);
             if (mRefreshRateChangeable != changeable) {
@@ -2089,14 +2101,14 @@
             }
         }
 
-        public void onLowPowerModeEnabledLocked(boolean b) {
+        private void onLowPowerModeEnabledLocked(boolean b) {
             if (mLowPowerModeEnabled != b) {
                 mLowPowerModeEnabled = b;
                 updateSensorStatus();
             }
         }
 
-        public void onDeviceConfigLowBrightnessThresholdsChanged(int[] displayThresholds,
+        private void onDeviceConfigLowBrightnessThresholdsChanged(int[] displayThresholds,
                 int[] ambientThresholds) {
             if (displayThresholds != null && ambientThresholds != null
                     && displayThresholds.length == ambientThresholds.length) {
@@ -2123,7 +2135,7 @@
             }
         }
 
-        public void onDeviceConfigHighBrightnessThresholdsChanged(int[] displayThresholds,
+        private void onDeviceConfigHighBrightnessThresholdsChanged(int[] displayThresholds,
                 int[] ambientThresholds) {
             if (displayThresholds != null && ambientThresholds != null
                     && displayThresholds.length == ambientThresholds.length) {
@@ -2150,7 +2162,7 @@
             }
         }
 
-        public void dumpLocked(PrintWriter pw) {
+        void dumpLocked(PrintWriter pw) {
             pw.println("  BrightnessObserver");
             pw.println("    mAmbientLux: " + mAmbientLux);
             pw.println("    mBrightness: " + mBrightness);
@@ -2400,7 +2412,7 @@
         }
 
         @VisibleForTesting
-        public void setDefaultDisplayState(int state) {
+        void setDefaultDisplayState(int state) {
             if (mLoggingEnabled) {
                 Slog.d(TAG, "setDefaultDisplayState: mDefaultDisplayState = "
                         + mDefaultDisplayState + ", state = " + state);
@@ -2475,7 +2487,7 @@
         }
 
         private final class LightSensorEventListener implements SensorEventListener {
-            final private static int INJECT_EVENTS_INTERVAL_MS = LIGHT_SENSOR_RATE_MS;
+            private static final int INJECT_EVENTS_INTERVAL_MS = LIGHT_SENSOR_RATE_MS;
             private float mLastSensorData;
             private long mTimestamp;
             private boolean mLoggingEnabled;
@@ -2658,7 +2670,7 @@
         }
     }
 
-    private static final class SensorObserver implements ProximityActiveListener,
+    protected static final class SensorObserver implements ProximityActiveListener,
             DisplayManager.DisplayListener {
         private final String mProximitySensorName = null;
         private final String mProximitySensorType = Sensor.STRING_TYPE_PROXIMITY;
@@ -2876,10 +2888,10 @@
             }
 
             final int hbmMode = info.highBrightnessMode;
-            final boolean isHbmActive = hbmMode != BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF &&
-                info.adjustedBrightness > info.highBrightnessTransitionPoint;
-            if (hbmMode == mHbmMode.get(displayId) &&
-                isHbmActive == mHbmActive.get(displayId)) {
+            final boolean isHbmActive = hbmMode != BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF
+                    && info.adjustedBrightness > info.highBrightnessTransitionPoint;
+            if (hbmMode == mHbmMode.get(displayId)
+                    && isHbmActive == mHbmActive.get(displayId)) {
                 // no change, ignore.
                 return;
             }
@@ -2901,7 +2913,7 @@
             Vote vote = null;
             if (mHbmActive.get(displayId, false)) {
                 final int hbmMode =
-                    mHbmMode.get(displayId, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF);
+                        mHbmMode.get(displayId, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF);
                 if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT) {
                     // Device resource properties take priority over DisplayDeviceConfig
                     if (mRefreshRateInHbmSunlight > 0) {
@@ -2909,7 +2921,7 @@
                                 mRefreshRateInHbmSunlight);
                     } else {
                         final List<RefreshRateLimitation> limits =
-                            mDisplayManagerInternal.getRefreshRateLimitations(displayId);
+                                mDisplayManagerInternal.getRefreshRateLimitations(displayId);
                         for (int i = 0; limits != null && i < limits.size(); i++) {
                             final RefreshRateLimitation limitation = limits.get(i);
                             if (limitation.type == REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE) {
@@ -2919,8 +2931,8 @@
                             }
                         }
                     }
-                } else if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR &&
-                        mRefreshRateInHbmHdr > 0) {
+                } else if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
+                        && mRefreshRateInHbmHdr > 0) {
                     // HBM for HDR vote isn't supported through DisplayDeviceConfig yet, so look for
                     // a vote from Device properties
                     vote = Vote.forPhysicalRefreshRates(mRefreshRateInHbmHdr, mRefreshRateInHbmHdr);
@@ -2941,56 +2953,7 @@
         }
     }
 
-    private final class SkinThermalStatusObserver extends IThermalEventListener.Stub {
-        private final BallotBox mBallotBox;
-        private final Injector mInjector;
-
-        private @Temperature.ThrottlingStatus int mStatus = -1;
-
-        SkinThermalStatusObserver(Injector injector, BallotBox ballotBox) {
-            mInjector = injector;
-            mBallotBox = ballotBox;
-        }
-
-        @Override
-        public void notifyThrottling(Temperature temp) {
-            mStatus = temp.getStatus();
-            if (mLoggingEnabled) {
-                Slog.d(TAG, "New thermal throttling status "
-                        + ", current thermal status = " + mStatus);
-            }
-            final Vote vote;
-            if (mStatus >= Temperature.THROTTLING_CRITICAL) {
-                vote = Vote.forRenderFrameRates(0f, 60f);
-            } else {
-                vote = null;
-            }
-            mBallotBox.vote(GLOBAL_ID, Vote.PRIORITY_SKIN_TEMPERATURE, vote);
-        }
-
-        public void observe() {
-            IThermalService thermalService = mInjector.getThermalService();
-            if (thermalService == null) {
-                Slog.w(TAG, "Could not observe thermal status. Service not available");
-                return;
-            }
-            try {
-                thermalService.registerThermalEventListenerWithType(this, Temperature.TYPE_SKIN);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Failed to register thermal status listener", e);
-            }
-        }
-
-        void dumpLocked(PrintWriter writer) {
-            writer.println("  SkinThermalStatusObserver:");
-            writer.println("    mStatus: " + mStatus);
-        }
-    }
-
     private class DeviceConfigDisplaySettings implements DeviceConfig.OnPropertiesChangedListener {
-        public DeviceConfigDisplaySettings() {
-        }
-
         public void startListening() {
             mDeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
                     BackgroundThread.getExecutor(), this);
@@ -3001,8 +2964,8 @@
          */
         public int[] getLowDisplayBrightnessThresholds() {
             return getIntArrayProperty(
-                    DisplayManager.DeviceConfig.
-                            KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS);
+                    DisplayManager.DeviceConfig
+                            .KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS);
         }
 
         /*
@@ -3010,8 +2973,8 @@
          */
         public int[] getLowAmbientBrightnessThresholds() {
             return getIntArrayProperty(
-                    DisplayManager.DeviceConfig.
-                            KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS);
+                    DisplayManager.DeviceConfig
+                            .KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS);
         }
 
         public int getRefreshRateInLowZone() {
@@ -3176,11 +3139,15 @@
         void registerDisplayListener(@NonNull DisplayManager.DisplayListener listener,
                 Handler handler, long flags);
 
+        Display[] getDisplays();
+
+        boolean getDisplayInfo(int displayId, DisplayInfo displayInfo);
+
         BrightnessInfo getBrightnessInfo(int displayId);
 
         boolean isDozeState(Display d);
 
-        IThermalService getThermalService();
+        boolean registerThermalServiceListener(IThermalEventListener listener);
 
         boolean supportsFrameRateOverride();
     }
@@ -3214,6 +3181,20 @@
         }
 
         @Override
+        public Display[] getDisplays() {
+            return getDisplayManager().getDisplays(DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED);
+        }
+
+        @Override
+        public boolean getDisplayInfo(int displayId, DisplayInfo displayInfo) {
+            Display display = getDisplayManager().getDisplay(displayId);
+            if (display != null) {
+                return display.getDisplayInfo(displayInfo);
+            }
+            return false;
+        }
+
+        @Override
         public BrightnessInfo getBrightnessInfo(int displayId) {
             final Display display = getDisplayManager().getDisplay(displayId);
             if (display != null) {
@@ -3231,9 +3212,20 @@
         }
 
         @Override
-        public IThermalService getThermalService() {
-            return IThermalService.Stub.asInterface(
-                    ServiceManager.getService(Context.THERMAL_SERVICE));
+        public boolean registerThermalServiceListener(IThermalEventListener listener) {
+            IThermalService thermalService = getThermalService();
+            if (thermalService == null) {
+                Slog.w(TAG, "Could not observe thermal status. Service not available");
+                return false;
+            }
+            try {
+                thermalService.registerThermalEventListenerWithType(listener,
+                        Temperature.TYPE_SKIN);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to register thermal status listener", e);
+                return false;
+            }
+            return true;
         }
 
         @Override
@@ -3247,6 +3239,11 @@
             }
             return mDisplayManager;
         }
+
+        private IThermalService getThermalService() {
+            return IThermalService.Stub.asInterface(
+                    ServiceManager.getService(Context.THERMAL_SERVICE));
+        }
     }
 
     interface BallotBox {
diff --git a/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java b/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java
new file mode 100644
index 0000000..f93d9ee
--- /dev/null
+++ b/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java
@@ -0,0 +1,271 @@
+/*
+ * 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.annotation.Nullable;
+import android.hardware.display.DisplayManager;
+import android.os.Handler;
+import android.os.IThermalEventListener;
+import android.os.Temperature;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.SurfaceControl;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
+
+import java.io.PrintWriter;
+
+final class SkinThermalStatusObserver extends IThermalEventListener.Stub implements
+        DisplayManager.DisplayListener {
+    private static final String TAG = "SkinThermalStatusObserver";
+
+    private final DisplayModeDirector.BallotBox mBallotBox;
+    private final DisplayModeDirector.Injector mInjector;
+
+    private boolean mLoggingEnabled;
+
+    private final Handler mHandler;
+    private final Object mThermalObserverLock = new Object();
+    @GuardedBy("mThermalObserverLock")
+    @Temperature.ThrottlingStatus
+    private int mStatus = -1;
+    @GuardedBy("mThermalObserverLock")
+    private final SparseArray<SparseArray<SurfaceControl.RefreshRateRange>>
+            mThermalThrottlingByDisplay = new SparseArray<>();
+
+    SkinThermalStatusObserver(DisplayModeDirector.Injector injector,
+            DisplayModeDirector.BallotBox ballotBox) {
+        this(injector, ballotBox, BackgroundThread.getHandler());
+    }
+
+    @VisibleForTesting
+    SkinThermalStatusObserver(DisplayModeDirector.Injector injector,
+            DisplayModeDirector.BallotBox ballotBox, Handler handler) {
+        mInjector = injector;
+        mBallotBox = ballotBox;
+        mHandler = handler;
+    }
+
+    void observe() {
+        // if failed to register thermal service listener, don't register display listener
+        if (!mInjector.registerThermalServiceListener(this)) {
+            return;
+        }
+
+        mInjector.registerDisplayListener(this, mHandler,
+                DisplayManager.EVENT_FLAG_DISPLAY_ADDED | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
+                        | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED);
+
+        populateInitialDisplayInfo();
+    }
+
+    void setLoggingEnabled(boolean enabled) {
+        mLoggingEnabled = enabled;
+    }
+
+    @Override
+    public void notifyThrottling(Temperature temp) {
+        @Temperature.ThrottlingStatus int currentStatus = temp.getStatus();
+
+        synchronized (mThermalObserverLock) {
+            if (mStatus == currentStatus) {
+                return; // status not changed, skip update
+            }
+            mStatus = currentStatus;
+            mHandler.post(this::updateVotes);
+        }
+
+        if (mLoggingEnabled) {
+            Slog.d(TAG, "New thermal throttling status " + ", current thermal status = "
+                    + currentStatus);
+        }
+    }
+
+    //region DisplayManager.DisplayListener
+    @Override
+    public void onDisplayAdded(int displayId) {
+        updateRefreshRateThermalThrottling(displayId);
+        if (mLoggingEnabled) {
+            Slog.d(TAG, "Display added:" + displayId);
+        }
+    }
+
+    @Override
+    public void onDisplayRemoved(int displayId) {
+        synchronized (mThermalObserverLock) {
+            mThermalThrottlingByDisplay.remove(displayId);
+            mHandler.post(() -> mBallotBox.vote(displayId,
+                    DisplayModeDirector.Vote.PRIORITY_SKIN_TEMPERATURE, null));
+        }
+        if (mLoggingEnabled) {
+            Slog.d(TAG, "Display removed and voted: displayId=" + displayId);
+        }
+    }
+
+    @Override
+    public void onDisplayChanged(int displayId) {
+        updateRefreshRateThermalThrottling(displayId);
+        if (mLoggingEnabled) {
+            Slog.d(TAG, "Display changed:" + displayId);
+        }
+    }
+    //endregion
+
+    private void populateInitialDisplayInfo() {
+        DisplayInfo info = new DisplayInfo();
+        Display[] displays = mInjector.getDisplays();
+        int size = displays.length;
+        SparseArray<SparseArray<SurfaceControl.RefreshRateRange>> localMap = new SparseArray<>(
+                size);
+        for (Display d : displays) {
+            final int displayId = d.getDisplayId();
+            d.getDisplayInfo(info);
+            localMap.put(displayId, info.refreshRateThermalThrottling);
+        }
+        synchronized (mThermalObserverLock) {
+            for (int i = 0; i < size; i++) {
+                mThermalThrottlingByDisplay.put(localMap.keyAt(i), localMap.valueAt(i));
+            }
+        }
+        if (mLoggingEnabled) {
+            Slog.d(TAG, "Display initial info:" + localMap);
+        }
+    }
+
+    private void updateRefreshRateThermalThrottling(int displayId) {
+        DisplayInfo displayInfo = new DisplayInfo();
+        mInjector.getDisplayInfo(displayId, displayInfo);
+        SparseArray<SurfaceControl.RefreshRateRange> throttlingMap =
+                displayInfo.refreshRateThermalThrottling;
+
+        synchronized (mThermalObserverLock) {
+            mThermalThrottlingByDisplay.put(displayId, throttlingMap);
+            mHandler.post(() -> updateVoteForDisplay(displayId));
+        }
+        if (mLoggingEnabled) {
+            Slog.d(TAG,
+                    "Thermal throttling updated: display=" + displayId + ", map=" + throttlingMap);
+        }
+    }
+
+    //region in mHandler thread
+    private void updateVotes() {
+        @Temperature.ThrottlingStatus int localStatus;
+        SparseArray<SparseArray<SurfaceControl.RefreshRateRange>> localMap;
+
+        synchronized (mThermalObserverLock) {
+            localStatus = mStatus;
+            localMap = mThermalThrottlingByDisplay.clone();
+        }
+        if (mLoggingEnabled) {
+            Slog.d(TAG, "Updating votes for status=" + localStatus + ", map=" + localMap);
+        }
+        int size = localMap.size();
+        for (int i = 0; i < size; i++) {
+            reportThrottlingIfNeeded(localMap.keyAt(i), localStatus, localMap.valueAt(i));
+        }
+    }
+
+    private void updateVoteForDisplay(int displayId) {
+        @Temperature.ThrottlingStatus int localStatus;
+        SparseArray<SurfaceControl.RefreshRateRange> localMap;
+
+        synchronized (mThermalObserverLock) {
+            localStatus = mStatus;
+            localMap = mThermalThrottlingByDisplay.get(displayId);
+        }
+        if (localMap == null) {
+            Slog.d(TAG, "Updating votes, display already removed, display=" + displayId);
+            return;
+        }
+        if (mLoggingEnabled) {
+            Slog.d(TAG, "Updating votes for status=" + localStatus + ", display =" + displayId
+                    + ", map=" + localMap);
+        }
+        reportThrottlingIfNeeded(displayId, localStatus, localMap);
+    }
+
+    private void reportThrottlingIfNeeded(int displayId,
+            @Temperature.ThrottlingStatus int currentStatus,
+            SparseArray<SurfaceControl.RefreshRateRange> throttlingMap) {
+        if (currentStatus == -1) { // no throttling status reported from thermal sensor yet
+            return;
+        }
+
+        if (throttlingMap.size() == 0) { // map is not configured, using default behaviour
+            fallbackReportThrottlingIfNeeded(displayId, currentStatus);
+            return;
+        }
+
+        SurfaceControl.RefreshRateRange foundRange = findBestMatchingRefreshRateRange(currentStatus,
+                throttlingMap);
+        // if status <= currentStatus not found in the map reset vote
+        DisplayModeDirector.Vote vote = null;
+        if (foundRange != null) { // otherwise vote with found range
+            vote = DisplayModeDirector.Vote.forRenderFrameRates(foundRange.min, foundRange.max);
+        }
+        mBallotBox.vote(displayId, DisplayModeDirector.Vote.PRIORITY_SKIN_TEMPERATURE, vote);
+        if (mLoggingEnabled) {
+            Slog.d(TAG, "Voted: vote=" + vote + ", display =" + displayId);
+        }
+    }
+
+    @Nullable
+    private SurfaceControl.RefreshRateRange findBestMatchingRefreshRateRange(
+            @Temperature.ThrottlingStatus int currentStatus,
+            SparseArray<SurfaceControl.RefreshRateRange> throttlingMap) {
+        SurfaceControl.RefreshRateRange foundRange = null;
+        for (int status = currentStatus; status >= 0; status--) {
+            foundRange = throttlingMap.get(status);
+            if (foundRange != null) {
+                break;
+            }
+        }
+        return foundRange;
+    }
+
+    private void fallbackReportThrottlingIfNeeded(int displayId,
+            @Temperature.ThrottlingStatus int currentStatus) {
+        DisplayModeDirector.Vote vote = null;
+        if (currentStatus >= Temperature.THROTTLING_CRITICAL) {
+            vote = DisplayModeDirector.Vote.forRenderFrameRates(0f, 60f);
+        }
+        mBallotBox.vote(displayId, DisplayModeDirector.Vote.PRIORITY_SKIN_TEMPERATURE, vote);
+        if (mLoggingEnabled) {
+            Slog.d(TAG, "Voted(fallback): vote=" + vote + ", display =" + displayId);
+        }
+    }
+    //endregion
+
+    void dumpLocked(PrintWriter writer) {
+        @Temperature.ThrottlingStatus int localStatus;
+        SparseArray<SparseArray<SurfaceControl.RefreshRateRange>> localMap;
+
+        synchronized (mThermalObserverLock) {
+            localStatus = mStatus;
+            localMap = mThermalThrottlingByDisplay.clone();
+        }
+
+        writer.println("  SkinThermalStatusObserver:");
+        writer.println("    mStatus: " + localStatus);
+        writer.println("    mThermalThrottlingByDisplay: " + localMap);
+    }
+}
diff --git a/services/core/java/com/android/server/dreams/DreamShellCommand.java b/services/core/java/com/android/server/dreams/DreamShellCommand.java
index ab84ae4..df70a32 100644
--- a/services/core/java/com/android/server/dreams/DreamShellCommand.java
+++ b/services/core/java/com/android/server/dreams/DreamShellCommand.java
@@ -39,26 +39,24 @@
 
     @Override
     public int onCommand(String cmd) {
-        final int callingUid = Binder.getCallingUid();
-        if (callingUid != Process.ROOT_UID) {
-            Slog.e(TAG, "Must be root before calling Dream shell commands");
-            return -1;
-        }
-
-        if (TextUtils.isEmpty(cmd)) {
-            return super.handleDefaultCommands(cmd);
-        }
         if (DEBUG) {
             Slog.d(TAG, "onCommand:" + cmd);
         }
 
-        switch (cmd) {
-            case "start-dreaming":
-                return startDreaming();
-            case "stop-dreaming":
-                return stopDreaming();
-            default:
-                return super.handleDefaultCommands(cmd);
+        try {
+            switch (cmd) {
+                case "start-dreaming":
+                    enforceCallerIsRoot();
+                    return startDreaming();
+                case "stop-dreaming":
+                    enforceCallerIsRoot();
+                    return stopDreaming();
+                default:
+                    return super.handleDefaultCommands(cmd);
+            }
+        } catch (SecurityException e) {
+            getOutPrintWriter().println(e);
+            return -1;
         }
     }
 
@@ -72,6 +70,12 @@
         return 0;
     }
 
+    private void enforceCallerIsRoot() {
+        if (Binder.getCallingUid() != Process.ROOT_UID) {
+            throw new SecurityException("Must be root to call Dream shell commands");
+        }
+    }
+
     @Override
     public void onHelp() {
         PrintWriter pw = getOutPrintWriter();
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 3563938..c0deb3f 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -700,6 +700,7 @@
         }
         if (mCecController == null) {
             Slog.i(TAG, "Device does not support HDMI-CEC.");
+            return;
         }
         if (mMhlController == null) {
             mMhlController = HdmiMhlControllerStub.create(this);
@@ -713,9 +714,6 @@
         if (mEarcController == null) {
             Slog.i(TAG, "Device does not support eARC.");
         }
-        if (mCecController == null && mEarcController == null) {
-            return;
-        }
         mHdmiCecNetwork = new HdmiCecNetwork(this, mCecController, mMhlController);
         if (isCecControlEnabled()) {
             initializeCec(INITIATED_BY_BOOT_UP);
diff --git a/services/core/java/com/android/server/input/InputManagerInternal.java b/services/core/java/com/android/server/input/InputManagerInternal.java
index 4d03e44..7e990c6 100644
--- a/services/core/java/com/android/server/input/InputManagerInternal.java
+++ b/services/core/java/com/android/server/input/InputManagerInternal.java
@@ -96,7 +96,11 @@
      */
     public abstract int getVirtualMousePointerDisplayId();
 
-    /** Gets the current position of the mouse cursor. */
+    /**
+     * Gets the current position of the mouse cursor.
+     *
+     * Returns NaN-s as the coordinates if the cursor is not available.
+     */
     public abstract PointF getCursorPosition();
 
     /**
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index b2b22a0..efc4f11 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -2863,9 +2863,6 @@
 
         int getPointerDisplayId();
 
-        /** Gets the x and y coordinates of the cursor's current position. */
-        PointF getCursorPosition();
-
         /**
          * Notifies window manager that a {@link android.view.MotionEvent#ACTION_DOWN} pointer event
          * occurred on a window that did not have focus.
@@ -3189,7 +3186,11 @@
 
         @Override
         public PointF getCursorPosition() {
-            return mWindowManagerCallbacks.getCursorPosition();
+            final float[] p = mNative.getMouseCursorPosition();
+            if (p == null || p.length != 2) {
+                throw new IllegalStateException("Failed to get mouse cursor position");
+            }
+            return new PointF(p[0], p[1]);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/input/KeyboardLayoutManager.java b/services/core/java/com/android/server/input/KeyboardLayoutManager.java
index e0253fc..f873a1b 100644
--- a/services/core/java/com/android/server/input/KeyboardLayoutManager.java
+++ b/services/core/java/com/android/server/input/KeyboardLayoutManager.java
@@ -45,14 +45,17 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.FeatureFlagUtils;
 import android.util.Log;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.view.InputDevice;
 import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.InputMethodSubtype;
 import android.widget.Toast;
 
@@ -75,6 +78,7 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 import java.util.stream.Stream;
 
 /**
@@ -102,8 +106,10 @@
     private final PersistentDataStore mDataStore;
     private final Handler mHandler;
 
-    private final List<InputDevice> mKeyboardsWithMissingLayouts = new ArrayList<>();
-    private boolean mKeyboardLayoutNotificationShown = false;
+    // Connected keyboards with associated keyboard layouts (either auto-detected or manually
+    // selected layout). If the mapped value is null/empty, it means that no layout has been
+    // configured for the keyboard and user might need to manually configure it from the Settings.
+    private final SparseArray<Set<String>> mConfiguredKeyboards = new SparseArray<>();
     private Toast mSwitchedKeyboardLayoutToast;
 
     // This cache stores "best-matched" layouts so that we don't need to run the matching
@@ -150,14 +156,16 @@
     @Override
     public void onInputDeviceAdded(int deviceId) {
         onInputDeviceChanged(deviceId);
+        if (useNewSettingsUi()) {
+            // Force native callback to set up keyboard layout overlay for newly added keyboards
+            reloadKeyboardLayouts();
+        }
     }
 
     @Override
     public void onInputDeviceRemoved(int deviceId) {
-        if (!useNewSettingsUi()) {
-            mKeyboardsWithMissingLayouts.removeIf(device -> device.getId() == deviceId);
-            maybeUpdateNotification();
-        }
+        mConfiguredKeyboards.remove(deviceId);
+        maybeUpdateNotification();
     }
 
     @Override
@@ -174,13 +182,53 @@
                     if (layout != null) {
                         setCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier(), layout);
                     } else {
-                        mKeyboardsWithMissingLayouts.add(inputDevice);
+                        mConfiguredKeyboards.put(inputDevice.getId(), new HashSet<>());
                     }
                 }
-                maybeUpdateNotification();
+            }
+        } else {
+            final InputDeviceIdentifier identifier = inputDevice.getIdentifier();
+            final String key = getLayoutDescriptor(identifier);
+            Set<String> selectedLayouts = new HashSet<>();
+            boolean needToShowMissingLayoutNotification = false;
+            for (ImeInfo imeInfo : getImeInfoListForLayoutMapping()) {
+                // Check if the layout has been previously configured
+                String layout = getKeyboardLayoutForInputDeviceInternal(identifier,
+                        new ImeInfo(imeInfo.mUserId, imeInfo.mImeSubtypeHandle,
+                                imeInfo.mImeSubtype));
+                if (layout == null) {
+                    needToShowMissingLayoutNotification = true;
+                    continue;
+                }
+                selectedLayouts.add(layout);
+            }
+
+            if (needToShowMissingLayoutNotification) {
+                // If even one layout not configured properly we will show configuration
+                // notification allowing user to set the keyboard layout.
+                selectedLayouts.clear();
+            }
+
+            if (DEBUG) {
+                Slog.d(TAG,
+                        "Layouts selected for input device: " + identifier + " -> selectedLayouts: "
+                                + selectedLayouts);
+            }
+            mConfiguredKeyboards.set(inputDevice.getId(), selectedLayouts);
+
+            synchronized (mDataStore) {
+                try {
+                    if (!mDataStore.setSelectedKeyboardLayouts(key, selectedLayouts)) {
+                        // No need to show the notification only if layout selection didn't change
+                        // from the previous configuration
+                        return;
+                    }
+                } finally {
+                    mDataStore.saveIfNeeded();
+                }
             }
         }
-        // TODO(b/259530132): Show notification for new Settings UI
+        maybeUpdateNotification();
     }
 
     private String getDefaultKeyboardLayout(final InputDevice inputDevice) {
@@ -283,7 +331,8 @@
     public KeyboardLayout[] getKeyboardLayoutsForInputDevice(
             final InputDeviceIdentifier identifier) {
         if (useNewSettingsUi()) {
-            return new KeyboardLayout[0];
+            // Provide all supported keyboard layouts since Ime info is not provided
+            return getKeyboardLayouts();
         }
         final String[] enabledLayoutDescriptors =
                 getEnabledKeyboardLayoutsForInputDevice(identifier);
@@ -478,15 +527,17 @@
         key.append("vendor:").append(identifier.getVendorId()).append(",product:").append(
                 identifier.getProductId());
 
-        InputDevice inputDevice = getInputDevice(identifier);
-        Objects.requireNonNull(inputDevice, "Input device must not be null");
-        // Some keyboards can have same product ID and vendor ID but different Keyboard info like
-        // language tag and layout type.
-        if (!TextUtils.isEmpty(inputDevice.getKeyboardLanguageTag())) {
-            key.append(",languageTag:").append(inputDevice.getKeyboardLanguageTag());
-        }
-        if (!TextUtils.isEmpty(inputDevice.getKeyboardLayoutType())) {
-            key.append(",layoutType:").append(inputDevice.getKeyboardLanguageTag());
+        if (useNewSettingsUi()) {
+            InputDevice inputDevice = getInputDevice(identifier);
+            Objects.requireNonNull(inputDevice, "Input device must not be null");
+            // Some keyboards can have same product ID and vendor ID but different Keyboard info
+            // like language tag and layout type.
+            if (!TextUtils.isEmpty(inputDevice.getKeyboardLanguageTag())) {
+                key.append(",languageTag:").append(inputDevice.getKeyboardLanguageTag());
+            }
+            if (!TextUtils.isEmpty(inputDevice.getKeyboardLayoutType())) {
+                key.append(",layoutType:").append(inputDevice.getKeyboardLanguageTag());
+            }
         }
         return key.toString();
     }
@@ -664,6 +715,12 @@
     public String[] getKeyboardLayoutOverlay(InputDeviceIdentifier identifier) {
         String keyboardLayoutDescriptor;
         if (useNewSettingsUi()) {
+            InputDevice inputDevice = getInputDevice(identifier);
+            if (inputDevice == null) {
+                // getKeyboardLayoutOverlay() called before input device added completely. Need
+                // to wait till the device is added which will call reloadKeyboardLayouts()
+                return null;
+            }
             if (mCurrentImeInfo == null) {
                 // Haven't received onInputMethodSubtypeChanged() callback from IMMS. Will reload
                 // keyboard layouts once we receive the callback.
@@ -986,66 +1043,140 @@
     }
 
     private void maybeUpdateNotification() {
+        if (mConfiguredKeyboards.size() == 0) {
+            hideKeyboardLayoutNotification();
+            return;
+        }
+        for (int i = 0; i < mConfiguredKeyboards.size(); i++) {
+            // If we have a keyboard with no selected layouts, we should always show missing
+            // layout notification even if there are other keyboards that are configured properly.
+            if (mConfiguredKeyboards.valueAt(i).isEmpty()) {
+                showMissingKeyboardLayoutNotification();
+                return;
+            }
+        }
+        showConfiguredKeyboardLayoutNotification();
+    }
+
+    // Must be called on handler.
+    private void showMissingKeyboardLayoutNotification() {
+        final Resources r = mContext.getResources();
+        final String missingKeyboardLayoutNotificationContent = r.getString(
+                R.string.select_keyboard_layout_notification_message);
+
+        if (mConfiguredKeyboards.size() == 1) {
+            final InputDevice device = getInputDevice(mConfiguredKeyboards.keyAt(0));
+            if (device == null) {
+                return;
+            }
+            showKeyboardLayoutNotification(
+                    r.getString(
+                            R.string.select_keyboard_layout_notification_title,
+                            device.getName()),
+                    missingKeyboardLayoutNotificationContent,
+                    device);
+        } else {
+            showKeyboardLayoutNotification(
+                    r.getString(R.string.select_multiple_keyboards_layout_notification_title),
+                    missingKeyboardLayoutNotificationContent,
+                    null);
+        }
+    }
+
+    private void showKeyboardLayoutNotification(@NonNull String intentTitle,
+            @NonNull String intentContent, @Nullable InputDevice targetDevice) {
+        final NotificationManager notificationManager = mContext.getSystemService(
+                NotificationManager.class);
+        if (notificationManager == null) {
+            return;
+        }
+
+        final Intent intent = new Intent(Settings.ACTION_HARD_KEYBOARD_SETTINGS);
+
+        if (targetDevice != null) {
+            intent.putExtra(Settings.EXTRA_INPUT_DEVICE_IDENTIFIER, targetDevice.getIdentifier());
+        }
+
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        final PendingIntent keyboardLayoutIntent = PendingIntent.getActivityAsUser(mContext, 0,
+                intent, PendingIntent.FLAG_IMMUTABLE, null, UserHandle.CURRENT);
+
+        Notification notification =
+                new Notification.Builder(mContext, SystemNotificationChannels.PHYSICAL_KEYBOARD)
+                        .setContentTitle(intentTitle)
+                        .setContentText(intentContent)
+                        .setContentIntent(keyboardLayoutIntent)
+                        .setSmallIcon(R.drawable.ic_settings_language)
+                        .setColor(mContext.getColor(
+                                com.android.internal.R.color.system_notification_accent_color))
+                        .setAutoCancel(true)
+                        .build();
+        notificationManager.notifyAsUser(null,
+                SystemMessageProto.SystemMessage.NOTE_SELECT_KEYBOARD_LAYOUT,
+                notification, UserHandle.ALL);
+    }
+
+    // Must be called on handler.
+    private void hideKeyboardLayoutNotification() {
         NotificationManager notificationManager = mContext.getSystemService(
                 NotificationManager.class);
         if (notificationManager == null) {
             return;
         }
-        if (!mKeyboardsWithMissingLayouts.isEmpty()) {
-            if (mKeyboardsWithMissingLayouts.size() > 1) {
-                // We have more than one keyboard missing a layout, so drop the
-                // user at the generic input methods page, so they can pick which
-                // one to set.
-                showMissingKeyboardLayoutNotification(notificationManager, null);
-            } else {
-                showMissingKeyboardLayoutNotification(notificationManager,
-                        mKeyboardsWithMissingLayouts.get(0));
-            }
-        } else if (mKeyboardLayoutNotificationShown) {
-            hideMissingKeyboardLayoutNotification(notificationManager);
-        }
+
+        notificationManager.cancelAsUser(null,
+                SystemMessageProto.SystemMessage.NOTE_SELECT_KEYBOARD_LAYOUT,
+                UserHandle.ALL);
     }
 
-    // Must be called on handler.
-    private void showMissingKeyboardLayoutNotification(NotificationManager notificationManager,
-            InputDevice device) {
-        if (!mKeyboardLayoutNotificationShown) {
-            final Intent intent = new Intent(Settings.ACTION_HARD_KEYBOARD_SETTINGS);
-            if (device != null) {
-                intent.putExtra(Settings.EXTRA_INPUT_DEVICE_IDENTIFIER, device.getIdentifier());
-            }
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                    | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
-                    | Intent.FLAG_ACTIVITY_CLEAR_TOP);
-            final PendingIntent keyboardLayoutIntent = PendingIntent.getActivityAsUser(mContext, 0,
-                    intent, PendingIntent.FLAG_IMMUTABLE, null, UserHandle.CURRENT);
+    private void showConfiguredKeyboardLayoutNotification() {
+        final Resources r = mContext.getResources();
 
-            Resources r = mContext.getResources();
-            Notification notification =
-                    new Notification.Builder(mContext, SystemNotificationChannels.PHYSICAL_KEYBOARD)
-                            .setContentTitle(r.getString(
-                                    R.string.select_keyboard_layout_notification_title))
-                            .setContentText(r.getString(
-                                    R.string.select_keyboard_layout_notification_message))
-                            .setContentIntent(keyboardLayoutIntent)
-                            .setSmallIcon(R.drawable.ic_settings_language)
-                            .setColor(mContext.getColor(
-                                    com.android.internal.R.color.system_notification_accent_color))
-                            .build();
-            notificationManager.notifyAsUser(null,
-                    SystemMessageProto.SystemMessage.NOTE_SELECT_KEYBOARD_LAYOUT,
-                    notification, UserHandle.ALL);
-            mKeyboardLayoutNotificationShown = true;
+        if (mConfiguredKeyboards.size() != 1) {
+            showKeyboardLayoutNotification(
+                    r.getString(R.string.keyboard_layout_notification_multiple_selected_title),
+                    r.getString(R.string.keyboard_layout_notification_multiple_selected_message),
+                    null);
+            return;
         }
+
+        final InputDevice inputDevice = getInputDevice(mConfiguredKeyboards.keyAt(0));
+        final Set<String> selectedLayouts = mConfiguredKeyboards.valueAt(0);
+        if (inputDevice == null || selectedLayouts == null || selectedLayouts.isEmpty()) {
+            return;
+        }
+
+        showKeyboardLayoutNotification(
+                r.getString(
+                        R.string.keyboard_layout_notification_selected_title,
+                        inputDevice.getName()),
+                createConfiguredNotificationText(mContext, selectedLayouts),
+                inputDevice);
     }
 
-    // Must be called on handler.
-    private void hideMissingKeyboardLayoutNotification(NotificationManager notificationManager) {
-        if (mKeyboardLayoutNotificationShown) {
-            mKeyboardLayoutNotificationShown = false;
-            notificationManager.cancelAsUser(null,
-                    SystemMessageProto.SystemMessage.NOTE_SELECT_KEYBOARD_LAYOUT,
-                    UserHandle.ALL);
+    private String createConfiguredNotificationText(@NonNull Context context,
+            @NonNull Set<String> selectedLayouts) {
+        final Resources r = context.getResources();
+        List<String> layoutNames = new ArrayList<>();
+        selectedLayouts.forEach(
+                (layoutDesc) -> layoutNames.add(getKeyboardLayout(layoutDesc).getLabel()));
+        Collections.sort(layoutNames);
+        switch (layoutNames.size()) {
+            case 1:
+                return r.getString(R.string.keyboard_layout_notification_one_selected_message,
+                        layoutNames.get(0));
+            case 2:
+                return r.getString(R.string.keyboard_layout_notification_two_selected_message,
+                        layoutNames.get(0), layoutNames.get(1));
+            case 3:
+                return r.getString(R.string.keyboard_layout_notification_three_selected_message,
+                        layoutNames.get(0), layoutNames.get(1), layoutNames.get(2));
+            default:
+                return r.getString(
+                        R.string.keyboard_layout_notification_more_than_three_selected_message,
+                        layoutNames.get(0), layoutNames.get(1), layoutNames.get(2));
         }
     }
 
@@ -1089,6 +1220,31 @@
                 identifier.getDescriptor()) : null;
     }
 
+    private List<ImeInfo> getImeInfoListForLayoutMapping() {
+        List<ImeInfo> imeInfoList = new ArrayList<>();
+        UserManager userManager = Objects.requireNonNull(
+                mContext.getSystemService(UserManager.class));
+        InputMethodManager inputMethodManager = Objects.requireNonNull(
+                mContext.getSystemService(InputMethodManager.class));
+        for (UserHandle userHandle : userManager.getUserHandles(true /* excludeDying */)) {
+            int userId = userHandle.getIdentifier();
+            for (InputMethodInfo imeInfo : inputMethodManager.getEnabledInputMethodListAsUser(
+                    userId)) {
+                for (InputMethodSubtype imeSubtype :
+                        inputMethodManager.getEnabledInputMethodSubtypeList(
+                                imeInfo, true /* allowsImplicitlyEnabledSubtypes */)) {
+                    if (!imeSubtype.isSuitableForPhysicalKeyboardLayoutMapping()) {
+                        continue;
+                    }
+                    imeInfoList.add(
+                            new ImeInfo(userId, InputMethodSubtypeHandle.of(imeInfo, imeSubtype),
+                                    imeSubtype));
+                }
+            }
+        }
+        return imeInfoList;
+    }
+
     private String createLayoutKey(InputDeviceIdentifier identifier, int userId,
             @NonNull InputMethodSubtypeHandle subtypeHandle) {
         Objects.requireNonNull(subtypeHandle, "subtypeHandle must not be null");
diff --git a/services/core/java/com/android/server/input/NativeInputManagerService.java b/services/core/java/com/android/server/input/NativeInputManagerService.java
index 22226e8..5395302d 100644
--- a/services/core/java/com/android/server/input/NativeInputManagerService.java
+++ b/services/core/java/com/android/server/input/NativeInputManagerService.java
@@ -224,6 +224,16 @@
     /** Set whether stylus button reporting through motion events should be enabled. */
     void setStylusButtonMotionEventsEnabled(boolean enabled);
 
+    /**
+     * Get the current position of the mouse cursor.
+     *
+     * If the mouse cursor is not currently shown, the coordinate values will be NaN-s.
+     *
+     * NOTE: This will grab the PointerController's lock, so we must be careful about calling this
+     * from the InputReader or Display threads, which may result in a deadlock.
+     */
+    float[] getMouseCursorPosition();
+
     /** The native implementation of InputManagerService methods. */
     class NativeImpl implements NativeInputManagerService {
         /** Pointer to native input manager service object, used by native code. */
@@ -465,5 +475,8 @@
 
         @Override
         public native void setStylusButtonMotionEventsEnabled(boolean enabled);
+
+        @Override
+        public native float[] getMouseCursorPosition();
     }
 }
diff --git a/services/core/java/com/android/server/input/PersistentDataStore.java b/services/core/java/com/android/server/input/PersistentDataStore.java
index a2b18362..bce210d 100644
--- a/services/core/java/com/android/server/input/PersistentDataStore.java
+++ b/services/core/java/com/android/server/input/PersistentDataStore.java
@@ -16,6 +16,7 @@
 
 package com.android.server.input;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.hardware.input.TouchCalibration;
 import android.util.ArrayMap;
@@ -43,6 +44,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -155,6 +157,16 @@
         return false;
     }
 
+    public boolean setSelectedKeyboardLayouts(String inputDeviceDescriptor,
+            @NonNull Set<String> selectedLayouts) {
+        InputDeviceState state = getOrCreateInputDeviceState(inputDeviceDescriptor);
+        if (state.setSelectedKeyboardLayouts(selectedLayouts)) {
+            setDirty();
+            return true;
+        }
+        return false;
+    }
+
     public String[] getKeyboardLayouts(String inputDeviceDescriptor) {
         InputDeviceState state = getInputDeviceState(inputDeviceDescriptor);
         if (state == null) {
@@ -408,6 +420,8 @@
 
         private final Map<String, String> mKeyboardLayoutMap = new ArrayMap<>();
 
+        private Set<String> mSelectedKeyboardLayouts;
+
         public TouchCalibration getTouchCalibration(int surfaceRotation) {
             try {
                 return mTouchCalibration[surfaceRotation];
@@ -439,6 +453,14 @@
             return !Objects.equals(mKeyboardLayoutMap.put(key, keyboardLayout), keyboardLayout);
         }
 
+        public boolean setSelectedKeyboardLayouts(@NonNull Set<String> selectedLayouts) {
+            if (Objects.equals(mSelectedKeyboardLayouts, selectedLayouts)) {
+                return false;
+            }
+            mSelectedKeyboardLayouts = new HashSet<>(selectedLayouts);
+            return true;
+        }
+
         @Nullable
         public String getCurrentKeyboardLayout() {
             return mCurrentKeyboardLayout;
@@ -588,6 +610,16 @@
                                 "Missing layout attribute on keyed-keyboard-layout.");
                     }
                     mKeyboardLayoutMap.put(key, layout);
+                } else if (parser.getName().equals("selected-keyboard-layout")) {
+                    String layout = parser.getAttributeValue(null, "layout");
+                    if (layout == null) {
+                        throw new XmlPullParserException(
+                                "Missing layout attribute on selected-keyboard-layout.");
+                    }
+                    if (mSelectedKeyboardLayouts == null) {
+                        mSelectedKeyboardLayouts = new HashSet<>();
+                    }
+                    mSelectedKeyboardLayouts.add(layout);
                 } else if (parser.getName().equals("light-info")) {
                     int lightId = parser.getAttributeInt(null, "light-id");
                     int lightBrightness = parser.getAttributeInt(null, "light-brightness");
@@ -668,6 +700,14 @@
                 serializer.endTag(null, "keyed-keyboard-layout");
             }
 
+            if (mSelectedKeyboardLayouts != null) {
+                for (String layout : mSelectedKeyboardLayouts) {
+                    serializer.startTag(null, "selected-keyboard-layout");
+                    serializer.attribute(null, "layout", layout);
+                    serializer.endTag(null, "selected-keyboard-layout");
+                }
+            }
+
             for (int i = 0; i < mKeyboardBacklightBrightnessMap.size(); i++) {
                 serializer.startTag(null, "light-info");
                 serializer.attributeInt(null, "light-id", mKeyboardBacklightBrightnessMap.keyAt(i));
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodDeviceConfigs.java b/services/core/java/com/android/server/inputmethod/InputMethodDeviceConfigs.java
index dc2799e..6cd2493 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodDeviceConfigs.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodDeviceConfigs.java
@@ -21,6 +21,8 @@
 import android.app.ActivityThread;
 import android.provider.DeviceConfig;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 /**
  * Class for the device-level configuration related to the input method manager
  * platform features in {@link DeviceConfig}.
@@ -56,4 +58,9 @@
     public boolean shouldHideImeWhenNoEditorFocus() {
         return mHideImeWhenNoEditorFocus;
     }
+
+    @VisibleForTesting
+    void destroy() {
+        DeviceConfig.removeOnPropertiesChangedListener(mDeviceConfigChangedListener);
+    }
 }
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index eba261a..91f91f8 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -1410,6 +1410,22 @@
         }
 
         @Override
+        public void onPackageDataCleared(String packageName, int uid) {
+            boolean changed = false;
+            for (InputMethodInfo imi : mMethodList) {
+                if (imi.getPackageName().equals(packageName)) {
+                    mAdditionalSubtypeMap.remove(imi.getId());
+                    changed = true;
+                }
+            }
+            if (changed) {
+                AdditionalSubtypeUtils.save(
+                        mAdditionalSubtypeMap, mMethodMap, mSettings.getCurrentUserId());
+                mChangedPackages.add(packageName);
+            }
+        }
+
+        @Override
         public void onFinishPackageChanges() {
             onFinishPackageChangesInternal();
             clearPackageChangeState();
@@ -3263,7 +3279,7 @@
                 notifyInputMethodSubtypeChangedLocked(userId, info, null);
                 return;
             }
-            if (newSubtype != oldSubtype) {
+            if (!newSubtype.equals(oldSubtype)) {
                 setSelectedInputMethodAndSubtypeLocked(info, subtypeId, true);
                 IInputMethodInvoker curMethod = getCurMethodLocked();
                 if (curMethod != null) {
@@ -3309,6 +3325,7 @@
             if (!canInteractWithImeLocked(uid, client, "showSoftInput", statsToken)) {
                 ImeTracker.forLogging().onFailed(
                         statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
+                Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
                 return false;
             }
             final long ident = Binder.clearCallingIdentity();
@@ -6442,19 +6459,21 @@
                                 0 /* flags */, null /* resultReceiver */,
                                 SoftInputShowHideReason.HIDE_RESET_SHELL_COMMAND);
                         mBindingController.unbindCurrentMethod();
-                        // Reset the current IME
-                        resetSelectedInputMethodAndSubtypeLocked(null);
-                        // Also reset the settings of the current IME
-                        mSettings.putSelectedInputMethod(null);
-                        // Disable all enabled IMEs.
-                        for (InputMethodInfo inputMethodInfo :
-                                mSettings.getEnabledInputMethodListLocked()) {
-                            setInputMethodEnabledLocked(inputMethodInfo.getId(), false);
+
+                        // Enable default IMEs, disable others
+                        var toDisable = mSettings.getEnabledInputMethodListLocked();
+                        var defaultEnabled = InputMethodInfoUtils.getDefaultEnabledImes(
+                                mContext, mMethodList);
+                        toDisable.removeAll(defaultEnabled);
+                        for (InputMethodInfo info : toDisable) {
+                            setInputMethodEnabledLocked(info.getId(), false);
                         }
-                        // Re-enable with default enabled IMEs.
-                        for (InputMethodInfo imi : InputMethodInfoUtils.getDefaultEnabledImes(
-                                mContext, mMethodList)) {
-                            setInputMethodEnabledLocked(imi.getId(), true);
+                        for (InputMethodInfo info : defaultEnabled) {
+                            setInputMethodEnabledLocked(info.getId(), true);
+                        }
+                        // Choose new default IME, reset to none if no IME available.
+                        if (!chooseNewDefaultIMELocked()) {
+                            resetSelectedInputMethodAndSubtypeLocked(null);
                         }
                         updateInputMethodsFromSettingsLocked(true /* enabledMayChange */);
                         InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(
diff --git a/services/core/java/com/android/server/locales/AppLocaleChangedAtomRecord.java b/services/core/java/com/android/server/locales/AppLocaleChangedAtomRecord.java
index 282e3c1..2be2ef8 100644
--- a/services/core/java/com/android/server/locales/AppLocaleChangedAtomRecord.java
+++ b/services/core/java/com/android/server/locales/AppLocaleChangedAtomRecord.java
@@ -30,7 +30,8 @@
     String mPrevLocales = "";
     int mStatus = FrameworkStatsLog
             .APPLICATION_LOCALES_CHANGED__STATUS__STATUS_UNSPECIFIED;
-
+    int mCaller = FrameworkStatsLog
+            .APPLICATION_LOCALES_CHANGED__CALLER__CALLER_UNKNOWN;
     AppLocaleChangedAtomRecord(int callingUid) {
         this.mCallingUid = callingUid;
     }
@@ -50,4 +51,8 @@
     void setStatus(int status) {
         this.mStatus = status;
     }
+
+    void setCaller(int caller) {
+        this.mCaller = caller;
+    }
 }
diff --git a/services/core/java/com/android/server/locales/AppSupportedLocalesChangedAtomRecord.java b/services/core/java/com/android/server/locales/AppSupportedLocalesChangedAtomRecord.java
new file mode 100644
index 0000000..de429f0
--- /dev/null
+++ b/services/core/java/com/android/server/locales/AppSupportedLocalesChangedAtomRecord.java
@@ -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.server.locales;
+
+import static android.os.Process.INVALID_UID;
+
+import com.android.internal.util.FrameworkStatsLog;
+
+/**
+ * Holds data used to report the AppSupportedLocalesChanged atom.
+ */
+public final class AppSupportedLocalesChangedAtomRecord {
+    // The uid which invoked this update.
+    final int mCallingUid;
+    // The uid for which the override of app’s supported locales change is being done.
+    int mTargetUid = INVALID_UID;
+    // The total number of locales in the override LocaleConfig.
+    int mNumLocales = -1;
+    // Whether the override is removed LocaleConfig from the storage.
+    boolean mOverrideRemoved = false;
+    // Whether the new override LocaleConfig is the same as the app’s LocaleConfig.
+    boolean mSameAsResConfig = false;
+    // Whether the new override LocaleConfig is the same as the previously effective one. This means
+    // a comparison with the previous override LocaleConfig if there was one, and a comparison with
+    // the resource LocaleConfig if no override was present.
+    boolean mSameAsPrevConfig = false;
+    // Application supported locales changed status.
+    int mStatus = FrameworkStatsLog
+            .APP_SUPPORTED_LOCALES_CHANGED__STATUS__STATUS_UNSPECIFIED;
+
+    AppSupportedLocalesChangedAtomRecord(int callingUid) {
+        this.mCallingUid = callingUid;
+    }
+
+    void setTargetUid(int targetUid) {
+        this.mTargetUid = targetUid;
+    }
+
+    void setNumLocales(int numLocales) {
+        this.mNumLocales = numLocales;
+    }
+
+    void setOverrideRemoved(boolean overrideRemoved) {
+        this.mOverrideRemoved = overrideRemoved;
+    }
+
+    void setSameAsResConfig(boolean sameAsResConfig) {
+        this.mSameAsResConfig = sameAsResConfig;
+    }
+
+    void setSameAsPrevConfig(boolean sameAsPrevConfig) {
+        this.mSameAsPrevConfig = sameAsPrevConfig;
+    }
+
+    void setStatus(int status) {
+        this.mStatus = status;
+    }
+}
diff --git a/services/core/java/com/android/server/locales/AppUpdateTracker.java b/services/core/java/com/android/server/locales/AppUpdateTracker.java
deleted file mode 100644
index 3474f1e..0000000
--- a/services/core/java/com/android/server/locales/AppUpdateTracker.java
+++ /dev/null
@@ -1,180 +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.server.locales;
-
-import android.app.LocaleConfig;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
-import android.os.LocaleList;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.util.ArraySet;
-import android.util.FeatureFlagUtils;
-import android.util.Log;
-import android.util.Slog;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.Set;
-
-/**
- * Track when a app is being updated.
- */
-public class AppUpdateTracker {
-    private static final String TAG = "AppUpdateTracker";
-
-    private final Context mContext;
-    private final LocaleManagerService mLocaleManagerService;
-    private final LocaleManagerBackupHelper mBackupHelper;
-
-    AppUpdateTracker(Context context, LocaleManagerService localeManagerService,
-            LocaleManagerBackupHelper backupHelper) {
-        mContext = context;
-        mLocaleManagerService = localeManagerService;
-        mBackupHelper = backupHelper;
-    }
-
-    /**
-     * <p><b>Note:</b> This is invoked by service's common monitor
-     * {@link LocaleManagerServicePackageMonitor#onPackageUpdateFinished} when a package is upgraded
-     * on device.
-     */
-    public void onPackageUpdateFinished(String packageName, int uid) {
-        Log.d(TAG, "onPackageUpdateFinished " + packageName);
-        int userId = UserHandle.getUserId(uid);
-        cleanApplicationLocalesIfNeeded(packageName, userId);
-    }
-
-    /**
-     * When the user has set per-app locales for a specific application from a delegate selector,
-     * and then the LocaleConfig of that application is removed in the upgraded version, the per-app
-     * locales needs to be reset to system default locales to avoid the user being unable to change
-     * system locales setting.
-     */
-    private void cleanApplicationLocalesIfNeeded(String packageName, int userId) {
-        Set<String> packageNames = new ArraySet<>();
-        SharedPreferences delegateAppLocalePackages = mBackupHelper.getPersistedInfo();
-        if (delegateAppLocalePackages != null) {
-            packageNames = delegateAppLocalePackages.getStringSet(Integer.toString(userId),
-                    new ArraySet<>());
-        }
-
-        try {
-            LocaleList appLocales = mLocaleManagerService.getApplicationLocales(packageName,
-                    userId);
-            if (appLocales.isEmpty() || isLocalesExistedInLocaleConfig(appLocales, packageName,
-                    userId) || !packageNames.contains(packageName)) {
-                return;
-            }
-        } catch (RemoteException | IllegalArgumentException e) {
-            Slog.e(TAG, "Exception when getting locales for " + packageName, e);
-            return;
-        }
-
-        Slog.d(TAG, "Clear app locales for " + packageName);
-        try {
-            mLocaleManagerService.setApplicationLocales(packageName, userId,
-                    LocaleList.forLanguageTags(""), false);
-        } catch (RemoteException | IllegalArgumentException e) {
-            Slog.e(TAG, "Could not clear locales for " + packageName, e);
-        }
-    }
-
-    /**
-     * Check whether the LocaleConfig is existed and the per-app locales is presented in the
-     * LocaleConfig file after the application is upgraded.
-     */
-    private boolean isLocalesExistedInLocaleConfig(LocaleList appLocales, String packageName,
-            int userId) {
-        LocaleList packageLocalesList = getPackageLocales(packageName, userId);
-        HashSet<Locale> packageLocales = new HashSet<>();
-
-        if (isSettingsAppLocalesOptIn()) {
-            if (packageLocalesList == null || packageLocalesList.isEmpty()) {
-                // The app locale feature is not enabled by the app
-                Slog.d(TAG, "opt-in: the app locale feature is not enabled");
-                return false;
-            }
-        } else {
-            if (packageLocalesList != null && packageLocalesList.isEmpty()) {
-                // The app locale feature is not enabled by the app
-                Slog.d(TAG, "opt-out: the app locale feature is not enabled");
-                return false;
-            }
-        }
-
-        if (packageLocalesList != null && !packageLocalesList.isEmpty()) {
-            // The app has added the supported locales into the LocaleConfig
-            for (int i = 0; i < packageLocalesList.size(); i++) {
-                packageLocales.add(packageLocalesList.get(i));
-            }
-            if (!matchesLocale(packageLocales, appLocales)) {
-                // The set app locales do not match with the list of app supported locales
-                Slog.d(TAG, "App locales: " + appLocales.toLanguageTags()
-                        + " are not existed in the supported locale list");
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    /**
-     * Get locales from LocaleConfig.
-     */
-    @VisibleForTesting
-    public LocaleList getPackageLocales(String packageName, int userId) {
-        try {
-            LocaleConfig localeConfig = new LocaleConfig(
-                    mContext.createPackageContextAsUser(packageName, 0, UserHandle.of(userId)));
-            if (localeConfig.getStatus() == LocaleConfig.STATUS_SUCCESS) {
-                return localeConfig.getSupportedLocales();
-            }
-        } catch (PackageManager.NameNotFoundException e) {
-            Slog.e(TAG, "Can not found the package name : " + packageName + " / " + e);
-        }
-        return null;
-    }
-
-    /**
-     * Check whether the feature to show per-app locales list in Settings is enabled.
-     */
-    @VisibleForTesting
-    public boolean isSettingsAppLocalesOptIn() {
-        return FeatureFlagUtils.isEnabled(mContext,
-                FeatureFlagUtils.SETTINGS_APP_LOCALE_OPT_IN_ENABLED);
-    }
-
-    private boolean matchesLocale(HashSet<Locale> supported, LocaleList appLocales) {
-        if (supported.size() <= 0 || appLocales.size() <= 0) {
-            return true;
-        }
-
-        for (int i = 0; i < appLocales.size(); i++) {
-            final Locale appLocale = appLocales.get(i);
-            if (supported.stream().anyMatch(
-                    locale -> LocaleList.matchesLanguageAndScript(locale, appLocale))) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-}
diff --git a/services/core/java/com/android/server/locales/LocaleManagerBackupHelper.java b/services/core/java/com/android/server/locales/LocaleManagerBackupHelper.java
index 898c6f1..6cd2ed4 100644
--- a/services/core/java/com/android/server/locales/LocaleManagerBackupHelper.java
+++ b/services/core/java/com/android/server/locales/LocaleManagerBackupHelper.java
@@ -22,6 +22,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
+import android.app.LocaleConfig;
 import android.app.backup.BackupManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -298,6 +299,16 @@
 
     /**
      * <p><b>Note:</b> This is invoked by service's common monitor
+     * {@link LocaleManagerServicePackageMonitor#onPackageUpdateFinished} when a package is upgraded
+     * on device.
+     */
+    void onPackageUpdateFinished(String packageName, int uid) {
+        int userId = UserHandle.getUserId(uid);
+        cleanApplicationLocalesIfNeeded(packageName, userId);
+    }
+
+    /**
+     * <p><b>Note:</b> This is invoked by service's common monitor
      * {@link LocaleManagerServicePackageMonitor#onPackageDataCleared} when a package's data
      * is cleared.
      */
@@ -608,4 +619,52 @@
             Slog.e(TAG, "failed to commit locale setter info");
         }
     }
+
+    boolean areLocalesSetFromDelegate(@UserIdInt int userId, String packageName) {
+        if (mDelegateAppLocalePackages == null) {
+            Slog.w(TAG, "Failed to persist data into the shared preference!");
+            return false;
+        }
+
+        String user = Integer.toString(userId);
+        Set<String> packageNames = new ArraySet<>(
+                mDelegateAppLocalePackages.getStringSet(user, new ArraySet<>()));
+
+        return packageNames.contains(packageName);
+    }
+
+    /**
+     * When the user has set per-app locales for a specific application from a delegate selector,
+     * and then the LocaleConfig of that application is removed in the upgraded version, the per-app
+     * locales need to be removed or reset to system default locales to avoid the user being unable
+     * to change system locales setting.
+     */
+    private void cleanApplicationLocalesIfNeeded(String packageName, int userId) {
+        if (mDelegateAppLocalePackages == null) {
+            Slog.w(TAG, "Failed to persist data into the shared preference!");
+            return;
+        }
+
+        String user = Integer.toString(userId);
+        Set<String> packageNames = new ArraySet<>(
+                mDelegateAppLocalePackages.getStringSet(user, new ArraySet<>()));
+        try {
+            LocaleList appLocales = mLocaleManagerService.getApplicationLocales(packageName,
+                    userId);
+            if (appLocales.isEmpty() || !packageNames.contains(packageName)) {
+                return;
+            }
+        } catch (RemoteException | IllegalArgumentException e) {
+            Slog.e(TAG, "Exception when getting locales for " + packageName, e);
+            return;
+        }
+
+        try {
+            LocaleConfig localeConfig = new LocaleConfig(
+                    mContext.createPackageContextAsUser(packageName, 0, UserHandle.of(userId)));
+            mLocaleManagerService.removeUnsupportedAppLocales(packageName, userId, localeConfig);
+        } catch (PackageManager.NameNotFoundException e) {
+            Slog.e(TAG, "Can not found the package name : " + packageName + " / " + e);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/locales/LocaleManagerService.java b/services/core/java/com/android/server/locales/LocaleManagerService.java
index 99d30f5..e3a555b 100644
--- a/services/core/java/com/android/server/locales/LocaleManagerService.java
+++ b/services/core/java/com/android/server/locales/LocaleManagerService.java
@@ -129,11 +129,8 @@
 
         mBackupHelper = new LocaleManagerBackupHelper(this,
                 mPackageManager, broadcastHandlerThread);
-        AppUpdateTracker appUpdateTracker =
-                new AppUpdateTracker(mContext, this, mBackupHelper);
-
         mPackageMonitor = new LocaleManagerServicePackageMonitor(mBackupHelper,
-                systemAppUpdateTracker, appUpdateTracker, this);
+                systemAppUpdateTracker, this);
         mPackageMonitor.register(context, broadcastHandlerThread.getLooper(),
                 UserHandle.ALL,
                 true);
@@ -250,7 +247,7 @@
             // set locales if the package name is owned by the app. Next, check if the caller has
             // the necessary permission and set locales.
             boolean isCallerOwner = isPackageOwnedByCaller(appPackageName, userId,
-                    atomRecordForMetrics);
+                    atomRecordForMetrics, null);
             if (!isCallerOwner) {
                 enforceChangeConfigurationPermission(atomRecordForMetrics);
             }
@@ -264,7 +261,7 @@
                 Binder.restoreCallingIdentity(token);
             }
         } finally {
-            logMetric(atomRecordForMetrics);
+            logAppLocalesMetric(atomRecordForMetrics);
         }
     }
 
@@ -355,32 +352,30 @@
     }
 
     /**
-     * Same as {@link LocaleManagerService#isPackageOwnedByCaller(String, int,
-     * AppLocaleChangedAtomRecord)}, but for methods that do not log locale atom.
-     */
-    private boolean isPackageOwnedByCaller(String appPackageName, int userId) {
-        return isPackageOwnedByCaller(appPackageName, userId, /* atomRecordForMetrics= */null);
-    }
-
-    /**
      * Checks if the package is owned by the calling app or not for the given user id.
      *
      * @throws IllegalArgumentException if package not found for given userid
      */
     private boolean isPackageOwnedByCaller(String appPackageName, int userId,
-            @Nullable AppLocaleChangedAtomRecord atomRecordForMetrics) {
+            @Nullable AppLocaleChangedAtomRecord atomRecordForMetrics,
+            @Nullable AppSupportedLocalesChangedAtomRecord appSupportedLocalesChangedAtomRecord) {
         final int uid = getPackageUid(appPackageName, userId);
         if (uid < 0) {
             Slog.w(TAG, "Unknown package " + appPackageName + " for user " + userId);
             if (atomRecordForMetrics != null) {
                 atomRecordForMetrics.setStatus(FrameworkStatsLog
                         .APPLICATION_LOCALES_CHANGED__STATUS__FAILURE_INVALID_TARGET_PACKAGE);
+            } else if (appSupportedLocalesChangedAtomRecord != null) {
+                appSupportedLocalesChangedAtomRecord.setStatus(FrameworkStatsLog
+                        .APP_SUPPORTED_LOCALES_CHANGED__STATUS__FAILURE_INVALID_TARGET_PACKAGE);
             }
             throw new IllegalArgumentException("Unknown package: " + appPackageName
                     + " for user " + userId);
         }
         if (atomRecordForMetrics != null) {
             atomRecordForMetrics.setTargetUid(uid);
+        } else if (appSupportedLocalesChangedAtomRecord != null) {
+            appSupportedLocalesChangedAtomRecord.setTargetUid(uid);
         }
         //Once valid package found, ignore the userId part for validating package ownership
         //as apps with INTERACT_ACROSS_USERS permission could be changing locale for different user.
@@ -425,7 +420,7 @@
         // current input method, and that app is querying locales of the current foreground app. If
         // neither conditions matched, check if the caller has the necessary permission and fetch
         // locales.
-        if (!isPackageOwnedByCaller(appPackageName, userId)
+        if (!isPackageOwnedByCaller(appPackageName, userId, null, null)
                 && !isCallerInstaller(appPackageName, userId)
                 && !(isCallerFromCurrentInputMethod(userId)
                     && mActivityManagerInternal.isAppForeground(
@@ -550,13 +545,14 @@
         return systemLocales;
     }
 
-    private void logMetric(@NonNull AppLocaleChangedAtomRecord atomRecordForMetrics) {
+    private void logAppLocalesMetric(@NonNull AppLocaleChangedAtomRecord atomRecordForMetrics) {
         FrameworkStatsLog.write(FrameworkStatsLog.APPLICATION_LOCALES_CHANGED,
                 atomRecordForMetrics.mCallingUid,
                 atomRecordForMetrics.mTargetUid,
                 atomRecordForMetrics.mNewLocales,
                 atomRecordForMetrics.mPrevLocales,
-                atomRecordForMetrics.mStatus);
+                atomRecordForMetrics.mStatus,
+                atomRecordForMetrics.mCaller);
     }
 
     /**
@@ -569,49 +565,74 @@
             return;
         }
 
-        requireNonNull(appPackageName);
-
-        //Allow apps with INTERACT_ACROSS_USERS permission to set locales for different user.
-        userId = mActivityManagerInternal.handleIncomingUser(
-                Binder.getCallingPid(), Binder.getCallingUid(), userId,
-                false /* allowAll */, ActivityManagerInternal.ALLOW_NON_FULL,
-                "setOverrideLocaleConfig", /* callerPackage= */ null);
-
-        // This function handles two types of set operations:
-        // 1.) A normal, an app overrides its own LocaleConfig.
-        // 2.) A privileged system application or service is granted the necessary permission to
-        // override a LocaleConfig of another package.
-        if (!isPackageOwnedByCaller(appPackageName, userId)) {
-            enforceSetAppSpecificLocaleConfigPermission();
-        }
-
-        final long token = Binder.clearCallingIdentity();
+        AppSupportedLocalesChangedAtomRecord atomRecord = new AppSupportedLocalesChangedAtomRecord(
+                Binder.getCallingUid());
         try {
-            setOverrideLocaleConfigUnchecked(appPackageName, userId, localeConfig);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
+            requireNonNull(appPackageName);
 
-        //TODO: Add metrics to monitor the usage by applications
+            //Allow apps with INTERACT_ACROSS_USERS permission to set locales for different user.
+            userId = mActivityManagerInternal.handleIncomingUser(
+                    Binder.getCallingPid(), Binder.getCallingUid(), userId,
+                    false /* allowAll */, ActivityManagerInternal.ALLOW_NON_FULL,
+                    "setOverrideLocaleConfig", /* callerPackage= */ null);
+
+            // This function handles two types of set operations:
+            // 1.) A normal, an app overrides its own LocaleConfig.
+            // 2.) A privileged system application or service is granted the necessary permission to
+            // override a LocaleConfig of another package.
+            if (!isPackageOwnedByCaller(appPackageName, userId, null, atomRecord)) {
+                enforceSetAppSpecificLocaleConfigPermission(atomRecord);
+            }
+
+            final long token = Binder.clearCallingIdentity();
+            try {
+                setOverrideLocaleConfigUnchecked(appPackageName, userId, localeConfig, atomRecord);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        } finally {
+            logAppSupportedLocalesChangedMetric(atomRecord);
+        }
     }
+
     private void setOverrideLocaleConfigUnchecked(@NonNull String appPackageName,
-            @UserIdInt int userId, @Nullable LocaleConfig overridelocaleConfig) {
+            @UserIdInt int userId, @Nullable LocaleConfig overrideLocaleConfig,
+            @NonNull AppSupportedLocalesChangedAtomRecord atomRecord) {
         synchronized (mWriteLock) {
             if (DEBUG) {
                 Slog.d(TAG,
                         "set the override LocaleConfig for package " + appPackageName + " and user "
                                 + userId);
             }
+            LocaleConfig resLocaleConfig = null;
+            try {
+                resLocaleConfig = LocaleConfig.fromContextIgnoringOverride(
+                        mContext.createPackageContext(appPackageName, 0));
+            } catch (PackageManager.NameNotFoundException e) {
+                Slog.e(TAG, "Unknown package name " + appPackageName);
+                return;
+            }
             final File file = getXmlFileNameForUser(appPackageName, userId);
 
-            if (overridelocaleConfig == null) {
+            if (overrideLocaleConfig == null) {
                 if (file.exists()) {
                     Slog.d(TAG, "remove the override LocaleConfig");
                     file.delete();
                 }
+                removeUnsupportedAppLocales(appPackageName, userId, resLocaleConfig);
+                atomRecord.setOverrideRemoved(true);
+                atomRecord.setStatus(FrameworkStatsLog
+                        .APP_SUPPORTED_LOCALES_CHANGED__STATUS__SUCCESS);
                 return;
             } else {
-                LocaleList localeList = overridelocaleConfig.getSupportedLocales();
+                if (overrideLocaleConfig.isSameLocaleConfig(
+                        getOverrideLocaleConfig(appPackageName, userId))) {
+                    Slog.d(TAG, "the same override, ignore it");
+                    atomRecord.setSameAsPrevConfig(true);
+                    return;
+                }
+
+                LocaleList localeList = overrideLocaleConfig.getSupportedLocales();
                 // Normally the LocaleList object should not be null. However we reassign it as the
                 // empty list in case it happens.
                 if (localeList == null) {
@@ -621,6 +642,7 @@
                     Slog.d(TAG,
                             "setOverrideLocaleConfig, localeList: " + localeList.toLanguageTags());
                 }
+                atomRecord.setNumLocales(localeList.size());
 
                 // Store the override LocaleConfig to the file storage.
                 final AtomicFile atomicFile = new AtomicFile(file);
@@ -633,11 +655,19 @@
                     if (stream != null) {
                         atomicFile.failWrite(stream);
                     }
+                    atomRecord.setStatus(FrameworkStatsLog
+                            .APP_SUPPORTED_LOCALES_CHANGED__STATUS__FAILURE_WRITE_TO_STORAGE);
                     return;
                 }
                 atomicFile.finishWrite(stream);
                 // Clear per-app locales if they are not in the override LocaleConfig.
-                removeUnsupportedAppLocales(appPackageName, userId, overridelocaleConfig);
+                removeUnsupportedAppLocales(appPackageName, userId, overrideLocaleConfig);
+                if (overrideLocaleConfig.isSameLocaleConfig(resLocaleConfig)) {
+                    Slog.d(TAG, "setOverrideLocaleConfig, same as the app's LocaleConfig");
+                    atomRecord.setSameAsResConfig(true);
+                }
+                atomRecord.setStatus(FrameworkStatsLog
+                        .APP_SUPPORTED_LOCALES_CHANGED__STATUS__SUCCESS);
                 if (DEBUG) {
                     Slog.i(TAG, "Successfully written to " + atomicFile);
                 }
@@ -646,23 +676,29 @@
     }
 
     /**
-     * Checks if the per-app locales are in the new override LocaleConfig. Per-app locales
-     * missing from the new LocaleConfig will be removed.
+     * Checks if the per-app locales are in the LocaleConfig. Per-app locales missing from the
+     * LocaleConfig will be removed.
      */
-    private void removeUnsupportedAppLocales(String appPackageName, int userId,
+    void removeUnsupportedAppLocales(String appPackageName, int userId,
             LocaleConfig localeConfig) {
         LocaleList appLocales = getApplicationLocalesUnchecked(appPackageName, userId);
-        // Remove the app locale from the locale list if it doesn't exist in the override
-        // LocaleConfig.
+        // Remove the per-app locales from the locale list if they don't exist in the LocaleConfig.
         boolean resetAppLocales = false;
         List<Locale> newAppLocales = new ArrayList<Locale>();
-        for (int i = 0; i < appLocales.size(); i++) {
-            if (!localeConfig.containsLocale(appLocales.get(i))) {
-                Slog.i(TAG, "reset the app locales");
-                resetAppLocales = true;
-                continue;
+
+        if (localeConfig == null) {
+            //Reset the app locales to the system default
+            Slog.i(TAG, "There is no LocaleConfig, reset app locales");
+            resetAppLocales = true;
+        } else {
+            for (int i = 0; i < appLocales.size(); i++) {
+                if (!localeConfig.containsLocale(appLocales.get(i))) {
+                    Slog.i(TAG, "Missing from the LocaleConfig, reset app locales");
+                    resetAppLocales = true;
+                    continue;
+                }
+                newAppLocales.add(appLocales.get(i));
             }
-            newAppLocales.add(appLocales.get(i));
         }
 
         if (resetAppLocales) {
@@ -670,17 +706,25 @@
             Locale[] locales = new Locale[newAppLocales.size()];
             try {
                 setApplicationLocales(appPackageName, userId,
-                        new LocaleList(newAppLocales.toArray(locales)), false);
+                        new LocaleList(newAppLocales.toArray(locales)),
+                        mBackupHelper.areLocalesSetFromDelegate(userId, appPackageName));
             } catch (RemoteException | IllegalArgumentException e) {
                 Slog.e(TAG, "Could not set locales for " + appPackageName, e);
             }
         }
     }
 
-    private void enforceSetAppSpecificLocaleConfigPermission() {
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.SET_APP_SPECIFIC_LOCALECONFIG,
-                "setOverrideLocaleConfig");
+    private void enforceSetAppSpecificLocaleConfigPermission(
+            AppSupportedLocalesChangedAtomRecord atomRecord) {
+        try {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.SET_APP_SPECIFIC_LOCALECONFIG,
+                    "setOverrideLocaleConfig");
+        } catch (SecurityException e) {
+            atomRecord.setStatus(FrameworkStatsLog
+                    .APP_SUPPORTED_LOCALES_CHANGED__STATUS__FAILURE_PERMISSION_ABSENT);
+            throw e;
+        }
     }
 
     /**
@@ -793,7 +837,19 @@
     @NonNull
     private File getXmlFileNameForUser(@NonNull String appPackageName, @UserIdInt int userId) {
         // TODO(b/262752965): use per-package data directory
-        final File dir = new File(Environment.getDataSystemDeDirectory(userId), LOCALE_CONFIGS);
+        final File dir = new File(Environment.getDataSystemCeDirectory(userId), LOCALE_CONFIGS);
         return new File(dir, appPackageName + SUFFIX_FILE_NAME);
     }
+
+    private void logAppSupportedLocalesChangedMetric(
+            @NonNull AppSupportedLocalesChangedAtomRecord atomRecord) {
+        FrameworkStatsLog.write(FrameworkStatsLog.APP_SUPPORTED_LOCALES_CHANGED,
+                atomRecord.mCallingUid,
+                atomRecord.mTargetUid,
+                atomRecord.mNumLocales,
+                atomRecord.mOverrideRemoved,
+                atomRecord.mSameAsResConfig,
+                atomRecord.mSameAsPrevConfig,
+                atomRecord.mStatus);
+    }
 }
diff --git a/services/core/java/com/android/server/locales/LocaleManagerServicePackageMonitor.java b/services/core/java/com/android/server/locales/LocaleManagerServicePackageMonitor.java
index 771e1b0..ecd3614 100644
--- a/services/core/java/com/android/server/locales/LocaleManagerServicePackageMonitor.java
+++ b/services/core/java/com/android/server/locales/LocaleManagerServicePackageMonitor.java
@@ -37,16 +37,13 @@
 final class LocaleManagerServicePackageMonitor extends PackageMonitor {
     private LocaleManagerBackupHelper mBackupHelper;
     private SystemAppUpdateTracker mSystemAppUpdateTracker;
-    private AppUpdateTracker mAppUpdateTracker;
     private LocaleManagerService mLocaleManagerService;
 
     LocaleManagerServicePackageMonitor(@NonNull LocaleManagerBackupHelper localeManagerBackupHelper,
             @NonNull SystemAppUpdateTracker systemAppUpdateTracker,
-            @NonNull AppUpdateTracker appUpdateTracker,
             @NonNull LocaleManagerService localeManagerService) {
         mBackupHelper = localeManagerBackupHelper;
         mSystemAppUpdateTracker = systemAppUpdateTracker;
-        mAppUpdateTracker = appUpdateTracker;
         mLocaleManagerService = localeManagerService;
     }
 
@@ -68,7 +65,7 @@
 
     @Override
     public void onPackageUpdateFinished(String packageName, int uid) {
-        mAppUpdateTracker.onPackageUpdateFinished(packageName, uid);
+        mBackupHelper.onPackageUpdateFinished(packageName, uid);
         mSystemAppUpdateTracker.onPackageUpdateFinished(packageName, uid);
     }
 }
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubService.java b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
index 94f12dd..653b718 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
@@ -1148,7 +1148,7 @@
         super.getPreloadedNanoAppIds_enforcePermission();
         Objects.requireNonNull(hubInfo, "hubInfo cannot be null");
 
-        long[] nanoappIds = mContextHubWrapper.getPreloadedNanoappIds();
+        long[] nanoappIds = mContextHubWrapper.getPreloadedNanoappIds(hubInfo.getId());
         if (nanoappIds == null) {
             return new long[0];
         }
@@ -1261,13 +1261,19 @@
             return;
         }
 
-        long[] preloadedNanoappIds = mContextHubWrapper.getPreloadedNanoappIds();
-        if (preloadedNanoappIds == null) {
-            return;
-        }
-        for (long preloadedNanoappId : preloadedNanoappIds) {
-            pw.print("ID: 0x");
-            pw.println(Long.toHexString(preloadedNanoappId));
+        for (int contextHubId: mContextHubIdToInfoMap.keySet()) {
+            long[] preloadedNanoappIds = mContextHubWrapper.getPreloadedNanoappIds(contextHubId);
+            if (preloadedNanoappIds == null) {
+                return;
+            }
+
+            pw.print("Context Hub (id=");
+            pw.print(contextHubId);
+            pw.println("):");
+            for (long preloadedNanoappId : preloadedNanoappIds) {
+                pw.print("  ID: 0x");
+                pw.println(Long.toHexString(preloadedNanoappId));
+            }
         }
     }
 
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 ca184ee..eb1a0e2 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.NanSessionRequest;
 import android.hardware.contexthub.V1_0.ContextHub;
 import android.hardware.contexthub.V1_0.ContextHubMsg;
 import android.hardware.contexthub.V1_0.TransactionResult;
@@ -362,9 +363,11 @@
      * Provides the list of preloaded nanoapp IDs on the system. The output of this API must
      * not change.
      *
-     * @return The list of preloaded nanoapp IDs
+     * @param contextHubId  The context Hub ID.
+     *
+     * @return The list of preloaded nanoapp IDs.
      */
-    public abstract long[] getPreloadedNanoappIds();
+    public abstract long[] getPreloadedNanoappIds(int contextHubId);
 
     /**
      * Registers a callback with the Context Hub.
@@ -456,8 +459,8 @@
                 });
             }
 
-            public void handleNanSessionRequest(boolean enable) {
-                // TODO(229888878): Implement
+            public void handleNanSessionRequest(NanSessionRequest request) {
+                // TODO(271471342): Implement
             }
 
             @Override
@@ -713,14 +716,14 @@
             }
         }
 
-        public long[] getPreloadedNanoappIds() {
+        public long[] getPreloadedNanoappIds(int contextHubId) {
             android.hardware.contexthub.IContextHub hub = getHub();
             if (hub == null) {
                 return null;
             }
 
             try {
-                return hub.getPreloadedNanoappIds();
+                return hub.getPreloadedNanoappIds(contextHubId);
             } catch (RemoteException e) {
                 Log.e(TAG, "Exception while getting preloaded nanoapp IDs: " + e.getMessage());
                 return null;
@@ -923,7 +926,7 @@
                     mHub.queryApps(contextHubId));
         }
 
-        public long[] getPreloadedNanoappIds() {
+        public long[] getPreloadedNanoappIds(int contextHubId) {
             return new long[0];
         }
 
diff --git a/services/core/java/com/android/server/location/gnss/GnssManagerService.java b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
index 2174f40..c962bc4 100644
--- a/services/core/java/com/android/server/location/gnss/GnssManagerService.java
+++ b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
@@ -295,6 +295,7 @@
         }
 
         ipw.println("Capabilities: " + mGnssNative.getCapabilities());
+        ipw.println("GNSS Hardware Model Name: " + getGnssHardwareModelName());
 
         if (mGnssStatusProvider.isSupported()) {
             ipw.println("Status Provider:");
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 0c69855..2b5f874 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -33,7 +33,6 @@
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN;
-import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PIN;
 import static com.android.internal.widget.LockPatternUtils.CURRENT_LSKF_BASED_PROTECTOR_ID_KEY;
 import static com.android.internal.widget.LockPatternUtils.EscrowTokenStateChangeCallback;
@@ -57,7 +56,7 @@
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.app.RemoteLockscreenValidationResult;
-import android.app.StartLockscreenValidationRequest;
+import android.app.RemoteLockscreenValidationSession;
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.app.admin.DeviceStateCache;
@@ -82,7 +81,6 @@
 import android.hardware.fingerprint.FingerprintManager;
 import android.net.Uri;
 import android.os.Binder;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -117,7 +115,6 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.EventLog;
-import android.util.Log;
 import android.util.LongSparseArray;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -201,7 +198,6 @@
     private static final String TAG = "LockSettingsService";
     private static final String PERMISSION = ACCESS_KEYGUARD_SECURE_STORAGE;
     private static final String BIOMETRIC_PERMISSION = MANAGE_BIOMETRIC;
-    private static final boolean DEBUG = Build.IS_DEBUGGABLE && Log.isLoggable(TAG, Log.DEBUG);
 
     private static final int PROFILE_KEY_IV_SIZE = 12;
     private static final String SEPARATE_PROFILE_CHALLENGE_KEY = "lockscreen.profilechallenge";
@@ -381,7 +377,6 @@
      */
     private void tieProfileLockIfNecessary(int profileUserId,
             LockscreenCredential profileUserPassword) {
-        if (DEBUG) Slog.v(TAG, "Check child profile lock for user: " + profileUserId);
         // Only for profiles that shares credential with parent
         if (!isCredentialSharableWithParent(profileUserId)) {
             return;
@@ -399,8 +394,7 @@
         // as its parent.
         final int parentId = mUserManager.getProfileParent(profileUserId).id;
         if (!isUserSecure(parentId) && !profileUserPassword.isNone()) {
-            if (DEBUG) Slog.v(TAG, "Parent does not have a screen lock but profile has one");
-
+            Slogf.i(TAG, "Clearing password for profile user %d to match parent", profileUserId);
             setLockCredentialInternal(LockscreenCredential.createNone(), profileUserPassword,
                     profileUserId, /* isLockTiedToParent= */ true);
             return;
@@ -416,7 +410,6 @@
             Slog.e(TAG, "Failed to talk to GateKeeper service", e);
             return;
         }
-        if (DEBUG) Slog.v(TAG, "Tie profile to parent now!");
         try (LockscreenCredential unifiedProfilePassword = generateRandomProfilePassword()) {
             setLockCredentialInternal(unifiedProfilePassword, profileUserPassword, profileUserId,
                     /* isLockTiedToParent= */ true);
@@ -428,6 +421,8 @@
     static class Injector {
 
         protected Context mContext;
+        private ServiceThread mHandlerThread;
+        private Handler mHandler;
 
         public Injector(Context context) {
             mContext = context;
@@ -438,14 +433,20 @@
         }
 
         public ServiceThread getServiceThread() {
-            ServiceThread handlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND,
-                    true /*allowIo*/);
-            handlerThread.start();
-            return handlerThread;
+            if (mHandlerThread == null) {
+                mHandlerThread = new ServiceThread(TAG,
+                        Process.THREAD_PRIORITY_BACKGROUND,
+                        true /*allowIo*/);
+                mHandlerThread.start();
+            }
+            return mHandlerThread;
         }
 
         public Handler getHandler(ServiceThread handlerThread) {
-            return new Handler(handlerThread.getLooper());
+            if (mHandler == null) {
+                mHandler = new Handler(handlerThread.getLooper());
+            }
+            return mHandler;
         }
 
         public LockSettingsStorage getStorage() {
@@ -526,7 +527,8 @@
 
         public RebootEscrowManager getRebootEscrowManager(RebootEscrowManager.Callbacks callbacks,
                 LockSettingsStorage storage) {
-            return new RebootEscrowManager(mContext, callbacks, storage);
+            return new RebootEscrowManager(mContext, callbacks, storage,
+                    getHandler(getServiceThread()));
         }
 
         public int binderGetCallingUid() {
@@ -690,8 +692,8 @@
         PendingIntent intent = PendingIntent.getActivity(mContext, 0, unlockIntent,
                 PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
 
-        Slog.d(TAG, TextUtils.formatSimple("showing encryption notification, user: %d; reason: %s",
-                user.getIdentifier(), reason));
+        Slogf.d(TAG, "Showing encryption notification for user %d; reason: %s",
+                user.getIdentifier(), reason);
 
         showEncryptionNotification(user, title, message, detail, intent);
     }
@@ -735,7 +737,7 @@
     }
 
     private void hideEncryptionNotification(UserHandle userHandle) {
-        Slog.d(TAG, "hide encryption notification, user: " + userHandle.getIdentifier());
+        Slogf.d(TAG, "Hiding encryption notification for user %d", userHandle.getIdentifier());
         mNotificationManager.cancelAsUser(null, SystemMessage.NOTE_FBE_ENCRYPTED_NOTIFICATION,
             userHandle);
     }
@@ -888,7 +890,6 @@
                 && !getBoolean("migrated_frp", false, 0)) {
             migrateFrpCredential();
             setBoolean("migrated_frp", true, 0);
-            Slog.i(TAG, "Migrated migrated_frp.");
         }
     }
 
@@ -1034,7 +1035,7 @@
     private void enforceFrpResolved() {
         final int mainUserId = mInjector.getUserManagerInternal().getMainUserId();
         if (mainUserId < 0) {
-            Slog.i(TAG, "No Main user on device; skip enforceFrpResolved");
+            Slog.d(TAG, "No Main user on device; skipping enforceFrpResolved");
             return;
         }
         final ContentResolver cr = mContext.getContentResolver();
@@ -1065,18 +1066,7 @@
         mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsHave");
     }
 
-    private static final String[] UNPROTECTED_SETTINGS = {
-        // These three LOCK_PATTERN_* settings have traditionally been readable via the public API
-        // android.provider.Settings.{System,Secure}.getString() without any permission.
-        Settings.Secure.LOCK_PATTERN_ENABLED,
-        Settings.Secure.LOCK_PATTERN_VISIBLE,
-        Settings.Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED,
-    };
-
     private final void checkDatabaseReadPermission(String requestedKey, int userId) {
-        if (ArrayUtils.contains(UNPROTECTED_SETTINGS, requestedKey)) {
-            return;
-        }
         if (!hasPermission(PERMISSION)) {
             throw new SecurityException("uid=" + getCallingUid() + " needs permission "
                     + PERMISSION + " to read " + requestedKey + " for user " + userId);
@@ -1190,9 +1180,6 @@
     @Override
     public boolean getBoolean(String key, boolean defaultValue, int userId) {
         checkDatabaseReadPermission(key, userId);
-        if (Settings.Secure.LOCK_PATTERN_ENABLED.equals(key)) {
-            return getCredentialTypeInternal(userId) == CREDENTIAL_TYPE_PATTERN;
-        }
         return mStorage.getBoolean(key, defaultValue, userId);
     }
 
@@ -1283,7 +1270,6 @@
     }
 
     private void unlockKeystore(byte[] password, int userHandle) {
-        if (DEBUG) Slog.v(TAG, "Unlock keystore for user: " + userHandle);
         Authorization.onLockScreenEvent(false, userHandle, password, null);
     }
 
@@ -1293,7 +1279,7 @@
             NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
             InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException,
             CertificateException, IOException {
-        if (DEBUG) Slog.v(TAG, "Get child profile decrypted key");
+        Slogf.d(TAG, "Decrypting password for tied profile %d", userId);
         byte[] storedData = mStorage.readChildProfileLock(userId);
         if (storedData == null) {
             throw new FileNotFoundException("Child profile lock file not found");
@@ -1342,7 +1328,6 @@
      * {@link com.android.server.SystemServiceManager#unlockUser} </em>
      */
     private void unlockUser(@UserIdInt int userId) {
-        Slogf.i(TAG, "Unlocking user %d", userId);
         // TODO: make this method fully async so we can update UI with progress strings
         final boolean alreadyUnlocked = mUserManager.isUserUnlockingOrUnlocked(userId);
         final CountDownLatch latch = new CountDownLatch(1);
@@ -1652,7 +1637,6 @@
             LockscreenCredential savedCredential, int userId, boolean isLockTiedToParent) {
         Objects.requireNonNull(credential);
         Objects.requireNonNull(savedCredential);
-        if (DEBUG) Slog.d(TAG, "setLockCredentialInternal: user=" + userId);
         synchronized (mSpManager) {
             if (savedCredential.isNone() && isProfileWithUnifiedLock(userId)) {
                 // get credential from keystore when profile has unified lock
@@ -1734,6 +1718,7 @@
         if (passwordHistoryLength == 0) {
             passwordHistory = "";
         } else {
+            Slogf.d(TAG, "Adding new password to password history for user %d", userHandle);
             final byte[] hashFactor = getHashFactor(password, userHandle);
             final byte[] salt = getSalt(userHandle).getBytes();
             String hash = password.passwordToHistoryHash(salt, hashFactor);
@@ -1765,7 +1750,6 @@
         if (salt == 0) {
             salt = SecureRandomUtils.randomLong();
             setLong(LockPatternUtils.LOCK_PASSWORD_SALT_KEY, salt, userId);
-            Slog.v(TAG, "Initialized lock password salt for user: " + userId);
         }
         return Long.toHexString(salt);
     }
@@ -1889,7 +1873,8 @@
     @VisibleForTesting /** Note: this method is overridden in unit tests */
     protected void tieProfileLockToParent(int profileUserId, int parentUserId,
             LockscreenCredential password) {
-        if (DEBUG) Slog.v(TAG, "tieProfileLockToParent for user: " + profileUserId);
+        Slogf.i(TAG, "Tying lock for profile user %d to parent user %d", profileUserId,
+                parentUserId);
         final byte[] iv;
         final byte[] ciphertext;
         final long parentSid;
@@ -2016,7 +2001,7 @@
     @Override
     public void resetKeyStore(int userId) {
         checkWritePermission();
-        if (DEBUG) Slog.v(TAG, "Reset keystore for user: " + userId);
+        Slogf.d(TAG, "Resetting keystore for user %d", userId);
         List<Integer> profileUserIds = new ArrayList<>();
         List<LockscreenCredential> profileUserDecryptedPasswords = new ArrayList<>();
         final List<UserInfo> profiles = mUserManager.getProfiles(userId);
@@ -2053,7 +2038,6 @@
                 int piUserId = profileUserIds.get(i);
                 LockscreenCredential piUserDecryptedPassword = profileUserDecryptedPasswords.get(i);
                 if (piUserId != -1 && piUserDecryptedPassword != null) {
-                    if (DEBUG) Slog.v(TAG, "Restore tied profile lock");
                     tieProfileLockToParent(piUserId, userId, piUserDecryptedPassword);
                 }
                 if (piUserDecryptedPassword != null) {
@@ -2146,7 +2130,7 @@
             Slog.e(TAG, "FRP credential can only be verified prior to provisioning.");
             return VerifyCredentialResponse.ERROR;
         }
-        Slog.d(TAG, "doVerifyCredential: user=" + userId);
+        Slogf.i(TAG, "Verifying lockscreen credential for user %d", userId);
 
         final AuthenticationResult authResult;
         VerifyCredentialResponse response;
@@ -2180,6 +2164,7 @@
             }
         }
         if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
+            Slogf.i(TAG, "Successfully verified lockscreen credential for user %d", userId);
             onCredentialVerified(authResult.syntheticPassword,
                     PasswordMetrics.computeForCredential(credential), userId);
             if ((flags & VERIFY_FLAG_REQUEST_GK_PW_HANDLE) != 0) {
@@ -2338,13 +2323,18 @@
     }
 
     private void removeKeystoreProfileKey(int targetUserId) {
-        Slog.i(TAG, "Remove keystore profile key for user: " + targetUserId);
+        final String encryptAlias = PROFILE_KEY_NAME_ENCRYPT + targetUserId;
+        final String decryptAlias = PROFILE_KEY_NAME_DECRYPT + targetUserId;
         try {
-            mJavaKeyStore.deleteEntry(PROFILE_KEY_NAME_ENCRYPT + targetUserId);
-            mJavaKeyStore.deleteEntry(PROFILE_KEY_NAME_DECRYPT + targetUserId);
+            if (mJavaKeyStore.containsAlias(encryptAlias) ||
+                    mJavaKeyStore.containsAlias(decryptAlias)) {
+                Slogf.i(TAG, "Removing keystore profile key for user %d", targetUserId);
+                mJavaKeyStore.deleteEntry(encryptAlias);
+                mJavaKeyStore.deleteEntry(decryptAlias);
+            }
         } catch (KeyStoreException e) {
-            // We have tried our best to remove all keys
-            Slog.e(TAG, "Unable to remove keystore profile key for user:" + targetUserId, e);
+            // We have tried our best to remove the key.
+            Slogf.e(TAG, e, "Error removing keystore profile key for user %d", targetUserId);
         }
     }
 
@@ -2533,7 +2523,7 @@
      * Starts a session to verify lock screen credentials provided by a remote device.
      */
     @NonNull
-    public StartLockscreenValidationRequest startRemoteLockscreenValidation() {
+    public RemoteLockscreenValidationSession startRemoteLockscreenValidation() {
         return mRecoverableKeyStoreManager.startRemoteLockscreenValidation(this);
     }
 
@@ -2692,7 +2682,7 @@
     @VisibleForTesting
     SyntheticPassword initializeSyntheticPassword(int userId) {
         synchronized (mSpManager) {
-            Slog.i(TAG, "Initialize SyntheticPassword for user: " + userId);
+            Slogf.i(TAG, "Initializing synthetic password for user %d", userId);
             Preconditions.checkState(getCurrentLskfBasedProtectorId(userId) ==
                     SyntheticPasswordManager.NULL_PROTECTOR_ID,
                     "Cannot reinitialize SP");
@@ -2703,6 +2693,7 @@
             setCurrentLskfBasedProtectorId(protectorId, userId);
             setUserKeyProtection(userId, sp.deriveFileBasedEncryptionKey());
             onSyntheticPasswordCreated(userId, sp);
+            Slogf.i(TAG, "Successfully initialized synthetic password for user %d", userId);
             return sp;
         }
     }
@@ -2739,8 +2730,11 @@
         final long finalHandle = handle;
         mHandler.postDelayed(() -> {
             synchronized (mGatekeeperPasswords) {
-                Slog.d(TAG, "Removing handle: " + finalHandle);
-                mGatekeeperPasswords.remove(finalHandle);
+                if (mGatekeeperPasswords.get(finalHandle) != null) {
+                    Slogf.d(TAG, "Cached Gatekeeper password with handle %016x has expired",
+                            finalHandle);
+                    mGatekeeperPasswords.remove(finalHandle);
+                }
             }
         }, GK_PW_HANDLE_STORE_DURATION_MS);
 
@@ -2789,7 +2783,8 @@
     @GuardedBy("mSpManager")
     private long setLockCredentialWithSpLocked(LockscreenCredential credential,
             SyntheticPassword sp, int userId) {
-        if (DEBUG) Slog.d(TAG, "setLockCredentialWithSpLocked: user=" + userId);
+        Slogf.i(TAG, "Changing lockscreen credential of user %d; newCredentialType=%s\n",
+                userId, LockPatternUtils.credentialTypeToString(credential.getType()));
         final int savedCredentialType = getCredentialTypeInternal(userId);
         final long oldProtectorId = getCurrentLskfBasedProtectorId(userId);
         final long newProtectorId = mSpManager.createLskfBasedProtector(getGateKeeperService(),
@@ -2834,6 +2829,7 @@
             }
         }
         mSpManager.destroyLskfBasedProtector(oldProtectorId, userId);
+        Slogf.i(TAG, "Successfully changed lockscreen credential of user %d", userId);
         return newProtectorId;
     }
 
@@ -2918,6 +2914,7 @@
     public byte[] getHashFactor(LockscreenCredential currentCredential, int userId) {
         checkPasswordReadPermission();
         try {
+            Slogf.d(TAG, "Getting password history hash factor for user %d", userId);
             if (isProfileWithUnifiedLock(userId)) {
                 try {
                     currentCredential = getDecryptedPasswordForTiedProfile(userId);
@@ -2943,7 +2940,7 @@
 
     private long addEscrowToken(@NonNull byte[] token, @TokenType int type, int userId,
             @NonNull EscrowTokenStateChangeCallback callback) {
-        if (DEBUG) Slog.d(TAG, "addEscrowToken: user=" + userId + ", type=" + type);
+        Slogf.i(TAG, "Adding escrow token for user %d", userId);
         synchronized (mSpManager) {
             // If the user has no LSKF, then the token can be activated immediately.  Otherwise, the
             // token can't be activated until the SP is unlocked by another protector (normally the
@@ -2961,18 +2958,20 @@
             long handle = mSpManager.addPendingToken(token, type, userId, callback);
             if (sp != null) {
                 // Activate the token immediately
+                Slogf.i(TAG, "Immediately activating escrow token %016x", handle);
                 mSpManager.createTokenBasedProtector(handle, sp, userId);
+            } else {
+                Slogf.i(TAG, "Escrow token %016x will be activated when user is unlocked", handle);
             }
             return handle;
         }
     }
 
     private void activateEscrowTokens(SyntheticPassword sp, int userId) {
-        if (DEBUG) Slog.d(TAG, "activateEscrowTokens: user=" + userId);
         synchronized (mSpManager) {
             disableEscrowTokenOnNonManagedDevicesIfNeeded(userId);
             for (long handle : mSpManager.getPendingTokensForUser(userId)) {
-                Slog.i(TAG, TextUtils.formatSimple("activateEscrowTokens: %x %d ", handle, userId));
+                Slogf.i(TAG, "Activating escrow token %016x for user %d", handle, userId);
                 mSpManager.createTokenBasedProtector(handle, sp, userId);
             }
         }
@@ -3043,6 +3042,8 @@
     @GuardedBy("mSpManager")
     private boolean setLockCredentialWithTokenInternalLocked(LockscreenCredential credential,
             long tokenHandle, byte[] token, int userId) {
+        Slogf.i(TAG, "Resetting lockscreen credential of user %d using escrow token %016x",
+                userId, tokenHandle);
         final AuthenticationResult result;
         result = mSpManager.unlockTokenBasedProtector(getGateKeeperService(), tokenHandle, token,
                     userId);
@@ -3065,8 +3066,9 @@
     private boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId) {
         AuthenticationResult authResult;
         synchronized (mSpManager) {
+            Slogf.i(TAG, "Unlocking user %d using escrow token %016x", userId, tokenHandle);
             if (!mSpManager.hasEscrowData(userId)) {
-                Slog.w(TAG, "Escrow token is disabled on the current user");
+                Slogf.w(TAG, "Escrow token support is disabled on user %d", userId);
                 return false;
             }
             authResult = mSpManager.unlockTokenBasedProtector(getGateKeeperService(), tokenHandle,
@@ -3077,6 +3079,7 @@
             }
         }
 
+        Slogf.i(TAG, "Unlocked synthetic password for user %d using escrow token", userId);
         onCredentialVerified(authResult.syntheticPassword,
                 loadPasswordMetrics(authResult.syntheticPassword, userId), userId);
         return true;
@@ -3104,24 +3107,19 @@
         return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(timestamp));
     }
 
-    private static String credentialTypeToString(int credentialType) {
-        switch (credentialType) {
-            case CREDENTIAL_TYPE_NONE:
-                return "None";
-            case CREDENTIAL_TYPE_PATTERN:
-                return "Pattern";
-            case CREDENTIAL_TYPE_PIN:
-                return "Pin";
-            case CREDENTIAL_TYPE_PASSWORD:
-                return "Password";
-            default:
-                return "Unknown " + credentialType;
-        }
-    }
-
     @Override
     protected void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, TAG, printWriter)) return;
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            dumpInternal(printWriter);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    private void dumpInternal(PrintWriter printWriter) {
         IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, "  ");
 
         pw.println("Current lock settings service state:");
@@ -3135,22 +3133,23 @@
             pw.println("User " + userId);
             pw.increaseIndent();
             synchronized (mSpManager) {
-                pw.println(TextUtils.formatSimple("LSKF-based SP protector ID: %x",
+                pw.println(TextUtils.formatSimple("LSKF-based SP protector ID: %016x",
                         getCurrentLskfBasedProtectorId(userId)));
-                pw.println(TextUtils.formatSimple("LSKF last changed: %s (previous protector: %x)",
-                        timestampToString(getLong(LSKF_LAST_CHANGED_TIME_KEY, 0, userId)),
-                        getLong(PREV_LSKF_BASED_PROTECTOR_ID_KEY, 0, userId)));
+                pw.println(TextUtils.formatSimple(
+                            "LSKF last changed: %s (previous protector: %016x)",
+                            timestampToString(getLong(LSKF_LAST_CHANGED_TIME_KEY, 0, userId)),
+                            getLong(PREV_LSKF_BASED_PROTECTOR_ID_KEY, 0, userId)));
             }
             try {
-                pw.println(TextUtils.formatSimple("SID: %x",
+                pw.println(TextUtils.formatSimple("SID: %016x",
                         getGateKeeperService().getSecureUserId(userId)));
             } catch (RemoteException e) {
                 // ignore.
             }
-            // It's OK to dump the password type since anyone with physical access can just
+            // It's OK to dump the credential type since anyone with physical access can just
             // observe it from the keyguard directly.
             pw.println("Quality: " + getKeyguardStoredQuality(userId));
-            pw.println("CredentialType: " + credentialTypeToString(
+            pw.println("CredentialType: " + LockPatternUtils.credentialTypeToString(
                     getCredentialTypeInternal(userId)));
             pw.println("SeparateChallenge: " + getSeparateProfileChallengeEnabledInternal(userId));
             pw.println(TextUtils.formatSimple("Metrics: %s",
@@ -3208,6 +3207,11 @@
      * if we are running an automotive build.
      */
     private void disableEscrowTokenOnNonManagedDevicesIfNeeded(int userId) {
+
+        if (!mSpManager.hasAnyEscrowData(userId)) {
+            return;
+        }
+
         // TODO(b/258213147): Remove
         final long identity = Binder.clearCallingIdentity();
         try {
@@ -3252,7 +3256,7 @@
         }
 
         // Disable escrow token permanently on all other device/user types.
-        Slog.i(TAG, "Disabling escrow token on user " + userId);
+        Slogf.i(TAG, "Permanently disabling support for escrow tokens on user %d", userId);
         mSpManager.destroyEscrowData(userId);
     }
 
@@ -3484,6 +3488,7 @@
             synchronized (mSpManager) {
                 mSpManager.verifyChallenge(getGateKeeperService(), sp, 0L, userId);
             }
+            Slogf.i(TAG, "Restored synthetic password for user %d using reboot escrow", userId);
             onCredentialVerified(sp, loadPasswordMetrics(sp, userId), userId);
         }
     }
diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
index 9b42cfc..e1cd2c5 100644
--- a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
+++ b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
@@ -205,6 +205,8 @@
 
     private final RebootEscrowKeyStoreManager mKeyStoreManager;
 
+    private final Handler mHandler;
+
     PowerManager.WakeLock mWakeLock;
 
     private ConnectivityManager.NetworkCallback mNetworkCallback;
@@ -399,19 +401,21 @@
         }
     }
 
-    RebootEscrowManager(Context context, Callbacks callbacks, LockSettingsStorage storage) {
-        this(new Injector(context, storage), callbacks, storage);
+    RebootEscrowManager(Context context, Callbacks callbacks, LockSettingsStorage storage,
+            Handler handler) {
+        this(new Injector(context, storage), callbacks, storage, handler);
     }
 
     @VisibleForTesting
     RebootEscrowManager(Injector injector, Callbacks callbacks,
-            LockSettingsStorage storage) {
+            LockSettingsStorage storage, Handler handler) {
         mInjector = injector;
         mCallbacks = callbacks;
         mStorage = storage;
         mUserManager = injector.getUserManager();
         mEventLog = injector.getEventLog();
         mKeyStoreManager = injector.getKeyStoreManager();
+        mHandler = handler;
     }
 
     /** Wrapper function to set error code serialized through handler, */
@@ -937,7 +941,7 @@
 
     private void setRebootEscrowReady(boolean ready) {
         if (mRebootEscrowReady != ready) {
-            mRebootEscrowListener.onPreparedForReboot(ready);
+            mHandler.post(() -> mRebootEscrowListener.onPreparedForReboot(ready));
         }
         mRebootEscrowReady = ready;
     }
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index d070b41..1663b01 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -744,6 +744,11 @@
                 && hasState(SP_P1_NAME, NULL_PROTECTOR_ID, userId);
     }
 
+    public boolean hasAnyEscrowData(int userId) {
+        return hasState(SP_E0_NAME, NULL_PROTECTOR_ID, userId)
+                || hasState(SP_P1_NAME, NULL_PROTECTOR_ID, userId);
+    }
+
     public void destroyEscrowData(int userId) {
         destroyState(SP_E0_NAME, NULL_PROTECTOR_ID, userId);
         destroyState(SP_P1_NAME, NULL_PROTECTOR_ID, userId);
@@ -786,11 +791,11 @@
             }
             Set<Integer> usedSlots = getUsedWeaverSlots();
             if (!usedSlots.contains(slot)) {
-                Slog.i(TAG, "Destroy weaver slot " + slot + " for user " + userId);
+                Slogf.i(TAG, "Erasing Weaver slot %d", slot);
                 weaverEnroll(slot, null, null);
                 mPasswordSlotManager.markSlotDeleted(slot);
             } else {
-                Slog.w(TAG, "Skip destroying reused weaver slot " + slot + " for user " + userId);
+                Slogf.i(TAG, "Weaver slot %d was already reused; not erasing it", slot);
             }
         }
     }
@@ -858,11 +863,13 @@
         long sid = GateKeeper.INVALID_SECURE_USER_ID;
         final byte[] protectorSecret;
 
+        Slogf.i(TAG, "Creating LSKF-based protector %016x for user %d", protectorId, userId);
+
         if (isWeaverAvailable()) {
             // Weaver is available, so make the protector use it to verify the LSKF.  Do this even
             // if the LSKF is empty, as that gives us support for securely deleting the protector.
             int weaverSlot = getNextAvailableWeaverSlot();
-            Slog.i(TAG, "Weaver enroll password to slot " + weaverSlot + " for user " + userId);
+            Slogf.i(TAG, "Enrolling LSKF for user %d into Weaver slot %d", userId, weaverSlot);
             byte[] weaverSecret = weaverEnroll(weaverSlot, stretchedLskfToWeaverKey(stretchedLskf),
                     null);
             if (weaverSecret == null) {
@@ -892,6 +899,7 @@
                 } catch (RemoteException ignore) {
                     Slog.w(TAG, "Failed to clear SID from gatekeeper");
                 }
+                Slogf.i(TAG, "Enrolling LSKF for user %d into Gatekeeper", userId);
                 GateKeeperResponse response;
                 try {
                     response = gatekeeper.enroll(fakeUserId(userId), null, null,
@@ -964,6 +972,7 @@
                 && LockPatternUtils.userOwnsFrpCredential(mContext, userInfo)
                 && getCredentialType(protectorId, userInfo.id) !=
                         LockPatternUtils.CREDENTIAL_TYPE_NONE) {
+            Slog.i(TAG, "Migrating FRP credential to persistent data block");
             PasswordData pwd = PasswordData.fromBytes(loadState(PASSWORD_DATA_NAME, protectorId,
                     userInfo.id));
             int weaverSlot = loadWeaverSlot(protectorId, userInfo.id);
@@ -1092,9 +1101,10 @@
             Slog.w(TAG, "User is not escrowable");
             return false;
         }
+        Slogf.i(TAG, "Creating token-based protector %016x for user %d", tokenHandle, userId);
         if (isWeaverAvailable()) {
             int slot = getNextAvailableWeaverSlot();
-            Slog.i(TAG, "Weaver enroll token to slot " + slot + " for user " + userId);
+            Slogf.i(TAG, "Using Weaver slot %d for new token-based protector", slot);
             if (weaverEnroll(slot, null, tokenData.weaverSecret) == null) {
                 Slog.e(TAG, "Failed to enroll weaver secret when activating token");
                 return false;
@@ -1170,8 +1180,9 @@
             storedType = pwd.credentialType;
         }
         if (!credential.checkAgainstStoredType(storedType)) {
-            Slog.e(TAG, TextUtils.formatSimple("Credential type mismatch: expected %d actual %d",
-                    storedType, credential.getType()));
+            Slogf.e(TAG, "Credential type mismatch: stored type is %s but provided type is %s",
+                    LockPatternUtils.credentialTypeToString(storedType),
+                    LockPatternUtils.credentialTypeToString(credential.getType()));
             result.gkResponse = VerifyCredentialResponse.ERROR;
             return result;
         }
@@ -1473,6 +1484,7 @@
 
     /** Destroy a token-based SP protector. */
     public void destroyTokenBasedProtector(long protectorId, int userId) {
+        Slogf.i(TAG, "Destroying token-based protector %016x for user %d", protectorId, userId);
         SyntheticPasswordBlob blob = SyntheticPasswordBlob.fromBytes(loadState(SP_BLOB_NAME,
                     protectorId, userId));
         destroyProtectorCommon(protectorId, userId);
@@ -1498,6 +1510,7 @@
      * Destroy an LSKF-based SP protector.  This is used when the user's LSKF is changed.
      */
     public void destroyLskfBasedProtector(long protectorId, int userId) {
+        Slogf.i(TAG, "Destroying LSKF-based protector %016x for user %d", protectorId, userId);
         destroyProtectorCommon(protectorId, userId);
         destroyState(PASSWORD_DATA_NAME, protectorId, userId);
         destroyState(PASSWORD_METRICS_NAME, protectorId, userId);
@@ -1658,6 +1671,9 @@
     }
 
     private String getProtectorKeyAlias(long protectorId) {
+        // Note, this arguably has a bug: %x should be %016x so that the protector ID is left-padded
+        // with zeroes, like how the synthetic password state files are named.  It's too late to fix
+        // this, though, and it doesn't actually matter.
         return TextUtils.formatSimple("%s%x", PROTECTOR_KEY_ALIAS_PREFIX, protectorId);
     }
 
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 c08958b..f073756 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -31,7 +31,7 @@
 import android.app.KeyguardManager;
 import android.app.PendingIntent;
 import android.app.RemoteLockscreenValidationResult;
-import android.app.StartLockscreenValidationRequest;
+import android.app.RemoteLockscreenValidationSession;
 import android.content.Context;
 import android.os.Binder;
 import android.os.RemoteException;
@@ -999,7 +999,7 @@
     /**
      * Starts a session to verify lock screen credentials provided by a remote device.
      */
-    public StartLockscreenValidationRequest startRemoteLockscreenValidation(
+    public RemoteLockscreenValidationSession startRemoteLockscreenValidation(
             LockSettingsService lockSettingsService) {
         if (mRemoteLockscreenValidationSessionStorage == null) {
             throw new UnsupportedOperationException("Under development");
@@ -1021,8 +1021,8 @@
         int badGuesses = mDatabase.getBadRemoteGuessCounter(userId);
         int remainingAttempts = Math.max(INVALID_REMOTE_GUESS_LIMIT - badGuesses, 0);
         // TODO(b/254335492): Schedule task to remove inactive session
-        return new StartLockscreenValidationRequest.Builder()
-                .setLockscreenUiType(keyguardCredentialsType)
+        return new RemoteLockscreenValidationSession.Builder()
+                .setLockType(keyguardCredentialsType)
                 .setRemainingAttempts(remainingAttempts)
                 .setSourcePublicKey(encodedPublicKey)
                 .build();
@@ -1046,7 +1046,9 @@
                 .build();
         }
         if (session == null) {
-            throw new IllegalStateException("There is no active lock screen check session");
+            return new RemoteLockscreenValidationResult.Builder()
+                .setResultCode(RemoteLockscreenValidationResult.RESULT_SESSION_EXPIRED)
+                .build();
         }
         byte[] decryptedCredentials;
         try {
diff --git a/services/core/java/com/android/server/media/AudioAttributesUtils.java b/services/core/java/com/android/server/media/AudioAttributesUtils.java
new file mode 100644
index 0000000..b9c9bae
--- /dev/null
+++ b/services/core/java/com/android/server/media/AudioAttributesUtils.java
@@ -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.server.media;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.media.AudioAttributes;
+import android.media.AudioDeviceAttributes;
+import android.media.AudioDeviceInfo;
+import android.media.MediaRoute2Info;
+
+/* package */ final class AudioAttributesUtils {
+
+    /* package */ static final AudioAttributes ATTRIBUTES_MEDIA = new AudioAttributes.Builder()
+            .setUsage(AudioAttributes.USAGE_MEDIA)
+            .build();
+
+    private AudioAttributesUtils() {
+        // no-op to prevent instantiation.
+    }
+
+    @MediaRoute2Info.Type
+    /* package */ static int mapToMediaRouteType(
+            @NonNull AudioDeviceAttributes audioDeviceAttributes) {
+        switch (audioDeviceAttributes.getType()) {
+            case AudioDeviceInfo.TYPE_BUILTIN_EARPIECE:
+            case AudioDeviceInfo.TYPE_BUILTIN_SPEAKER:
+                return MediaRoute2Info.TYPE_BUILTIN_SPEAKER;
+            case AudioDeviceInfo.TYPE_WIRED_HEADSET:
+                return MediaRoute2Info.TYPE_WIRED_HEADSET;
+            case AudioDeviceInfo.TYPE_WIRED_HEADPHONES:
+                return MediaRoute2Info.TYPE_WIRED_HEADPHONES;
+            case AudioDeviceInfo.TYPE_DOCK:
+            case AudioDeviceInfo.TYPE_DOCK_ANALOG:
+                return MediaRoute2Info.TYPE_DOCK;
+            case AudioDeviceInfo.TYPE_HDMI:
+                return MediaRoute2Info.TYPE_HDMI;
+            case AudioDeviceInfo.TYPE_USB_DEVICE:
+                return MediaRoute2Info.TYPE_USB_DEVICE;
+            case AudioDeviceInfo.TYPE_BLUETOOTH_A2DP:
+                return MediaRoute2Info.TYPE_BLUETOOTH_A2DP;
+            case AudioDeviceInfo.TYPE_BLE_HEADSET:
+                return MediaRoute2Info.TYPE_BLE_HEADSET;
+            case AudioDeviceInfo.TYPE_HEARING_AID:
+                return MediaRoute2Info.TYPE_HEARING_AID;
+            default:
+                return MediaRoute2Info.TYPE_UNKNOWN;
+        }
+    }
+
+
+    /* package */ static boolean isDeviceOutputAttributes(
+            @Nullable AudioDeviceAttributes audioDeviceAttributes) {
+        if (audioDeviceAttributes == null) {
+            return false;
+        }
+
+        if (audioDeviceAttributes.getRole() != AudioDeviceAttributes.ROLE_OUTPUT) {
+            return false;
+        }
+
+        switch (audioDeviceAttributes.getType()) {
+            case AudioDeviceInfo.TYPE_BUILTIN_EARPIECE:
+            case AudioDeviceInfo.TYPE_BUILTIN_SPEAKER:
+            case AudioDeviceInfo.TYPE_WIRED_HEADSET:
+            case AudioDeviceInfo.TYPE_WIRED_HEADPHONES:
+            case AudioDeviceInfo.TYPE_DOCK:
+            case AudioDeviceInfo.TYPE_DOCK_ANALOG:
+            case AudioDeviceInfo.TYPE_HDMI:
+            case AudioDeviceInfo.TYPE_USB_DEVICE:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    /* package */ static boolean isBluetoothOutputAttributes(
+            @Nullable AudioDeviceAttributes audioDeviceAttributes) {
+        if (audioDeviceAttributes == null) {
+            return false;
+        }
+
+        if (audioDeviceAttributes.getRole() != AudioDeviceAttributes.ROLE_OUTPUT) {
+            return false;
+        }
+
+        switch (audioDeviceAttributes.getType()) {
+            case AudioDeviceInfo.TYPE_BLUETOOTH_A2DP:
+            case AudioDeviceInfo.TYPE_BLE_HEADSET:
+            case AudioDeviceInfo.TYPE_BLE_SPEAKER:
+            case AudioDeviceInfo.TYPE_HEARING_AID:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+}
diff --git a/services/core/java/com/android/server/media/AudioPoliciesBluetoothRouteController.java b/services/core/java/com/android/server/media/AudioPoliciesBluetoothRouteController.java
new file mode 100644
index 0000000..eb997ba
--- /dev/null
+++ b/services/core/java/com/android/server/media/AudioPoliciesBluetoothRouteController.java
@@ -0,0 +1,482 @@
+/*
+ * 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.media;
+
+import static android.bluetooth.BluetoothAdapter.ACTIVE_DEVICE_AUDIO;
+import static android.bluetooth.BluetoothAdapter.STATE_CONNECTED;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
+import android.bluetooth.BluetoothProfile;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.media.AudioManager;
+import android.media.AudioSystem;
+import android.media.MediaRoute2Info;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.Slog;
+import android.util.SparseBooleanArray;
+import android.util.SparseIntArray;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Controls bluetooth routes and provides selected route override.
+ *
+ * <p>The controller offers similar functionality to {@link LegacyBluetoothRouteController} but does
+ * not support routes selection logic. Instead, relies on external clients to make a decision
+ * about currently selected route.
+ *
+ * <p>Selected route override should be used by {@link AudioManager} which is aware of Audio
+ * Policies.
+ */
+/* package */ class AudioPoliciesBluetoothRouteController
+        implements BluetoothRouteController {
+    private static final String TAG = "APBtRouteController";
+
+    private static final String HEARING_AID_ROUTE_ID_PREFIX = "HEARING_AID_";
+    private static final String LE_AUDIO_ROUTE_ID_PREFIX = "LE_AUDIO_";
+
+    @NonNull
+    private final AdapterStateChangedReceiver mAdapterStateChangedReceiver =
+            new AdapterStateChangedReceiver();
+
+    @NonNull
+    private final DeviceStateChangedReceiver mDeviceStateChangedReceiver =
+            new DeviceStateChangedReceiver();
+
+    @NonNull
+    private final Map<String, BluetoothRouteInfo> mBluetoothRoutes = new HashMap<>();
+
+    @NonNull
+    private final SparseIntArray mVolumeMap = new SparseIntArray();
+
+    @NonNull
+    private final Context mContext;
+    @NonNull
+    private final BluetoothAdapter mBluetoothAdapter;
+    @NonNull
+    private final BluetoothRouteController.BluetoothRoutesUpdatedListener mListener;
+    @NonNull
+    private final BluetoothProfileMonitor mBluetoothProfileMonitor;
+    @NonNull
+    private final AudioManager mAudioManager;
+
+    @Nullable
+    private BluetoothRouteInfo mSelectedBluetoothRoute;
+
+    AudioPoliciesBluetoothRouteController(@NonNull Context context,
+            @NonNull BluetoothAdapter bluetoothAdapter,
+            @NonNull BluetoothRouteController.BluetoothRoutesUpdatedListener listener) {
+        this(context, bluetoothAdapter,
+                new BluetoothProfileMonitor(context, bluetoothAdapter), listener);
+    }
+
+    @VisibleForTesting
+    AudioPoliciesBluetoothRouteController(@NonNull Context context,
+            @NonNull BluetoothAdapter bluetoothAdapter,
+            @NonNull BluetoothProfileMonitor bluetoothProfileMonitor,
+            @NonNull BluetoothRouteController.BluetoothRoutesUpdatedListener listener) {
+        Objects.requireNonNull(context);
+        Objects.requireNonNull(bluetoothAdapter);
+        Objects.requireNonNull(bluetoothProfileMonitor);
+        Objects.requireNonNull(listener);
+
+        mContext = context;
+        mBluetoothAdapter = bluetoothAdapter;
+        mBluetoothProfileMonitor = bluetoothProfileMonitor;
+        mAudioManager = mContext.getSystemService(AudioManager.class);
+        mListener = listener;
+
+        updateBluetoothRoutes();
+    }
+
+    @Override
+    public void start(UserHandle user) {
+        mBluetoothProfileMonitor.start();
+
+        IntentFilter adapterStateChangedIntentFilter = new IntentFilter();
+
+        adapterStateChangedIntentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
+        mContext.registerReceiverAsUser(mAdapterStateChangedReceiver, user,
+                adapterStateChangedIntentFilter, null, null);
+
+        IntentFilter deviceStateChangedIntentFilter = new IntentFilter();
+
+        deviceStateChangedIntentFilter.addAction(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED);
+        deviceStateChangedIntentFilter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
+        deviceStateChangedIntentFilter.addAction(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED);
+        deviceStateChangedIntentFilter.addAction(
+                BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
+        deviceStateChangedIntentFilter.addAction(
+                BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED);
+        deviceStateChangedIntentFilter.addAction(
+                BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED);
+
+        mContext.registerReceiverAsUser(mDeviceStateChangedReceiver, user,
+                deviceStateChangedIntentFilter, null, null);
+    }
+
+    @Override
+    public void stop() {
+        mContext.unregisterReceiver(mAdapterStateChangedReceiver);
+        mContext.unregisterReceiver(mDeviceStateChangedReceiver);
+    }
+
+    @Override
+    public boolean selectRoute(@Nullable String deviceAddress) {
+        synchronized (this) {
+            // Fetch all available devices in order to avoid race conditions with Bluetooth stack.
+            updateBluetoothRoutes();
+
+            if (deviceAddress == null) {
+                mSelectedBluetoothRoute = null;
+                return true;
+            }
+
+            BluetoothRouteInfo bluetoothRouteInfo = mBluetoothRoutes.get(deviceAddress);
+
+            if (bluetoothRouteInfo == null) {
+                Slog.w(TAG, "Cannot find bluetooth route for " + deviceAddress);
+                return false;
+            }
+
+            mSelectedBluetoothRoute = bluetoothRouteInfo;
+            setRouteConnectionState(mSelectedBluetoothRoute, STATE_CONNECTED);
+
+            updateConnectivityStateForDevicesInTheSameGroup();
+
+            return true;
+        }
+    }
+
+    /**
+     * Updates connectivity state for devices in the same devices group.
+     *
+     * <p>{@link BluetoothProfile#LE_AUDIO} and {@link BluetoothProfile#HEARING_AID} support
+     * grouping devices. Devices that belong to the same group should have the same routeId but
+     * different physical address.
+     *
+     * <p>In case one of the devices from the group is selected then other devices should also
+     * reflect this by changing their connectivity status to
+     * {@link MediaRoute2Info#CONNECTION_STATE_CONNECTED}.
+     */
+    private void updateConnectivityStateForDevicesInTheSameGroup() {
+        synchronized (this) {
+            for (BluetoothRouteInfo btRoute : mBluetoothRoutes.values()) {
+                if (TextUtils.equals(btRoute.mRoute.getId(), mSelectedBluetoothRoute.mRoute.getId())
+                        && !TextUtils.equals(btRoute.mBtDevice.getAddress(),
+                        mSelectedBluetoothRoute.mBtDevice.getAddress())) {
+                    setRouteConnectionState(btRoute, STATE_CONNECTED);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void transferTo(@Nullable String routeId) {
+        if (routeId == null) {
+            mBluetoothAdapter.removeActiveDevice(ACTIVE_DEVICE_AUDIO);
+            return;
+        }
+
+        BluetoothRouteInfo btRouteInfo = findBluetoothRouteWithRouteId(routeId);
+
+        if (btRouteInfo == null) {
+            Slog.w(TAG, "transferTo: Unknown route. ID=" + routeId);
+            return;
+        }
+
+        mBluetoothAdapter.setActiveDevice(btRouteInfo.mBtDevice, ACTIVE_DEVICE_AUDIO);
+    }
+
+    @Nullable
+    private BluetoothRouteInfo findBluetoothRouteWithRouteId(@Nullable String routeId) {
+        if (routeId == null) {
+            return null;
+        }
+        synchronized (this) {
+            for (BluetoothRouteInfo btRouteInfo : mBluetoothRoutes.values()) {
+                if (TextUtils.equals(btRouteInfo.mRoute.getId(), routeId)) {
+                    return btRouteInfo;
+                }
+            }
+        }
+        return null;
+    }
+
+    private void updateBluetoothRoutes() {
+        Set<BluetoothDevice> bondedDevices = mBluetoothAdapter.getBondedDevices();
+
+        if (bondedDevices == null) {
+            return;
+        }
+
+        synchronized (this) {
+            mBluetoothRoutes.clear();
+
+            // We need to query all available to BT stack devices in order to avoid inconsistency
+            // between external services, like, AndroidManager, and BT stack.
+            for (BluetoothDevice device : bondedDevices) {
+                if (isDeviceConnected(device)) {
+                    BluetoothRouteInfo newBtRoute = createBluetoothRoute(device);
+                    if (newBtRoute.mConnectedProfiles.size() > 0) {
+                        mBluetoothRoutes.put(device.getAddress(), newBtRoute);
+                    }
+                }
+            }
+        }
+    }
+
+    @VisibleForTesting
+        /* package */ boolean isDeviceConnected(@NonNull BluetoothDevice device) {
+        return device.isConnected();
+    }
+
+    @Nullable
+    @Override
+    public MediaRoute2Info getSelectedRoute() {
+        synchronized (this) {
+            if (mSelectedBluetoothRoute == null) {
+                return null;
+            }
+
+            return mSelectedBluetoothRoute.mRoute;
+        }
+    }
+
+    @NonNull
+    @Override
+    public List<MediaRoute2Info> getTransferableRoutes() {
+        List<MediaRoute2Info> routes = getAllBluetoothRoutes();
+        synchronized (this) {
+            if (mSelectedBluetoothRoute != null) {
+                routes.remove(mSelectedBluetoothRoute.mRoute);
+            }
+        }
+        return routes;
+    }
+
+    @NonNull
+    @Override
+    public List<MediaRoute2Info> getAllBluetoothRoutes() {
+        List<MediaRoute2Info> routes = new ArrayList<>();
+        List<String> routeIds = new ArrayList<>();
+
+        MediaRoute2Info selectedRoute = getSelectedRoute();
+        if (selectedRoute != null) {
+            routes.add(selectedRoute);
+            routeIds.add(selectedRoute.getId());
+        }
+
+        synchronized (this) {
+            for (BluetoothRouteInfo btRoute : mBluetoothRoutes.values()) {
+                // A pair of hearing aid devices or having the same hardware address
+                if (routeIds.contains(btRoute.mRoute.getId())) {
+                    continue;
+                }
+                routes.add(btRoute.mRoute);
+                routeIds.add(btRoute.mRoute.getId());
+            }
+        }
+        return routes;
+    }
+
+    @Override
+    public boolean updateVolumeForDevices(int devices, int volume) {
+        int routeType;
+        if ((devices & (AudioSystem.DEVICE_OUT_HEARING_AID)) != 0) {
+            routeType = MediaRoute2Info.TYPE_HEARING_AID;
+        } else if ((devices & (AudioManager.DEVICE_OUT_BLUETOOTH_A2DP
+                | AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES
+                | AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) != 0) {
+            routeType = MediaRoute2Info.TYPE_BLUETOOTH_A2DP;
+        } else if ((devices & (AudioManager.DEVICE_OUT_BLE_HEADSET)) != 0) {
+            routeType = MediaRoute2Info.TYPE_BLE_HEADSET;
+        } else {
+            return false;
+        }
+
+        synchronized (this) {
+            mVolumeMap.put(routeType, volume);
+            if (mSelectedBluetoothRoute == null
+                    || mSelectedBluetoothRoute.mRoute.getType() != routeType) {
+                return false;
+            }
+
+            mSelectedBluetoothRoute.mRoute =
+                    new MediaRoute2Info.Builder(mSelectedBluetoothRoute.mRoute)
+                            .setVolume(volume)
+                            .build();
+        }
+
+        notifyBluetoothRoutesUpdated();
+        return true;
+    }
+
+    private void notifyBluetoothRoutesUpdated() {
+        mListener.onBluetoothRoutesUpdated(getAllBluetoothRoutes());
+    }
+
+    private BluetoothRouteInfo createBluetoothRoute(BluetoothDevice device) {
+        BluetoothRouteInfo
+                newBtRoute = new BluetoothRouteInfo();
+        newBtRoute.mBtDevice = device;
+
+        String routeId = device.getAddress();
+        String deviceName = device.getName();
+        if (TextUtils.isEmpty(deviceName)) {
+            deviceName = mContext.getResources().getText(R.string.unknownName).toString();
+        }
+        int type = MediaRoute2Info.TYPE_BLUETOOTH_A2DP;
+        newBtRoute.mConnectedProfiles = new SparseBooleanArray();
+        if (mBluetoothProfileMonitor.isProfileSupported(BluetoothProfile.A2DP, device)) {
+            newBtRoute.mConnectedProfiles.put(BluetoothProfile.A2DP, true);
+        }
+        if (mBluetoothProfileMonitor.isProfileSupported(BluetoothProfile.HEARING_AID, device)) {
+            newBtRoute.mConnectedProfiles.put(BluetoothProfile.HEARING_AID, true);
+            // Intentionally assign the same ID for a pair of devices to publish only one of them.
+            routeId = HEARING_AID_ROUTE_ID_PREFIX
+                    + mBluetoothProfileMonitor.getGroupId(BluetoothProfile.HEARING_AID, device);
+            type = MediaRoute2Info.TYPE_HEARING_AID;
+        }
+        if (mBluetoothProfileMonitor.isProfileSupported(BluetoothProfile.LE_AUDIO, device)) {
+            newBtRoute.mConnectedProfiles.put(BluetoothProfile.LE_AUDIO, true);
+            routeId = LE_AUDIO_ROUTE_ID_PREFIX
+                    + mBluetoothProfileMonitor.getGroupId(BluetoothProfile.LE_AUDIO, device);
+            type = MediaRoute2Info.TYPE_BLE_HEADSET;
+        }
+
+        // Current volume will be set when connected.
+        newBtRoute.mRoute = new MediaRoute2Info.Builder(routeId, deviceName)
+                .addFeature(MediaRoute2Info.FEATURE_LIVE_AUDIO)
+                .addFeature(MediaRoute2Info.FEATURE_LOCAL_PLAYBACK)
+                .setConnectionState(MediaRoute2Info.CONNECTION_STATE_DISCONNECTED)
+                .setDescription(mContext.getResources().getText(
+                        R.string.bluetooth_a2dp_audio_route_name).toString())
+                .setType(type)
+                .setVolumeHandling(MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
+                .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
+                .setAddress(device.getAddress())
+                .build();
+        return newBtRoute;
+    }
+
+    private void setRouteConnectionState(@NonNull BluetoothRouteInfo btRoute,
+            @MediaRoute2Info.ConnectionState int state) {
+        if (btRoute == null) {
+            Slog.w(TAG, "setRouteConnectionState: route shouldn't be null");
+            return;
+        }
+        if (btRoute.mRoute.getConnectionState() == state) {
+            return;
+        }
+
+        MediaRoute2Info.Builder builder = new MediaRoute2Info.Builder(btRoute.mRoute)
+                .setConnectionState(state);
+        builder.setType(btRoute.getRouteType());
+
+
+
+        if (state == MediaRoute2Info.CONNECTION_STATE_CONNECTED) {
+            int currentVolume;
+            synchronized (this) {
+                currentVolume = mVolumeMap.get(btRoute.getRouteType(), 0);
+            }
+            builder.setVolume(currentVolume);
+        }
+
+        btRoute.mRoute = builder.build();
+    }
+
+    private static class BluetoothRouteInfo {
+        private BluetoothDevice mBtDevice;
+        private MediaRoute2Info mRoute;
+        private SparseBooleanArray mConnectedProfiles;
+
+        @MediaRoute2Info.Type
+        int getRouteType() {
+            // Let hearing aid profile have a priority.
+            if (mConnectedProfiles.get(BluetoothProfile.HEARING_AID, false)) {
+                return MediaRoute2Info.TYPE_HEARING_AID;
+            }
+
+            if (mConnectedProfiles.get(BluetoothProfile.LE_AUDIO, false)) {
+                return MediaRoute2Info.TYPE_BLE_HEADSET;
+            }
+
+            return MediaRoute2Info.TYPE_BLUETOOTH_A2DP;
+        }
+    }
+
+    private class AdapterStateChangedReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
+            if (state == BluetoothAdapter.STATE_OFF
+                    || state == BluetoothAdapter.STATE_TURNING_OFF) {
+                synchronized (AudioPoliciesBluetoothRouteController.this) {
+                    mBluetoothRoutes.clear();
+                }
+                notifyBluetoothRoutesUpdated();
+            } else if (state == BluetoothAdapter.STATE_ON) {
+                updateBluetoothRoutes();
+
+                boolean shouldCallListener;
+                synchronized (AudioPoliciesBluetoothRouteController.this) {
+                    shouldCallListener = !mBluetoothRoutes.isEmpty();
+                }
+
+                if (shouldCallListener) {
+                    notifyBluetoothRoutesUpdated();
+                }
+            }
+        }
+    }
+
+    private class DeviceStateChangedReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            switch (intent.getAction()) {
+                case BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED:
+                case BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED:
+                case BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED:
+                case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED:
+                case BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED:
+                case BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED:
+                    updateBluetoothRoutes();
+                    notifyBluetoothRoutesUpdated();
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/media/AudioPoliciesDeviceRouteController.java b/services/core/java/com/android/server/media/AudioPoliciesDeviceRouteController.java
new file mode 100644
index 0000000..182aa6f
--- /dev/null
+++ b/services/core/java/com/android/server/media/AudioPoliciesDeviceRouteController.java
@@ -0,0 +1,240 @@
+/*
+ * 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.media;
+
+import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
+import static android.media.MediaRoute2Info.FEATURE_LIVE_VIDEO;
+import static android.media.MediaRoute2Info.FEATURE_LOCAL_PLAYBACK;
+import static android.media.MediaRoute2Info.TYPE_BUILTIN_SPEAKER;
+import static android.media.MediaRoute2Info.TYPE_DOCK;
+import static android.media.MediaRoute2Info.TYPE_HDMI;
+import static android.media.MediaRoute2Info.TYPE_USB_DEVICE;
+import static android.media.MediaRoute2Info.TYPE_WIRED_HEADPHONES;
+import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.AudioRoutesInfo;
+import android.media.IAudioRoutesObserver;
+import android.media.IAudioService;
+import android.media.MediaRoute2Info;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.Objects;
+
+
+/* package */ final class AudioPoliciesDeviceRouteController implements DeviceRouteController {
+
+    private static final String TAG = "APDeviceRoutesController";
+
+    private static final String DEVICE_ROUTE_ID = "DEVICE_ROUTE";
+
+    @NonNull
+    private final Context mContext;
+    @NonNull
+    private final AudioManager mAudioManager;
+    @NonNull
+    private final IAudioService mAudioService;
+
+    @NonNull
+    private final OnDeviceRouteChangedListener mOnDeviceRouteChangedListener;
+    @NonNull
+    private final AudioRoutesObserver mAudioRoutesObserver = new AudioRoutesObserver();
+
+    private int mDeviceVolume;
+
+    @NonNull
+    private MediaRoute2Info mDeviceRoute;
+    @Nullable
+    private MediaRoute2Info mSelectedRoute;
+
+    @VisibleForTesting
+    /* package */ AudioPoliciesDeviceRouteController(@NonNull Context context,
+            @NonNull AudioManager audioManager,
+            @NonNull IAudioService audioService,
+            @NonNull OnDeviceRouteChangedListener onDeviceRouteChangedListener) {
+        Objects.requireNonNull(context);
+        Objects.requireNonNull(audioManager);
+        Objects.requireNonNull(audioService);
+        Objects.requireNonNull(onDeviceRouteChangedListener);
+
+        mContext = context;
+        mOnDeviceRouteChangedListener = onDeviceRouteChangedListener;
+
+        mAudioManager = audioManager;
+        mAudioService = audioService;
+
+        AudioRoutesInfo newAudioRoutes = null;
+        try {
+            newAudioRoutes = mAudioService.startWatchingRoutes(mAudioRoutesObserver);
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Cannot connect to audio service to start listen to routes", e);
+        }
+
+        mDeviceRoute = createRouteFromAudioInfo(newAudioRoutes);
+    }
+
+    @Override
+    public synchronized boolean selectRoute(@Nullable Integer type) {
+        if (type == null) {
+            mSelectedRoute = null;
+            return true;
+        }
+
+        if (!isDeviceRouteType(type)) {
+            return false;
+        }
+
+        mSelectedRoute = createRouteFromAudioInfo(type);
+        return true;
+    }
+
+    @Override
+    @NonNull
+    public synchronized MediaRoute2Info getDeviceRoute() {
+        if (mSelectedRoute != null) {
+            return mSelectedRoute;
+        }
+        return mDeviceRoute;
+    }
+
+    @Override
+    public synchronized boolean updateVolume(int volume) {
+        if (mDeviceVolume == volume) {
+            return false;
+        }
+
+        mDeviceVolume = volume;
+
+        if (mSelectedRoute != null) {
+            mSelectedRoute = new MediaRoute2Info.Builder(mSelectedRoute)
+                    .setVolume(volume)
+                    .build();
+        }
+
+        mDeviceRoute = new MediaRoute2Info.Builder(mDeviceRoute)
+                .setVolume(volume)
+                .build();
+
+        return true;
+    }
+
+    @NonNull
+    private MediaRoute2Info createRouteFromAudioInfo(@Nullable AudioRoutesInfo newRoutes) {
+        int type = TYPE_BUILTIN_SPEAKER;
+
+        if (newRoutes != null) {
+            if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADPHONES) != 0) {
+                type = TYPE_WIRED_HEADPHONES;
+            } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADSET) != 0) {
+                type = TYPE_WIRED_HEADSET;
+            } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) {
+                type = TYPE_DOCK;
+            } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HDMI) != 0) {
+                type = TYPE_HDMI;
+            } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_USB) != 0) {
+                type = TYPE_USB_DEVICE;
+            }
+        }
+
+        return createRouteFromAudioInfo(type);
+    }
+
+    @NonNull
+    private MediaRoute2Info createRouteFromAudioInfo(@MediaRoute2Info.Type int type) {
+        int name = R.string.default_audio_route_name;
+
+        switch (type) {
+            case TYPE_WIRED_HEADPHONES:
+            case TYPE_WIRED_HEADSET:
+                name = R.string.default_audio_route_name_headphones;
+                break;
+            case TYPE_DOCK:
+                name = R.string.default_audio_route_name_dock_speakers;
+                break;
+            case TYPE_HDMI:
+                name = R.string.default_audio_route_name_external_device;
+                break;
+            case TYPE_USB_DEVICE:
+                name = R.string.default_audio_route_name_usb;
+                break;
+        }
+
+        synchronized (this) {
+            return new MediaRoute2Info.Builder(
+                    DEVICE_ROUTE_ID, mContext.getResources().getText(name).toString())
+                    .setVolumeHandling(mAudioManager.isVolumeFixed()
+                            ? MediaRoute2Info.PLAYBACK_VOLUME_FIXED
+                            : MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
+                    .setVolume(mDeviceVolume)
+                    .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
+                    .setType(type)
+                    .addFeature(FEATURE_LIVE_AUDIO)
+                    .addFeature(FEATURE_LIVE_VIDEO)
+                    .addFeature(FEATURE_LOCAL_PLAYBACK)
+                    .setConnectionState(MediaRoute2Info.CONNECTION_STATE_CONNECTED)
+                    .build();
+        }
+    }
+
+    /**
+     * Checks if the given type is a device route.
+     *
+     * <p>Device route means a route which is either built-in or wired to the current device.
+     *
+     * @param type specifies the type of the device.
+     * @return {@code true} if the device is wired or built-in and {@code false} otherwise.
+     */
+    private boolean isDeviceRouteType(@MediaRoute2Info.Type int type) {
+        switch (type) {
+            case TYPE_BUILTIN_SPEAKER:
+            case TYPE_WIRED_HEADPHONES:
+            case TYPE_WIRED_HEADSET:
+            case TYPE_DOCK:
+            case TYPE_HDMI:
+            case TYPE_USB_DEVICE:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    private class AudioRoutesObserver extends IAudioRoutesObserver.Stub {
+
+        @Override
+        public void dispatchAudioRoutesChanged(AudioRoutesInfo newAudioRoutes) {
+            boolean isDeviceRouteChanged;
+            MediaRoute2Info deviceRoute = createRouteFromAudioInfo(newAudioRoutes);
+
+            synchronized (AudioPoliciesDeviceRouteController.this) {
+                mDeviceRoute = deviceRoute;
+                isDeviceRouteChanged = mSelectedRoute == null;
+            }
+
+            if (isDeviceRouteChanged) {
+                mOnDeviceRouteChangedListener.onDeviceRouteChanged(deviceRoute);
+            }
+        }
+    }
+
+}
diff --git a/services/core/java/com/android/server/media/BluetoothProfileMonitor.java b/services/core/java/com/android/server/media/BluetoothProfileMonitor.java
new file mode 100644
index 0000000..b129dd0
--- /dev/null
+++ b/services/core/java/com/android/server/media/BluetoothProfileMonitor.java
@@ -0,0 +1,178 @@
+/*
+ * 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.media;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+
+import java.util.Objects;
+
+/* package */ class BluetoothProfileMonitor {
+
+    /* package */ static final long GROUP_ID_NO_GROUP = -1L;
+
+    @NonNull
+    private final ProfileListener mProfileListener = new ProfileListener();
+
+    @NonNull
+    private final Context mContext;
+    @NonNull
+    private final BluetoothAdapter mBluetoothAdapter;
+
+    @Nullable
+    private BluetoothA2dp mA2dpProfile;
+    @Nullable
+    private BluetoothHearingAid mHearingAidProfile;
+    @Nullable
+    private BluetoothLeAudio mLeAudioProfile;
+
+    @Nullable
+    private OnProfileChangedListener mOnProfileChangedListener;
+
+    BluetoothProfileMonitor(@NonNull Context context,
+            @NonNull BluetoothAdapter bluetoothAdapter) {
+        Objects.requireNonNull(context);
+        Objects.requireNonNull(bluetoothAdapter);
+
+        mContext = context;
+        mBluetoothAdapter = bluetoothAdapter;
+    }
+
+    /* package */ synchronized void setOnProfileChangedListener(
+            @NonNull OnProfileChangedListener listener) {
+        mOnProfileChangedListener = listener;
+    }
+
+    /* package */ void start() {
+        mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.A2DP);
+        mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.HEARING_AID);
+        mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.LE_AUDIO);
+    }
+
+    /* package */ boolean isProfileSupported(int profile, @NonNull BluetoothDevice device) {
+        BluetoothProfile bluetoothProfile;
+
+        synchronized (this) {
+            switch (profile) {
+                case BluetoothProfile.A2DP:
+                    bluetoothProfile = mA2dpProfile;
+                    break;
+                case BluetoothProfile.LE_AUDIO:
+                    bluetoothProfile = mLeAudioProfile;
+                    break;
+                case BluetoothProfile.HEARING_AID:
+                    bluetoothProfile = mHearingAidProfile;
+                    break;
+                default:
+                    throw new IllegalArgumentException(profile
+                            + " is not supported as Bluetooth profile");
+            }
+        }
+
+        if (bluetoothProfile == null) {
+            return false;
+        }
+
+        return bluetoothProfile.getConnectedDevices().contains(device);
+    }
+
+    /* package */ long getGroupId(int profile, @NonNull BluetoothDevice device) {
+        synchronized (this) {
+            switch (profile) {
+                case BluetoothProfile.A2DP:
+                    return GROUP_ID_NO_GROUP;
+                case BluetoothProfile.LE_AUDIO:
+                    return mLeAudioProfile == null ? GROUP_ID_NO_GROUP : mLeAudioProfile.getGroupId(
+                            device);
+                case BluetoothProfile.HEARING_AID:
+                    return mHearingAidProfile == null
+                            ? GROUP_ID_NO_GROUP : mHearingAidProfile.getHiSyncId(device);
+                default:
+                    throw new IllegalArgumentException(profile
+                            + " is not supported as Bluetooth profile");
+            }
+        }
+    }
+
+    /* package */ interface OnProfileChangedListener {
+        void onProfileChange(int profile);
+    }
+
+    private final class ProfileListener implements BluetoothProfile.ServiceListener {
+        @Override
+        public void onServiceConnected(int profile, BluetoothProfile proxy) {
+            OnProfileChangedListener listener;
+
+            synchronized (BluetoothProfileMonitor.this) {
+                switch (profile) {
+                    case BluetoothProfile.A2DP:
+                        mA2dpProfile = (BluetoothA2dp) proxy;
+                        break;
+                    case BluetoothProfile.HEARING_AID:
+                        mHearingAidProfile = (BluetoothHearingAid) proxy;
+                        break;
+                    case BluetoothProfile.LE_AUDIO:
+                        mLeAudioProfile = (BluetoothLeAudio) proxy;
+                        break;
+                    default:
+                        return;
+                }
+
+                listener = mOnProfileChangedListener;
+            }
+
+            if (listener != null) {
+                listener.onProfileChange(profile);
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(int profile) {
+            OnProfileChangedListener listener;
+
+            synchronized (BluetoothProfileMonitor.this) {
+                switch (profile) {
+                    case BluetoothProfile.A2DP:
+                        mA2dpProfile = null;
+                        break;
+                    case BluetoothProfile.HEARING_AID:
+                        mHearingAidProfile = null;
+                        break;
+                    case BluetoothProfile.LE_AUDIO:
+                        mLeAudioProfile = null;
+                        break;
+                    default:
+                        return;
+                }
+
+                listener = mOnProfileChangedListener;
+            }
+
+            if (listener != null) {
+                listener.onProfileChange(profile);
+            }
+        }
+    }
+
+}
diff --git a/services/core/java/com/android/server/media/BluetoothRouteController.java b/services/core/java/com/android/server/media/BluetoothRouteController.java
index 08691d0..66985e0 100644
--- a/services/core/java/com/android/server/media/BluetoothRouteController.java
+++ b/services/core/java/com/android/server/media/BluetoothRouteController.java
@@ -53,7 +53,16 @@
             return new NoOpBluetoothRouteController();
         }
 
-        return new LegacyBluetoothRouteController(context, btAdapter, listener);
+        MediaFeatureFlagManager flagManager = MediaFeatureFlagManager.getInstance();
+        boolean isUsingLegacyController = flagManager.getBoolean(
+                MediaFeatureFlagManager.FEATURE_AUDIO_STRATEGIES_IS_USING_LEGACY_CONTROLLER,
+                true);
+
+        if (isUsingLegacyController) {
+            return new LegacyBluetoothRouteController(context, btAdapter, listener);
+        } else {
+            return new AudioPoliciesBluetoothRouteController(context, btAdapter, listener);
+        }
     }
 
     /**
@@ -68,6 +77,17 @@
      */
     void stop();
 
+
+    /**
+     * Selects the route with the given {@code deviceAddress}.
+     *
+     * @param deviceAddress The physical address of the device to select. May be null to unselect
+     *                      the currently selected device.
+     * @return Whether the selection succeeds. If the selection fails, the state of the instance
+     * remains unaltered.
+     */
+    boolean selectRoute(@Nullable String deviceAddress);
+
     /**
      * Transfers Bluetooth output to the given route.
      *
@@ -145,6 +165,12 @@
         }
 
         @Override
+        public boolean selectRoute(String deviceAddress) {
+            // no op
+            return false;
+        }
+
+        @Override
         public void transferTo(String routeId) {
             // no op
         }
diff --git a/services/core/java/com/android/server/media/DeviceRouteController.java b/services/core/java/com/android/server/media/DeviceRouteController.java
new file mode 100644
index 0000000..3875c84
--- /dev/null
+++ b/services/core/java/com/android/server/media/DeviceRouteController.java
@@ -0,0 +1,107 @@
+/*
+ * 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.media;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.IAudioRoutesObserver;
+import android.media.IAudioService;
+import android.media.MediaRoute2Info;
+import android.os.ServiceManager;
+
+/**
+ * Controls device routes.
+ *
+ * <p>A device route is a system wired route, for example, built-in speaker, wired
+ * headsets and headphones, dock, hdmi, or usb devices.
+ *
+ * @see SystemMediaRoute2Provider
+ */
+/* package */ interface DeviceRouteController {
+
+    /**
+     * Returns a new instance of {@link DeviceRouteController}.
+     */
+    /* package */ static DeviceRouteController createInstance(@NonNull Context context,
+            @NonNull OnDeviceRouteChangedListener onDeviceRouteChangedListener) {
+        AudioManager audioManager = context.getSystemService(AudioManager.class);
+        IAudioService audioService = IAudioService.Stub.asInterface(
+                ServiceManager.getService(Context.AUDIO_SERVICE));
+
+        MediaFeatureFlagManager flagManager = MediaFeatureFlagManager.getInstance();
+        boolean isUsingLegacyController = flagManager.getBoolean(
+                MediaFeatureFlagManager.FEATURE_AUDIO_STRATEGIES_IS_USING_LEGACY_CONTROLLER,
+                true);
+
+        if (isUsingLegacyController) {
+            return new LegacyDeviceRouteController(context,
+                    audioManager,
+                    audioService,
+                    onDeviceRouteChangedListener);
+        } else {
+            return new AudioPoliciesDeviceRouteController(context,
+                    audioManager,
+                    audioService,
+                    onDeviceRouteChangedListener);
+        }
+    }
+
+    /**
+     * Select the route with the given built-in or wired {@link MediaRoute2Info.Type}.
+     *
+     * <p>If the type is {@code null} then unselects the route and falls back to the default device
+     * route observed from
+     * {@link com.android.server.audio.AudioService#startWatchingRoutes(IAudioRoutesObserver)}.
+     *
+     * @param type device type. May be {@code null} to unselect currently selected route.
+     * @return whether the selection succeeds. If the selection fails the state of the controller
+     * remains intact.
+     */
+    boolean selectRoute(@Nullable @MediaRoute2Info.Type Integer type);
+
+    /**
+     * Returns currently selected device (built-in or wired) route.
+     *
+     * @return non-null device route.
+     */
+    @NonNull
+    MediaRoute2Info getDeviceRoute();
+
+    /**
+     * Updates device route volume.
+     *
+     * @param volume specifies a volume for the device route or 0 for unknown.
+     * @return {@code true} if updated successfully and {@code false} otherwise.
+     */
+    boolean updateVolume(int volume);
+
+    /**
+     * Interface for receiving events when device route has changed.
+     */
+    interface OnDeviceRouteChangedListener {
+
+        /**
+         * Called when device route has changed.
+         *
+         * @param deviceRoute non-null device route.
+         */
+        void onDeviceRouteChanged(@NonNull MediaRoute2Info deviceRoute);
+    }
+
+}
diff --git a/services/core/java/com/android/server/media/LegacyBluetoothRouteController.java b/services/core/java/com/android/server/media/LegacyBluetoothRouteController.java
index 7979d2a..e31a7fc 100644
--- a/services/core/java/com/android/server/media/LegacyBluetoothRouteController.java
+++ b/services/core/java/com/android/server/media/LegacyBluetoothRouteController.java
@@ -52,7 +52,7 @@
 import java.util.Set;
 
 class LegacyBluetoothRouteController implements BluetoothRouteController {
-    private static final String TAG = "BTRouteProvider";
+    private static final String TAG = "LBtRouteProvider";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private static final String HEARING_AID_ROUTE_ID_PREFIX = "HEARING_AID_";
@@ -132,6 +132,12 @@
         mContext.unregisterReceiver(mDeviceStateChangedReceiver);
     }
 
+    @Override
+    public boolean selectRoute(String deviceAddress) {
+        // No-op as the class decides if a route is selected based on Bluetooth events.
+        return false;
+    }
+
     /**
      * Transfers to a given bluetooth route.
      * The dedicated BT device with the route would be activated.
diff --git a/services/core/java/com/android/server/media/LegacyDeviceRouteController.java b/services/core/java/com/android/server/media/LegacyDeviceRouteController.java
new file mode 100644
index 0000000..971d11f
--- /dev/null
+++ b/services/core/java/com/android/server/media/LegacyDeviceRouteController.java
@@ -0,0 +1,184 @@
+/*
+ * 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.media;
+
+import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
+import static android.media.MediaRoute2Info.FEATURE_LIVE_VIDEO;
+import static android.media.MediaRoute2Info.FEATURE_LOCAL_PLAYBACK;
+import static android.media.MediaRoute2Info.TYPE_BUILTIN_SPEAKER;
+import static android.media.MediaRoute2Info.TYPE_DOCK;
+import static android.media.MediaRoute2Info.TYPE_HDMI;
+import static android.media.MediaRoute2Info.TYPE_USB_DEVICE;
+import static android.media.MediaRoute2Info.TYPE_WIRED_HEADPHONES;
+import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.AudioRoutesInfo;
+import android.media.IAudioRoutesObserver;
+import android.media.IAudioService;
+import android.media.MediaRoute2Info;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.Objects;
+
+/**
+ * Controls device routes.
+ *
+ * <p>A device route is a system wired route, for example, built-in speaker, wired
+ * headsets and headphones, dock, hdmi, or usb devices.
+ *
+ * <p>Thread safe.
+ *
+ * @see SystemMediaRoute2Provider
+ */
+/* package */ final class LegacyDeviceRouteController implements DeviceRouteController {
+
+    private static final String TAG = "LDeviceRouteController";
+
+    private static final String DEVICE_ROUTE_ID = "DEVICE_ROUTE";
+
+    @NonNull
+    private final Context mContext;
+    @NonNull
+    private final AudioManager mAudioManager;
+    @NonNull
+    private final IAudioService mAudioService;
+
+    @NonNull
+    private final OnDeviceRouteChangedListener mOnDeviceRouteChangedListener;
+    @NonNull
+    private final AudioRoutesObserver mAudioRoutesObserver = new AudioRoutesObserver();
+
+    private int mDeviceVolume;
+    private MediaRoute2Info mDeviceRoute;
+
+    @VisibleForTesting
+    /* package */ LegacyDeviceRouteController(@NonNull Context context,
+            @NonNull AudioManager audioManager,
+            @NonNull IAudioService audioService,
+            @NonNull OnDeviceRouteChangedListener onDeviceRouteChangedListener) {
+        Objects.requireNonNull(context);
+        Objects.requireNonNull(audioManager);
+        Objects.requireNonNull(audioService);
+        Objects.requireNonNull(onDeviceRouteChangedListener);
+
+        mContext = context;
+        mOnDeviceRouteChangedListener = onDeviceRouteChangedListener;
+
+        mAudioManager = audioManager;
+        mAudioService = audioService;
+
+        AudioRoutesInfo newAudioRoutes = null;
+        try {
+            newAudioRoutes = mAudioService.startWatchingRoutes(mAudioRoutesObserver);
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Cannot connect to audio service to start listen to routes", e);
+        }
+
+        mDeviceRoute = createRouteFromAudioInfo(newAudioRoutes);
+    }
+
+    @Override
+    public boolean selectRoute(@Nullable Integer type) {
+        // No-op as the controller does not support selection from the outside of the class.
+        return false;
+    }
+
+    @Override
+    @NonNull
+    public synchronized MediaRoute2Info getDeviceRoute() {
+        return mDeviceRoute;
+    }
+
+    @Override
+    public synchronized boolean updateVolume(int volume) {
+        if (mDeviceVolume == volume) {
+            return false;
+        }
+
+        mDeviceVolume = volume;
+        mDeviceRoute = new MediaRoute2Info.Builder(mDeviceRoute)
+                .setVolume(volume)
+                .build();
+
+        return true;
+    }
+
+    private MediaRoute2Info createRouteFromAudioInfo(@Nullable AudioRoutesInfo newRoutes) {
+        int name = R.string.default_audio_route_name;
+        int type = TYPE_BUILTIN_SPEAKER;
+
+        if (newRoutes != null) {
+            if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADPHONES) != 0) {
+                type = TYPE_WIRED_HEADPHONES;
+                name = com.android.internal.R.string.default_audio_route_name_headphones;
+            } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADSET) != 0) {
+                type = TYPE_WIRED_HEADSET;
+                name = com.android.internal.R.string.default_audio_route_name_headphones;
+            } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) {
+                type = TYPE_DOCK;
+                name = com.android.internal.R.string.default_audio_route_name_dock_speakers;
+            } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HDMI) != 0) {
+                type = TYPE_HDMI;
+                name = com.android.internal.R.string.default_audio_route_name_external_device;
+            } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_USB) != 0) {
+                type = TYPE_USB_DEVICE;
+                name = com.android.internal.R.string.default_audio_route_name_usb;
+            }
+        }
+
+        synchronized (this) {
+            return new MediaRoute2Info.Builder(
+                    DEVICE_ROUTE_ID, mContext.getResources().getText(name).toString())
+                    .setVolumeHandling(mAudioManager.isVolumeFixed()
+                            ? MediaRoute2Info.PLAYBACK_VOLUME_FIXED
+                            : MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
+                    .setVolume(mDeviceVolume)
+                    .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
+                    .setType(type)
+                    .addFeature(FEATURE_LIVE_AUDIO)
+                    .addFeature(FEATURE_LIVE_VIDEO)
+                    .addFeature(FEATURE_LOCAL_PLAYBACK)
+                    .setConnectionState(MediaRoute2Info.CONNECTION_STATE_CONNECTED)
+                    .build();
+        }
+    }
+
+    private void notifyDeviceRouteUpdate(@NonNull MediaRoute2Info deviceRoute) {
+        mOnDeviceRouteChangedListener.onDeviceRouteChanged(deviceRoute);
+    }
+
+    private class AudioRoutesObserver extends IAudioRoutesObserver.Stub {
+
+        @Override
+        public void dispatchAudioRoutesChanged(AudioRoutesInfo newAudioRoutes) {
+            MediaRoute2Info deviceRoute = createRouteFromAudioInfo(newAudioRoutes);
+            synchronized (LegacyDeviceRouteController.this) {
+                mDeviceRoute = deviceRoute;
+            }
+            notifyDeviceRouteUpdate(deviceRoute);
+        }
+    }
+
+}
diff --git a/services/core/java/com/android/server/media/MediaFeatureFlagManager.java b/services/core/java/com/android/server/media/MediaFeatureFlagManager.java
new file mode 100644
index 0000000..70ee38f
--- /dev/null
+++ b/services/core/java/com/android/server/media/MediaFeatureFlagManager.java
@@ -0,0 +1,66 @@
+/*
+ * 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.media;
+
+import android.annotation.StringDef;
+import android.provider.DeviceConfig;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/* package */ class MediaFeatureFlagManager {
+
+    /**
+     * Namespace for media better together features.
+     */
+    private static final String NAMESPACE_MEDIA_BETTER_TOGETHER = "media_better_together";
+
+    @StringDef(prefix = "FEATURE_", value = {
+            FEATURE_AUDIO_STRATEGIES_IS_USING_LEGACY_CONTROLLER
+    })
+    @Target({ ElementType.TYPE_USE, ElementType.TYPE_PARAMETER })
+    @Retention(RetentionPolicy.SOURCE)
+    /* package */ @interface MediaFeatureFlag {}
+
+    /**
+     * Whether to use old legacy implementation of BluetoothRouteController or new
+     * 'Audio Strategies'-aware controller.
+     */
+    /* package */ static final @MediaFeatureFlag String
+            FEATURE_AUDIO_STRATEGIES_IS_USING_LEGACY_CONTROLLER =
+            "BluetoothRouteController__enable_legacy_bluetooth_routes_controller";
+
+    private static final MediaFeatureFlagManager sInstance = new MediaFeatureFlagManager();
+
+    private MediaFeatureFlagManager() {
+        // Empty to prevent instantiation.
+    }
+
+    /* package */ static MediaFeatureFlagManager getInstance() {
+        return sInstance;
+    }
+
+    /**
+     * Returns a boolean value from {@link DeviceConfig} from the system_time namespace, or
+     * {@code defaultValue} if there is no explicit value set.
+     */
+    public boolean getBoolean(@MediaFeatureFlag String key, boolean defaultValue) {
+        return DeviceConfig.getBoolean(NAMESPACE_MEDIA_BETTER_TOGETHER, key, defaultValue);
+    }
+}
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index 76ff19f..5d5c621 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -16,25 +16,15 @@
 
 package com.android.server.media;
 
-import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
-import static android.media.MediaRoute2Info.FEATURE_LIVE_VIDEO;
-import static android.media.MediaRoute2Info.FEATURE_LOCAL_PLAYBACK;
-import static android.media.MediaRoute2Info.TYPE_BUILTIN_SPEAKER;
-import static android.media.MediaRoute2Info.TYPE_DOCK;
-import static android.media.MediaRoute2Info.TYPE_HDMI;
-import static android.media.MediaRoute2Info.TYPE_USB_DEVICE;
-import static android.media.MediaRoute2Info.TYPE_WIRED_HEADPHONES;
-import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET;
-
+import android.annotation.NonNull;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.media.AudioAttributes;
+import android.media.AudioDeviceAttributes;
 import android.media.AudioManager;
-import android.media.AudioRoutesInfo;
-import android.media.IAudioRoutesObserver;
-import android.media.IAudioService;
 import android.media.MediaRoute2Info;
 import android.media.MediaRoute2ProviderInfo;
 import android.media.MediaRoute2ProviderService;
@@ -43,16 +33,14 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Slog;
 
-import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -68,44 +56,49 @@
             SystemMediaRoute2Provider.class.getName());
 
     static final String DEFAULT_ROUTE_ID = "DEFAULT_ROUTE";
-    static final String DEVICE_ROUTE_ID = "DEVICE_ROUTE";
     static final String SYSTEM_SESSION_ID = "SYSTEM_SESSION";
 
     private final AudioManager mAudioManager;
-    private final IAudioService mAudioService;
     private final Handler mHandler;
     private final Context mContext;
     private final UserHandle mUser;
-    private final BluetoothRouteController mBtRouteProvider;
+
+    private final DeviceRouteController mDeviceRouteController;
+    private final BluetoothRouteController mBluetoothRouteController;
 
     private String mSelectedRouteId;
     // For apps without MODIFYING_AUDIO_ROUTING permission.
     // This should be the currently selected route.
     MediaRoute2Info mDefaultRoute;
-    MediaRoute2Info mDeviceRoute;
     RoutingSessionInfo mDefaultSessionInfo;
-    int mDeviceVolume;
 
     private final AudioManagerBroadcastReceiver mAudioReceiver =
             new AudioManagerBroadcastReceiver();
 
+    private final AudioManager.OnDevicesForAttributesChangedListener
+            mOnDevicesForAttributesChangedListener =
+            new AudioManager.OnDevicesForAttributesChangedListener() {
+                @Override
+                public void onDevicesForAttributesChanged(@NonNull AudioAttributes attributes,
+                        @NonNull List<AudioDeviceAttributes> devices) {
+                    if (attributes.getUsage() != AudioAttributes.USAGE_MEDIA) {
+                        return;
+                    }
+
+                    mHandler.post(() -> {
+                        updateSelectedAudioDevice(devices);
+                        notifyProviderState();
+                        if (updateSessionInfosIfNeeded()) {
+                            notifySessionInfoUpdated();
+                        }
+                    });
+                }
+            };
+
     private final Object mRequestLock = new Object();
     @GuardedBy("mRequestLock")
     private volatile SessionCreationRequest mPendingSessionCreationRequest;
 
-    final IAudioRoutesObserver.Stub mAudioRoutesObserver = new IAudioRoutesObserver.Stub() {
-        @Override
-        public void dispatchAudioRoutesChanged(final AudioRoutesInfo newRoutes) {
-            mHandler.post(() -> {
-                updateDeviceRoute(newRoutes);
-                notifyProviderState();
-                if (updateSessionInfosIfNeeded()) {
-                    notifySessionInfoUpdated();
-                }
-            });
-        }
-    };
-
     SystemMediaRoute2Provider(Context context, UserHandle user) {
         super(COMPONENT_NAME);
         mIsSystemRouteProvider = true;
@@ -114,25 +107,33 @@
         mHandler = new Handler(Looper.getMainLooper());
 
         mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
-        mAudioService = IAudioService.Stub.asInterface(
-                ServiceManager.getService(Context.AUDIO_SERVICE));
 
-        mBtRouteProvider = BluetoothRouteController.createInstance(context, (routes) -> {
+        mBluetoothRouteController = BluetoothRouteController.createInstance(context, (routes) -> {
             publishProviderState();
             if (updateSessionInfosIfNeeded()) {
                 notifySessionInfoUpdated();
             }
         });
 
-        AudioRoutesInfo newAudioRoutes = null;
-        try {
-            newAudioRoutes = mAudioService.startWatchingRoutes(mAudioRoutesObserver);
-        } catch (RemoteException e) {
-        }
+        mDeviceRouteController = DeviceRouteController.createInstance(context, (deviceRoute) -> {
+            mHandler.post(() -> {
+                publishProviderState();
+                if (updateSessionInfosIfNeeded()) {
+                    notifySessionInfoUpdated();
+                }
+            });
+        });
 
-        // The methods below should be called after all fields are initialized, as they
+        mAudioManager.addOnDevicesForAttributesChangedListener(
+                AudioAttributesUtils.ATTRIBUTES_MEDIA, mContext.getMainExecutor(),
+                mOnDevicesForAttributesChangedListener);
+
+        // These methods below should be called after all fields are initialized, as they
         // access the fields inside.
-        updateDeviceRoute(newAudioRoutes);
+        List<AudioDeviceAttributes> devices =
+                mAudioManager.getDevicesForAttributes(AudioAttributesUtils.ATTRIBUTES_MEDIA);
+        updateSelectedAudioDevice(devices);
+        updateProviderState();
         updateSessionInfosIfNeeded();
     }
 
@@ -143,7 +144,7 @@
                 intentFilter, null, null);
 
         mHandler.post(() -> {
-            mBtRouteProvider.start(mUser);
+            mBluetoothRouteController.start(mUser);
             notifyProviderState();
         });
         updateVolume();
@@ -152,7 +153,7 @@
     public void stop() {
         mContext.unregisterReceiver(mAudioReceiver);
         mHandler.post(() -> {
-            mBtRouteProvider.stop();
+            mBluetoothRouteController.stop();
             notifyProviderState();
         });
     }
@@ -216,10 +217,12 @@
             // The currently selected route is the default route.
             return;
         }
-        if (TextUtils.equals(routeId, mDeviceRoute.getId())) {
-            mBtRouteProvider.transferTo(null);
+
+        MediaRoute2Info deviceRoute = mDeviceRouteController.getDeviceRoute();
+        if (TextUtils.equals(routeId, deviceRoute.getId())) {
+            mBluetoothRouteController.transferTo(null);
         } else {
-            mBtRouteProvider.transferTo(routeId);
+            mBluetoothRouteController.transferTo(routeId);
         }
     }
 
@@ -254,58 +257,46 @@
             if (mSessionInfos.isEmpty()) {
                 return null;
             }
+
+            MediaRoute2Info deviceRoute = mDeviceRouteController.getDeviceRoute();
+
             RoutingSessionInfo.Builder builder = new RoutingSessionInfo.Builder(
                     SYSTEM_SESSION_ID, packageName).setSystemSession(true);
-            builder.addSelectedRoute(mDeviceRoute.getId());
-            for (MediaRoute2Info route : mBtRouteProvider.getAllBluetoothRoutes()) {
+            builder.addSelectedRoute(deviceRoute.getId());
+            for (MediaRoute2Info route : mBluetoothRouteController.getAllBluetoothRoutes()) {
                 builder.addTransferableRoute(route.getId());
             }
             return builder.setProviderId(mUniqueId).build();
         }
     }
 
-    private void updateDeviceRoute(AudioRoutesInfo newRoutes) {
-        int name = R.string.default_audio_route_name;
-        int type = TYPE_BUILTIN_SPEAKER;
-        if (newRoutes != null) {
-            if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADPHONES) != 0) {
-                type = TYPE_WIRED_HEADPHONES;
-                name = com.android.internal.R.string.default_audio_route_name_headphones;
-            } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADSET) != 0) {
-                type = TYPE_WIRED_HEADSET;
-                name = com.android.internal.R.string.default_audio_route_name_headphones;
-            } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) {
-                type = TYPE_DOCK;
-                name = com.android.internal.R.string.default_audio_route_name_dock_speakers;
-            } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HDMI) != 0) {
-                type = TYPE_HDMI;
-                name = com.android.internal.R.string.default_audio_route_name_external_device;
-            } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_USB) != 0) {
-                type = TYPE_USB_DEVICE;
-                name = com.android.internal.R.string.default_audio_route_name_usb;
-            }
+    private void updateSelectedAudioDevice(@NonNull List<AudioDeviceAttributes> devices) {
+        if (devices.isEmpty()) {
+            Slog.w(TAG, "The list of preferred devices was empty.");
+            return;
         }
 
-        mDeviceRoute = new MediaRoute2Info.Builder(
-                DEVICE_ROUTE_ID, mContext.getResources().getText(name).toString())
-                .setVolumeHandling(mAudioManager.isVolumeFixed()
-                        ? MediaRoute2Info.PLAYBACK_VOLUME_FIXED
-                        : MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
-                .setVolume(mDeviceVolume)
-                .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
-                .setType(type)
-                .addFeature(FEATURE_LIVE_AUDIO)
-                .addFeature(FEATURE_LIVE_VIDEO)
-                .addFeature(FEATURE_LOCAL_PLAYBACK)
-                .setConnectionState(MediaRoute2Info.CONNECTION_STATE_CONNECTED)
-                .build();
-        updateProviderState();
+        AudioDeviceAttributes audioDeviceAttributes = devices.get(0);
+
+        if (AudioAttributesUtils.isDeviceOutputAttributes(audioDeviceAttributes)) {
+            mDeviceRouteController.selectRoute(
+                    AudioAttributesUtils.mapToMediaRouteType(audioDeviceAttributes));
+            mBluetoothRouteController.selectRoute(null);
+        } else if (AudioAttributesUtils.isBluetoothOutputAttributes(audioDeviceAttributes)) {
+            mDeviceRouteController.selectRoute(null);
+            mBluetoothRouteController.selectRoute(audioDeviceAttributes.getAddress());
+        } else {
+            Slog.w(TAG, "Unknown audio attributes: " + audioDeviceAttributes);
+        }
     }
 
     private void updateProviderState() {
         MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder();
-        builder.addRoute(mDeviceRoute);
-        for (MediaRoute2Info route : mBtRouteProvider.getAllBluetoothRoutes()) {
+
+        // We must have a device route in the provider info.
+        builder.addRoute(mDeviceRouteController.getDeviceRoute());
+
+        for (MediaRoute2Info route : mBluetoothRouteController.getAllBluetoothRoutes()) {
             builder.addRoute(route);
         }
         MediaRoute2ProviderInfo providerInfo = builder.build();
@@ -327,11 +318,12 @@
                     SYSTEM_SESSION_ID, "" /* clientPackageName */)
                     .setSystemSession(true);
 
-            MediaRoute2Info selectedRoute = mDeviceRoute;
-            MediaRoute2Info selectedBtRoute = mBtRouteProvider.getSelectedRoute();
+            MediaRoute2Info deviceRoute = mDeviceRouteController.getDeviceRoute();
+            MediaRoute2Info selectedRoute = deviceRoute;
+            MediaRoute2Info selectedBtRoute = mBluetoothRouteController.getSelectedRoute();
             if (selectedBtRoute != null) {
                 selectedRoute = selectedBtRoute;
-                builder.addTransferableRoute(mDeviceRoute.getId());
+                builder.addTransferableRoute(deviceRoute.getId());
             }
             mSelectedRouteId = selectedRoute.getId();
             mDefaultRoute = new MediaRoute2Info.Builder(DEFAULT_ROUTE_ID, selectedRoute)
@@ -340,7 +332,7 @@
                     .build();
             builder.addSelectedRoute(mSelectedRouteId);
 
-            for (MediaRoute2Info route : mBtRouteProvider.getTransferableRoutes()) {
+            for (MediaRoute2Info route : mBluetoothRouteController.getTransferableRoutes()) {
                 builder.addTransferableRoute(route.getId());
             }
 
@@ -420,15 +412,12 @@
                     .build();
         }
 
-        if (mBtRouteProvider.updateVolumeForDevices(devices, volume)) {
+        if (mBluetoothRouteController.updateVolumeForDevices(devices, volume)) {
             return;
         }
-        if (mDeviceVolume != volume) {
-            mDeviceVolume = volume;
-            mDeviceRoute = new MediaRoute2Info.Builder(mDeviceRoute)
-                    .setVolume(volume)
-                    .build();
-        }
+
+        mDeviceRouteController.updateVolume(volume);
+
         publishProviderState();
     }
 
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index 77b9abe..4832618 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -16,6 +16,9 @@
 
 package com.android.server.media.projection;
 
+import static android.app.ActivityManagerInternal.MEDIA_PROJECTION_TOKEN_EVENT_CREATED;
+import static android.app.ActivityManagerInternal.MEDIA_PROJECTION_TOKEN_EVENT_DESTROYED;
+
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -484,6 +487,9 @@
             userHandle = new UserHandle(UserHandle.getUserId(uid));
             mTargetSdkVersion = targetSdkVersion;
             mIsPrivileged = isPrivileged;
+            // TODO(b/267740338): Add unit test.
+            mActivityManagerInternal.notifyMediaProjectionEvent(uid, asBinder(),
+                    MEDIA_PROJECTION_TOKEN_EVENT_CREATED);
         }
 
         @Override // Binder call
@@ -630,6 +636,9 @@
                 mToken = null;
                 unregisterCallback(mCallback);
                 mCallback = null;
+                // TODO(b/267740338): Add unit test.
+                mActivityManagerInternal.notifyMediaProjectionEvent(uid, asBinder(),
+                        MEDIA_PROJECTION_TOKEN_EVENT_DESTROYED);
             }
         }
 
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 56f3296..92be094 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -1650,15 +1650,7 @@
                         mContext, 0, snoozeIntent, FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE));
 
                 final Intent viewIntent = buildViewDataUsageIntent(res, policy.template);
-                // TODO: Resolve to single code path.
-                if (UserManager.isHeadlessSystemUserMode()) {
-                    builder.setContentIntent(PendingIntent.getActivityAsUser(
-                            mContext, 0, viewIntent, FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE,
-                            /* options= */ null, UserHandle.CURRENT));
-                } else {
-                    builder.setContentIntent(PendingIntent.getActivity(
-                            mContext, 0, viewIntent, FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE));
-                }
+                setContentIntent(builder, viewIntent);
                 break;
             }
             case TYPE_LIMIT: {
@@ -1679,15 +1671,7 @@
                 builder.setSmallIcon(R.drawable.stat_notify_disabled_data);
 
                 final Intent intent = buildNetworkOverLimitIntent(res, policy.template);
-                // TODO: Resolve to single code path.
-                if (UserManager.isHeadlessSystemUserMode()) {
-                    builder.setContentIntent(PendingIntent.getActivityAsUser(
-                            mContext, 0, intent, FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE,
-                            /* options= */ null, UserHandle.CURRENT));
-                } else {
-                    builder.setContentIntent(PendingIntent.getActivity(
-                            mContext, 0, intent, FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE));
-                }
+                setContentIntent(builder, intent);
                 break;
             }
             case TYPE_LIMIT_SNOOZED: {
@@ -1711,15 +1695,7 @@
                 builder.setChannelId(SystemNotificationChannels.NETWORK_STATUS);
 
                 final Intent intent = buildViewDataUsageIntent(res, policy.template);
-                // TODO: Resolve to single code path.
-                if (UserManager.isHeadlessSystemUserMode()) {
-                    builder.setContentIntent(PendingIntent.getActivityAsUser(
-                            mContext, 0, intent, FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE,
-                            /* options= */ null, UserHandle.CURRENT));
-                } else {
-                    builder.setContentIntent(PendingIntent.getActivity(
-                            mContext, 0, intent, FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE));
-                }
+                setContentIntent(builder, intent);
                 break;
             }
             case TYPE_RAPID: {
@@ -1739,15 +1715,7 @@
                         mContext, 0, snoozeIntent, FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE));
 
                 final Intent viewIntent = buildViewDataUsageIntent(res, policy.template);
-                // TODO: Resolve to single code path.
-                if (UserManager.isHeadlessSystemUserMode()) {
-                    builder.setContentIntent(PendingIntent.getActivityAsUser(
-                            mContext, 0, viewIntent, FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE,
-                            /* options= */ null, UserHandle.CURRENT));
-                } else {
-                    builder.setContentIntent(PendingIntent.getActivity(
-                            mContext, 0, viewIntent, FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE));
-                }
+                setContentIntent(builder, viewIntent);
                 break;
             }
             default: {
@@ -1765,6 +1733,17 @@
         mActiveNotifs.add(notificationId);
     }
 
+    private void setContentIntent(Notification.Builder builder, Intent intent) {
+        if (UserManager.isHeadlessSystemUserMode()) {
+            builder.setContentIntent(PendingIntent.getActivityAsUser(
+                    mContext, 0, intent, FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE,
+                    /* options= */ null, UserHandle.CURRENT));
+        } else {
+            builder.setContentIntent(PendingIntent.getActivity(
+                    mContext, 0, intent, FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE));
+        }
+    }
+
     private void cancelNotification(NotificationId notificationId) {
         mContext.getSystemService(NotificationManager.class).cancel(notificationId.getTag(),
                 notificationId.getId());
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 53e841d..73440b7 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -892,6 +892,7 @@
         return allowedComponents;
     }
 
+    @NonNull
     protected List<String> getAllowedPackages(int userId) {
         final List<String> allowedPackages = new ArrayList<>();
         synchronized (mApproved) {
@@ -1181,25 +1182,6 @@
         return installed;
     }
 
-    protected Set<String> getAllowedPackages() {
-        final Set<String> allowedPackages = new ArraySet<>();
-        synchronized (mApproved) {
-            for (int k = 0; k < mApproved.size(); k++) {
-                ArrayMap<Boolean, ArraySet<String>> allowedByType = mApproved.valueAt(k);
-                for (int i = 0; i < allowedByType.size(); i++) {
-                    final ArraySet<String> allowed = allowedByType.valueAt(i);
-                    for (int j = 0; j < allowed.size(); j++) {
-                        String pkgName = getPackageName(allowed.valueAt(j));
-                        if (!TextUtils.isEmpty(pkgName)) {
-                            allowedPackages.add(pkgName);
-                        }
-                    }
-                }
-            }
-        }
-        return allowedPackages;
-    }
-
     private void trimApprovedListsAccordingToInstalledServices(int userId) {
         synchronized (mApproved) {
             final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 0d39457..c2e8df1 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2055,8 +2055,8 @@
 
     // TODO - replace these methods with new fields in the VisibleForTesting constructor
     @VisibleForTesting
-    void setAudioManager(AudioManager audioMananger) {
-        mAudioManager = audioMananger;
+    void setAudioManager(AudioManager audioManager) {
+        mAudioManager = audioManager;
     }
 
     @VisibleForTesting
@@ -2709,16 +2709,18 @@
     }
 
     private void sendRegisteredOnlyBroadcast(String action) {
-        Intent intent = new Intent(action);
-        getContext().sendBroadcastAsUser(intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY),
-                UserHandle.ALL, null);
+        int[] userIds = mUmInternal.getProfileIds(mAmi.getCurrentUserId(), true);
+        Intent intent = new Intent(action).addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+        for (int userId : userIds) {
+            getContext().sendBroadcastAsUser(intent, UserHandle.of(userId), null);
+        }
         // explicitly send the broadcast to all DND packages, even if they aren't currently running
-        intent.setFlags(0);
-        final Set<String> dndApprovedPackages = mConditionProviders.getAllowedPackages();
-        for (String pkg : dndApprovedPackages) {
-            intent.setPackage(pkg);
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-            getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
+        for (int userId : userIds) {
+            for (String pkg : mConditionProviders.getAllowedPackages(userId)) {
+                Intent pkgIntent = new Intent(action).setPackage(pkg).setFlags(
+                        Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+                getContext().sendBroadcastAsUser(pkgIntent, UserHandle.of(userId));
+            }
         }
     }
 
@@ -5770,7 +5772,7 @@
                 switch (report) {
                     case REPORT_REMOTE_VIEWS:
                         Slog.e(TAG, "pullStats REPORT_REMOTE_VIEWS from: "
-                                + startMs + "  wtih " + doAgg);
+                                + startMs + "  with " + doAgg);
                         PulledStats stats = mUsageStats.remoteViewStats(startMs, doAgg);
                         if (stats != null) {
                             out.add(stats.toParcelFileDescriptor(report));
@@ -6468,7 +6470,7 @@
             }
         }
 
-        // Don't allow client applications to cancel foreground service notis or autobundled
+        // Don't allow client applications to cancel foreground service notifs or autobundled
         // summaries.
         final int mustNotHaveFlags = isCallingUidSystem() ? 0 :
                 (FLAG_FOREGROUND_SERVICE | FLAG_AUTOGROUP_SUMMARY);
@@ -8340,7 +8342,7 @@
                         Thread.sleep(waitMs);
                     } catch (InterruptedException e) { }
                     // Notifications might be canceled before it actually vibrates due to waitMs,
-                    // so need to check the notification still valide for vibrate.
+                    // so need to check that the notification is still valid for vibrate.
                     synchronized (mNotificationLock) {
                         if (mNotificationsByKey.get(record.getKey()) != null) {
                             if (record.getKey().equals(mVibrateNotificationKey)) {
@@ -11694,7 +11696,7 @@
                     }
                 } else if (PRIORITY_ARG.equals(a)) {
                     // Bugreport will call the service twice with priority arguments, first to dump
-                    // critical sections and then non critical ones. Set approriate filters
+                    // critical sections and then non critical ones. Set appropriate filters
                     // to generate the desired data.
                     if (ai < args.length - 1) {
                         ai++;
diff --git a/services/core/java/com/android/server/notification/OWNERS b/services/core/java/com/android/server/notification/OWNERS
index 5a19656..6c4dd6d 100644
--- a/services/core/java/com/android/server/notification/OWNERS
+++ b/services/core/java/com/android/server/notification/OWNERS
@@ -1,4 +1,6 @@
-dsandler@android.com
+# Bug component: 34005
+
 juliacr@google.com
-beverlyt@google.com
-pixel@google.com
+yurilin@google.com
+jeffdq@google.com
+dsandler@android.com
\ No newline at end of file
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index c63cddd..4bafbc7 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -135,7 +135,6 @@
     private static final String ATT_SHOW_BADGE = "show_badge";
     private static final String ATT_APP_USER_LOCKED_FIELDS = "app_user_locked_fields";
     private static final String ATT_ENABLED = "enabled";
-    private static final String ATT_USER_ALLOWED = "allowed";
     private static final String ATT_HIDE_SILENT = "hide_gentle";
     private static final String ATT_SENT_INVALID_MESSAGE = "sent_invalid_msg";
     private static final String ATT_SENT_VALID_MESSAGE = "sent_valid_msg";
@@ -363,15 +362,12 @@
                     String delegateName = XmlUtils.readStringAttribute(parser, ATT_NAME);
                     boolean delegateEnabled = parser.getAttributeBoolean(
                             null, ATT_ENABLED, Delegate.DEFAULT_ENABLED);
-                    boolean userAllowed = parser.getAttributeBoolean(
-                            null, ATT_USER_ALLOWED, Delegate.DEFAULT_USER_ALLOWED);
                     Delegate d = null;
                     if (delegateId != UNKNOWN_UID && !TextUtils.isEmpty(delegateName)) {
-                        d = new Delegate(delegateName, delegateId, delegateEnabled, userAllowed);
+                        d = new Delegate(delegateName, delegateId, delegateEnabled);
                     }
                     r.delegate = d;
                 }
-
             }
 
             try {
@@ -640,9 +636,6 @@
                     if (r.delegate.mEnabled != Delegate.DEFAULT_ENABLED) {
                         out.attributeBoolean(null, ATT_ENABLED, r.delegate.mEnabled);
                     }
-                    if (r.delegate.mUserAllowed != Delegate.DEFAULT_USER_ALLOWED) {
-                        out.attributeBoolean(null, ATT_USER_ALLOWED, r.delegate.mUserAllowed);
-                    }
                     out.endTag(null, TAG_DELEGATE);
                 }
 
@@ -725,10 +718,17 @@
 
     @Override
     public void setShowBadge(String packageName, int uid, boolean showBadge) {
+        boolean changed = false;
         synchronized (mPackagePreferences) {
-            getOrCreatePackagePreferencesLocked(packageName, uid).showBadge = showBadge;
+            PackagePreferences pkgPrefs = getOrCreatePackagePreferencesLocked(packageName, uid);
+            if (pkgPrefs.showBadge != showBadge) {
+                pkgPrefs.showBadge = showBadge;
+                changed = true;
+            }
         }
-        updateConfig();
+        if (changed) {
+            updateConfig();
+        }
     }
 
     public boolean isInInvalidMsgState(String packageName, int uid) {
@@ -862,11 +862,11 @@
             if (r == null) {
                 throw new IllegalArgumentException("Invalid package");
             }
+            if (r.groups.size() >= NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT) {
+                throw new IllegalStateException("Limit exceed; cannot create more groups");
+            }
             if (fromTargetApp) {
                 group.setBlocked(false);
-                if (r.groups.size() >= NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT) {
-                    throw new IllegalStateException("Limit exceed; cannot create more groups");
-                }
             }
             final NotificationChannelGroup oldGroup = r.groups.get(group.getId());
             if (oldGroup != null) {
@@ -985,7 +985,9 @@
                     needsPolicyFileChange = true;
                 }
 
-                updateConfig();
+                if (needsPolicyFileChange) {
+                    updateConfig();
+                }
                 if (needsPolicyFileChange && !wasUndeleted) {
                     mNotificationChannelLogger.logNotificationChannelModified(existing, uid, pkg,
                             previousLoggingImportance, false);
@@ -1072,6 +1074,7 @@
             boolean fromUser) {
         Objects.requireNonNull(updatedChannel);
         Objects.requireNonNull(updatedChannel.getId());
+        boolean changed = false;
         boolean needsDndChange = false;
         synchronized (mPackagePreferences) {
             PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
@@ -1105,6 +1108,7 @@
                         ? Notification.PRIORITY_MAX : Notification.PRIORITY_DEFAULT;
                 r.visibility = updatedChannel.getLockscreenVisibility();
                 r.showBadge = updatedChannel.canShowBadge();
+                changed = true;
             }
 
             if (!channel.equals(updatedChannel)) {
@@ -1113,17 +1117,21 @@
                         .setSubtype(fromUser ? 1 : 0));
                 mNotificationChannelLogger.logNotificationChannelModified(updatedChannel, uid, pkg,
                         NotificationChannelLogger.getLoggingImportance(channel), fromUser);
+                changed = true;
             }
 
             if (updatedChannel.canBypassDnd() != mAreChannelsBypassingDnd
                     || channel.getImportance() != updatedChannel.getImportance()) {
                 needsDndChange = true;
+                changed = true;
             }
         }
         if (needsDndChange) {
             updateChannelsBypassingDnd();
         }
-        updateConfig();
+        if (changed) {
+            updateConfig();
+        }
     }
 
     @Override
@@ -1788,7 +1796,7 @@
             if (prefs == null || prefs.delegate == null) {
                 return null;
             }
-            if (!prefs.delegate.mUserAllowed || !prefs.delegate.mEnabled) {
+            if (!prefs.delegate.mEnabled) {
                 return null;
             }
             return prefs.delegate.mPkg;
@@ -1802,46 +1810,20 @@
             String delegatePkg, int delegateUid) {
         synchronized (mPackagePreferences) {
             PackagePreferences prefs = getOrCreatePackagePreferencesLocked(sourcePkg, sourceUid);
-
-            boolean userAllowed = prefs.delegate == null || prefs.delegate.mUserAllowed;
-            Delegate delegate = new Delegate(delegatePkg, delegateUid, true, userAllowed);
-            prefs.delegate = delegate;
+            prefs.delegate = new Delegate(delegatePkg, delegateUid, true);
         }
-        updateConfig();
     }
 
     /**
      * Used by an app to turn off its notification delegate.
      */
     public void revokeNotificationDelegate(String sourcePkg, int sourceUid) {
-        boolean changed = false;
         synchronized (mPackagePreferences) {
             PackagePreferences prefs = getPackagePreferencesLocked(sourcePkg, sourceUid);
             if (prefs != null && prefs.delegate != null) {
                 prefs.delegate.mEnabled = false;
-                changed = true;
             }
         }
-        if (changed) {
-            updateConfig();
-        }
-    }
-
-    /**
-     * Toggles whether an app can have a notification delegate on behalf of a user.
-     */
-    public void toggleNotificationDelegate(String sourcePkg, int sourceUid, boolean userAllowed) {
-        boolean changed = false;
-        synchronized (mPackagePreferences) {
-            PackagePreferences prefs = getPackagePreferencesLocked(sourcePkg, sourceUid);
-            if (prefs != null && prefs.delegate != null) {
-                prefs.delegate.mUserAllowed = userAllowed;
-                changed = true;
-            }
-        }
-        if (changed) {
-            updateConfig();
-        }
     }
 
     /**
@@ -2726,17 +2708,15 @@
 
     private static class Delegate {
         static final boolean DEFAULT_ENABLED = true;
-        static final boolean DEFAULT_USER_ALLOWED = true;
-        String mPkg;
-        int mUid = UNKNOWN_UID;
-        boolean mEnabled = DEFAULT_ENABLED;
-        boolean mUserAllowed = DEFAULT_USER_ALLOWED;
 
-        Delegate(String pkg, int uid, boolean enabled, boolean userAllowed) {
+        final String mPkg;
+        final int mUid;
+        boolean mEnabled;
+
+        Delegate(String pkg, int uid, boolean enabled) {
             mPkg = pkg;
             mUid = uid;
             mEnabled = enabled;
-            mUserAllowed = userAllowed;
         }
 
         public boolean isAllowed(String pkg, int uid) {
@@ -2745,7 +2725,7 @@
             }
             return pkg.equals(mPkg)
                     && uid == mUid
-                    && (mUserAllowed && mEnabled);
+                    && mEnabled;
         }
     }
 }
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 4b2c88c..2774462 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -20,7 +20,7 @@
 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_ENABLED;
 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_REMOVED;
 import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY;
-import static android.service.notification.DNDModeProto.ROOT_CONFIG;
+import static android.service.notification.NotificationServiceProto.ROOT_CONFIG;
 import static android.util.StatsLog.ANNOTATION_ID_IS_UID;
 
 import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;
diff --git a/services/core/java/com/android/server/pm/Computer.java b/services/core/java/com/android/server/pm/Computer.java
index fac7748..c232b36 100644
--- a/services/core/java/com/android/server/pm/Computer.java
+++ b/services/core/java/com/android/server/pm/Computer.java
@@ -678,8 +678,4 @@
 
     @NonNull
     Collection<SharedUserSetting> getAllSharedUsers();
-
-    boolean isChangeEnabled(long changeId, int uid);
-
-    boolean isChangeEnabled(long changeId, ApplicationInfo info);
 }
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index 21f661b..5984360 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -125,7 +125,6 @@
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
 import com.android.modules.utils.TypedXmlSerializer;
-import com.android.server.compat.PlatformCompat;
 import com.android.server.pm.Installer.LegacyDexoptDisabledException;
 import com.android.server.pm.dex.DexManager;
 import com.android.server.pm.dex.PackageDexUsage;
@@ -575,7 +574,8 @@
                     list = new ArrayList<>(1);
                     list.add(ri);
                     PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
-                            this, list, false, intent, resolvedType, filterCallingUid);
+                            mInjector.getCompatibility(), mComponentResolver,
+                            list, false, intent, resolvedType, filterCallingUid);
                 }
             }
         } else {
@@ -591,7 +591,7 @@
                     String callingPkgName = getInstantAppPackageName(filterCallingUid);
                     boolean isRequesterInstantApp = isInstantApp(callingPkgName, userId);
                     lockedResult.result = maybeAddInstantAppInstaller(
-                            lockedResult.result, intent, resolvedType, flags, filterCallingUid,
+                            lockedResult.result, intent, resolvedType, flags,
                             userId, resolveForStart, isRequesterInstantApp);
                 }
                 if (lockedResult.sortResult) {
@@ -604,7 +604,8 @@
         if (originalIntent != null) {
             // We also have to ensure all components match the original intent
             PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
-                    this, list, false, originalIntent, resolvedType, filterCallingUid);
+                    mInjector.getCompatibility(), mComponentResolver,
+                    list, false, originalIntent, resolvedType, filterCallingUid);
         }
 
         return skipPostResolution ? list : applyPostResolutionFilter(
@@ -686,7 +687,8 @@
                     list = new ArrayList<>(1);
                     list.add(ri);
                     PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
-                            this, list, false, intent, resolvedType, callingUid);
+                            mInjector.getCompatibility(), mComponentResolver,
+                            list, false, intent, resolvedType, callingUid);
                 }
             }
         } else {
@@ -697,7 +699,8 @@
         if (originalIntent != null) {
             // We also have to ensure all components match the original intent
             PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
-                    this, list, false, originalIntent, resolvedType, callingUid);
+                    mInjector.getCompatibility(), mComponentResolver,
+                    list, false, originalIntent, resolvedType, callingUid);
         }
 
         return list;
@@ -710,7 +713,7 @@
         String pkgName = intent.getPackage();
         if (pkgName == null) {
             final List<ResolveInfo> resolveInfos = mComponentResolver.queryServices(this, intent,
-                    resolvedType, flags, callingUid, userId);
+                    resolvedType, flags, userId);
             if (resolveInfos == null) {
                 return Collections.emptyList();
             }
@@ -720,7 +723,7 @@
         final AndroidPackage pkg = mPackages.get(pkgName);
         if (pkg != null) {
             final List<ResolveInfo> resolveInfos = mComponentResolver.queryServices(this, intent,
-                    resolvedType, flags, pkg.getServices(), callingUid,
+                    resolvedType, flags, pkg.getServices(),
                     userId);
             if (resolveInfos == null) {
                 return Collections.emptyList();
@@ -750,7 +753,7 @@
                  {@link PackageManager.SKIP_CURRENT_PROFILE} set.
                  */
                 result.addAll(filterIfNotSystemUser(mComponentResolver.queryActivities(this,
-                        intent, resolvedType, flags, filterCallingUid, userId), userId));
+                        intent, resolvedType, flags, userId), userId));
             }
             addInstant = isInstantAppResolutionAllowed(intent, result, userId,
                     false /*skipPackageCheck*/, flags);
@@ -774,7 +777,7 @@
                     || !shouldFilterApplication(setting, filterCallingUid, userId))) {
                 result.addAll(filterIfNotSystemUser(mComponentResolver.queryActivities(this,
                         intent, resolvedType, flags, setting.getAndroidPackage().getActivities(),
-                        filterCallingUid, userId), userId));
+                        userId), userId));
             }
             if (result == null || result.size() == 0) {
                 // the caller wants to resolve for a particular package; however, there
@@ -1105,7 +1108,7 @@
             return null;
         }
         List<ResolveInfo> resultTargetUser = mComponentResolver.queryActivities(this, intent,
-                resolvedType, flags, Binder.getCallingUid(), parentUserId);
+                resolvedType, flags, parentUserId);
 
         if (resultTargetUser == null || resultTargetUser.isEmpty()) {
             return null;
@@ -1343,7 +1346,7 @@
 
     private List<ResolveInfo> maybeAddInstantAppInstaller(List<ResolveInfo> result,
             Intent intent, String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags,
-            int callingUid, int userId, boolean resolveForStart, boolean isRequesterInstantApp) {
+            int userId, boolean resolveForStart, boolean isRequesterInstantApp) {
         // first, check to see if we've got an instant app already installed
         final boolean alreadyResolvedLocally = (flags & PackageManager.MATCH_INSTANT) != 0;
         ResolveInfo localInstantApp = null;
@@ -1356,7 +1359,6 @@
                             | PackageManager.GET_RESOLVED_FILTER
                             | PackageManager.MATCH_INSTANT
                             | PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY,
-                    callingUid,
                     userId);
             for (int i = instantApps.size() - 1; i >= 0; --i) {
                 final ResolveInfo info = instantApps.get(i);
@@ -3691,13 +3693,10 @@
                 ps, callingUid, component, TYPE_ACTIVITY, userId, true /* filterUninstall */)) {
             return false;
         }
-        final boolean callerBlocksNullAction = isChangeEnabled(
-                IntentFilter.BLOCK_NULL_ACTION_INTENTS, callingUid);
         for (int i=0; i< a.getIntents().size(); i++) {
             if (a.getIntents().get(i).getIntentFilter()
                     .match(intent.getAction(), resolvedType, intent.getScheme(),
-                            intent.getData(), intent.getCategories(), TAG,
-                            /*supportWildcards*/ false, callerBlocksNullAction, null, null) >= 0) {
+                            intent.getData(), intent.getCategories(), TAG) >= 0) {
                 return true;
             }
         }
@@ -5795,37 +5794,4 @@
     public UserInfo[] getUserInfos() {
         return mInjector.getUserManagerInternal().getUserInfos();
     }
-
-    @Override
-    public boolean isChangeEnabled(long changeId, int uid) {
-        final PlatformCompat compat = mInjector.getCompatibility();
-        int appId = UserHandle.getAppId(uid);
-        SettingBase s = mSettings.getSettingBase(appId);
-        if (s instanceof PackageSetting) {
-            var ps = (PackageSetting) s;
-            if (ps.getAndroidPackage() == null) return false;
-            var info = new ApplicationInfo();
-            info.packageName = ps.getPackageName();
-            info.targetSdkVersion = ps.getAndroidPackage().getTargetSdkVersion();
-            return compat.isChangeEnabledInternal(changeId, info);
-        } else if (s instanceof SharedUserSetting) {
-            var ss = (SharedUserSetting) s;
-            List<AndroidPackage> packages = ss.getPackages();
-            for (int i = 0; i < packages.size(); ++i) {
-                var pkg = packages.get(i);
-                var info = new ApplicationInfo();
-                info.packageName = pkg.getPackageName();
-                info.targetSdkVersion = pkg.getTargetSdkVersion();
-                if (compat.isChangeEnabledInternal(changeId, info)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public boolean isChangeEnabled(long changeId, ApplicationInfo info) {
-        return mInjector.getCompatibility().isChangeEnabledInternal(changeId, info);
-    }
 }
diff --git a/services/core/java/com/android/server/pm/DefaultCrossProfileResolver.java b/services/core/java/com/android/server/pm/DefaultCrossProfileResolver.java
index ee8f560..90d89c6 100644
--- a/services/core/java/com/android/server/pm/DefaultCrossProfileResolver.java
+++ b/services/core/java/com/android/server/pm/DefaultCrossProfileResolver.java
@@ -23,7 +23,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
-import android.os.Binder;
 import android.util.SparseBooleanArray;
 
 import com.android.internal.app.IntentForwarderActivity;
@@ -279,7 +278,7 @@
         }
 
         List<ResolveInfo> resultTargetUser = mComponentResolver.queryActivities(computer, intent,
-                resolvedType, flags, Binder.getCallingUid(), targetUserId);
+                resolvedType, flags, targetUserId);
         if (CollectionUtils.isEmpty(resultTargetUser)) {
             return null;
         }
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index a868470..7fe6c7d 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -164,6 +164,7 @@
 import com.android.server.EventLogTags;
 import com.android.server.LocalManagerRegistry;
 import com.android.server.art.model.DexoptParams;
+import com.android.server.art.model.DexoptResult;
 import com.android.server.pm.Installer.LegacyDexoptDisabledException;
 import com.android.server.pm.dex.ArtManagerService;
 import com.android.server.pm.dex.DexManager;
@@ -2534,8 +2535,9 @@
                                     packageManagerLocal.withFilteredSnapshot()) {
                         DexoptParams params =
                                 dexoptOptions.convertToDexoptParams(0 /* extraFlags */);
-                        DexOptHelper.getArtManagerLocal().dexoptPackage(
+                        DexoptResult dexOptResult = DexOptHelper.getArtManagerLocal().dexoptPackage(
                                 snapshot, packageName, params);
+                        installRequest.onDexoptFinished(dexOptResult);
                     }
                 } else {
                     try {
diff --git a/services/core/java/com/android/server/pm/InstallRequest.java b/services/core/java/com/android/server/pm/InstallRequest.java
index 46ea010..95e7904 100644
--- a/services/core/java/com/android/server/pm/InstallRequest.java
+++ b/services/core/java/com/android/server/pm/InstallRequest.java
@@ -43,6 +43,7 @@
 import android.util.ExceptionUtils;
 import android.util.Slog;
 
+import com.android.server.art.model.DexoptResult;
 import com.android.server.pm.parsing.pkg.ParsedPackage;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageState;
@@ -127,6 +128,8 @@
     private final int mSessionId;
     private final int mRequireUserAction;
 
+    private int mDexoptStatus;
+
     // New install
     InstallRequest(InstallingSession params) {
         mUserId = params.getUser().getIdentifier();
@@ -609,6 +612,10 @@
         return mRequireUserAction;
     }
 
+    public int getDexoptStatus() {
+        return mDexoptStatus;
+    }
+
     public void setScanFlags(int scanFlags) {
         mScanFlags = scanFlags;
     }
@@ -799,6 +806,25 @@
         }
     }
 
+    public void onDexoptFinished(DexoptResult dexoptResult) {
+        if (mPackageMetrics == null) {
+            return;
+        }
+        mDexoptStatus = dexoptResult.getFinalStatus();
+        if (mDexoptStatus != DexoptResult.DEXOPT_PERFORMED) {
+            return;
+        }
+        long durationMillis = 0;
+        for (DexoptResult.PackageDexoptResult packageResult :
+                dexoptResult.getPackageDexoptResults()) {
+            for (DexoptResult.DexContainerFileDexoptResult fileResult :
+                    packageResult.getDexContainerFileDexoptResults()) {
+                durationMillis += fileResult.getDex2oatWallTimeMillis();
+            }
+        }
+        mPackageMetrics.onStepFinished(PackageMetrics.STEP_DEXOPT, durationMillis);
+    }
+
     public void onInstallCompleted() {
         if (getReturnCode() == INSTALL_SUCCEEDED) {
             if (mPackageMetrics != null) {
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 9329f06..0d417e4 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -136,9 +136,7 @@
     }
 
     /**
-     * @param isolated indicates if this object should <em>not</em> connect to
-     *            the real {@code installd}. All remote calls will be ignored
-     *            unless you extend this class and intercept them.
+     * @param isolated Make the installer isolated. See {@link isIsolated}.
      */
     public Installer(Context context, boolean isolated) {
         super(context);
@@ -153,6 +151,15 @@
         mWarnIfHeld = warnIfHeld;
     }
 
+    /**
+     * Returns true if the installer is isolated, i.e. if this object should <em>not</em> connect to
+     * the real {@code installd}. All remote calls will be ignored unless you extend this class and
+     * intercept them.
+     */
+    public boolean isIsolated() {
+        return mIsolated;
+    }
+
     @Override
     public void onStart() {
         if (mIsolated) {
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 9e01c7a..84bee50 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -39,6 +39,7 @@
 import android.app.AppGlobals;
 import android.app.IApplicationThread;
 import android.app.PendingIntent;
+import android.app.admin.DevicePolicyCache;
 import android.app.admin.DevicePolicyManager;
 import android.app.usage.UsageStatsManagerInternal;
 import android.content.ActivityNotFoundException;
@@ -85,6 +86,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Pair;
 import android.util.Slog;
@@ -107,6 +109,7 @@
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.ExecutionException;
 
@@ -623,7 +626,7 @@
                     // package does not exist; should not happen
                     return null;
                 }
-                return new LauncherActivityInfoInternal(activityInfo, incrementalStatesInfo);
+                return new LauncherActivityInfoInternal(activityInfo, incrementalStatesInfo, user);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -676,7 +679,7 @@
                     continue;
                 }
                 results.add(new LauncherActivityInfoInternal(ri.activityInfo,
-                        incrementalStatesInfo));
+                        incrementalStatesInfo, user));
             }
             return results;
         }
@@ -1078,6 +1081,55 @@
         }
 
         @Override
+        @NonNull
+        public Map<String, LauncherActivityInfoInternal> getActivityOverrides(String callingPackage,
+                int userId) {
+            ensureShortcutPermission(callingPackage);
+            int callingUid = Binder.getCallingUid();
+            final long callerIdentity = Binder.clearCallingIdentity();
+            try {
+                Map<String, LauncherActivityInfoInternal> shortcutOverridesInfo = new ArrayMap<>();
+                UserHandle managedUserHandle = getManagedProfile(userId);
+                if (managedUserHandle == null) {
+                    return shortcutOverridesInfo;
+                }
+
+                List<String> packagesToOverride =
+                        DevicePolicyCache.getInstance().getLauncherShortcutOverrides();
+                for (String packageName : packagesToOverride) {
+                    Intent intent = new Intent(Intent.ACTION_MAIN)
+                            .addCategory(Intent.CATEGORY_LAUNCHER)
+                            .setPackage(packageName);
+
+                    List<LauncherActivityInfoInternal> possibleShortcutOverrides =
+                            queryIntentLauncherActivities(
+                                    intent,
+                                    callingUid,
+                                    managedUserHandle
+                            );
+
+                    if (!possibleShortcutOverrides.isEmpty()) {
+                        shortcutOverridesInfo.put(packageName, possibleShortcutOverrides.get(0));
+                    }
+                }
+                return shortcutOverridesInfo;
+            } finally {
+                Binder.restoreCallingIdentity(callerIdentity);
+            }
+        }
+
+
+        @Nullable
+        private UserHandle getManagedProfile(int userId) {
+            for (UserInfo profile : mUm.getProfiles(userId)) {
+                if (profile.isManagedProfile()) {
+                    return profile.getUserHandle();
+                }
+            }
+            return null;
+        }
+
+        @Override
         public boolean startShortcut(String callingPackage, String packageName, String featureId,
                 String shortcutId, Rect sourceBounds, Bundle startActivityOptions,
                 int targetUserId) {
diff --git a/services/core/java/com/android/server/pm/NoFilteringResolver.java b/services/core/java/com/android/server/pm/NoFilteringResolver.java
index e53e756..3923890 100644
--- a/services/core/java/com/android/server/pm/NoFilteringResolver.java
+++ b/services/core/java/com/android/server/pm/NoFilteringResolver.java
@@ -102,7 +102,7 @@
             boolean hasNonNegativePriorityResult,
             Function<String, PackageStateInternal> pkgSettingFunction) {
         List<ResolveInfo> resolveInfos = mComponentResolver.queryActivities(computer,
-                intent, resolvedType, flags, Binder.getCallingUid(), targetUserId);
+                intent, resolvedType, flags, targetUserId);
         List<CrossProfileDomainInfo> crossProfileDomainInfos = new ArrayList<>();
         if (resolveInfos != null) {
 
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 767c0a7..6a2ddc8 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.pm;
 
+import static com.android.server.pm.DexOptHelper.useArtService;
 import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
 import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
@@ -301,6 +302,15 @@
                     throws InstallerException {
                 final StringBuilder builder = new StringBuilder();
 
+                if (useArtService()) {
+                    if ((dexFlags & DEXOPT_SECONDARY_DEX) != 0) {
+                        // installd may change the reference profile in place for secondary dex
+                        // files, which isn't safe with the lock free approach in ART Service.
+                        throw new IllegalArgumentException(
+                                "Invalid OTA dexopt call for secondary dex");
+                    }
+                }
+
                 // The current version. For v10, see b/115993344.
                 builder.append("10 ");
 
@@ -353,7 +363,6 @@
         PackageDexOptimizer optimizer = new OTADexoptPackageDexOptimizer(
                 collectingInstaller, mPackageManagerService.mInstallLock, mContext);
 
-        // TODO(b/251903639): Allow this use of legacy dexopt code even when ART Service is enabled.
         try {
             optimizer.performDexOpt(pkg, pkgSetting, null /* ISAs */,
                     null /* CompilerStats.PackageStats */,
@@ -362,9 +371,19 @@
                     new DexoptOptions(pkg.getPackageName(), compilationReason,
                             DexoptOptions.DEXOPT_BOOT_COMPLETE));
         } catch (LegacyDexoptDisabledException e) {
-            throw new RuntimeException(e);
+            // OTA is still allowed to use the legacy dexopt code even when ART Service is enabled.
+            // The installer is isolated and won't call into installd, and the dexopt() method is
+            // overridden to only collect the command above. Hence we shouldn't go into any code
+            // path where this exception is thrown.
+            Slog.wtf(TAG, e);
         }
 
+        // ART Service compat note: These commands are consumed by the otapreopt binary, which uses
+        // the same legacy dexopt code as installd to invoke dex2oat. It provides output path
+        // implementations (see calculate_odex_file_path and create_cache_path in
+        // frameworks/native/cmds/installd/otapreopt.cpp) to write to different odex files than
+        // those used by ART Service in its ordinary operations, so it doesn't interfere with ART
+        // Service even when dalvik.vm.useartservice is true.
         return commands;
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 0a90e7a3..8a4080f 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -18,6 +18,7 @@
 
 import static android.content.pm.ApplicationInfo.HIDDEN_API_ENFORCEMENT_DISABLED;
 
+import static com.android.server.pm.DexOptHelper.useArtService;
 import static com.android.server.pm.Installer.DEXOPT_BOOTCOMPLETE;
 import static com.android.server.pm.Installer.DEXOPT_DEBUGGABLE;
 import static com.android.server.pm.Installer.DEXOPT_ENABLE_HIDDEN_API_CHECKS;
@@ -329,8 +330,22 @@
 
             String profileName = ArtManager.getProfileName(
                     i == 0 ? null : pkg.getSplitNames()[i - 1]);
-            final boolean isUsedByOtherApps = options.isDexoptAsSharedLibrary()
-                    || packageUseInfo.isUsedByOtherApps(path);
+
+            final boolean isUsedByOtherApps;
+            if (options.isDexoptAsSharedLibrary()) {
+                isUsedByOtherApps = true;
+            } else if (useArtService()) {
+                // We get here when collecting dexopt commands in OTA preopt, even when ART Service
+                // is in use. packageUseInfo isn't useful in that case since the legacy dex use
+                // database hasn't been updated. So we'd have to query ART Service instead, but it
+                // doesn't provide that API. Just cop-out and bypass the cloud profile handling.
+                // That means such apps will get preopted wrong, and we'll leave it to a later
+                // background dexopt after reboot instead.
+                isUsedByOtherApps = false;
+            } else {
+                isUsedByOtherApps = packageUseInfo.isUsedByOtherApps(path);
+            }
+
             String compilerFilter = getRealCompilerFilter(pkg, options.getCompilerFilter());
             // If the app is used by other apps, we must not use the existing profile because it
             // may contain user data, unless the profile is newly created on install.
@@ -446,6 +461,14 @@
     private boolean prepareCloudProfile(AndroidPackage pkg, String profileName, String path,
             @Nullable String dexMetadataPath) throws LegacyDexoptDisabledException {
         if (dexMetadataPath != null) {
+            if (mInstaller.isIsolated()) {
+                // If the installer is isolated, the two calls to it below will return immediately,
+                // so this only short-circuits that a bit. We need to do it to avoid the
+                // LegacyDexoptDisabledException getting thrown first, when we get here during OTA
+                // preopt and ART Service is enabled.
+                return true;
+            }
+
             try {
                 // Make sure we don't keep any existing contents.
                 mInstaller.deleteReferenceProfile(pkg.getPackageName(), profileName);
@@ -879,7 +902,12 @@
     private int getDexoptNeeded(String packageName, String path, String isa, String compilerFilter,
             String classLoaderContext, int profileAnalysisResult, boolean downgrade,
             int dexoptFlags, String oatDir) throws LegacyDexoptDisabledException {
-        Installer.checkLegacyDexoptDisabled();
+        // Allow calls from OtaDexoptService even when ART Service is in use. The installer is
+        // isolated in that case so later calls to it won't call into installd anyway.
+        if (!mInstaller.isIsolated()) {
+            Installer.checkLegacyDexoptDisabled();
+        }
+
         final boolean shouldBePublic = (dexoptFlags & DEXOPT_PUBLIC) != 0;
         final boolean isProfileGuidedFilter = (dexoptFlags & DEXOPT_PROFILE_GUIDED) != 0;
         boolean newProfile = profileAnalysisResult == PROFILE_ANALYSIS_OPTIMIZE;
@@ -948,6 +976,8 @@
      */
     private int analyseProfiles(AndroidPackage pkg, int uid, String profileName,
             String compilerFilter) throws LegacyDexoptDisabledException {
+        Installer.checkLegacyDexoptDisabled();
+
         // Check if we are allowed to merge and if the compiler filter is profile guided.
         if (!isProfileGuidedCompilerFilter(compilerFilter)) {
             return PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index de5f0c4..d3ee52c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -7218,6 +7218,7 @@
      * TODO(b/182523293): This should be removed once we finish migration of permission storage.
      */
     void writeSettingsLPrTEMP(boolean sync) {
+        snapshotComputer(false);
         mPermissionManager.writeLegacyPermissionsTEMP(mSettings.mPermissions);
         mSettings.writeLPr(mLiveComputer, sync);
     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 9036d4c..3f9a0bc 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -16,7 +16,6 @@
 
 package com.android.server.pm;
 
-import static android.content.IntentFilter.BLOCK_NULL_ACTION_INTENTS;
 import static android.content.pm.PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
 import static android.content.pm.PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
 import static android.content.pm.PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
@@ -25,6 +24,7 @@
 import static android.system.OsConstants.O_RDWR;
 
 import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
+import static com.android.internal.util.FrameworkStatsLog.UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__EXPLICIT_INTENT_FILTER_UNMATCH;
 import static com.android.server.LocalManagerRegistry.ManagerNotFoundException;
 import static com.android.server.pm.PackageManagerService.COMPRESSED_EXTENSION;
 import static com.android.server.pm.PackageManagerService.DEBUG_COMPRESSION;
@@ -95,6 +95,8 @@
 import com.android.server.IntentResolver;
 import com.android.server.LocalManagerRegistry;
 import com.android.server.Watchdog;
+import com.android.server.am.ActivityManagerUtils;
+import com.android.server.compat.PlatformCompat;
 import com.android.server.pm.dex.PackageDexUsage;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageStateInternal;
@@ -1166,8 +1168,10 @@
         return (ps.getFlags() & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
     }
 
+    // Static to give access to ComputeEngine
     public static void applyEnforceIntentFilterMatching(
-            Computer computer, List<ResolveInfo> resolveInfos, boolean isReceiver,
+            PlatformCompat compat, ComponentResolverApi resolver,
+            List<ResolveInfo> resolveInfos, boolean isReceiver,
             Intent intent, String resolvedType, int filterCallingUid) {
         if (DISABLE_ENFORCE_INTENTS_TO_MATCH_INTENT_FILTERS.get()) return;
 
@@ -1175,11 +1179,6 @@
                 ? new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM)
                 : null;
 
-        final boolean callerBlocksNullAction = computer.isChangeEnabled(
-                BLOCK_NULL_ACTION_INTENTS, filterCallingUid);
-
-        final ComponentResolverApi resolver = computer.getComponentResolver();
-
         for (int i = resolveInfos.size() - 1; i >= 0; --i) {
             final ComponentInfo info = resolveInfos.get(i).getComponentInfo();
 
@@ -1189,16 +1188,6 @@
                 continue;
             }
 
-            // Only enforce filter matching if target app's target SDK >= T
-            if (!computer.isChangeEnabled(
-                    ENFORCE_INTENTS_TO_MATCH_INTENT_FILTERS, info.applicationInfo)) {
-                continue;
-            }
-
-            // Block null action intent if either source or target app's target SDK >= U
-            final boolean blockNullAction = callerBlocksNullAction
-                    || computer.isChangeEnabled(BLOCK_NULL_ACTION_INTENTS, info.applicationInfo);
-
             final ParsedMainComponent comp;
             if (info instanceof ActivityInfo) {
                 if (isReceiver) {
@@ -1217,24 +1206,32 @@
                 continue;
             }
 
+            // Only enforce filter matching if target app's target SDK >= T
+            final boolean enforce = compat.isChangeEnabledInternal(
+                    ENFORCE_INTENTS_TO_MATCH_INTENT_FILTERS, info.applicationInfo);
+
             boolean match = false;
             for (int j = 0, size = comp.getIntents().size(); j < size; ++j) {
                 IntentFilter intentFilter = comp.getIntents().get(j).getIntentFilter();
-                if (IntentResolver.intentMatchesFilter(
-                        intentFilter, intent, resolvedType, blockNullAction)) {
+                if (IntentResolver.intentMatchesFilter(intentFilter, intent, resolvedType)) {
                     match = true;
                     break;
                 }
             }
             if (!match) {
-                Slog.w(TAG, "Intent does not match component's intent filter: " + intent);
-                Slog.w(TAG, "Access blocked: " + comp.getComponentName());
-                if (DEBUG_INTENT_MATCHING) {
-                    Slog.v(TAG, "Component intent filters:");
-                    comp.getIntents().forEach(f -> f.getIntentFilter().dump(logPrinter, "  "));
-                    Slog.v(TAG, "-----------------------------");
+                ActivityManagerUtils.logUnsafeIntentEvent(
+                        UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__EXPLICIT_INTENT_FILTER_UNMATCH,
+                        filterCallingUid, intent, resolvedType, enforce);
+                if (enforce) {
+                    Slog.w(TAG, "Intent does not match component's intent filter: " + intent);
+                    Slog.w(TAG, "Access blocked: " + comp.getComponentName());
+                    if (DEBUG_INTENT_MATCHING) {
+                        Slog.v(TAG, "Component intent filters:");
+                        comp.getIntents().forEach(f -> f.getIntentFilter().dump(logPrinter, "  "));
+                        Slog.v(TAG, "-----------------------------");
+                    }
+                    resolveInfos.remove(i);
                 }
-                resolveInfos.remove(i);
             }
         }
     }
diff --git a/services/core/java/com/android/server/pm/PackageMetrics.java b/services/core/java/com/android/server/pm/PackageMetrics.java
index fe014a4..80d6ebb 100644
--- a/services/core/java/com/android/server/pm/PackageMetrics.java
+++ b/services/core/java/com/android/server/pm/PackageMetrics.java
@@ -48,12 +48,14 @@
     public static final int STEP_SCAN = 2;
     public static final int STEP_RECONCILE = 3;
     public static final int STEP_COMMIT = 4;
+    public static final int STEP_DEXOPT = 5;
 
     @IntDef(prefix = {"STEP_"}, value = {
             STEP_PREPARE,
             STEP_SCAN,
             STEP_RECONCILE,
             STEP_COMMIT,
+            STEP_DEXOPT
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface StepInt {
@@ -175,6 +177,10 @@
         }
     }
 
+    public void onStepFinished(@StepInt int step, long durationMillis) {
+        mInstallSteps.put(step, new InstallStep(durationMillis));
+    }
+
     // List of steps (e.g., 1, 2, 3) and corresponding list of durations (e.g., 200ms, 100ms, 150ms)
     private Pair<int[], long[]> getInstallStepDurations() {
         ArrayList<Integer> steps = new ArrayList<>();
@@ -203,6 +209,11 @@
             mStartTimestampMillis = System.currentTimeMillis();
         }
 
+        InstallStep(long durationMillis) {
+            mStartTimestampMillis = -1;
+            mDurationMillis = durationMillis;
+        }
+
         void finish() {
             mDurationMillis = System.currentTimeMillis() - mStartTimestampMillis;
         }
diff --git a/services/core/java/com/android/server/pm/ResilientAtomicFile.java b/services/core/java/com/android/server/pm/ResilientAtomicFile.java
new file mode 100644
index 0000000..19aa4f8
--- /dev/null
+++ b/services/core/java/com/android/server/pm/ResilientAtomicFile.java
@@ -0,0 +1,265 @@
+/*
+ * 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;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.FileUtils;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+import android.util.Slog;
+
+import com.android.server.security.FileIntegrity;
+
+import libcore.io.IoUtils;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+final class ResilientAtomicFile implements Closeable {
+    private static final String LOG_TAG = "ResilientAtomicFile";
+
+    private final File mFile;
+
+    private final File mTemporaryBackup;
+
+    private final File mReserveCopy;
+
+    private final int mFileMode;
+
+    private final String mDebugName;
+
+    private final ReadEventLogger mReadEventLogger;
+
+    // Write state.
+    private FileOutputStream mMainOutStream = null;
+    private FileInputStream mMainInStream = null;
+    private FileOutputStream mReserveOutStream = null;
+    private FileInputStream mReserveInStream = null;
+
+    // Read state.
+    private File mCurrentFile = null;
+    private FileInputStream mCurrentInStream = null;
+
+    private void finalizeOutStream(FileOutputStream str) throws IOException {
+        // Flash/sync + set permissions.
+        str.flush();
+        FileUtils.sync(str);
+        FileUtils.setPermissions(str.getFD(), mFileMode, -1, -1);
+    }
+
+    ResilientAtomicFile(@NonNull File file, @NonNull File temporaryBackup,
+            @NonNull File reserveCopy, int fileMode, String debugName,
+            @Nullable ReadEventLogger readEventLogger) {
+        mFile = file;
+        mTemporaryBackup = temporaryBackup;
+        mReserveCopy = reserveCopy;
+        mFileMode = fileMode;
+        mDebugName = debugName;
+        mReadEventLogger = readEventLogger;
+    }
+
+    public File getBaseFile() {
+        return mFile;
+    }
+
+    public FileOutputStream startWrite() throws IOException {
+        if (mMainOutStream != null) {
+            throw new IllegalStateException("Duplicate startWrite call?");
+        }
+
+        new File(mFile.getParent()).mkdirs();
+
+        if (mFile.exists()) {
+            // Presence of backup settings file indicates that we failed
+            // to persist packages earlier. So preserve the older
+            // backup for future reference since the current packages
+            // might have been corrupted.
+            if (!mTemporaryBackup.exists()) {
+                if (!mFile.renameTo(mTemporaryBackup)) {
+                    throw new IOException("Unable to backup " + mDebugName
+                            + " file, current changes will be lost at reboot");
+                }
+            } else {
+                mFile.delete();
+                Slog.w(LOG_TAG, "Preserving older " + mDebugName + " backup");
+            }
+        }
+        // Reserve copy is not valid anymore.
+        mReserveCopy.delete();
+
+        // In case of MT access, it's possible the files get overwritten during write.
+        // Let's open all FDs we need now.
+        mMainOutStream = new FileOutputStream(mFile);
+        mMainInStream = new FileInputStream(mFile);
+        mReserveOutStream = new FileOutputStream(mReserveCopy);
+        mReserveInStream = new FileInputStream(mReserveCopy);
+
+        return mMainOutStream;
+    }
+
+    public void finishWrite(FileOutputStream str) throws IOException {
+        if (mMainOutStream != str) {
+            throw new IllegalStateException("Invalid incoming stream.");
+        }
+
+        // Flush and set permissions.
+        try (FileOutputStream mainOutStream = mMainOutStream) {
+            mMainOutStream = null;
+            finalizeOutStream(mainOutStream);
+        }
+        // New file successfully written, old one are no longer needed.
+        mTemporaryBackup.delete();
+
+        try (FileInputStream mainInStream = mMainInStream;
+             FileInputStream reserveInStream = mReserveInStream) {
+            mMainInStream = null;
+            mReserveInStream = null;
+
+            // Copy main file to reserve.
+            try (FileOutputStream reserveOutStream = mReserveOutStream) {
+                mReserveOutStream = null;
+                FileUtils.copy(mainInStream, reserveOutStream);
+                finalizeOutStream(reserveOutStream);
+            }
+
+            // Protect both main and reserve using fs-verity.
+            try (ParcelFileDescriptor mainPfd = ParcelFileDescriptor.dup(mainInStream.getFD());
+                 ParcelFileDescriptor copyPfd = ParcelFileDescriptor.dup(reserveInStream.getFD())) {
+                FileIntegrity.setUpFsVerity(mainPfd);
+                FileIntegrity.setUpFsVerity(copyPfd);
+            } catch (IOException e) {
+                Slog.e(LOG_TAG, "Failed to verity-protect " + mDebugName, e);
+            }
+        } catch (IOException e) {
+            Slog.e(LOG_TAG, "Failed to write reserve copy " + mDebugName + ": " + mReserveCopy, e);
+        }
+    }
+
+    public void failWrite(FileOutputStream str) {
+        if (mMainOutStream != str) {
+            throw new IllegalStateException("Invalid incoming stream.");
+        }
+
+        // Close all FDs.
+        close();
+
+        // Clean up partially written files
+        if (mFile.exists()) {
+            if (!mFile.delete()) {
+                Slog.i(LOG_TAG, "Failed to clean up mangled file: " + mFile);
+            }
+        }
+    }
+
+    public FileInputStream openRead() throws IOException {
+        if (mTemporaryBackup.exists()) {
+            try {
+                mCurrentFile = mTemporaryBackup;
+                mCurrentInStream = new FileInputStream(mCurrentFile);
+                if (mReadEventLogger != null) {
+                    mReadEventLogger.logEvent(Log.INFO,
+                            "Need to read from backup " + mDebugName + " file");
+                }
+                if (mFile.exists()) {
+                    // If both the backup and normal file exist, we
+                    // ignore the normal one since it might have been
+                    // corrupted.
+                    Slog.w(LOG_TAG, "Cleaning up " + mDebugName + " file " + mFile);
+                    mFile.delete();
+                }
+                // Ignore reserve copy as well.
+                mReserveCopy.delete();
+            } catch (java.io.IOException e) {
+                // We'll try for the normal settings file.
+            }
+        }
+
+        if (mCurrentInStream != null) {
+            return mCurrentInStream;
+        }
+
+        if (mFile.exists()) {
+            mCurrentFile = mFile;
+            mCurrentInStream = new FileInputStream(mCurrentFile);
+        } else if (mReserveCopy.exists()) {
+            mCurrentFile = mReserveCopy;
+            mCurrentInStream = new FileInputStream(mCurrentFile);
+            if (mReadEventLogger != null) {
+                mReadEventLogger.logEvent(Log.INFO,
+                        "Need to read from reserve copy " + mDebugName + " file");
+            }
+        }
+
+        if (mCurrentInStream == null) {
+            if (mReadEventLogger != null) {
+                mReadEventLogger.logEvent(Log.INFO, "No " + mDebugName + " file");
+            }
+        }
+
+        return mCurrentInStream;
+    }
+
+    public void failRead(FileInputStream str, Exception e) {
+        if (mCurrentInStream != str) {
+            throw new IllegalStateException("Invalid incoming stream.");
+        }
+        mCurrentInStream = null;
+        IoUtils.closeQuietly(str);
+
+        if (mReadEventLogger != null) {
+            mReadEventLogger.logEvent(Log.ERROR,
+                    "Error reading " + mDebugName + ", removing " + mCurrentFile + '\n'
+                            + Log.getStackTraceString(e));
+        }
+
+        mCurrentFile.delete();
+        mCurrentFile = null;
+    }
+
+    public void delete() {
+        mFile.delete();
+        mTemporaryBackup.delete();
+        mReserveCopy.delete();
+    }
+
+    @Override
+    public void close() {
+        IoUtils.closeQuietly(mMainOutStream);
+        IoUtils.closeQuietly(mMainInStream);
+        IoUtils.closeQuietly(mReserveOutStream);
+        IoUtils.closeQuietly(mReserveInStream);
+        IoUtils.closeQuietly(mCurrentInStream);
+        mMainOutStream = null;
+        mMainInStream = null;
+        mReserveOutStream = null;
+        mReserveInStream = null;
+        mCurrentInStream = null;
+        mCurrentFile = null;
+    }
+
+    public String toString() {
+        return mFile.getPath();
+    }
+
+    interface ReadEventLogger {
+        void logEvent(int priority, String msg);
+    }
+}
diff --git a/services/core/java/com/android/server/pm/ResolveIntentHelper.java b/services/core/java/com/android/server/pm/ResolveIntentHelper.java
index 8bca4a9..7ed10a4 100644
--- a/services/core/java/com/android/server/pm/ResolveIntentHelper.java
+++ b/services/core/java/com/android/server/pm/ResolveIntentHelper.java
@@ -18,6 +18,7 @@
 
 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
 
+import static com.android.internal.util.FrameworkStatsLog.UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__INTERNAL_NON_EXPORTED_COMPONENT_MATCH;
 import static com.android.server.pm.PackageManagerService.DEBUG_INSTANT;
 import static com.android.server.pm.PackageManagerService.DEBUG_INTENT_MATCHING;
 import static com.android.server.pm.PackageManagerService.TAG;
@@ -55,9 +56,9 @@
 
 import com.android.internal.app.ResolverActivity;
 import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.FrameworkStatsLog;
 import com.android.server.LocalServices;
 import com.android.server.am.ActivityManagerService;
+import com.android.server.am.ActivityManagerUtils;
 import com.android.server.compat.PlatformCompat;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageStateInternal;
@@ -130,18 +131,9 @@
                 boolean hasToBeExportedToMatch = platformCompat.isChangeEnabledByUid(
                         ActivityManagerService.IMPLICIT_INTENTS_ONLY_MATCH_EXPORTED_COMPONENTS,
                         filterCallingUid);
-                String[] categories = intent.getCategories() == null ? new String[0]
-                        : intent.getCategories().toArray(String[]::new);
-                FrameworkStatsLog.write(FrameworkStatsLog.UNSAFE_INTENT_EVENT_REPORTED,
-                        FrameworkStatsLog.UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__INTERNAL_NON_EXPORTED_COMPONENT_MATCH,
-                        filterCallingUid,
-                        query.get(i).getComponentInfo().getComponentName().flattenToShortString(),
-                        callerPackage,
-                        intent.getAction(),
-                        categories,
-                        resolvedType,
-                        intent.getScheme(),
-                        hasToBeExportedToMatch);
+                ActivityManagerUtils.logUnsafeIntentEvent(
+                        UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__INTERNAL_NON_EXPORTED_COMPONENT_MATCH,
+                        filterCallingUid, intent, resolvedType, hasToBeExportedToMatch);
                 if (callback != null) {
                     handler.post(() -> {
                         try {
@@ -466,14 +458,15 @@
                     list = new ArrayList<>(1);
                     list.add(ri);
                     PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
-                            computer, list, true, intent, resolvedType, filterCallingUid);
+                            mPlatformCompat, componentResolver, list, true, intent,
+                            resolvedType, filterCallingUid);
                 }
             }
         } else {
             String pkgName = intent.getPackage();
             if (pkgName == null) {
-                final List<ResolveInfo> result = componentResolver.queryReceivers(
-                        computer, intent, resolvedType, flags, filterCallingUid, userId);
+                final List<ResolveInfo> result = componentResolver
+                        .queryReceivers(computer, intent, resolvedType, flags, userId);
                 if (result != null) {
                     list = result;
                 }
@@ -481,7 +474,7 @@
             final AndroidPackage pkg = computer.getPackage(pkgName);
             if (pkg != null) {
                 final List<ResolveInfo> result = componentResolver.queryReceivers(computer,
-                        intent, resolvedType, flags, pkg.getReceivers(), filterCallingUid, userId);
+                        intent, resolvedType, flags, pkg.getReceivers(), userId);
                 if (result != null) {
                     list = result;
                 }
@@ -491,7 +484,8 @@
         if (originalIntent != null) {
             // We also have to ensure all components match the original intent
             PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
-                    computer, list, true, originalIntent, resolvedType, filterCallingUid);
+                    mPlatformCompat, componentResolver,
+                    list, true, originalIntent, resolvedType, filterCallingUid);
         }
 
         return computer.applyPostResolutionFilter(list, instantAppPkgName, false, queryingUid,
@@ -575,7 +569,7 @@
         String pkgName = intent.getPackage();
         if (pkgName == null) {
             final List<ResolveInfo> resolveInfos = componentResolver.queryProviders(computer,
-                    intent, resolvedType, flags, callingUid, userId);
+                    intent, resolvedType, flags, userId);
             if (resolveInfos == null) {
                 return Collections.emptyList();
             }
@@ -585,7 +579,7 @@
         final AndroidPackage pkg = computer.getPackage(pkgName);
         if (pkg != null) {
             final List<ResolveInfo> resolveInfos = componentResolver.queryProviders(computer,
-                    intent, resolvedType, flags, pkg.getProviders(), callingUid, userId);
+                    intent, resolvedType, flags, pkg.getProviders(), userId);
             if (resolveInfos == null) {
                 return Collections.emptyList();
             }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index f1998f7..b6557d0 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -119,7 +119,6 @@
 import com.android.server.pm.verify.domain.DomainVerificationLegacySettings;
 import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
 import com.android.server.pm.verify.domain.DomainVerificationPersistence;
-import com.android.server.security.FileIntegrity;
 import com.android.server.utils.Slogf;
 import com.android.server.utils.Snappable;
 import com.android.server.utils.SnapshotCache;
@@ -172,7 +171,7 @@
 /**
  * Holds information about dynamic settings.
  */
-public final class Settings implements Watchable, Snappable {
+public final class Settings implements Watchable, Snappable, ResilientAtomicFile.ReadEventLogger {
     private static final String TAG = "PackageSettings";
 
     /**
@@ -344,7 +343,7 @@
     private static final String ATTR_BLOCK_UNINSTALL = "blockUninstall";
     private static final String ATTR_ENABLED = "enabled";
     private static final String ATTR_ENABLED_CALLER = "enabledCaller";
-    private static final String ATTR_DOMAIN_VERIFICATON_STATE = "domainVerificationStatus";
+    private static final String ATTR_DOMAIN_VERIFICATION_STATE = "domainVerificationStatus";
     private static final String ATTR_APP_LINK_GENERATION = "app-link-generation";
     private static final String ATTR_INSTALL_REASON = "install-reason";
     private static final String ATTR_UNINSTALL_REASON = "uninstall-reason";
@@ -1511,16 +1510,22 @@
         return new File(new File(mSystemDir, "users"), Integer.toString(userId));
     }
 
-    // The method itself does not have to be guarded, but the file does.
-    @GuardedBy("mPackageRestrictionsLock")
-    private File getUserPackagesStateFile(int userId) {
-        return new File(getUserSystemDirectory(userId), "package-restrictions.xml");
+    private ResilientAtomicFile getUserPackagesStateFile(int userId) {
+        File mainFile = new File(getUserSystemDirectory(userId), "package-restrictions.xml");
+        File temporaryBackup = new File(getUserSystemDirectory(userId),
+                "package-restrictions-backup.xml");
+        File reserveCopy = new File(getUserSystemDirectory(userId),
+                "package-restrictions.xml.reservecopy");
+        return new ResilientAtomicFile(mainFile, temporaryBackup, reserveCopy,
+                FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP | FileUtils.S_IWGRP,
+                "package restrictions", this);
     }
 
-    // The method itself does not have to be guarded, but the file does.
-    @GuardedBy("mPackageRestrictionsLock")
-    private File getUserPackagesStateBackupFile(int userId) {
-        return new File(getUserSystemDirectory(userId), "package-restrictions-backup.xml");
+    private ResilientAtomicFile getSettingsFile() {
+        return new ResilientAtomicFile(mSettingsFilename, mPreviousSettingsFilename,
+                mSettingsReserveCopyFilename,
+                FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP | FileUtils.S_IWGRP,
+                "package manager settings", this);
     }
 
     private File getUserRuntimePermissionsFile(int userId) {
@@ -1730,272 +1735,243 @@
         }
     }
 
+    @Override
+    public void logEvent(int priority, String msg) {
+        mReadMessages.append(msg + "\n");
+        PackageManagerService.reportSettingsProblem(priority, msg);
+    }
+
+
     void readPackageRestrictionsLPr(int userId,
             @NonNull ArrayMap<String, Long> origFirstInstallTimes) {
         if (DEBUG_MU) {
             Log.i(TAG, "Reading package restrictions for user=" + userId);
         }
-        FileInputStream str = null;
 
-        synchronized (mPackageRestrictionsLock) {
-            File userPackagesStateFile = getUserPackagesStateFile(userId);
-            File backupFile = getUserPackagesStateBackupFile(userId);
-            if (backupFile.exists()) {
-                try {
-                    str = new FileInputStream(backupFile);
-                    mReadMessages.append("Reading from backup stopped packages file\n");
-                    PackageManagerService.reportSettingsProblem(Log.INFO,
-                            "Need to read from backup stopped packages file");
-                    if (userPackagesStateFile.exists()) {
-                        // If both the backup and normal file exist, we
-                        // ignore the normal one since it might have been
-                        // corrupted.
-                        Slog.w(PackageManagerService.TAG, "Cleaning up stopped packages file "
-                                + userPackagesStateFile);
-                        userPackagesStateFile.delete();
+        try (ResilientAtomicFile atomicFile = getUserPackagesStateFile(userId)) {
+            FileInputStream str = null;
+            try {
+                synchronized (mPackageRestrictionsLock) {
+                    str = atomicFile.openRead();
+                    if (str == null) {
+                        // At first boot, make sure no packages are stopped.
+                        // We usually want to have third party apps initialize
+                        // in the stopped state, but not at first boot.  Also
+                        // consider all applications to be installed.
+                        for (PackageSetting pkg : mPackages.values()) {
+                            pkg.setUserState(userId, 0, COMPONENT_ENABLED_STATE_DEFAULT,
+                                    true  /*installed*/,
+                                    false /*stopped*/,
+                                    false /*notLaunched*/,
+                                    false /*hidden*/,
+                                    0 /*distractionFlags*/,
+                                    null /*suspendParams*/,
+                                    false /*instantApp*/,
+                                    false /*virtualPreload*/,
+                                    null /*lastDisableAppCaller*/,
+                                    null /*enabledComponents*/,
+                                    null /*disabledComponents*/,
+                                    PackageManager.INSTALL_REASON_UNKNOWN,
+                                    PackageManager.UNINSTALL_REASON_UNKNOWN,
+                                    null /*harmfulAppWarning*/,
+                                    null /* splashScreenTheme*/,
+                                    0 /*firstInstallTime*/
+                            );
+                        }
+                        return;
                     }
-                } catch (java.io.IOException e) {
-                    // We'll try for the normal settings file.
-                }
-            }
-
-            if (str == null && userPackagesStateFile.exists()) {
-                try {
-                    str = new FileInputStream(userPackagesStateFile);
-                    if (DEBUG_MU) Log.i(TAG, "Reading " + userPackagesStateFile);
-                } catch (java.io.IOException e) {
-                    mReadMessages.append("Error reading: " + e.toString());
-                    PackageManagerService.reportSettingsProblem(Log.ERROR,
-                            "Error reading settings: " + e);
-                    Slog.wtf(TAG, "Error reading package manager stopped packages", e);
-                }
-            }
-        }
-
-        if (str == null) {
-            mReadMessages.append("No stopped packages file found\n");
-            PackageManagerService.reportSettingsProblem(Log.INFO,
-                    "No stopped packages file; "
-                            + "assuming all started");
-            // At first boot, make sure no packages are stopped.
-            // We usually want to have third party apps initialize
-            // in the stopped state, but not at first boot.  Also
-            // consider all applications to be installed.
-            for (PackageSetting pkg : mPackages.values()) {
-                pkg.setUserState(userId, 0, COMPONENT_ENABLED_STATE_DEFAULT,
-                        true  /*installed*/,
-                        false /*stopped*/,
-                        false /*notLaunched*/,
-                        false /*hidden*/,
-                        0 /*distractionFlags*/,
-                        null /*suspendParams*/,
-                        false /*instantApp*/,
-                        false /*virtualPreload*/,
-                        null /*lastDisableAppCaller*/,
-                        null /*enabledComponents*/,
-                        null /*disabledComponents*/,
-                        PackageManager.INSTALL_REASON_UNKNOWN,
-                        PackageManager.UNINSTALL_REASON_UNKNOWN,
-                        null /*harmfulAppWarning*/,
-                        null /* splashScreenTheme*/,
-                        0 /*firstInstallTime*/
-                );
-            }
-            return;
-        }
-
-        try {
-            final TypedXmlPullParser parser = Xml.resolvePullParser(str);
-
-            int type;
-            while ((type=parser.next()) != XmlPullParser.START_TAG
-                       && type != XmlPullParser.END_DOCUMENT) {
-                ;
-            }
-
-            if (type != XmlPullParser.START_TAG) {
-                mReadMessages.append("No start tag found in package restrictions file\n");
-                PackageManagerService.reportSettingsProblem(Log.WARN,
-                        "No start tag found in package manager stopped packages");
-                return;
-            }
-
-            int outerDepth = parser.getDepth();
-            PackageSetting ps = null;
-            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
-                   && (type != XmlPullParser.END_TAG
-                           || parser.getDepth() > outerDepth)) {
-                if (type == XmlPullParser.END_TAG
-                        || type == XmlPullParser.TEXT) {
-                    continue;
                 }
 
-                String tagName = parser.getName();
-                if (tagName.equals(TAG_PACKAGE)) {
-                    String name = parser.getAttributeValue(null, ATTR_NAME);
-                    ps = mPackages.get(name);
-                    if (ps == null) {
-                        Slog.w(PackageManagerService.TAG, "No package known for stopped package "
-                                + name);
-                        XmlUtils.skipCurrentTag(parser);
+                final TypedXmlPullParser parser = Xml.resolvePullParser(str);
+
+                int type;
+                while ((type = parser.next()) != XmlPullParser.START_TAG
+                        && type != XmlPullParser.END_DOCUMENT) {
+                    // nothing
+                }
+
+                if (type != XmlPullParser.START_TAG) {
+                    mReadMessages.append("No start tag found in package restrictions file\n");
+                    PackageManagerService.reportSettingsProblem(Log.WARN,
+                            "No start tag found in package manager package restrictions file");
+                    return;
+                }
+
+                int outerDepth = parser.getDepth();
+                PackageSetting ps = null;
+                while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                        && (type != XmlPullParser.END_TAG
+                        || parser.getDepth() > outerDepth)) {
+                    if (type == XmlPullParser.END_TAG
+                            || type == XmlPullParser.TEXT) {
                         continue;
                     }
 
-                    final long ceDataInode =
-                            parser.getAttributeLong(null, ATTR_CE_DATA_INODE, 0);
-                    final boolean installed =
-                            parser.getAttributeBoolean(null, ATTR_INSTALLED, true);
-                    final boolean stopped =
-                            parser.getAttributeBoolean(null, ATTR_STOPPED, false);
-                    final boolean notLaunched =
-                            parser.getAttributeBoolean(null, ATTR_NOT_LAUNCHED, false);
-
-                    // For backwards compatibility with the previous name of "blocked", which
-                    // now means hidden, read the old attribute as well.
-                    boolean hidden = parser.getAttributeBoolean(null, ATTR_HIDDEN, false);
-                    if (!hidden) {
-                        hidden = parser.getAttributeBoolean(null, ATTR_BLOCKED, false);
-                    }
-
-                    final int distractionFlags = parser.getAttributeInt(null, ATTR_DISTRACTION_FLAGS, 0);
-                    final boolean suspended = parser.getAttributeBoolean(null, ATTR_SUSPENDED, false);
-                    String oldSuspendingPackage = parser.getAttributeValue(null,
-                            ATTR_SUSPENDING_PACKAGE);
-                    final String dialogMessage = parser.getAttributeValue(null,
-                            ATTR_SUSPEND_DIALOG_MESSAGE);
-                    if (suspended && oldSuspendingPackage == null) {
-                        oldSuspendingPackage = PLATFORM_PACKAGE_NAME;
-                    }
-
-                    final boolean blockUninstall =
-                            parser.getAttributeBoolean(null, ATTR_BLOCK_UNINSTALL, false);
-                    final boolean instantApp =
-                            parser.getAttributeBoolean(null, ATTR_INSTANT_APP, false);
-                    final boolean virtualPreload =
-                            parser.getAttributeBoolean(null, ATTR_VIRTUAL_PRELOAD, false);
-                    final int enabled = parser.getAttributeInt(null, ATTR_ENABLED,
-                            COMPONENT_ENABLED_STATE_DEFAULT);
-                    final String enabledCaller = parser.getAttributeValue(null,
-                            ATTR_ENABLED_CALLER);
-                    final String harmfulAppWarning =
-                            parser.getAttributeValue(null, ATTR_HARMFUL_APP_WARNING);
-                    final int verifState = parser.getAttributeInt(null,
-                            ATTR_DOMAIN_VERIFICATON_STATE,
-                            PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED);
-                    final int installReason = parser.getAttributeInt(null, ATTR_INSTALL_REASON,
-                            PackageManager.INSTALL_REASON_UNKNOWN);
-                    final int uninstallReason = parser.getAttributeInt(null, ATTR_UNINSTALL_REASON,
-                            PackageManager.UNINSTALL_REASON_UNKNOWN);
-                    final String splashScreenTheme = parser.getAttributeValue(null,
-                            ATTR_SPLASH_SCREEN_THEME);
-                    final long firstInstallTime = parser.getAttributeLongHex(null,
-                            ATTR_FIRST_INSTALL_TIME, 0);
-
-                    ArraySet<String> enabledComponents = null;
-                    ArraySet<String> disabledComponents = null;
-                    PersistableBundle suspendedAppExtras = null;
-                    PersistableBundle suspendedLauncherExtras = null;
-                    SuspendDialogInfo oldSuspendDialogInfo = null;
-
-                    int packageDepth = parser.getDepth();
-                    ArrayMap<String, SuspendParams> suspendParamsMap = null;
-                    while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
-                            && (type != XmlPullParser.END_TAG
-                            || parser.getDepth() > packageDepth)) {
-                        if (type == XmlPullParser.END_TAG
-                                || type == XmlPullParser.TEXT) {
+                    String tagName = parser.getName();
+                    if (tagName.equals(TAG_PACKAGE)) {
+                        String name = parser.getAttributeValue(null, ATTR_NAME);
+                        ps = mPackages.get(name);
+                        if (ps == null) {
+                            Slog.w(PackageManagerService.TAG,
+                                    "No package known for package restrictions " + name);
+                            XmlUtils.skipCurrentTag(parser);
                             continue;
                         }
-                        switch (parser.getName()) {
-                            case TAG_ENABLED_COMPONENTS:
-                                enabledComponents = readComponentsLPr(parser);
-                                break;
-                            case TAG_DISABLED_COMPONENTS:
-                                disabledComponents = readComponentsLPr(parser);
-                                break;
-                            case TAG_SUSPENDED_APP_EXTRAS:
-                                suspendedAppExtras = PersistableBundle.restoreFromXml(parser);
-                                break;
-                            case TAG_SUSPENDED_LAUNCHER_EXTRAS:
-                                suspendedLauncherExtras = PersistableBundle.restoreFromXml(parser);
-                                break;
-                            case TAG_SUSPENDED_DIALOG_INFO:
-                                oldSuspendDialogInfo = SuspendDialogInfo.restoreFromXml(parser);
-                                break;
-                            case TAG_SUSPEND_PARAMS:
-                                final String suspendingPackage = parser.getAttributeValue(null,
-                                        ATTR_SUSPENDING_PACKAGE);
-                                if (suspendingPackage == null) {
-                                    Slog.wtf(TAG, "No suspendingPackage found inside tag "
-                                            + TAG_SUSPEND_PARAMS);
-                                    continue;
-                                }
-                                if (suspendParamsMap == null) {
-                                    suspendParamsMap = new ArrayMap<>();
-                                }
-                                suspendParamsMap.put(suspendingPackage,
-                                        SuspendParams.restoreFromXml(parser));
-                                break;
-                            default:
-                                Slog.wtf(TAG, "Unknown tag " + parser.getName() + " under tag "
-                                        + TAG_PACKAGE);
+
+                        final long ceDataInode =
+                                parser.getAttributeLong(null, ATTR_CE_DATA_INODE, 0);
+                        final boolean installed =
+                                parser.getAttributeBoolean(null, ATTR_INSTALLED, true);
+                        final boolean stopped =
+                                parser.getAttributeBoolean(null, ATTR_STOPPED, false);
+                        final boolean notLaunched =
+                                parser.getAttributeBoolean(null, ATTR_NOT_LAUNCHED, false);
+
+                        // For backwards compatibility with the previous name of "blocked", which
+                        // now means hidden, read the old attribute as well.
+                        boolean hidden = parser.getAttributeBoolean(null, ATTR_HIDDEN, false);
+                        if (!hidden) {
+                            hidden = parser.getAttributeBoolean(null, ATTR_BLOCKED, false);
                         }
-                    }
-                    if (oldSuspendDialogInfo == null && !TextUtils.isEmpty(dialogMessage)) {
-                        oldSuspendDialogInfo = new SuspendDialogInfo.Builder()
-                                .setMessage(dialogMessage)
-                                .build();
-                    }
-                    if (suspended && suspendParamsMap == null) {
-                        final SuspendParams suspendParams = new SuspendParams(
-                                        oldSuspendDialogInfo,
-                                        suspendedAppExtras,
-                                        suspendedLauncherExtras);
-                        suspendParamsMap = new ArrayMap<>();
-                        suspendParamsMap.put(oldSuspendingPackage, suspendParams);
-                    }
 
-                    if (blockUninstall) {
-                        setBlockUninstallLPw(userId, name, true);
-                    }
-                    ps.setUserState(userId, ceDataInode, enabled, installed, stopped, notLaunched,
-                            hidden, distractionFlags, suspendParamsMap, instantApp, virtualPreload,
-                            enabledCaller, enabledComponents, disabledComponents, installReason,
-                            uninstallReason, harmfulAppWarning, splashScreenTheme,
-                            firstInstallTime != 0 ? firstInstallTime :
-                                    origFirstInstallTimes.getOrDefault(name, 0L));
+                        final int distractionFlags = parser.getAttributeInt(null,
+                                ATTR_DISTRACTION_FLAGS, 0);
+                        final boolean suspended = parser.getAttributeBoolean(null, ATTR_SUSPENDED,
+                                false);
+                        String oldSuspendingPackage = parser.getAttributeValue(null,
+                                ATTR_SUSPENDING_PACKAGE);
+                        final String dialogMessage = parser.getAttributeValue(null,
+                                ATTR_SUSPEND_DIALOG_MESSAGE);
+                        if (suspended && oldSuspendingPackage == null) {
+                            oldSuspendingPackage = PLATFORM_PACKAGE_NAME;
+                        }
 
-                    mDomainVerificationManager.setLegacyUserState(name, userId, verifState);
-                } else if (tagName.equals("preferred-activities")) {
-                    readPreferredActivitiesLPw(parser, userId);
-                } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
-                    readPersistentPreferredActivitiesLPw(parser, userId);
-                } else if (tagName.equals(TAG_CROSS_PROFILE_INTENT_FILTERS)) {
-                    readCrossProfileIntentFiltersLPw(parser, userId);
-                } else if (tagName.equals(TAG_DEFAULT_APPS)) {
-                    readDefaultAppsLPw(parser, userId);
-                } else if (tagName.equals(TAG_BLOCK_UNINSTALL_PACKAGES)) {
-                    readBlockUninstallPackagesLPw(parser, userId);
-                } else {
-                    Slog.w(PackageManagerService.TAG, "Unknown element under <stopped-packages>: "
-                          + parser.getName());
-                    XmlUtils.skipCurrentTag(parser);
+                        final boolean blockUninstall =
+                                parser.getAttributeBoolean(null, ATTR_BLOCK_UNINSTALL, false);
+                        final boolean instantApp =
+                                parser.getAttributeBoolean(null, ATTR_INSTANT_APP, false);
+                        final boolean virtualPreload =
+                                parser.getAttributeBoolean(null, ATTR_VIRTUAL_PRELOAD, false);
+                        final int enabled = parser.getAttributeInt(null, ATTR_ENABLED,
+                                COMPONENT_ENABLED_STATE_DEFAULT);
+                        final String enabledCaller = parser.getAttributeValue(null,
+                                ATTR_ENABLED_CALLER);
+                        final String harmfulAppWarning =
+                                parser.getAttributeValue(null, ATTR_HARMFUL_APP_WARNING);
+                        final int verifState = parser.getAttributeInt(null,
+                                ATTR_DOMAIN_VERIFICATION_STATE,
+                                PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED);
+                        final int installReason = parser.getAttributeInt(null, ATTR_INSTALL_REASON,
+                                PackageManager.INSTALL_REASON_UNKNOWN);
+                        final int uninstallReason = parser.getAttributeInt(null,
+                                ATTR_UNINSTALL_REASON,
+                                PackageManager.UNINSTALL_REASON_UNKNOWN);
+                        final String splashScreenTheme = parser.getAttributeValue(null,
+                                ATTR_SPLASH_SCREEN_THEME);
+                        final long firstInstallTime = parser.getAttributeLongHex(null,
+                                ATTR_FIRST_INSTALL_TIME, 0);
+
+                        ArraySet<String> enabledComponents = null;
+                        ArraySet<String> disabledComponents = null;
+                        PersistableBundle suspendedAppExtras = null;
+                        PersistableBundle suspendedLauncherExtras = null;
+                        SuspendDialogInfo oldSuspendDialogInfo = null;
+
+                        int packageDepth = parser.getDepth();
+                        ArrayMap<String, SuspendParams> suspendParamsMap = null;
+                        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                                && (type != XmlPullParser.END_TAG
+                                || parser.getDepth() > packageDepth)) {
+                            if (type == XmlPullParser.END_TAG
+                                    || type == XmlPullParser.TEXT) {
+                                continue;
+                            }
+                            switch (parser.getName()) {
+                                case TAG_ENABLED_COMPONENTS:
+                                    enabledComponents = readComponentsLPr(parser);
+                                    break;
+                                case TAG_DISABLED_COMPONENTS:
+                                    disabledComponents = readComponentsLPr(parser);
+                                    break;
+                                case TAG_SUSPENDED_APP_EXTRAS:
+                                    suspendedAppExtras = PersistableBundle.restoreFromXml(parser);
+                                    break;
+                                case TAG_SUSPENDED_LAUNCHER_EXTRAS:
+                                    suspendedLauncherExtras = PersistableBundle.restoreFromXml(
+                                            parser);
+                                    break;
+                                case TAG_SUSPENDED_DIALOG_INFO:
+                                    oldSuspendDialogInfo = SuspendDialogInfo.restoreFromXml(parser);
+                                    break;
+                                case TAG_SUSPEND_PARAMS:
+                                    final String suspendingPackage = parser.getAttributeValue(null,
+                                            ATTR_SUSPENDING_PACKAGE);
+                                    if (suspendingPackage == null) {
+                                        Slog.wtf(TAG, "No suspendingPackage found inside tag "
+                                                + TAG_SUSPEND_PARAMS);
+                                        continue;
+                                    }
+                                    if (suspendParamsMap == null) {
+                                        suspendParamsMap = new ArrayMap<>();
+                                    }
+                                    suspendParamsMap.put(suspendingPackage,
+                                            SuspendParams.restoreFromXml(parser));
+                                    break;
+                                default:
+                                    Slog.wtf(TAG, "Unknown tag " + parser.getName() + " under tag "
+                                            + TAG_PACKAGE);
+                            }
+                        }
+                        if (oldSuspendDialogInfo == null && !TextUtils.isEmpty(dialogMessage)) {
+                            oldSuspendDialogInfo = new SuspendDialogInfo.Builder()
+                                    .setMessage(dialogMessage)
+                                    .build();
+                        }
+                        if (suspended && suspendParamsMap == null) {
+                            final SuspendParams suspendParams = new SuspendParams(
+                                    oldSuspendDialogInfo,
+                                    suspendedAppExtras,
+                                    suspendedLauncherExtras);
+                            suspendParamsMap = new ArrayMap<>();
+                            suspendParamsMap.put(oldSuspendingPackage, suspendParams);
+                        }
+
+                        if (blockUninstall) {
+                            setBlockUninstallLPw(userId, name, true);
+                        }
+                        ps.setUserState(userId, ceDataInode, enabled, installed, stopped,
+                                notLaunched,
+                                hidden, distractionFlags, suspendParamsMap, instantApp,
+                                virtualPreload,
+                                enabledCaller, enabledComponents, disabledComponents, installReason,
+                                uninstallReason, harmfulAppWarning, splashScreenTheme,
+                                firstInstallTime != 0 ? firstInstallTime :
+                                        origFirstInstallTimes.getOrDefault(name, 0L));
+
+                        mDomainVerificationManager.setLegacyUserState(name, userId, verifState);
+                    } else if (tagName.equals("preferred-activities")) {
+                        readPreferredActivitiesLPw(parser, userId);
+                    } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
+                        readPersistentPreferredActivitiesLPw(parser, userId);
+                    } else if (tagName.equals(TAG_CROSS_PROFILE_INTENT_FILTERS)) {
+                        readCrossProfileIntentFiltersLPw(parser, userId);
+                    } else if (tagName.equals(TAG_DEFAULT_APPS)) {
+                        readDefaultAppsLPw(parser, userId);
+                    } else if (tagName.equals(TAG_BLOCK_UNINSTALL_PACKAGES)) {
+                        readBlockUninstallPackagesLPw(parser, userId);
+                    } else {
+                        Slog.w(PackageManagerService.TAG,
+                                "Unknown element under <stopped-packages>: "
+                                        + parser.getName());
+                        XmlUtils.skipCurrentTag(parser);
+                    }
                 }
+            } catch (IOException | XmlPullParserException e) {
+                // Remove corrupted file and retry.
+                atomicFile.failRead(str, e);
+
+                readPackageRestrictionsLPr(userId, origFirstInstallTimes);
             }
-
-            str.close();
-        } catch (XmlPullParserException e) {
-            mReadMessages.append("Error reading: " + e.toString());
-            PackageManagerService.reportSettingsProblem(Log.ERROR,
-                    "Error reading stopped packages: " + e);
-            Slog.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages",
-                    e);
-
-        } catch (java.io.IOException e) {
-            mReadMessages.append("Error reading: " + e.toString());
-            PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
-            Slog.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages",
-                    e);
         }
     }
 
@@ -2165,219 +2141,176 @@
             Log.i(TAG, "Writing package restrictions for user=" + userId);
         }
 
-        final File userPackagesStateFile;
-        final File backupFile;
-        final FileOutputStream fstr;
+        FileOutputStream str = null;
+        try (ResilientAtomicFile atomicFile = getUserPackagesStateFile(userId)) {
+            try {
+                synchronized (mPackageRestrictionsLock) {
+                    if (!sync) {
+                        int pending = mPendingAsyncPackageRestrictionsWrites.get(userId, 0) - 1;
+                        if (pending < 0) {
+                            Log.i(TAG, "Cancel writing package restrictions for user=" + userId);
+                            return;
+                        }
+                        mPendingAsyncPackageRestrictionsWrites.put(userId, pending);
+                    }
 
-        synchronized (mPackageRestrictionsLock) {
-            if (!sync) {
-                int pending = mPendingAsyncPackageRestrictionsWrites.get(userId, 0) - 1;
-                if (pending < 0) {
-                    Log.i(TAG, "Cancel writing package restrictions for user=" + userId);
-                    return;
-                }
-                mPendingAsyncPackageRestrictionsWrites.put(userId, pending);
-            }
-
-            // Keep the old stopped packages around until we know the new ones have
-            // been successfully written.
-            userPackagesStateFile = getUserPackagesStateFile(userId);
-            backupFile = getUserPackagesStateBackupFile(userId);
-            new File(userPackagesStateFile.getParent()).mkdirs();
-            if (userPackagesStateFile.exists()) {
-                // Presence of backup settings file indicates that we failed
-                // to persist packages earlier. So preserve the older
-                // backup for future reference since the current packages
-                // might have been corrupted.
-                if (!backupFile.exists()) {
-                    if (!userPackagesStateFile.renameTo(backupFile)) {
+                    try {
+                        str = atomicFile.startWrite();
+                    } catch (java.io.IOException e) {
                         Slog.wtf(PackageManagerService.TAG,
-                                "Unable to backup user packages state file, "
-                                        + "current changes will be lost at reboot");
+                                "Unable to write package manager package restrictions, "
+                                        + " current changes will be lost at reboot", e);
                         return;
                     }
-                } else {
-                    userPackagesStateFile.delete();
-                    Slog.w(PackageManagerService.TAG, "Preserving older stopped packages backup");
                 }
-            }
 
-            try {
-                fstr = new FileOutputStream(userPackagesStateFile);
-                // File is created, set permissions.
-                FileUtils.setPermissions(userPackagesStateFile.toString(),
-                        FileUtils.S_IRUSR | FileUtils.S_IWUSR
-                                | FileUtils.S_IRGRP | FileUtils.S_IWGRP,
-                        -1, -1);
-            } catch (java.io.IOException e) {
-                Slog.wtf(PackageManagerService.TAG,
-                        "Unable to write package manager user packages state, "
-                                + " current changes will be lost at reboot", e);
-                return;
-            }
-        }
+                synchronized (mLock) {
+                    final TypedXmlSerializer serializer = Xml.resolveSerializer(str);
+                    serializer.startDocument(null, true);
+                    serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output",
+                            true);
 
-        try {
-            synchronized (mLock) {
-                final TypedXmlSerializer serializer = Xml.resolveSerializer(fstr);
-                serializer.startDocument(null, true);
-                serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output",
-                        true);
+                    serializer.startTag(null, TAG_PACKAGE_RESTRICTIONS);
 
-                serializer.startTag(null, TAG_PACKAGE_RESTRICTIONS);
+                    if (DEBUG_MU) {
+                        Slogf.i(TAG, "Writing %s (%d packages)", atomicFile,
+                                mPackages.values().size());
+                    }
+                    for (final PackageSetting pkg : mPackages.values()) {
+                        final PackageUserStateInternal ustate = pkg.readUserState(userId);
+                        if (DEBUG_MU) {
+                            Log.v(TAG, "  pkg=" + pkg.getPackageName()
+                                    + ", installed=" + ustate.isInstalled()
+                                    + ", state=" + ustate.getEnabledState());
+                        }
+
+                        serializer.startTag(null, TAG_PACKAGE);
+                        serializer.attribute(null, ATTR_NAME, pkg.getPackageName());
+                        if (ustate.getCeDataInode() != 0) {
+                            serializer.attributeLong(null, ATTR_CE_DATA_INODE,
+                                    ustate.getCeDataInode());
+                        }
+                        if (!ustate.isInstalled()) {
+                            serializer.attributeBoolean(null, ATTR_INSTALLED, false);
+                        }
+                        if (ustate.isStopped()) {
+                            serializer.attributeBoolean(null, ATTR_STOPPED, true);
+                        }
+                        if (ustate.isNotLaunched()) {
+                            serializer.attributeBoolean(null, ATTR_NOT_LAUNCHED, true);
+                        }
+                        if (ustate.isHidden()) {
+                            serializer.attributeBoolean(null, ATTR_HIDDEN, true);
+                        }
+                        if (ustate.getDistractionFlags() != 0) {
+                            serializer.attributeInt(null, ATTR_DISTRACTION_FLAGS,
+                                    ustate.getDistractionFlags());
+                        }
+                        if (ustate.isSuspended()) {
+                            serializer.attributeBoolean(null, ATTR_SUSPENDED, true);
+                        }
+                        if (ustate.isInstantApp()) {
+                            serializer.attributeBoolean(null, ATTR_INSTANT_APP, true);
+                        }
+                        if (ustate.isVirtualPreload()) {
+                            serializer.attributeBoolean(null, ATTR_VIRTUAL_PRELOAD, true);
+                        }
+                        if (ustate.getEnabledState() != COMPONENT_ENABLED_STATE_DEFAULT) {
+                            serializer.attributeInt(null, ATTR_ENABLED, ustate.getEnabledState());
+                            if (ustate.getLastDisableAppCaller() != null) {
+                                serializer.attribute(null, ATTR_ENABLED_CALLER,
+                                        ustate.getLastDisableAppCaller());
+                            }
+                        }
+                        if (ustate.getInstallReason() != PackageManager.INSTALL_REASON_UNKNOWN) {
+                            serializer.attributeInt(null, ATTR_INSTALL_REASON,
+                                    ustate.getInstallReason());
+                        }
+                        serializer.attributeLongHex(null, ATTR_FIRST_INSTALL_TIME,
+                                ustate.getFirstInstallTimeMillis());
+                        if (ustate.getUninstallReason()
+                                != PackageManager.UNINSTALL_REASON_UNKNOWN) {
+                            serializer.attributeInt(null, ATTR_UNINSTALL_REASON,
+                                    ustate.getUninstallReason());
+                        }
+                        if (ustate.getHarmfulAppWarning() != null) {
+                            serializer.attribute(null, ATTR_HARMFUL_APP_WARNING,
+                                    ustate.getHarmfulAppWarning());
+                        }
+                        if (ustate.getSplashScreenTheme() != null) {
+                            serializer.attribute(null, ATTR_SPLASH_SCREEN_THEME,
+                                    ustate.getSplashScreenTheme());
+                        }
+                        if (ustate.isSuspended()) {
+                            for (int i = 0; i < ustate.getSuspendParams().size(); i++) {
+                                final String suspendingPackage = ustate.getSuspendParams().keyAt(i);
+                                serializer.startTag(null, TAG_SUSPEND_PARAMS);
+                                serializer.attribute(null, ATTR_SUSPENDING_PACKAGE,
+                                        suspendingPackage);
+                                final SuspendParams params =
+                                        ustate.getSuspendParams().valueAt(i);
+                                if (params != null) {
+                                    params.saveToXml(serializer);
+                                }
+                                serializer.endTag(null, TAG_SUSPEND_PARAMS);
+                            }
+                        }
+                        final ArraySet<String> enabledComponents = ustate.getEnabledComponents();
+                        if (enabledComponents != null && enabledComponents.size() > 0) {
+                            serializer.startTag(null, TAG_ENABLED_COMPONENTS);
+                            for (int i = 0; i < enabledComponents.size(); i++) {
+                                serializer.startTag(null, TAG_ITEM);
+                                serializer.attribute(null, ATTR_NAME,
+                                        enabledComponents.valueAt(i));
+                                serializer.endTag(null, TAG_ITEM);
+                            }
+                            serializer.endTag(null, TAG_ENABLED_COMPONENTS);
+                        }
+                        final ArraySet<String> disabledComponents = ustate.getDisabledComponents();
+                        if (disabledComponents != null && disabledComponents.size() > 0) {
+                            serializer.startTag(null, TAG_DISABLED_COMPONENTS);
+                            for (int i = 0; i < disabledComponents.size(); i++) {
+                                serializer.startTag(null, TAG_ITEM);
+                                serializer.attribute(null, ATTR_NAME,
+                                        disabledComponents.valueAt(i));
+                                serializer.endTag(null, TAG_ITEM);
+                            }
+                            serializer.endTag(null, TAG_DISABLED_COMPONENTS);
+                        }
+
+                        serializer.endTag(null, TAG_PACKAGE);
+                    }
+
+                    writePreferredActivitiesLPr(serializer, userId, true);
+                    writePersistentPreferredActivitiesLPr(serializer, userId);
+                    writeCrossProfileIntentFiltersLPr(serializer, userId);
+                    writeDefaultAppsLPr(serializer, userId);
+                    writeBlockUninstallPackagesLPr(serializer, userId);
+
+                    serializer.endTag(null, TAG_PACKAGE_RESTRICTIONS);
+
+                    serializer.endDocument();
+                }
+
+                atomicFile.finishWrite(str);
 
                 if (DEBUG_MU) {
-                    Slogf.i(TAG, "Writing %s (%d packages)", userPackagesStateFile,
-                            mPackages.values().size());
-                }
-                for (final PackageSetting pkg : mPackages.values()) {
-                    final PackageUserStateInternal ustate = pkg.readUserState(userId);
-                    if (DEBUG_MU) {
-                        Log.v(TAG, "  pkg=" + pkg.getPackageName()
-                                + ", installed=" + ustate.isInstalled()
-                                + ", state=" + ustate.getEnabledState());
-                    }
-
-                    serializer.startTag(null, TAG_PACKAGE);
-                    serializer.attribute(null, ATTR_NAME, pkg.getPackageName());
-                    if (ustate.getCeDataInode() != 0) {
-                        serializer.attributeLong(null, ATTR_CE_DATA_INODE, ustate.getCeDataInode());
-                    }
-                    if (!ustate.isInstalled()) {
-                        serializer.attributeBoolean(null, ATTR_INSTALLED, false);
-                    }
-                    if (ustate.isStopped()) {
-                        serializer.attributeBoolean(null, ATTR_STOPPED, true);
-                    }
-                    if (ustate.isNotLaunched()) {
-                        serializer.attributeBoolean(null, ATTR_NOT_LAUNCHED, true);
-                    }
-                    if (ustate.isHidden()) {
-                        serializer.attributeBoolean(null, ATTR_HIDDEN, true);
-                    }
-                    if (ustate.getDistractionFlags() != 0) {
-                        serializer.attributeInt(null, ATTR_DISTRACTION_FLAGS,
-                                ustate.getDistractionFlags());
-                    }
-                    if (ustate.isSuspended()) {
-                        serializer.attributeBoolean(null, ATTR_SUSPENDED, true);
-                    }
-                    if (ustate.isInstantApp()) {
-                        serializer.attributeBoolean(null, ATTR_INSTANT_APP, true);
-                    }
-                    if (ustate.isVirtualPreload()) {
-                        serializer.attributeBoolean(null, ATTR_VIRTUAL_PRELOAD, true);
-                    }
-                    if (ustate.getEnabledState() != COMPONENT_ENABLED_STATE_DEFAULT) {
-                        serializer.attributeInt(null, ATTR_ENABLED, ustate.getEnabledState());
-                        if (ustate.getLastDisableAppCaller() != null) {
-                            serializer.attribute(null, ATTR_ENABLED_CALLER,
-                                    ustate.getLastDisableAppCaller());
-                        }
-                    }
-                    if (ustate.getInstallReason() != PackageManager.INSTALL_REASON_UNKNOWN) {
-                        serializer.attributeInt(null, ATTR_INSTALL_REASON,
-                                ustate.getInstallReason());
-                    }
-                    serializer.attributeLongHex(null, ATTR_FIRST_INSTALL_TIME,
-                            ustate.getFirstInstallTimeMillis());
-                    if (ustate.getUninstallReason() != PackageManager.UNINSTALL_REASON_UNKNOWN) {
-                        serializer.attributeInt(null, ATTR_UNINSTALL_REASON,
-                                ustate.getUninstallReason());
-                    }
-                    if (ustate.getHarmfulAppWarning() != null) {
-                        serializer.attribute(null, ATTR_HARMFUL_APP_WARNING,
-                                ustate.getHarmfulAppWarning());
-                    }
-                    if (ustate.getSplashScreenTheme() != null) {
-                        serializer.attribute(null, ATTR_SPLASH_SCREEN_THEME,
-                                ustate.getSplashScreenTheme());
-                    }
-                    if (ustate.isSuspended()) {
-                        for (int i = 0; i < ustate.getSuspendParams().size(); i++) {
-                            final String suspendingPackage = ustate.getSuspendParams().keyAt(i);
-                            serializer.startTag(null, TAG_SUSPEND_PARAMS);
-                            serializer.attribute(null, ATTR_SUSPENDING_PACKAGE, suspendingPackage);
-                            final SuspendParams params =
-                                    ustate.getSuspendParams().valueAt(i);
-                            if (params != null) {
-                                params.saveToXml(serializer);
-                            }
-                            serializer.endTag(null, TAG_SUSPEND_PARAMS);
-                        }
-                    }
-                    final ArraySet<String> enabledComponents = ustate.getEnabledComponents();
-                    if (enabledComponents != null && enabledComponents.size() > 0) {
-                        serializer.startTag(null, TAG_ENABLED_COMPONENTS);
-                        for (int i = 0; i < enabledComponents.size(); i++) {
-                            serializer.startTag(null, TAG_ITEM);
-                            serializer.attribute(null, ATTR_NAME,
-                                    enabledComponents.valueAt(i));
-                            serializer.endTag(null, TAG_ITEM);
-                        }
-                        serializer.endTag(null, TAG_ENABLED_COMPONENTS);
-                    }
-                    final ArraySet<String> disabledComponents = ustate.getDisabledComponents();
-                    if (disabledComponents != null && disabledComponents.size() > 0) {
-                        serializer.startTag(null, TAG_DISABLED_COMPONENTS);
-                        for (int i = 0; i < disabledComponents.size(); i++) {
-                            serializer.startTag(null, TAG_ITEM);
-                            serializer.attribute(null, ATTR_NAME,
-                                    disabledComponents.valueAt(i));
-                            serializer.endTag(null, TAG_ITEM);
-                        }
-                        serializer.endTag(null, TAG_DISABLED_COMPONENTS);
-                    }
-
-                    serializer.endTag(null, TAG_PACKAGE);
+                    Log.i(TAG, "New package restrictions successfully written for user=" + userId
+                            + ": " + atomicFile);
                 }
 
-                writePreferredActivitiesLPr(serializer, userId, true);
-                writePersistentPreferredActivitiesLPr(serializer, userId);
-                writeCrossProfileIntentFiltersLPr(serializer, userId);
-                writeDefaultAppsLPr(serializer, userId);
-                writeBlockUninstallPackagesLPr(serializer, userId);
+                com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
+                        "package-user-" + userId, SystemClock.uptimeMillis() - startTime);
 
-                serializer.endTag(null, TAG_PACKAGE_RESTRICTIONS);
-
-                serializer.endDocument();
-            }
-
-            fstr.flush();
-            FileUtils.sync(fstr);
-            IoUtils.closeQuietly(fstr);
-
-            synchronized (mPackageRestrictionsLock) {
-                // File is created, set permissions.
-                FileUtils.setPermissions(userPackagesStateFile.toString(),
-                        FileUtils.S_IRUSR | FileUtils.S_IWUSR
-                                | FileUtils.S_IRGRP | FileUtils.S_IWGRP,
-                        -1, -1);
-                // New settings successfully written, old ones are no longer needed.
-                backupFile.delete();
-            }
-
-            if (DEBUG_MU) {
-                Log.i(TAG, "New settings successfully written for user=" + userId + ": "
-                        + userPackagesStateFile);
-            }
-
-            com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
-                    "package-user-" + userId, SystemClock.uptimeMillis() - startTime);
-
-            // Done, all is good!
-            return;
-        } catch (java.io.IOException e) {
-            Slog.wtf(PackageManagerService.TAG,
-                    "Unable to write package manager user packages state, "
-                    + " current changes will be lost at reboot", e);
-        }
-
-        // Clean up partially written files
-        if (userPackagesStateFile.exists()) {
-            if (!userPackagesStateFile.delete()) {
-                Log.i(PackageManagerService.TAG, "Failed to clean up mangled file: "
-                        + mStoppedPackagesFilename);
+                // Done, all is good!
+                return;
+            } catch (java.io.IOException e) {
+                Slog.wtf(PackageManagerService.TAG,
+                        "Unable to write package manager package restrictions, "
+                                + " current changes will be lost at reboot", e);
+                if (str != null) {
+                    atomicFile.failWrite(str);
+                }
             }
         }
     }
@@ -2589,153 +2522,108 @@
         // right time.
         invalidatePackageCache();
 
-        // Keep the old settings around until we know the new ones have
-        // been successfully written.
-        if (mSettingsFilename.exists()) {
-            // Presence of backup settings file indicates that we failed
-            // to persist settings earlier. So preserve the older
-            // backup for future reference since the current settings
-            // might have been corrupted.
-            if (!mPreviousSettingsFilename.exists()) {
-                if (!mSettingsFilename.renameTo(mPreviousSettingsFilename)) {
-                    Slog.wtf(PackageManagerService.TAG,
-                            "Unable to store older package manager settings, "
-                            + " current changes will be lost at reboot");
-                    return;
-                }
-            } else {
-                mSettingsFilename.delete();
-                Slog.w(PackageManagerService.TAG, "Preserving older settings backup");
-            }
-        }
-
         mPastSignatures.clear();
 
-        try {
-            final FileOutputStream fstr = new FileOutputStream(mSettingsFilename);
-            final TypedXmlSerializer serializer = Xml.resolveSerializer(fstr);
-            serializer.startDocument(null, true);
-            serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
-
-            serializer.startTag(null, "packages");
-
-            for (int i = 0; i < mVersion.size(); i++) {
-                final String volumeUuid = mVersion.keyAt(i);
-                final VersionInfo ver = mVersion.valueAt(i);
-
-                serializer.startTag(null, TAG_VERSION);
-                XmlUtils.writeStringAttribute(serializer, ATTR_VOLUME_UUID, volumeUuid);
-                serializer.attributeInt(null, ATTR_SDK_VERSION, ver.sdkVersion);
-                serializer.attributeInt(null, ATTR_DATABASE_VERSION, ver.databaseVersion);
-                XmlUtils.writeStringAttribute(serializer, ATTR_BUILD_FINGERPRINT,
-                        ver.buildFingerprint);
-                XmlUtils.writeStringAttribute(serializer, ATTR_FINGERPRINT, ver.fingerprint);
-                serializer.endTag(null, TAG_VERSION);
-            }
-
-            if (mVerifierDeviceIdentity != null) {
-                serializer.startTag(null, "verifier");
-                serializer.attribute(null, "device", mVerifierDeviceIdentity.toString());
-                serializer.endTag(null, "verifier");
-            }
-
-            serializer.startTag(null, "permission-trees");
-            mPermissions.writePermissionTrees(serializer);
-            serializer.endTag(null, "permission-trees");
-
-            serializer.startTag(null, "permissions");
-            mPermissions.writePermissions(serializer);
-            serializer.endTag(null, "permissions");
-
-            for (final PackageSetting pkg : mPackages.values()) {
-                if (pkg.getPkg() != null && pkg.getPkg().isApex()) {
-                    // Don't persist APEX which doesn't have a valid app id and will fail to load
-                    continue;
-                }
-                writePackageLPr(serializer, pkg);
-            }
-
-            for (final PackageSetting pkg : mDisabledSysPackages.values()) {
-                if (pkg.getPkg() != null && pkg.getPkg().isApex()) {
-                    // Don't persist APEX which doesn't have a valid app id and will fail to load
-                    continue;
-                }
-                writeDisabledSysPackageLPr(serializer, pkg);
-            }
-
-            for (final SharedUserSetting usr : mSharedUsers.values()) {
-                serializer.startTag(null, "shared-user");
-                serializer.attribute(null, ATTR_NAME, usr.name);
-                serializer.attributeInt(null, "userId", usr.mAppId);
-                usr.signatures.writeXml(serializer, "sigs", mPastSignatures.untrackedStorage());
-                serializer.endTag(null, "shared-user");
-            }
-
-            if (mRenamedPackages.size() > 0) {
-                for (Map.Entry<String, String> e : mRenamedPackages.entrySet()) {
-                    serializer.startTag(null, "renamed-package");
-                    serializer.attribute(null, "new", e.getKey());
-                    serializer.attribute(null, "old", e.getValue());
-                    serializer.endTag(null, "renamed-package");
-                }
-            }
-
-            mDomainVerificationManager.writeSettings(computer, serializer,
-                    false /* includeSignatures */, UserHandle.USER_ALL);
-
-            mKeySetManagerService.writeKeySetManagerServiceLPr(serializer);
-
-            serializer.endTag(null, "packages");
-
-            serializer.endDocument();
-
-            fstr.flush();
-            FileUtils.sync(fstr);
-            fstr.close();
-
-            // New settings successfully written, old ones are no longer needed.
-            mPreviousSettingsFilename.delete();
-            mSettingsReserveCopyFilename.delete();
-
-            FileUtils.setPermissions(mSettingsFilename.toString(),
-                    FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP | FileUtils.S_IWGRP,
-                    -1, -1);
-
-            try (FileInputStream in = new FileInputStream(mSettingsFilename);
-                 FileOutputStream out = new FileOutputStream(mSettingsReserveCopyFilename)) {
-                FileUtils.copy(in, out);
-                out.flush();
-                FileUtils.sync(out);
-            } catch (IOException e) {
-                Slog.e(TAG,
-                        "Failed to write reserve copy of settings: " + mSettingsReserveCopyFilename,
-                        e);
-            }
-
+        try (ResilientAtomicFile atomicFile = getSettingsFile()) {
+            FileOutputStream str = null;
             try {
-                FileIntegrity.setUpFsVerity(mSettingsFilename);
-                FileIntegrity.setUpFsVerity(mSettingsReserveCopyFilename);
-            } catch (IOException e) {
-                Slog.e(TAG, "Failed to verity-protect settings", e);
-            }
+                str = atomicFile.startWrite();
 
-            writeKernelMappingLPr();
-            writePackageListLPr();
-            writeAllUsersPackageRestrictionsLPr(sync);
-            writeAllRuntimePermissionsLPr();
-            com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
-                    "package", SystemClock.uptimeMillis() - startTime);
-            return;
+                final TypedXmlSerializer serializer = Xml.resolveSerializer(str);
+                serializer.startDocument(null, true);
+                serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output",
+                        true);
 
-        } catch(java.io.IOException e) {
-            Slog.wtf(PackageManagerService.TAG, "Unable to write package manager settings, "
-                    + "current changes will be lost at reboot", e);
-        }
-        // Clean up partially written files
-        if (mSettingsFilename.exists()) {
-            if (!mSettingsFilename.delete()) {
-                Slog.wtf(PackageManagerService.TAG, "Failed to clean up mangled file: "
-                        + mSettingsFilename);
+                serializer.startTag(null, "packages");
+
+                for (int i = 0; i < mVersion.size(); i++) {
+                    final String volumeUuid = mVersion.keyAt(i);
+                    final VersionInfo ver = mVersion.valueAt(i);
+
+                    serializer.startTag(null, TAG_VERSION);
+                    XmlUtils.writeStringAttribute(serializer, ATTR_VOLUME_UUID, volumeUuid);
+                    serializer.attributeInt(null, ATTR_SDK_VERSION, ver.sdkVersion);
+                    serializer.attributeInt(null, ATTR_DATABASE_VERSION, ver.databaseVersion);
+                    XmlUtils.writeStringAttribute(serializer, ATTR_BUILD_FINGERPRINT,
+                            ver.buildFingerprint);
+                    XmlUtils.writeStringAttribute(serializer, ATTR_FINGERPRINT, ver.fingerprint);
+                    serializer.endTag(null, TAG_VERSION);
+                }
+
+                if (mVerifierDeviceIdentity != null) {
+                    serializer.startTag(null, "verifier");
+                    serializer.attribute(null, "device", mVerifierDeviceIdentity.toString());
+                    serializer.endTag(null, "verifier");
+                }
+
+                serializer.startTag(null, "permission-trees");
+                mPermissions.writePermissionTrees(serializer);
+                serializer.endTag(null, "permission-trees");
+
+                serializer.startTag(null, "permissions");
+                mPermissions.writePermissions(serializer);
+                serializer.endTag(null, "permissions");
+
+                for (final PackageSetting pkg : mPackages.values()) {
+                    if (pkg.getPkg() != null && pkg.getPkg().isApex()) {
+                        // Don't persist APEX which doesn't have a valid app id and will fail to
+                        // load
+                        continue;
+                    }
+                    writePackageLPr(serializer, pkg);
+                }
+
+                for (final PackageSetting pkg : mDisabledSysPackages.values()) {
+                    if (pkg.getPkg() != null && pkg.getPkg().isApex()) {
+                        // Don't persist APEX which doesn't have a valid app id and will fail to
+                        // load
+                        continue;
+                    }
+                    writeDisabledSysPackageLPr(serializer, pkg);
+                }
+
+                for (final SharedUserSetting usr : mSharedUsers.values()) {
+                    serializer.startTag(null, "shared-user");
+                    serializer.attribute(null, ATTR_NAME, usr.name);
+                    serializer.attributeInt(null, "userId", usr.mAppId);
+                    usr.signatures.writeXml(serializer, "sigs", mPastSignatures.untrackedStorage());
+                    serializer.endTag(null, "shared-user");
+                }
+
+                if (mRenamedPackages.size() > 0) {
+                    for (Map.Entry<String, String> e : mRenamedPackages.entrySet()) {
+                        serializer.startTag(null, "renamed-package");
+                        serializer.attribute(null, "new", e.getKey());
+                        serializer.attribute(null, "old", e.getValue());
+                        serializer.endTag(null, "renamed-package");
+                    }
+                }
+
+                mDomainVerificationManager.writeSettings(computer, serializer,
+                        false /* includeSignatures */, UserHandle.USER_ALL);
+
+                mKeySetManagerService.writeKeySetManagerServiceLPr(serializer);
+
+                serializer.endTag(null, "packages");
+
+                serializer.endDocument();
+
+                atomicFile.finishWrite(str);
+
+                writeKernelMappingLPr();
+                writePackageListLPr();
+                writeAllUsersPackageRestrictionsLPr(sync);
+                writeAllRuntimePermissionsLPr();
+                com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
+                        "package", SystemClock.uptimeMillis() - startTime);
+                return;
+
+            } catch (java.io.IOException e) {
+                Slog.wtf(PackageManagerService.TAG, "Unable to write package manager settings, "
+                        + "current changes will be lost at reboot", e);
+                if (str != null) {
+                    atomicFile.failWrite(str);
+                }
             }
         }
         //Debug.stopMethodTracing();
@@ -3160,183 +3048,140 @@
         mInstallerPackages.clear();
         originalFirstInstallTimes.clear();
 
-        File file = null;
-        FileInputStream str = null;
+        try (ResilientAtomicFile atomicFile = getSettingsFile()) {
+            FileInputStream str = null;
+            try {
+                str = atomicFile.openRead();
+                if (str == null) {
+                    // Not necessary, but will avoid wtf-s in the "finally" section.
+                    findOrCreateVersion(StorageManager.UUID_PRIVATE_INTERNAL).forceCurrent();
+                    findOrCreateVersion(StorageManager.UUID_PRIMARY_PHYSICAL).forceCurrent();
+                    return false;
+                }
+                final TypedXmlPullParser parser = Xml.resolvePullParser(str);
 
-        try {
-            // Check if the previous write was incomplete.
-            if (mPreviousSettingsFilename.exists()) {
-                try {
-                    file = mPreviousSettingsFilename;
-                    str = new FileInputStream(file);
-                    mReadMessages.append("Reading from backup settings file\n");
-                    PackageManagerService.reportSettingsProblem(Log.INFO,
-                            "Need to read from backup settings file");
-                    if (mSettingsFilename.exists()) {
-                        // If both the previous and current settings files exist,
-                        // we ignore the current since it might have been corrupted.
-                        Slog.w(PackageManagerService.TAG, "Cleaning up settings file "
-                                + mSettingsFilename);
-                        mSettingsFilename.delete();
+                int type;
+                while ((type = parser.next()) != XmlPullParser.START_TAG
+                        && type != XmlPullParser.END_DOCUMENT) {
+                    // nothing
+                }
+
+                if (type != XmlPullParser.START_TAG) {
+                    mReadMessages.append("No start tag found in settings file\n");
+                    PackageManagerService.reportSettingsProblem(Log.WARN,
+                            "No start tag found in package manager settings");
+                    Slog.wtf(PackageManagerService.TAG,
+                            "No start tag found in package manager settings");
+                    return false;
+                }
+
+                int outerDepth = parser.getDepth();
+                while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                        && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+                    if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                        continue;
                     }
-                    // Ignore reserve copy as well.
-                    mSettingsReserveCopyFilename.delete();
-                } catch (java.io.IOException e) {
-                    // We'll try for the normal settings file.
-                }
-            }
-            if (str == null) {
-                if (mSettingsFilename.exists()) {
-                    // Using packages.xml.
-                    file = mSettingsFilename;
-                    str = new FileInputStream(file);
-                } else if (mSettingsReserveCopyFilename.exists()) {
-                    // Using reserve copy.
-                    file = mSettingsReserveCopyFilename;
-                    str = new FileInputStream(file);
-                    mReadMessages.append("Reading from reserve copy settings file\n");
-                    PackageManagerService.reportSettingsProblem(Log.INFO,
-                            "Need to read from reserve copy settings file");
-                }
-            }
-            if (str == null) {
-                // No available data sources.
-                mReadMessages.append("No settings file found\n");
-                PackageManagerService.reportSettingsProblem(Log.INFO,
-                        "No settings file; creating initial state");
-                // Not necessary, but will avoid wtf-s in the "finally" section.
-                findOrCreateVersion(StorageManager.UUID_PRIVATE_INTERNAL).forceCurrent();
-                findOrCreateVersion(StorageManager.UUID_PRIMARY_PHYSICAL).forceCurrent();
-                return false;
-            }
-            final TypedXmlPullParser parser = Xml.resolvePullParser(str);
 
-            int type;
-            while ((type = parser.next()) != XmlPullParser.START_TAG
-                    && type != XmlPullParser.END_DOCUMENT) {
-                ;
-            }
+                    String tagName = parser.getName();
+                    if (tagName.equals("package")) {
+                        readPackageLPw(parser, users, originalFirstInstallTimes);
+                    } else if (tagName.equals("permissions")) {
+                        mPermissions.readPermissions(parser);
+                    } else if (tagName.equals("permission-trees")) {
+                        mPermissions.readPermissionTrees(parser);
+                    } else if (tagName.equals("shared-user")) {
+                        readSharedUserLPw(parser, users);
+                    } else if (tagName.equals("preferred-packages")) {
+                        // no longer used.
+                    } else if (tagName.equals("preferred-activities")) {
+                        // Upgrading from old single-user implementation;
+                        // these are the preferred activities for user 0.
+                        readPreferredActivitiesLPw(parser, 0);
+                    } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
+                        // TODO: check whether this is okay! as it is very
+                        // similar to how preferred-activities are treated
+                        readPersistentPreferredActivitiesLPw(parser, 0);
+                    } else if (tagName.equals(TAG_CROSS_PROFILE_INTENT_FILTERS)) {
+                        // TODO: check whether this is okay! as it is very
+                        // similar to how preferred-activities are treated
+                        readCrossProfileIntentFiltersLPw(parser, 0);
+                    } else if (tagName.equals(TAG_DEFAULT_BROWSER)) {
+                        readDefaultAppsLPw(parser, 0);
+                    } else if (tagName.equals("updated-package")) {
+                        readDisabledSysPackageLPw(parser, users);
+                    } else if (tagName.equals("renamed-package")) {
+                        String nname = parser.getAttributeValue(null, "new");
+                        String oname = parser.getAttributeValue(null, "old");
+                        if (nname != null && oname != null) {
+                            mRenamedPackages.put(nname, oname);
+                        }
+                    } else if (tagName.equals("last-platform-version")) {
+                        // Upgrade from older XML schema
+                        final VersionInfo internal = findOrCreateVersion(
+                                StorageManager.UUID_PRIVATE_INTERNAL);
+                        final VersionInfo external = findOrCreateVersion(
+                                StorageManager.UUID_PRIMARY_PHYSICAL);
 
-            if (type != XmlPullParser.START_TAG) {
-                mReadMessages.append("No start tag found in settings file\n");
-                PackageManagerService.reportSettingsProblem(Log.WARN,
-                        "No start tag found in package manager settings");
-                Slog.wtf(PackageManagerService.TAG,
-                        "No start tag found in package manager settings");
-                return false;
-            }
+                        internal.sdkVersion = parser.getAttributeInt(null, "internal", 0);
+                        external.sdkVersion = parser.getAttributeInt(null, "external", 0);
+                        internal.buildFingerprint = external.buildFingerprint =
+                                XmlUtils.readStringAttribute(parser, "buildFingerprint");
+                        internal.fingerprint = external.fingerprint =
+                                XmlUtils.readStringAttribute(parser, "fingerprint");
 
-            int outerDepth = parser.getDepth();
-            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                    continue;
-                }
+                    } else if (tagName.equals("database-version")) {
+                        // Upgrade from older XML schema
+                        final VersionInfo internal = findOrCreateVersion(
+                                StorageManager.UUID_PRIVATE_INTERNAL);
+                        final VersionInfo external = findOrCreateVersion(
+                                StorageManager.UUID_PRIMARY_PHYSICAL);
 
-                String tagName = parser.getName();
-                if (tagName.equals("package")) {
-                    readPackageLPw(parser, users, originalFirstInstallTimes);
-                } else if (tagName.equals("permissions")) {
-                    mPermissions.readPermissions(parser);
-                } else if (tagName.equals("permission-trees")) {
-                    mPermissions.readPermissionTrees(parser);
-                } else if (tagName.equals("shared-user")) {
-                    readSharedUserLPw(parser, users);
-                } else if (tagName.equals("preferred-packages")) {
-                    // no longer used.
-                } else if (tagName.equals("preferred-activities")) {
-                    // Upgrading from old single-user implementation;
-                    // these are the preferred activities for user 0.
-                    readPreferredActivitiesLPw(parser, 0);
-                } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
-                    // TODO: check whether this is okay! as it is very
-                    // similar to how preferred-activities are treated
-                    readPersistentPreferredActivitiesLPw(parser, 0);
-                } else if (tagName.equals(TAG_CROSS_PROFILE_INTENT_FILTERS)) {
-                    // TODO: check whether this is okay! as it is very
-                    // similar to how preferred-activities are treated
-                    readCrossProfileIntentFiltersLPw(parser, 0);
-                } else if (tagName.equals(TAG_DEFAULT_BROWSER)) {
-                    readDefaultAppsLPw(parser, 0);
-                } else if (tagName.equals("updated-package")) {
-                    readDisabledSysPackageLPw(parser, users);
-                } else if (tagName.equals("renamed-package")) {
-                    String nname = parser.getAttributeValue(null, "new");
-                    String oname = parser.getAttributeValue(null, "old");
-                    if (nname != null && oname != null) {
-                        mRenamedPackages.put(nname, oname);
+                        internal.databaseVersion = parser.getAttributeInt(null, "internal", 0);
+                        external.databaseVersion = parser.getAttributeInt(null, "external", 0);
+
+                    } else if (tagName.equals("verifier")) {
+                        final String deviceIdentity = parser.getAttributeValue(null, "device");
+                        try {
+                            mVerifierDeviceIdentity = VerifierDeviceIdentity.parse(deviceIdentity);
+                        } catch (IllegalArgumentException e) {
+                            Slog.w(PackageManagerService.TAG, "Discard invalid verifier device id: "
+                                    + e.getMessage());
+                        }
+                    } else if (TAG_READ_EXTERNAL_STORAGE.equals(tagName)) {
+                        // No longer used.
+                    } else if (tagName.equals("keyset-settings")) {
+                        mKeySetManagerService.readKeySetsLPw(parser,
+                                mKeySetRefs.untrackedStorage());
+                    } else if (TAG_VERSION.equals(tagName)) {
+                        final String volumeUuid = XmlUtils.readStringAttribute(parser,
+                                ATTR_VOLUME_UUID);
+                        final VersionInfo ver = findOrCreateVersion(volumeUuid);
+                        ver.sdkVersion = parser.getAttributeInt(null, ATTR_SDK_VERSION);
+                        ver.databaseVersion = parser.getAttributeInt(null, ATTR_DATABASE_VERSION);
+                        ver.buildFingerprint = XmlUtils.readStringAttribute(parser,
+                                ATTR_BUILD_FINGERPRINT);
+                        ver.fingerprint = XmlUtils.readStringAttribute(parser, ATTR_FINGERPRINT);
+                    } else if (tagName.equals(
+                            DomainVerificationPersistence.TAG_DOMAIN_VERIFICATIONS)) {
+                        mDomainVerificationManager.readSettings(computer, parser);
+                    } else if (tagName.equals(
+                            DomainVerificationLegacySettings.TAG_DOMAIN_VERIFICATIONS_LEGACY)) {
+                        mDomainVerificationManager.readLegacySettings(parser);
+                    } else {
+                        Slog.w(PackageManagerService.TAG, "Unknown element under <packages>: "
+                                + parser.getName());
+                        XmlUtils.skipCurrentTag(parser);
                     }
-                } else if (tagName.equals("last-platform-version")) {
-                    // Upgrade from older XML schema
-                    final VersionInfo internal = findOrCreateVersion(
-                            StorageManager.UUID_PRIVATE_INTERNAL);
-                    final VersionInfo external = findOrCreateVersion(
-                            StorageManager.UUID_PRIMARY_PHYSICAL);
-
-                    internal.sdkVersion = parser.getAttributeInt(null, "internal", 0);
-                    external.sdkVersion = parser.getAttributeInt(null, "external", 0);
-                    internal.buildFingerprint = external.buildFingerprint =
-                            XmlUtils.readStringAttribute(parser, "buildFingerprint");
-                    internal.fingerprint = external.fingerprint =
-                            XmlUtils.readStringAttribute(parser, "fingerprint");
-
-                } else if (tagName.equals("database-version")) {
-                    // Upgrade from older XML schema
-                    final VersionInfo internal = findOrCreateVersion(
-                            StorageManager.UUID_PRIVATE_INTERNAL);
-                    final VersionInfo external = findOrCreateVersion(
-                            StorageManager.UUID_PRIMARY_PHYSICAL);
-
-                    internal.databaseVersion = parser.getAttributeInt(null, "internal", 0);
-                    external.databaseVersion = parser.getAttributeInt(null, "external", 0);
-
-                } else if (tagName.equals("verifier")) {
-                    final String deviceIdentity = parser.getAttributeValue(null, "device");
-                    try {
-                        mVerifierDeviceIdentity = VerifierDeviceIdentity.parse(deviceIdentity);
-                    } catch (IllegalArgumentException e) {
-                        Slog.w(PackageManagerService.TAG, "Discard invalid verifier device id: "
-                                + e.getMessage());
-                    }
-                } else if (TAG_READ_EXTERNAL_STORAGE.equals(tagName)) {
-                    // No longer used.
-                } else if (tagName.equals("keyset-settings")) {
-                    mKeySetManagerService.readKeySetsLPw(parser, mKeySetRefs.untrackedStorage());
-                } else if (TAG_VERSION.equals(tagName)) {
-                    final String volumeUuid = XmlUtils.readStringAttribute(parser,
-                            ATTR_VOLUME_UUID);
-                    final VersionInfo ver = findOrCreateVersion(volumeUuid);
-                    ver.sdkVersion = parser.getAttributeInt(null, ATTR_SDK_VERSION);
-                    ver.databaseVersion = parser.getAttributeInt(null, ATTR_DATABASE_VERSION);
-                    ver.buildFingerprint = XmlUtils.readStringAttribute(parser,
-                            ATTR_BUILD_FINGERPRINT);
-                    ver.fingerprint = XmlUtils.readStringAttribute(parser, ATTR_FINGERPRINT);
-                } else if (tagName.equals(DomainVerificationPersistence.TAG_DOMAIN_VERIFICATIONS)) {
-                    mDomainVerificationManager.readSettings(computer, parser);
-                } else if (tagName.equals(
-                        DomainVerificationLegacySettings.TAG_DOMAIN_VERIFICATIONS_LEGACY)) {
-                    mDomainVerificationManager.readLegacySettings(parser);
-                } else {
-                    Slog.w(PackageManagerService.TAG, "Unknown element under <packages>: "
-                            + parser.getName());
-                    XmlUtils.skipCurrentTag(parser);
                 }
+
+                str.close();
+            } catch (IOException | XmlPullParserException e) {
+                // Remove corrupted file and retry.
+                atomicFile.failRead(str, e);
+
+                // Ignore the result to not mark this as a "first boot".
+                readSettingsLPw(computer, users, originalFirstInstallTimes);
             }
-
-            str.close();
-        } catch (IOException | XmlPullParserException e) {
-            mReadMessages.append("Error reading: " + e.toString());
-            PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
-            Slog.wtf(PackageManagerService.TAG, "Error reading package manager settings", e);
-
-            // Remove corrupted file and retry.
-            Slog.e(TAG,
-                    "Error reading package manager settings, removing " + file + " and retrying.",
-                    e);
-            file.delete();
-
-            // Ignore the result to not mark this as a "first boot".
-            readSettingsLPw(computer, users, originalFirstInstallTimes);
         }
 
         return true;
@@ -4488,10 +4333,7 @@
         mPreferredActivities.remove(userId);
 
         synchronized (mPackageRestrictionsLock) {
-            File file = getUserPackagesStateFile(userId);
-            file.delete();
-            file = getUserPackagesStateBackupFile(userId);
-            file.delete();
+            getUserPackagesStateFile(userId).delete();
             mPendingAsyncPackageRestrictionsWrites.delete(userId);
         }
 
@@ -5034,19 +4876,20 @@
             }
         }
         pw.print(prefix); pw.print("  timeStamp=");
-            date.setTime(ps.getLastModifiedTime());
-            pw.println(sdf.format(date));
+        date.setTime(ps.getLastModifiedTime());
+        pw.println(sdf.format(date));
         pw.print(prefix); pw.print("  lastUpdateTime=");
-            date.setTime(ps.getLastUpdateTime());
-            pw.println(sdf.format(date));
-        if (ps.getInstallSource().mInstallerPackageName != null) {
-            pw.print(prefix); pw.print("  installerPackageName=");
-            pw.println(ps.getInstallSource().mInstallerPackageName);
-        }
-        if (ps.getInstallSource().mInstallerPackageUid != INVALID_UID) {
-            pw.print(prefix); pw.print("  installerPackageUid=");
-            pw.println(ps.getInstallSource().mInstallerPackageUid);
-        }
+        date.setTime(ps.getLastUpdateTime());
+        pw.println(sdf.format(date));
+        pw.print(prefix); pw.print("  installerPackageName=");
+        pw.println(ps.getInstallSource().mInstallerPackageName);
+        pw.print(prefix); pw.print("  installerPackageUid=");
+        pw.println(ps.getInstallSource().mInstallerPackageUid);
+        pw.print(prefix); pw.print("  initiatingPackageName=");
+        pw.println(ps.getInstallSource().mInitiatingPackageName);
+        pw.print(prefix); pw.print("  originatingPackageName=");
+        pw.println(ps.getInstallSource().mOriginatingPackageName);
+
         if (ps.getInstallSource().mUpdateOwnerPackageName != null) {
             pw.print(prefix); pw.print("  updateOwnerPackageName=");
             pw.println(ps.getInstallSource().mUpdateOwnerPackageName);
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 6d5e2b0..28cb7f0 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -430,6 +430,7 @@
             @NonNull List<ShortcutInfo> changedShortcuts) {
         Preconditions.checkArgument(newShortcut.isEnabled(),
                 "pushDynamicShortcuts() cannot publish disabled shortcuts");
+        ensureShortcutCountBeforePush();
 
         newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
 
@@ -437,7 +438,7 @@
         final ShortcutInfo oldShortcut = findShortcutById(newShortcut.getId());
         boolean deleted = false;
 
-        if (oldShortcut == null) {
+        if (oldShortcut == null || !oldShortcut.isDynamic()) {
             final ShortcutService service = mShortcutUser.mService;
             final int maxShortcuts = service.getMaxActivityShortcuts();
 
@@ -446,18 +447,12 @@
             final ArrayList<ShortcutInfo> activityShortcuts = all.get(newShortcut.getActivity());
 
             if (activityShortcuts != null && activityShortcuts.size() > maxShortcuts) {
-                Slog.e(TAG, "Error pushing shortcut. There are already "
-                        + activityShortcuts.size() + " shortcuts, exceeding the " + maxShortcuts
-                        + " shortcuts limit when pushing the new shortcut " + newShortcut
-                        + ". Id of shortcuts currently available in system memory are "
-                        + activityShortcuts.stream().map(ShortcutInfo::getId)
-                        .collect(Collectors.joining(",", "[", "]")));
-                // TODO: This should not have happened. If it does, identify the root cause where
-                //  possible, otherwise bail-out early to prevent memory issue.
+                // Root cause was discovered in b/233155034, so this should not be happening.
+                service.wtf("Error pushing shortcut. There are already "
+                        + activityShortcuts.size() + " shortcuts.");
             }
             if (activityShortcuts != null && activityShortcuts.size() == maxShortcuts) {
                 // Max has reached. Delete the shortcut with lowest rank.
-
                 // Sort by isManifestShortcut() and getRank().
                 Collections.sort(activityShortcuts, mShortcutTypeAndRankComparator);
 
@@ -473,7 +468,8 @@
                 deleted = deleteDynamicWithId(shortcut.getId(), /* ignoreInvisible =*/ true,
                         /*ignorePersistedShortcuts=*/ true) != null;
             }
-        } else {
+        }
+        if (oldShortcut != null) {
             // It's an update case.
             // Make sure the target is updatable. (i.e. should be mutable.)
             oldShortcut.ensureUpdatableWith(newShortcut, /*isUpdating=*/ false);
@@ -505,6 +501,32 @@
         return deleted;
     }
 
+    private void ensureShortcutCountBeforePush() {
+        final ShortcutService service = mShortcutUser.mService;
+        // Ensure the total number of shortcuts doesn't exceed the hard limit per app.
+        final int maxShortcutPerApp = service.getMaxAppShortcuts();
+        synchronized (mLock) {
+            final List<ShortcutInfo> appShortcuts = mShortcuts.values().stream().filter(si ->
+                    !si.isPinned()).collect(Collectors.toList());
+            if (appShortcuts.size() >= maxShortcutPerApp) {
+                // Max has reached. Removes shortcuts until they fall within the hard cap.
+                // Sort by isManifestShortcut(), isDynamic() and getLastChangedTimestamp().
+                Collections.sort(appShortcuts, mShortcutTypeRankAndTimeComparator);
+
+                while (appShortcuts.size() >= maxShortcutPerApp) {
+                    final ShortcutInfo shortcut = appShortcuts.remove(appShortcuts.size() - 1);
+                    if (shortcut.isDeclaredInManifest()) {
+                        // All shortcuts are manifest shortcuts and cannot be removed.
+                        throw new IllegalArgumentException(getPackageName() + " has published "
+                                + appShortcuts.size() + " manifest shortcuts across different"
+                                + " activities.");
+                    }
+                    forceDeleteShortcutInner(shortcut.getId());
+                }
+            }
+        }
+    }
+
     /**
      * Remove all shortcuts that aren't pinned, cached nor dynamic.
      *
@@ -1371,6 +1393,61 @@
     };
 
     /**
+     * To sort by isManifestShortcut(), isDynamic(), getRank() and
+     * getLastChangedTimestamp(). i.e. manifest shortcuts come before non-manifest shortcuts,
+     * dynamic shortcuts come before floating shortcuts, then sort by last changed timestamp.
+     *
+     * This is used to decide which shortcuts to remove when the total number of shortcuts retained
+     * for the app exceeds the limit defined in {@link ShortcutService#getMaxAppShortcuts()}.
+     *
+     * (Note the number of manifest shortcuts is always <= the max number, because if there are
+     * more, ShortcutParser would ignore the rest.)
+     */
+    final Comparator<ShortcutInfo> mShortcutTypeRankAndTimeComparator = (ShortcutInfo a,
+            ShortcutInfo b) -> {
+        if (a.isDeclaredInManifest() && !b.isDeclaredInManifest()) {
+            return -1;
+        }
+        if (!a.isDeclaredInManifest() && b.isDeclaredInManifest()) {
+            return 1;
+        }
+        if (a.isDynamic() && b.isDynamic()) {
+            return Integer.compare(a.getRank(), b.getRank());
+        }
+        if (a.isDynamic()) {
+            return -1;
+        }
+        if (b.isDynamic()) {
+            return 1;
+        }
+        if (a.isCached() && b.isCached()) {
+            // if both shortcuts are cached, prioritize shortcuts cached by people tile,
+            if (a.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)
+                    && !b.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)) {
+                return -1;
+            } else if (!a.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)
+                    && b.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)) {
+                return 1;
+            }
+            // followed by bubbles.
+            if (a.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)
+                    && !b.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)) {
+                return -1;
+            } else if (!a.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)
+                    && b.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)) {
+                return 1;
+            }
+        }
+        if (a.isCached()) {
+            return -1;
+        }
+        if (b.isCached()) {
+            return 1;
+        }
+        return Long.compare(b.getLastChangedTimestamp(), a.getLastChangedTimestamp());
+    };
+
+    /**
      * Build a list of shortcuts for each target activity and return as a map. The result won't
      * contain "floating" shortcuts because they don't belong on any activities.
      */
@@ -1971,6 +2048,9 @@
                                         shortcutUser.getUserId(), fromBackup);
                                 // Don't use addShortcut(), we don't need to save the icon.
                                 ret.mShortcuts.put(si.getId(), si);
+                            } catch (IOException e) {
+                                // Don't ignore IO exceptions.
+                                throw e;
                             } catch (Exception e) {
                                 // b/246540168 malformed shortcuts should be ignored
                                 Slog.e(TAG, "Failed parsing shortcut.", e);
diff --git a/services/core/java/com/android/server/pm/ShortcutPackageItem.java b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
index e20330d..8b118da 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackageItem.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
@@ -27,6 +27,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
 import com.android.modules.utils.TypedXmlSerializer;
+import com.android.server.security.FileIntegrity;
 
 import org.json.JSONException;
 import org.json.JSONObject;
@@ -180,6 +181,12 @@
 
             os.flush();
             file.finishWrite(os);
+
+            try {
+                FileIntegrity.setUpFsVerity(path);
+            } catch (IOException e) {
+                Slog.e(TAG, "Failed to verity-protect " + path, e);
+            }
         } catch (XmlPullParserException | IOException e) {
             Slog.e(TAG, "Failed to write to file " + file.getBaseFile(), e);
             file.failWrite(os);
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index b7c3b97..50f88d3 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -119,7 +119,6 @@
 import com.android.modules.utils.TypedXmlSerializer;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
-import com.android.server.security.FileIntegrity;
 import com.android.server.uri.UriGrantsManagerInternal;
 
 import org.json.JSONArray;
@@ -180,6 +179,9 @@
     static final int DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY = 15;
 
     @VisibleForTesting
+    static final int DEFAULT_MAX_SHORTCUTS_PER_APP = 100;
+
+    @VisibleForTesting
     static final int DEFAULT_MAX_ICON_DIMENSION_DP = 96;
 
     @VisibleForTesting
@@ -260,6 +262,11 @@
         String KEY_MAX_SHORTCUTS = "max_shortcuts";
 
         /**
+         * Key name for the max shortcuts can be retained in system ram per app. (int)
+         */
+        String KEY_MAX_SHORTCUTS_PER_APP = "max_shortcuts_per_app";
+
+        /**
          * Key name for icon compression quality, 0-100.
          */
         String KEY_ICON_QUALITY = "icon_quality";
@@ -332,11 +339,16 @@
             new SparseArray<>();
 
     /**
-     * Max number of dynamic + manifest shortcuts that each application can have at a time.
+     * Max number of dynamic + manifest shortcuts that each activity can have at a time.
      */
     private int mMaxShortcuts;
 
     /**
+     * Max number of shortcuts that can exists in system ram for each application.
+     */
+    private int mMaxShortcutsPerApp;
+
+    /**
      * Max number of updating API calls that each application can make during the interval.
      */
     int mMaxUpdatesPerInterval;
@@ -810,6 +822,9 @@
         mMaxShortcuts = Math.max(0, (int) parser.getLong(
                 ConfigConstants.KEY_MAX_SHORTCUTS, DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY));
 
+        mMaxShortcutsPerApp = Math.max(0, (int) parser.getLong(
+                ConfigConstants.KEY_MAX_SHORTCUTS_PER_APP, DEFAULT_MAX_SHORTCUTS_PER_APP));
+
         final int iconDimensionDp = Math.max(1, injectIsLowRamDevice()
                 ? (int) parser.getLong(
                 ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM,
@@ -1054,57 +1069,38 @@
     }
 
     @VisibleForTesting
-    final File getUserFile(@UserIdInt int userId) {
-        return new File(injectUserDataPath(userId), FILENAME_USER_PACKAGES);
-    }
-
-    @VisibleForTesting
-    final File getReserveCopyUserFile(@UserIdInt int userId) {
-        return new File(injectUserDataPath(userId), FILENAME_USER_PACKAGES_RESERVE_COPY);
+    final ResilientAtomicFile getUserFile(@UserIdInt int userId) {
+        File mainFile = new File(injectUserDataPath(userId), FILENAME_USER_PACKAGES);
+        File temporaryBackup = new File(injectUserDataPath(userId),
+                FILENAME_USER_PACKAGES + ".backup");
+        File reserveCopy = new File(injectUserDataPath(userId),
+                FILENAME_USER_PACKAGES_RESERVE_COPY);
+        int fileMode = FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IXOTH;
+        return new ResilientAtomicFile(mainFile, temporaryBackup, reserveCopy, fileMode,
+                "user shortcut", null);
     }
 
     @GuardedBy("mLock")
     private void saveUserLocked(@UserIdInt int userId) {
-        final File path = getUserFile(userId);
-        if (DEBUG || DEBUG_REBOOT) {
-            Slog.d(TAG, "Saving to " + path);
-        }
+        try (ResilientAtomicFile file = getUserFile(userId)) {
+            FileOutputStream os = null;
+            try {
+                if (DEBUG || DEBUG_REBOOT) {
+                    Slog.d(TAG, "Saving to " + file);
+                }
 
-        final File reservePath = getReserveCopyUserFile(userId);
-        reservePath.delete();
+                os = file.startWrite();
 
-        path.getParentFile().mkdirs();
-        final AtomicFile file = new AtomicFile(path);
-        FileOutputStream os = null;
-        try {
-            os = file.startWrite();
+                saveUserInternalLocked(userId, os, /* forBackup= */ false);
 
-            saveUserInternalLocked(userId, os, /* forBackup= */ false);
+                file.finishWrite(os);
 
-            file.finishWrite(os);
-
-            // Remove all dangling bitmap files.
-            cleanupDanglingBitmapDirectoriesLocked(userId);
-        } catch (XmlPullParserException | IOException e) {
-            Slog.e(TAG, "Failed to write to file " + file.getBaseFile(), e);
-            file.failWrite(os);
-        }
-
-        // Store the reserve copy of the file.
-        try (FileInputStream in = new FileInputStream(path);
-             FileOutputStream out = new FileOutputStream(reservePath)) {
-            FileUtils.copy(in, out);
-            FileUtils.sync(out);
-        } catch (IOException e) {
-            Slog.e(TAG, "Failed to write reserve copy: " + path, e);
-        }
-
-        // Protect both primary and reserve copy with fs-verity.
-        try {
-            FileIntegrity.setUpFsVerity(path);
-            FileIntegrity.setUpFsVerity(reservePath);
-        } catch (IOException e) {
-            Slog.e(TAG, "Failed to verity-protect", e);
+                // Remove all dangling bitmap files.
+                cleanupDanglingBitmapDirectoriesLocked(userId);
+            } catch (XmlPullParserException | IOException e) {
+                Slog.e(TAG, "Failed to write to file " + file, e);
+                file.failWrite(os);
+            }
         }
 
         getUserShortcutsLocked(userId).logSharingShortcutStats(mMetricsLogger);
@@ -1141,29 +1137,26 @@
 
     @Nullable
     private ShortcutUser loadUserLocked(@UserIdInt int userId) {
-        final File path = getUserFile(userId);
-        if (DEBUG || DEBUG_REBOOT) {
-            Slog.d(TAG, "Loading from " + path);
-        }
-
-        try (FileInputStream in = new AtomicFile(path).openRead()) {
-            return loadUserInternal(userId, in, /* forBackup= */ false);
-        } catch (FileNotFoundException e) {
-            if (DEBUG || DEBUG_REBOOT) {
-                Slog.d(TAG, "Not found " + path);
-            }
-        } catch (Exception e) {
-            final File reservePath = getReserveCopyUserFile(userId);
-            Slog.e(TAG, "Reading from reserve copy: " + reservePath, e);
-            try (FileInputStream in = new AtomicFile(reservePath).openRead()) {
+        try (ResilientAtomicFile file = getUserFile(userId)) {
+            FileInputStream in = null;
+            try {
+                if (DEBUG || DEBUG_REBOOT) {
+                    Slog.d(TAG, "Loading from " + file);
+                }
+                in = file.openRead();
+                if (in == null) {
+                    if (DEBUG || DEBUG_REBOOT) {
+                        Slog.d(TAG, "Not found " + file);
+                    }
+                    return null;
+                }
                 return loadUserInternal(userId, in, /* forBackup= */ false);
-            } catch (Exception exceptionReadingReserveFile) {
-                Slog.e(TAG, "Failed to read reserve copy: " + reservePath,
-                        exceptionReadingReserveFile);
+            } catch (Exception e) {
+                // Remove corrupted file and retry.
+                file.failRead(in, e);
+                return loadUserLocked(userId);
             }
-            Slog.e(TAG, "Failed to read file " + path, e);
         }
-        return null;
     }
 
     private ShortcutUser loadUserInternal(@UserIdInt int userId, InputStream is,
@@ -1652,7 +1645,7 @@
             return false;
         }
         int uid = injectGetPackageUid(systemChooser.getPackageName(), UserHandle.USER_SYSTEM);
-        return uid == callingUid;
+        return UserHandle.getAppId(uid) == UserHandle.getAppId(callingUid);
     }
 
     private void enforceSystemOrShell() {
@@ -1786,6 +1779,13 @@
     }
 
     /**
+     * Return the max number of shortcuts can be retaiend in system ram for each application.
+     */
+    int getMaxAppShortcuts() {
+        return mMaxShortcutsPerApp;
+    }
+
+    /**
      * - Sends a notification to LauncherApps
      * - Write to file
      */
@@ -4350,14 +4350,8 @@
             @NonNull ComponentName activity, @UserIdInt int userId) {
         final long start = getStatStartTime();
         try {
-            final ActivityInfo ai;
-            try {
-                ai = mContext.getPackageManager().getActivityInfoAsUser(activity,
-                        PackageManager.ComponentInfoFlags.of(PACKAGE_MATCH_FLAGS), userId);
-            } catch (NameNotFoundException e) {
-                return false;
-            }
-            return ai.enabled && ai.exported;
+            return queryActivities(new Intent(), activity.getPackageName(), activity, userId)
+                    .size() > 0;
         } finally {
             logDurationStat(Stats.IS_ACTIVITY_ENABLED, start);
         }
diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java
index 9ef1bba..721ad88 100644
--- a/services/core/java/com/android/server/pm/UserManagerInternal.java
+++ b/services/core/java/com/android/server/pm/UserManagerInternal.java
@@ -64,12 +64,11 @@
     })
     public @interface UserAssignmentResult {}
 
-    // TODO(b/248408342): Move keep annotation to the method referencing these fields reflectively.
-    @Keep public static final int USER_START_MODE_FOREGROUND = 1;
-    @Keep public static final int USER_START_MODE_BACKGROUND = 2;
-    @Keep public static final int USER_START_MODE_BACKGROUND_VISIBLE = 3;
-
     private static final String PREFIX_USER_START_MODE = "USER_START_MODE_";
+
+    /**
+     * Type used to indicate how a user started.
+     */
     @IntDef(flag = false, prefix = {PREFIX_USER_START_MODE}, value = {
             USER_START_MODE_FOREGROUND,
             USER_START_MODE_BACKGROUND,
@@ -77,6 +76,32 @@
     })
     public @interface UserStartMode {}
 
+    // TODO(b/248408342): Move keep annotations below to the method referencing these fields
+    // reflectively.
+
+    /** (Full) user started on foreground (a.k.a. "current user"). */
+    @Keep public static final int USER_START_MODE_FOREGROUND = 1;
+
+    /**
+     * User (full or profile) started on background and is
+     * {@link UserManager#isUserVisible() invisible}.
+     *
+     * <p>This is the "traditional" way of starting a background user, and can be used to start
+     * profiles as well, although starting an invisible profile is not common from the System UI
+     * (it could be done through APIs or adb, though).
+     */
+    @Keep public static final int USER_START_MODE_BACKGROUND = 2;
+
+    /**
+     * User (full or profile) started on background and is
+     * {@link UserManager#isUserVisible() visible}.
+     *
+     * <p>This is the "traditional" way of starting a profile (i.e., when the profile of the current
+     * user is the current foreground user), but it can also be used to start a full user associated
+     * with a display (which is the case on automotives with passenger displays).
+     */
+    @Keep public static final int USER_START_MODE_BACKGROUND_VISIBLE = 3;
+
     public interface UserRestrictionsListener {
         /**
          * Called when a user restriction changes.
@@ -466,8 +491,11 @@
     public abstract boolean isUserVisible(@UserIdInt int userId, int displayId);
 
     /**
-     * Returns the display id assigned to the user, or {@code Display.INVALID_DISPLAY} if the
-     * user is not assigned to any display.
+     * Returns the main display id assigned to the user, or {@code Display.INVALID_DISPLAY} if the
+     * user is not assigned to any main display.
+     *
+     * <p>In the context of multi-user multi-display, there can be multiple main displays, at most
+     * one per each zone. Main displays are where UI is launched which a user interacts with.
      *
      * <p>The current foreground user and its running profiles are associated with the
      * {@link android.view.Display#DEFAULT_DISPLAY default display}, while other users would only be
@@ -478,9 +506,20 @@
      *
      * <p>If the user is a profile and is running, it's assigned to its parent display.
      */
+    // TODO(b/272366483) rename this method to avoid confusion with getDisplaysAssignedTOUser().
     public abstract int getDisplayAssignedToUser(@UserIdInt int userId);
 
     /**
+     * Returns all display ids assigned to the user including {@link
+     * #assignUserToExtraDisplay(int, int) extra displays}, or {@code null} if there is no display
+     * assigned to the specified user.
+     *
+     * <p>Note that this method is different from {@link #getDisplayAssignedToUser(int)}, which
+     * returns a main display only.
+     */
+    public abstract @Nullable int[] getDisplaysAssignedToUser(@UserIdInt int userId);
+
+    /**
      * Returns the main user (i.e., not a profile) that is assigned to the display, or the
      * {@link android.app.ActivityManager#getCurrentUser() current foreground user} if no user is
      * associated with the display.
@@ -548,5 +587,6 @@
 
      * @throws UserManager.CheckedUserOperationException if no switchable user can be found
      */
-    public abstract @UserIdInt int getBootUser() throws UserManager.CheckedUserOperationException;
+    public abstract @UserIdInt int getBootUser(boolean waitUntilSet)
+            throws UserManager.CheckedUserOperationException;
 }
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index dd014ee..cc40363 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -114,6 +114,7 @@
 import android.util.TypedValue;
 import android.util.Xml;
 
+import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IAppOpsService;
@@ -160,7 +161,9 @@
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 
@@ -277,6 +280,8 @@
     static final int WRITE_USER_MSG = 1;
     static final int WRITE_USER_DELAY = 2*1000;  // 2 seconds
 
+    private static final long BOOT_USER_SET_TIMEOUT_MS = 300_000;
+
     // Tron counters
     private static final String TRON_GUEST_CREATED = "users_guest_created";
     private static final String TRON_USER_CREATED = "users_user_created";
@@ -332,6 +337,8 @@
     /** Indicates that this is the 1st boot after the system user mode was changed by emulation. */
     private boolean mUpdatingSystemUserMode;
 
+    /** Count down latch to wait while boot user is not set.*/
+    private final CountDownLatch mBootUserLatch = new CountDownLatch(1);
     /**
      * Internal non-parcelable wrapper for UserInfo that is not exposed to other system apps.
      */
@@ -951,18 +958,62 @@
             Slogf.i(LOG_TAG, "setBootUser %d", userId);
             mBootUser = userId;
         }
+        mBootUserLatch.countDown();
     }
 
     @Override
     public @UserIdInt int getBootUser() {
         checkCreateUsersPermission("Get boot user");
         try {
-            return mLocalService.getBootUser();
+            return getBootUserUnchecked();
         } catch (UserManager.CheckedUserOperationException e) {
             throw e.toServiceSpecificException();
         }
     }
 
+    private @UserIdInt int getBootUserUnchecked() throws UserManager.CheckedUserOperationException {
+        synchronized (mUsersLock) {
+            if (mBootUser != UserHandle.USER_NULL) {
+                final UserData userData = mUsers.get(mBootUser);
+                if (userData != null && userData.info.supportsSwitchToByUser()) {
+                    Slogf.i(LOG_TAG, "Using provided boot user: %d", mBootUser);
+                    return mBootUser;
+                } else {
+                    Slogf.w(LOG_TAG,
+                            "Provided boot user cannot be switched to: %d", mBootUser);
+                }
+            }
+        }
+
+        if (isHeadlessSystemUserMode()) {
+            // Return the previous foreground user, if there is one.
+            final int previousUser = getPreviousFullUserToEnterForeground();
+            if (previousUser != UserHandle.USER_NULL) {
+                Slogf.i(LOG_TAG, "Boot user is previous user %d", previousUser);
+                return previousUser;
+            }
+            // No previous user. Return the first switchable user if there is one.
+            synchronized (mUsersLock) {
+                final int userSize = mUsers.size();
+                for (int i = 0; i < userSize; i++) {
+                    final UserData userData = mUsers.valueAt(i);
+                    if (userData.info.supportsSwitchToByUser()) {
+                        int firstSwitchable = userData.info.id;
+                        Slogf.i(LOG_TAG,
+                                "Boot user is first switchable user %d", firstSwitchable);
+                        return firstSwitchable;
+                    }
+                }
+            }
+            // No switchable users found. Uh oh!
+            throw new UserManager.CheckedUserOperationException(
+                    "No switchable users found", USER_OPERATION_ERROR_UNKNOWN);
+        }
+        // Not HSUM, return system user.
+        return UserHandle.USER_SYSTEM;
+    }
+
+
     @Override
     public int getPreviousFullUserToEnterForeground() {
         checkQueryOrCreateUsersPermission("get previous user");
@@ -1494,7 +1545,8 @@
         // intentSender
         unlockIntent.putExtra(Intent.EXTRA_INTENT, pendingIntent.getIntentSender());
         unlockIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-        mContext.startActivity(unlockIntent);
+        mContext.startActivityAsUser(
+                unlockIntent, UserHandle.of(getProfileParentIdUnchecked(userId)));
     }
 
     @Override
@@ -2048,6 +2100,27 @@
                 + "permission to: check " + name);
     }
 
+    /**
+     * Enforces that the calling user is in the same profile group as {@code userId} or that only
+     * the system UID or root's UID or apps that have the
+     * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or
+     * {@link android.Manifest.permission#CREATE_USERS CREATE_USERS} or
+     * {@link android.Manifest.permission#QUERY_USERS QUERY_USERS}
+     * can make certain calls to the UserManager.
+     *
+     * @param userId the user's id
+     * @param name used as message if SecurityException is thrown
+     * @throws SecurityException if the caller lacks the required permissions.
+     */
+    private void checkQueryOrCreateUsersPermissionIfCallerInOtherProfileGroup(
+            @UserIdInt int userId, String name) {
+        final int callingUserId = UserHandle.getCallingUserId();
+        if (callingUserId == userId || isSameProfileGroupNoChecks(callingUserId, userId)) {
+            return;
+        }
+        checkQueryOrCreateUsersPermission(name);
+    }
+
     @Override
     public boolean isDemoUser(@UserIdInt int userId) {
         final int callingUserId = UserHandle.getCallingUserId();
@@ -2062,6 +2135,15 @@
     }
 
     @Override
+    public boolean isAdminUser(@UserIdInt int userId) {
+        checkQueryOrCreateUsersPermissionIfCallerInOtherProfileGroup(userId, "isAdminUser");
+        synchronized (mUsersLock) {
+            final UserInfo userInfo = getUserInfoLU(userId);
+            return userInfo != null && userInfo.isAdmin();
+        }
+    }
+
+    @Override
     public boolean isPreCreated(@UserIdInt int userId) {
         checkManageOrInteractPermissionIfCallerInOtherProfileGroup(userId, "isPreCreated");
         synchronized (mUsersLock) {
@@ -3473,15 +3555,15 @@
                     return;
                 }
                 final int oldMainUserId = getMainUserIdUnchecked();
-                final int oldFlags = systemUserData.info.flags;
-                final int newFlags;
+                final int oldSysFlags = systemUserData.info.flags;
+                final int newSysFlags;
                 final String newUserType;
                 if (newHeadlessSystemUserMode) {
                     newUserType = UserManager.USER_TYPE_SYSTEM_HEADLESS;
-                    newFlags = oldFlags & ~UserInfo.FLAG_FULL & ~UserInfo.FLAG_MAIN;
+                    newSysFlags = oldSysFlags & ~UserInfo.FLAG_FULL & ~UserInfo.FLAG_MAIN;
                 } else {
                     newUserType = UserManager.USER_TYPE_FULL_SYSTEM;
-                    newFlags = oldFlags | UserInfo.FLAG_FULL;
+                    newSysFlags = oldSysFlags | UserInfo.FLAG_FULL | UserInfo.FLAG_MAIN;
                 }
 
                 if (systemUserData.info.userType.equals(newUserType)) {
@@ -3492,18 +3574,19 @@
                 Slogf.i(LOG_TAG, "Persisting emulated system user data: type changed from %s to "
                         + "%s, flags changed from %s to %s",
                         systemUserData.info.userType, newUserType,
-                        UserInfo.flagsToString(oldFlags), UserInfo.flagsToString(newFlags));
+                        UserInfo.flagsToString(oldSysFlags), UserInfo.flagsToString(newSysFlags));
 
                 systemUserData.info.userType = newUserType;
-                systemUserData.info.flags = newFlags;
+                systemUserData.info.flags = newSysFlags;
                 writeUserLP(systemUserData);
 
-                // Switch the MainUser to a reasonable choice if needed.
-                // (But if there was no MainUser, we deliberately continue to have no MainUser.)
+                // Designate the MainUser to a reasonable choice if needed.
                 final UserData oldMain = getUserDataNoChecks(oldMainUserId);
                 if (newHeadlessSystemUserMode) {
-                    if (oldMain != null && (oldMain.info.flags & UserInfo.FLAG_SYSTEM) != 0) {
-                        // System was MainUser. So we need a new choice for Main. Pick the oldest.
+                    final boolean mainIsAlreadyNonSystem =
+                            oldMain != null && (oldMain.info.flags & UserInfo.FLAG_SYSTEM) == 0;
+                    if (!mainIsAlreadyNonSystem && isMainUserPermanentAdmin()) {
+                        // We need a new choice for Main. Pick the oldest.
                         // If no oldest, don't set any. Let the BootUserInitializer do that later.
                         final UserInfo newMainUser = getEarliestCreatedFullUser();
                         if (newMainUser != null) {
@@ -3513,16 +3596,16 @@
                         }
                     }
                 } else {
+                    // We already made user 0 Main above. Now strip it from the old Main user.
                     // TODO(b/256624031): For now, we demand the Main user (if there is one) is
                     //  always the system in non-HSUM. In the future, when we relax this, change how
                     //  we handle MAIN.
                     if (oldMain != null && (oldMain.info.flags & UserInfo.FLAG_SYSTEM) == 0) {
-                        // Someone else was the MainUser; transfer it to System.
                         Slogf.i(LOG_TAG, "Transferring Main to user 0 from " + oldMain.info.id);
                         oldMain.info.flags &= ~UserInfo.FLAG_MAIN;
-                        systemUserData.info.flags |= UserInfo.FLAG_MAIN;
                         writeUserLP(oldMain);
-                        writeUserLP(systemUserData);
+                    } else {
+                        Slogf.i(LOG_TAG, "Designated user 0 to be Main");
                     }
                 }
             }
@@ -3604,6 +3687,13 @@
         } finally {
             IoUtils.closeQuietly(fis);
         }
+
+        synchronized (mUsersLock) {
+            if (mUsers.size() == 0) {
+                Slog.e(LOG_TAG, "mUsers is empty, fallback to single user");
+                fallbackToSingleUserLP();
+            }
+        }
     }
 
     /**
@@ -3779,12 +3869,14 @@
         if (userVersion < 11) {
             // Add FLAG_MAIN
             if (isHeadlessSystemUserMode()) {
-                final UserInfo earliestCreatedUser = getEarliestCreatedFullUser();
-                if (earliestCreatedUser != null) {
-                    earliestCreatedUser.flags |= UserInfo.FLAG_MAIN;
-                    userIdsToWrite.add(earliestCreatedUser.id);
+                if (isMainUserPermanentAdmin()) {
+                    final UserInfo earliestCreatedUser = getEarliestCreatedFullUser();
+                    if (earliestCreatedUser != null) {
+                        earliestCreatedUser.flags |= UserInfo.FLAG_MAIN;
+                        userIdsToWrite.add(earliestCreatedUser.id);
+                    }
                 }
-            } else {
+            } else { // not isHeadlessSystemUserMode
                 synchronized (mUsersLock) {
                     final UserData userData = mUsers.get(UserHandle.USER_SYSTEM);
                     userData.info.flags |= UserInfo.FLAG_MAIN;
@@ -7098,6 +7190,11 @@
         }
 
         @Override
+        public @Nullable int[] getDisplaysAssignedToUser(@UserIdInt int userId) {
+            return mUserVisibilityMediator.getDisplaysAssignedToUser(userId);
+        }
+
+        @Override
         public @UserIdInt int getUserAssignedToDisplay(int displayId) {
             return mUserVisibilityMediator.getUserAssignedToDisplay(displayId);
         }
@@ -7141,47 +7238,29 @@
         }
 
         @Override
-        public @UserIdInt int getBootUser() throws UserManager.CheckedUserOperationException {
-            synchronized (mUsersLock) {
-                // TODO(b/242195409): On Automotive, block if boot user not provided.
-                if (mBootUser != UserHandle.USER_NULL) {
-                    final UserData userData = mUsers.get(mBootUser);
-                    if (userData != null && userData.info.supportsSwitchToByUser()) {
-                        Slogf.i(LOG_TAG, "Using provided boot user: %d", mBootUser);
-                        return mBootUser;
-                    } else {
-                        Slogf.w(LOG_TAG,
-                                "Provided boot user cannot be switched to: %d", mBootUser);
+        public @UserIdInt int getBootUser(boolean waitUntilSet)
+                throws UserManager.CheckedUserOperationException {
+            if (waitUntilSet) {
+                final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
+                t.traceBegin("wait-boot-user");
+                try {
+                    if (mBootUserLatch.getCount() != 0) {
+                        Slogf.d(LOG_TAG,
+                                "Sleeping for boot user to be set. "
+                                + "Max sleep for Time: %d", BOOT_USER_SET_TIMEOUT_MS);
                     }
+                    if (!mBootUserLatch.await(BOOT_USER_SET_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                        Slogf.w(LOG_TAG, "Boot user not set. Timeout: %d",
+                                BOOT_USER_SET_TIMEOUT_MS);
+                    }
+                } catch (InterruptedException e) {
+                    Thread.currentThread().interrupt();
+                    Slogf.w(LOG_TAG, e, "InterruptedException during wait for boot user.");
                 }
+                t.traceEnd();
             }
 
-            if (isHeadlessSystemUserMode()) {
-                // Return the previous foreground user, if there is one.
-                final int previousUser = getPreviousFullUserToEnterForeground();
-                if (previousUser != UserHandle.USER_NULL) {
-                    Slogf.i(LOG_TAG, "Boot user is previous user %d", previousUser);
-                    return previousUser;
-                }
-                // No previous user. Return the first switchable user if there is one.
-                synchronized (mUsersLock) {
-                    final int userSize = mUsers.size();
-                    for (int i = 0; i < userSize; i++) {
-                        final UserData userData = mUsers.valueAt(i);
-                        if (userData.info.supportsSwitchToByUser()) {
-                            int firstSwitchable = userData.info.id;
-                            Slogf.i(LOG_TAG,
-                                    "Boot user is first switchable user %d", firstSwitchable);
-                            return firstSwitchable;
-                        }
-                    }
-                }
-                // No switchable users found. Uh oh!
-                throw new UserManager.CheckedUserOperationException(
-                        "No switchable users found", USER_OPERATION_ERROR_UNKNOWN);
-            }
-            // Not HSUM, return system user.
-            return UserHandle.USER_SYSTEM;
+            return getBootUserUnchecked();
         }
 
     } // class LocalService
@@ -7369,9 +7448,19 @@
      * If the main user is a permanent admin user it can't be deleted
      * or downgraded to non-admin status.
      */
-    private static boolean isMainUserPermanentAdmin() {
+    public boolean isMainUserPermanentAdmin() {
         return Resources.getSystem()
-                .getBoolean(com.android.internal.R.bool.config_isMainUserPermanentAdmin);
+                .getBoolean(R.bool.config_isMainUserPermanentAdmin);
+    }
+
+    /**
+     * Returns true if {@link com.android.internal.R.bool#config_canSwitchToHeadlessSystemUser}
+     * is true. If allowed, headless system user can run in the foreground even though
+     * it is not a full user.
+     */
+    public boolean canSwitchToHeadlessSystemUser() {
+        return Resources.getSystem()
+                .getBoolean(R.bool.config_canSwitchToHeadlessSystemUser);
     }
 
 }
diff --git a/services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java b/services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java
index eed2a78..333c98c 100644
--- a/services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java
+++ b/services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java
@@ -150,6 +150,10 @@
                     return runIsUserVisible();
                 case "get-main-user":
                     return runGetMainUserId();
+                case "can-switch-to-headless-system-user":
+                    return canSwitchToHeadlessSystemUser();
+                case "is-main-user-permanent-admin":
+                    return isMainUserPermanentAdmin();
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -376,6 +380,7 @@
             final int pid = Process.myPid();
             Slogf.i(LOG_TAG, "Restarting Android runtime(PID=%d) to finalize changes", pid);
             pw.println("Restarting Android runtime to finalize changes");
+            pw.println("The restart may trigger a 'Broken pipe' message; this is to be expected.");
             pw.flush();
 
             // Ideally there should be a cleaner / safer option to restart system_server, but
@@ -532,6 +537,20 @@
         return 0;
     }
 
+    private int canSwitchToHeadlessSystemUser() {
+        PrintWriter pw = getOutPrintWriter();
+        boolean canSwitchToHeadlessSystemUser = mService.canSwitchToHeadlessSystemUser();
+        pw.println(canSwitchToHeadlessSystemUser);
+        return 0;
+    }
+
+    private int isMainUserPermanentAdmin() {
+        PrintWriter pw = getOutPrintWriter();
+        boolean isMainUserPermanentAdmin = mService.isMainUserPermanentAdmin();
+        pw.println(isMainUserPermanentAdmin);
+        return 0;
+    }
+
     /**
      * Gets the {@link UserManager} associated with the context of the given user.
      */
diff --git a/services/core/java/com/android/server/pm/UserVisibilityMediator.java b/services/core/java/com/android/server/pm/UserVisibilityMediator.java
index 3f7502b..b67850a 100644
--- a/services/core/java/com/android/server/pm/UserVisibilityMediator.java
+++ b/services/core/java/com/android/server/pm/UserVisibilityMediator.java
@@ -42,6 +42,7 @@
 import android.util.EventLog;
 import android.util.IndentingPrintWriter;
 import android.util.IntArray;
+import android.util.Log;
 import android.util.SparseIntArray;
 import android.view.Display;
 
@@ -55,6 +56,8 @@
 import com.android.server.utils.Slogf;
 
 import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
@@ -77,11 +80,11 @@
  */
 public final class UserVisibilityMediator implements Dumpable {
 
-    private static final boolean DBG = false; // DO NOT SUBMIT WITH TRUE
-    private static final boolean VERBOSE = false; // DO NOT SUBMIT WITH TRUE
-
     private static final String TAG = UserVisibilityMediator.class.getSimpleName();
 
+    private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
+    private static final boolean VERBOSE = false; // DO NOT SUBMIT WITH TRUE
+
     private static final String PREFIX_SECONDARY_DISPLAY_MAPPING = "SECONDARY_DISPLAY_MAPPING_";
     public static final int SECONDARY_DISPLAY_MAPPING_NEEDED = 1;
     public static final int SECONDARY_DISPLAY_MAPPING_NOT_NEEDED = 2;
@@ -98,14 +101,14 @@
     })
     public @interface SecondaryDisplayMappingStatus {}
 
-    // TODO(b/242195409): might need to change this if boot logic is refactored for HSUM devices
+    // TODO(b/266158156): might need to change this if boot logic is refactored for HSUM devices
     @VisibleForTesting
     static final int INITIAL_CURRENT_USER_ID = USER_SYSTEM;
 
     private final Object mLock = new Object();
 
     private final boolean mVisibleBackgroundUsersEnabled;
-    private final boolean mVisibleBackgroundUserOnDefaultDisplayAllowed;
+    private final boolean mVisibleBackgroundUserOnDefaultDisplayEnabled;
 
     @UserIdInt
     @GuardedBy("mLock")
@@ -132,10 +135,23 @@
     private final SparseIntArray mExtraDisplaysAssignedToUsers;
 
     /**
-     * Mapping from each started user to its profile group.
+     * Mapping of each user that started visible (key) to its profile group id (value).
+     *
+     * <p>It's used to determine not just if the user is visible, but also
+     * {@link #isProfile(int, int) if it's a profile}.
      */
     @GuardedBy("mLock")
-    private final SparseIntArray mStartedProfileGroupIds = new SparseIntArray();
+    private final SparseIntArray mStartedVisibleProfileGroupIds = new SparseIntArray();
+
+    /**
+     * List of profiles that have explicitly started invisible.
+     *
+     * <p>Only used for debugging purposes (and set when {@link #DBG} is {@code true}), hence we
+     * don't care about autoboxing.
+     */
+    @GuardedBy("mLock")
+    @Nullable
+    private final List<Integer> mStartedInvisibleProfileUserIds;
 
     /**
      * Handler user to call listeners
@@ -152,11 +168,17 @@
     }
 
     @VisibleForTesting
-    UserVisibilityMediator(boolean backgroundUsersOnDisplaysEnabled,
-            boolean visibleBackgroundUserOnDefaultDisplayAllowed, Handler handler) {
-        mVisibleBackgroundUsersEnabled = backgroundUsersOnDisplaysEnabled;
-        mVisibleBackgroundUserOnDefaultDisplayAllowed =
-                visibleBackgroundUserOnDefaultDisplayAllowed;
+    UserVisibilityMediator(boolean visibleBackgroundUsersOnDisplaysEnabled,
+            boolean visibleBackgroundUserOnDefaultDisplayEnabled, Handler handler) {
+        mVisibleBackgroundUsersEnabled = visibleBackgroundUsersOnDisplaysEnabled;
+        if (visibleBackgroundUserOnDefaultDisplayEnabled
+                && !visibleBackgroundUsersOnDisplaysEnabled) {
+            throw new IllegalArgumentException("Cannot have "
+                    + "visibleBackgroundUserOnDefaultDisplayEnabled without "
+                    + "visibleBackgroundUsersOnDisplaysEnabled");
+        }
+        mVisibleBackgroundUserOnDefaultDisplayEnabled =
+                visibleBackgroundUserOnDefaultDisplayEnabled;
         if (mVisibleBackgroundUsersEnabled) {
             mUsersAssignedToDisplayOnStart = new SparseIntArray();
             mExtraDisplaysAssignedToUsers = new SparseIntArray();
@@ -164,9 +186,14 @@
             mUsersAssignedToDisplayOnStart = null;
             mExtraDisplaysAssignedToUsers = null;
         }
+        mStartedInvisibleProfileUserIds = DBG ? new ArrayList<>(4) : null;
         mHandler = handler;
-        // TODO(b/242195409): might need to change this if boot logic is refactored for HSUM devices
-        mStartedProfileGroupIds.put(INITIAL_CURRENT_USER_ID, INITIAL_CURRENT_USER_ID);
+        // TODO(b/266158156): might need to change this if boot logic is refactored for HSUM devices
+        mStartedVisibleProfileGroupIds.put(INITIAL_CURRENT_USER_ID, INITIAL_CURRENT_USER_ID);
+
+        if (DBG) {
+            Slogf.i(TAG, "UserVisibilityMediator created with DBG on");
+        }
     }
 
     /**
@@ -177,6 +204,8 @@
             int displayId) {
         Preconditions.checkArgument(!isSpecialUserId(userId), "user id cannot be generic: %d",
                 userId);
+        validateUserStartMode(userStartMode);
+
         // This method needs to perform 4 actions:
         //
         // 1. Check if the user can be started given the provided arguments
@@ -224,14 +253,29 @@
 
             visibleUsersBefore = getVisibleUsers();
 
-            // Set current user / profiles state
-            if (userStartMode == USER_START_MODE_FOREGROUND) {
-                mCurrentUserId = userId;
+            // Set current user / started users state
+            switch (userStartMode) {
+                case USER_START_MODE_FOREGROUND:
+                    mCurrentUserId = userId;
+                    // Fallthrough
+                case USER_START_MODE_BACKGROUND_VISIBLE:
+                    if (DBG) {
+                        Slogf.d(TAG, "adding visible user / profile group id mapping (%d -> %d)",
+                                userId, profileGroupId);
+                    }
+                    mStartedVisibleProfileGroupIds.put(userId, profileGroupId);
+                    break;
+                case USER_START_MODE_BACKGROUND:
+                    if (mStartedInvisibleProfileUserIds != null
+                            && isProfile(userId, profileGroupId)) {
+                        Slogf.d(TAG, "adding user %d to list of invisible profiles", userId);
+                        mStartedInvisibleProfileUserIds.add(userId);
+                    }
+                    break;
+                default:
+                    Slogf.wtf(TAG,  "invalid userStartMode passed to assignUserToDisplayOnStart: "
+                            + "%d", userStartMode);
             }
-            if (DBG) {
-                Slogf.d(TAG, "adding user / profile mapping (%d -> %d)", userId, profileGroupId);
-            }
-            mStartedProfileGroupIds.put(userId, profileGroupId);
 
             //  Set user / display state
             switch (mappingResult) {
@@ -280,14 +324,14 @@
 
         boolean visibleBackground = userStartMode == USER_START_MODE_BACKGROUND_VISIBLE;
         if (displayId == DEFAULT_DISPLAY && visibleBackground) {
-            if (mVisibleBackgroundUserOnDefaultDisplayAllowed && isCurrentUserLocked(userId)) {
+            if (mVisibleBackgroundUserOnDefaultDisplayEnabled && isCurrentUserLocked(userId)) {
                 // Shouldn't happen - UserController returns before calling this method
                 Slogf.wtf(TAG, "trying to start current user (%d) visible in background on default"
                         + " display", userId);
                 return USER_ASSIGNMENT_RESULT_SUCCESS_ALREADY_VISIBLE;
 
             }
-            if (!mVisibleBackgroundUserOnDefaultDisplayAllowed
+            if (!mVisibleBackgroundUserOnDefaultDisplayEnabled
                     && !isProfile(userId, profileGroupId)) {
                 Slogf.wtf(TAG, "cannot start full user (%d) visible on default display", userId);
                 return USER_ASSIGNMENT_RESULT_FAILURE;
@@ -297,38 +341,44 @@
         boolean foreground = userStartMode == USER_START_MODE_FOREGROUND;
         if (displayId != DEFAULT_DISPLAY) {
             if (foreground) {
-                Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %b, %d) failed: cannot start "
+                Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %s, %d) failed: cannot start "
                         + "foreground user on secondary display", userId, profileGroupId,
-                        foreground, displayId);
+                        userStartModeToString(userStartMode), displayId);
                 return USER_ASSIGNMENT_RESULT_FAILURE;
             }
             if (!mVisibleBackgroundUsersEnabled) {
-                Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %b, %d) failed: called on "
+                Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %s, %d) failed: called on "
                         + "device that doesn't support multiple users on multiple displays",
-                        userId, profileGroupId, foreground, displayId);
+                        userId, profileGroupId, userStartModeToString(userStartMode), displayId);
                 return USER_ASSIGNMENT_RESULT_FAILURE;
             }
         }
 
         if (isProfile(userId, profileGroupId)) {
             if (displayId != DEFAULT_DISPLAY) {
-                Slogf.w(TAG, "canStartUserLocked(%d, %d, %b, %d) failed: cannot start profile user "
-                        + "on secondary display", userId, profileGroupId, foreground,
-                        displayId);
+                Slogf.w(TAG, "canStartUserLocked(%d, %d, %s, %d) failed: cannot start profile user "
+                        + "on secondary display", userId, profileGroupId,
+                        userStartModeToString(userStartMode), displayId);
                 return USER_ASSIGNMENT_RESULT_FAILURE;
             }
-            if (foreground) {
-                Slogf.w(TAG, "startUser(%d, %d, %b, %d) failed: cannot start profile user in "
-                        + "foreground", userId, profileGroupId, foreground, displayId);
-                return USER_ASSIGNMENT_RESULT_FAILURE;
-            } else {
-                boolean isParentVisibleOnDisplay = isUserVisible(profileGroupId, displayId);
-                if (DBG) {
-                    Slogf.d(TAG, "parent visible on display: %b", isParentVisibleOnDisplay);
-                }
-                return isParentVisibleOnDisplay
-                        ? USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE
-                        : USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
+            switch (userStartMode) {
+                case USER_START_MODE_FOREGROUND:
+                    Slogf.w(TAG, "startUser(%d, %d, %s, %d) failed: cannot start profile user in "
+                            + "foreground", userId, profileGroupId,
+                            userStartModeToString(userStartMode), displayId);
+                    return USER_ASSIGNMENT_RESULT_FAILURE;
+                case USER_START_MODE_BACKGROUND_VISIBLE:
+                    boolean isParentVisibleOnDisplay = isUserVisible(profileGroupId, displayId);
+                    if (!isParentVisibleOnDisplay) {
+                        Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %s, %d) failed: cannot"
+                                + " start profile user visible when its parent is not visible in "
+                                + "that display", userId, profileGroupId,
+                                userStartModeToString(userStartMode), displayId);
+                        return USER_ASSIGNMENT_RESULT_FAILURE;
+                    }
+                    return USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE;
+                case USER_START_MODE_BACKGROUND:
+                    return USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
             }
         } else if (mUsersAssignedToDisplayOnStart != null
                 && isUserAssignedToDisplayOnStartLocked(userId, displayId)) {
@@ -339,7 +389,7 @@
         }
 
         return foreground || displayId != DEFAULT_DISPLAY
-                || (visibleBackground && mVisibleBackgroundUserOnDefaultDisplayAllowed)
+                || (visibleBackground && mVisibleBackgroundUserOnDefaultDisplayEnabled)
                         ? USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE
                         : USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
     }
@@ -350,11 +400,12 @@
             @UserIdInt int profileGroupId, @UserStartMode int userStartMode, int displayId) {
         if (displayId == DEFAULT_DISPLAY) {
             boolean mappingNeeded = false;
-            if (mVisibleBackgroundUserOnDefaultDisplayAllowed
+            if (mVisibleBackgroundUserOnDefaultDisplayEnabled
                     && userStartMode == USER_START_MODE_BACKGROUND_VISIBLE) {
                 int userStartedOnDefaultDisplay = getUserStartedOnDisplay(DEFAULT_DISPLAY);
-                if (userStartedOnDefaultDisplay != USER_NULL) {
-                    Slogf.w(TAG, "getUserVisibilityOnStartLocked(): cannot start user %d visible on"
+                if (userStartedOnDefaultDisplay != USER_NULL
+                        && userStartedOnDefaultDisplay != profileGroupId) {
+                    Slogf.w(TAG, "canAssignUserToDisplayLocked(): cannot start user %d visible on"
                             + " default display because user %d already did so", userId,
                             userStartedOnDefaultDisplay);
                     return SECONDARY_DISPLAY_MAPPING_FAILED;
@@ -468,7 +519,7 @@
                         userId, displayId);
                 return false;
             }
-            if (isStartedProfile(userId)) {
+            if (isStartedVisibleProfileLocked(userId)) {
                 Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): failed because user is a profile",
                         userId, displayId);
                 return false;
@@ -556,10 +607,14 @@
     @GuardedBy("mLock")
     private void unassignUserFromAllDisplaysOnStopLocked(@UserIdInt int userId) {
         if (DBG) {
-            Slogf.d(TAG, "Removing %d from mStartedProfileGroupIds (%s)", userId,
-                    mStartedProfileGroupIds);
+            Slogf.d(TAG, "Removing %d from mStartedVisibleProfileGroupIds (%s)", userId,
+                    mStartedVisibleProfileGroupIds);
         }
-        mStartedProfileGroupIds.delete(userId);
+        mStartedVisibleProfileGroupIds.delete(userId);
+        if (mStartedInvisibleProfileUserIds != null) {
+            Slogf.d(TAG, "Removing %d from list of invisible profiles", userId);
+            mStartedInvisibleProfileUserIds.remove(Integer.valueOf(userId));
+        }
 
         if (!mVisibleBackgroundUsersEnabled) {
             // Don't need to update mUsersAssignedToDisplayOnStart because methods (such as
@@ -589,7 +644,8 @@
      * See {@link UserManagerInternal#isUserVisible(int)}.
      */
     public boolean isUserVisible(@UserIdInt int userId) {
-        // First check current foreground user and their profiles (on main display)
+        // For optimization (as most devices don't support visible background users), check for
+        // current foreground user and their profiles first
         if (isCurrentUserOrRunningProfileOfCurrentUser(userId)) {
             if (VERBOSE) {
                 Slogf.v(TAG, "isUserVisible(%d): true to current user or profile", userId);
@@ -598,19 +654,31 @@
         }
 
         if (!mVisibleBackgroundUsersEnabled) {
-            if (DBG) {
-                Slogf.d(TAG, "isUserVisible(%d): false for non-current user (or its profiles) when"
+            if (VERBOSE) {
+                Slogf.v(TAG, "isUserVisible(%d): false for non-current user (or its profiles) when"
                         + " device doesn't support visible background users", userId);
             }
             return false;
         }
 
-        boolean visible;
+
         synchronized (mLock) {
-            visible = mUsersAssignedToDisplayOnStart.indexOfKey(userId) >= 0;
+            int profileGroupId;
+            synchronized (mLock) {
+                profileGroupId = mStartedVisibleProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
+            }
+            if (isProfile(userId, profileGroupId)) {
+                return isUserAssignedToDisplayOnStartLocked(profileGroupId);
+            }
+            return isUserAssignedToDisplayOnStartLocked(userId);
         }
-        if (DBG) {
-            Slogf.d(TAG, "isUserVisible(%d): %b from mapping", userId, visible);
+    }
+
+    @GuardedBy("mLock")
+    private boolean isUserAssignedToDisplayOnStartLocked(@UserIdInt int userId) {
+        boolean visible = mUsersAssignedToDisplayOnStart.indexOfKey(userId) >= 0;
+        if (VERBOSE) {
+            Slogf.v(TAG, "isUserAssignedToDisplayOnStartLocked(%d): %b", userId, visible);
         }
         return visible;
     }
@@ -640,7 +708,8 @@
             return false;
         }
 
-        // Current user is always visible on:
+        // For optimization (as most devices don't support visible background users), check for
+        // current user and profile first. Current user is always visible on:
         // - Default display
         // - Secondary displays when device doesn't support visible bg users
         //   - Or when explicitly added (which is checked below)
@@ -662,22 +731,34 @@
         }
 
         synchronized (mLock) {
-            if (mUsersAssignedToDisplayOnStart.get(userId, Display.INVALID_DISPLAY) == displayId) {
-                // User assigned to display on start
-                return true;
+            int profileGroupId;
+            synchronized (mLock) {
+                profileGroupId = mStartedVisibleProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
             }
-
-            // Check for extra display assignment
-            return mExtraDisplaysAssignedToUsers.get(displayId, USER_NULL) == userId;
+            if (isProfile(userId, profileGroupId)) {
+                return isFullUserVisibleOnBackgroundLocked(profileGroupId, displayId);
+            }
+            return isFullUserVisibleOnBackgroundLocked(userId, displayId);
         }
     }
 
+    // NOTE: it doesn't check if the userId is a full user, it's up to the caller to check that
+    @GuardedBy("mLock")
+    private boolean isFullUserVisibleOnBackgroundLocked(@UserIdInt int userId, int displayId) {
+        if (mUsersAssignedToDisplayOnStart.get(userId, Display.INVALID_DISPLAY) == displayId) {
+            // User assigned to display on start
+            return true;
+        }
+        // Check for extra display assignment
+        return mExtraDisplaysAssignedToUsers.get(displayId, USER_NULL) == userId;
+    }
+
     /**
      * See {@link UserManagerInternal#getDisplayAssignedToUser(int)}.
      */
     public int getDisplayAssignedToUser(@UserIdInt int userId) {
         if (isCurrentUserOrRunningProfileOfCurrentUser(userId)) {
-            if (mVisibleBackgroundUserOnDefaultDisplayAllowed) {
+            if (mVisibleBackgroundUserOnDefaultDisplayEnabled) {
                 // When device supports visible bg users on default display, the default display is
                 // assigned to the current user, unless a user is started visible on it
                 int userStartedOnDefaultDisplay;
@@ -705,6 +786,49 @@
         }
     }
 
+    /** See {@link UserManagerInternal#getDisplaysAssignedToUser(int)}. */
+    @Nullable
+    public int[] getDisplaysAssignedToUser(@UserIdInt int userId) {
+        int mainDisplayId = getDisplayAssignedToUser(userId);
+        if (mainDisplayId == INVALID_DISPLAY) {
+            // The user will not have any extra displays if they have no main display.
+            // Return null if no display is assigned to the user.
+            if (DBG) {
+                Slogf.d(TAG, "getDisplaysAssignedToUser(): returning null"
+                        + " because there is no display assigned to user %d", userId);
+            }
+            return null;
+        }
+
+        synchronized (mLock) {
+            if (mExtraDisplaysAssignedToUsers == null
+                    || mExtraDisplaysAssignedToUsers.size() == 0) {
+                return new int[]{mainDisplayId};
+            }
+
+            int count = 0;
+            int[] displayIds = new int[mExtraDisplaysAssignedToUsers.size() + 1];
+            displayIds[count++] = mainDisplayId;
+            for (int i = 0; i < mExtraDisplaysAssignedToUsers.size(); ++i) {
+                if (mExtraDisplaysAssignedToUsers.valueAt(i) == userId) {
+                    displayIds[count++] = mExtraDisplaysAssignedToUsers.keyAt(i);
+                }
+            }
+            // Return the array if the array length happens to be correct.
+            if (displayIds.length == count) {
+                return displayIds;
+            }
+
+            // Copy the results to a new array with the exact length. The size of displayIds[] is
+            // initialized to `1 + mExtraDisplaysAssignedToUsers.size()`, which is usually larger
+            // than the actual length, because mExtraDisplaysAssignedToUsers contains displayIds for
+            // other users. Therefore, we need to copy to a new array with the correct length.
+            int[] results = new int[count];
+            System.arraycopy(displayIds, 0, results, 0, count);
+            return results;
+        }
+    }
+
     /**
      * See {@link UserManagerInternal#getUserAssignedToDisplay(int)}.
      */
@@ -726,7 +850,7 @@
     private @UserIdInt int getUserAssignedToDisplay(@UserIdInt int displayId,
             boolean returnCurrentUserByDefault) {
         if (returnCurrentUserByDefault
-                && ((displayId == DEFAULT_DISPLAY && !mVisibleBackgroundUserOnDefaultDisplayAllowed
+                && ((displayId == DEFAULT_DISPLAY && !mVisibleBackgroundUserOnDefaultDisplayEnabled
                 || !mVisibleBackgroundUsersEnabled))) {
             return getCurrentUserId();
         }
@@ -737,7 +861,7 @@
                     continue;
                 }
                 int userId = mUsersAssignedToDisplayOnStart.keyAt(i);
-                if (!isStartedProfile(userId)) {
+                if (!isStartedVisibleProfileLocked(userId)) {
                     return userId;
                 } else if (DBG) {
                     Slogf.d(TAG, "getUserAssignedToDisplay(%d): skipping user %d because it's "
@@ -770,8 +894,8 @@
         // number of users is too small, the gain is probably not worth the increase on complexity.
         IntArray visibleUsers = new IntArray();
         synchronized (mLock) {
-            for (int i = 0; i < mStartedProfileGroupIds.size(); i++) {
-                int userId = mStartedProfileGroupIds.keyAt(i);
+            for (int i = 0; i < mStartedVisibleProfileGroupIds.size(); i++) {
+                int userId = mStartedVisibleProfileGroupIds.keyAt(i);
                 if (isUserVisible(userId)) {
                     visibleUsers.add(userId);
                 }
@@ -804,7 +928,7 @@
         }
     }
 
-    // TODO(b/242195409): remove this method if not needed anymore
+    // TODO(b/266158156): remove this method if not needed anymore
     /**
      * Nofify all listeners that the system user visibility changed.
      */
@@ -866,6 +990,9 @@
         ipw.println("UserVisibilityMediator");
         ipw.increaseIndent();
 
+        ipw.print("DBG: ");
+        ipw.println(DBG);
+
         synchronized (mLock) {
             ipw.print("Current user id: ");
             ipw.println(mCurrentUserId);
@@ -873,14 +1000,18 @@
             ipw.print("Visible users: ");
             ipw.println(getVisibleUsers());
 
-            dumpSparseIntArray(ipw, mStartedProfileGroupIds, "started user / profile group",
-                    "u", "pg");
+            dumpSparseIntArray(ipw, mStartedVisibleProfileGroupIds,
+                    "started visible user / profile group", "u", "pg");
+            if (mStartedInvisibleProfileUserIds != null) {
+                ipw.print("Profiles started invisible: ");
+                ipw.println(mStartedInvisibleProfileUserIds);
+            }
 
             ipw.print("Supports visible background users on displays: ");
             ipw.println(mVisibleBackgroundUsersEnabled);
 
-            ipw.print("Allows visible background users on default display: ");
-            ipw.println(mVisibleBackgroundUserOnDefaultDisplayAllowed);
+            ipw.print("Supports visible background users on default display: ");
+            ipw.println(mVisibleBackgroundUserOnDefaultDisplayEnabled);
 
             dumpSparseIntArray(ipw, mUsersAssignedToDisplayOnStart, "user / display", "u", "d");
             dumpSparseIntArray(ipw, mExtraDisplaysAssignedToUsers, "extra display / user",
@@ -982,22 +1113,25 @@
             if (mCurrentUserId == userId) {
                 return true;
             }
-            return mStartedProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID) == mCurrentUserId;
+            return mStartedVisibleProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID)
+                    == mCurrentUserId;
         }
     }
 
-    private boolean isStartedProfile(@UserIdInt int userId) {
-        int profileGroupId;
-        synchronized (mLock) {
-            profileGroupId = mStartedProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
-        }
+    @GuardedBy("mLock")
+    private boolean isStartedVisibleProfileLocked(@UserIdInt int userId) {
+        int profileGroupId = mStartedVisibleProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
         return isProfile(userId, profileGroupId);
     }
 
-    private @UserIdInt int getStartedProfileGroupId(@UserIdInt int userId) {
-        synchronized (mLock) {
-            return mStartedProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
+    private void validateUserStartMode(@UserStartMode int userStartMode) {
+        switch (userStartMode) {
+            case USER_START_MODE_FOREGROUND:
+            case USER_START_MODE_BACKGROUND:
+            case USER_START_MODE_BACKGROUND_VISIBLE:
+                return;
         }
+        throw new IllegalArgumentException("Invalid user start mode: " + userStartMode);
     }
 
     private static String secondaryDisplayMappingStatusToString(
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index e74b459..e5e32f0 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -1085,7 +1085,7 @@
     public void grantDefaultPermissionsToActiveLuiApp(String packageName, int userId) {
         Log.i(TAG, "Granting permissions to active LUI app for user:" + userId);
         grantSystemFixedPermissionsToSystemPackage(NO_PM_CACHE, packageName, userId,
-                CAMERA_PERMISSIONS);
+                CAMERA_PERMISSIONS, NOTIFICATION_PERMISSIONS);
     }
 
     public void revokeDefaultPermissionsFromLuiApps(String[] packageNames, int userId) {
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 977fab1..fac681a 100644
--- a/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
@@ -807,10 +807,10 @@
         }
     }
 
-    private abstract static class MimeGroupsAwareIntentResolver<F extends ParsedComponent>
-            extends IntentResolver<Pair<F, ParsedIntentInfo>, ResolveInfo> {
-        private final ArrayMap<String, Pair<F, ParsedIntentInfo>[]> mMimeGroupToFilter =
-                new ArrayMap<>();
+    private abstract static class MimeGroupsAwareIntentResolver<F extends Pair<?
+            extends ParsedComponent, ParsedIntentInfo>, R>
+            extends IntentResolver<F, R> {
+        private final ArrayMap<String, F[]> mMimeGroupToFilter = new ArrayMap<>();
         private boolean mIsUpdatingMimeGroup = false;
 
         @NonNull
@@ -822,7 +822,7 @@
         }
 
         // Copy constructor used in creating snapshots
-        MimeGroupsAwareIntentResolver(MimeGroupsAwareIntentResolver<F> orig,
+        MimeGroupsAwareIntentResolver(MimeGroupsAwareIntentResolver<F, R> orig,
                 @NonNull UserManagerService userManager) {
             mUserManager = userManager;
             copyFrom(orig);
@@ -831,7 +831,7 @@
         }
 
         @Override
-        public void addFilter(@Nullable PackageDataSnapshot snapshot, Pair<F, ParsedIntentInfo> f) {
+        public void addFilter(@Nullable PackageDataSnapshot snapshot, F f) {
             IntentFilter intentFilter = getIntentFilter(f);
             // We assume Computer is available for this class and all subclasses. Because this class
             // uses subclass method override to handle logic, the Computer parameter must be in the
@@ -846,7 +846,7 @@
         }
 
         @Override
-        protected void removeFilterInternal(Pair<F, ParsedIntentInfo> f) {
+        protected void removeFilterInternal(F f) {
             IntentFilter intentFilter = getIntentFilter(f);
             if (!mIsUpdatingMimeGroup) {
                 unregister_intent_filter(f, intentFilter.mimeGroupsIterator(), mMimeGroupToFilter,
@@ -857,86 +857,6 @@
             intentFilter.clearDynamicDataTypes();
         }
 
-        @Override
-        public List<ResolveInfo> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
-                String resolvedType, boolean defaultOnly, int callingUid, @UserIdInt int userId) {
-            if (!mUserManager.exists(userId)) return null;
-            long flags = (defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0);
-            return super.queryIntent(snapshot, intent, resolvedType, defaultOnly, callingUid,
-                    userId, flags);
-        }
-
-        List<ResolveInfo> queryIntent(@NonNull Computer computer, Intent intent,
-                String resolvedType, long flags, int callingUid, int userId) {
-            if (!mUserManager.exists(userId)) return null;
-            return super.queryIntent(computer, intent, resolvedType,
-                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, callingUid, userId, flags);
-        }
-
-        List<ResolveInfo> queryIntentForPackage(@NonNull Computer computer, Intent intent,
-                String resolvedType, long flags, List<F> packageComponents,
-                int callingUid, int userId) {
-            if (!mUserManager.exists(userId)) {
-                return null;
-            }
-            if (packageComponents == null) {
-                return Collections.emptyList();
-            }
-            final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
-            final int componentsSize = packageComponents.size();
-            ArrayList<Pair<F, ParsedIntentInfo>[]> listCut = new ArrayList<>(componentsSize);
-
-            List<ParsedIntentInfo> intentFilters;
-            for (int i = 0; i < componentsSize; ++i) {
-                F component = packageComponents.get(i);
-                intentFilters = component.getIntents();
-                if (!intentFilters.isEmpty()) {
-                    Pair<F, ParsedIntentInfo>[] array = newArray(intentFilters.size());
-                    for (int arrayIndex = 0; arrayIndex < intentFilters.size(); arrayIndex++) {
-                        array[arrayIndex] = Pair.create(component, intentFilters.get(arrayIndex));
-                    }
-                    listCut.add(array);
-                }
-            }
-            return super.queryIntentFromList(computer, intent, resolvedType,
-                    defaultOnly, listCut, callingUid, userId, flags);
-        }
-
-        @Override
-        protected boolean isPackageForFilter(String packageName, Pair<F, ParsedIntentInfo> info) {
-            return packageName.equals(info.first.getPackageName());
-        }
-
-        @Override
-        protected void sortResults(List<ResolveInfo> results) {
-            results.sort(RESOLVE_PRIORITY_SORTER);
-        }
-
-        @Override
-        protected void filterResults(@NonNull Computer computer, @NonNull Intent intent,
-                List<ResolveInfo> results) {
-            if (intent.getAction() != null) return;
-            // When the resolved component is targeting U+, block null action intents
-            for (int i = results.size() - 1; i >= 0; --i) {
-                if (computer.isChangeEnabled(IntentFilter.BLOCK_NULL_ACTION_INTENTS,
-                        results.get(i).getComponentInfo().applicationInfo)) {
-                    results.remove(i);
-                }
-            }
-        }
-
-        @Override
-        protected Pair<F, ParsedIntentInfo>[] newArray(int size) {
-            //noinspection unchecked
-            return (Pair<F, ParsedIntentInfo>[]) new Pair<?, ?>[size];
-        }
-
-        @Override
-        protected IntentFilter getIntentFilter(
-                @NonNull Pair<F, ParsedIntentInfo> input) {
-            return input.second.getIntentFilter();
-        }
-
         /**
          * Updates MIME group by applying changes to all IntentFilters
          * that contain the group and repopulating m*ToFilter maps accordingly
@@ -947,12 +867,12 @@
          */
         public boolean updateMimeGroup(@NonNull Computer computer, String packageName,
                 String mimeGroup) {
-            Pair<F, ParsedIntentInfo>[] filters = mMimeGroupToFilter.get(mimeGroup);
+            F[] filters = mMimeGroupToFilter.get(mimeGroup);
             int n = filters != null ? filters.length : 0;
 
             mIsUpdatingMimeGroup = true;
             boolean hasChanges = false;
-            Pair<F, ParsedIntentInfo> filter;
+            F filter;
             for (int i = 0; i < n && (filter = filters[i]) != null; i++) {
                 if (isPackageForFilter(packageName, filter)) {
                     hasChanges |= updateFilter(computer, filter);
@@ -962,7 +882,7 @@
             return hasChanges;
         }
 
-        private boolean updateFilter(@NonNull Computer computer, Pair<F, ParsedIntentInfo> f) {
+        private boolean updateFilter(@NonNull Computer computer, F f) {
             IntentFilter filter = getIntentFilter(f);
             List<String> oldTypes = filter.dataTypes();
             removeFilter(f);
@@ -987,7 +907,7 @@
             return first.equals(second);
         }
 
-        private void applyMimeGroups(@NonNull Computer computer, Pair<F, ParsedIntentInfo> f) {
+        private void applyMimeGroups(@NonNull Computer computer, F f) {
             IntentFilter filter = getIntentFilter(f);
 
             for (int i = filter.countMimeGroups() - 1; i >= 0; i--) {
@@ -1011,8 +931,8 @@
         }
 
         @Override
-        protected boolean isFilterStopped(@NonNull Computer computer,
-                Pair<F, ParsedIntentInfo> filter, @UserIdInt int userId) {
+        protected boolean isFilterStopped(@NonNull Computer computer, F filter,
+                @UserIdInt int userId) {
             if (!mUserManager.exists(userId)) {
                 return true;
             }
@@ -1028,7 +948,7 @@
     }
 
     public static class ActivityIntentResolver
-            extends MimeGroupsAwareIntentResolver<ParsedActivity> {
+            extends MimeGroupsAwareIntentResolver<Pair<ParsedActivity, ParsedIntentInfo>, ResolveInfo> {
 
         @NonNull
         private UserNeedsBadgingCache mUserNeedsBadging;
@@ -1049,6 +969,53 @@
             mUserNeedsBadging = userNeedsBadgingCache;
         }
 
+        @Override
+        public List<ResolveInfo> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
+                String resolvedType, boolean defaultOnly, @UserIdInt int userId) {
+            if (!mUserManager.exists(userId)) return null;
+            long flags = (defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0);
+            return super.queryIntent(snapshot, intent, resolvedType, defaultOnly, userId, flags);
+        }
+
+        List<ResolveInfo> queryIntent(@NonNull Computer computer, Intent intent,
+                String resolvedType, long flags, int userId) {
+            if (!mUserManager.exists(userId)) {
+                return null;
+            }
+            return super.queryIntent(computer, intent, resolvedType,
+                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId, flags);
+        }
+
+        List<ResolveInfo> queryIntentForPackage(@NonNull Computer computer, Intent intent,
+                String resolvedType, long flags, List<ParsedActivity> packageActivities,
+                int userId) {
+            if (!mUserManager.exists(userId)) {
+                return null;
+            }
+            if (packageActivities == null) {
+                return Collections.emptyList();
+            }
+            final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
+            final int activitiesSize = packageActivities.size();
+            ArrayList<Pair<ParsedActivity, ParsedIntentInfo>[]> listCut =
+                    new ArrayList<>(activitiesSize);
+
+            List<ParsedIntentInfo> intentFilters;
+            for (int i = 0; i < activitiesSize; ++i) {
+                ParsedActivity activity = packageActivities.get(i);
+                intentFilters = activity.getIntents();
+                if (!intentFilters.isEmpty()) {
+                    Pair<ParsedActivity, ParsedIntentInfo>[] array = newArray(intentFilters.size());
+                    for (int arrayIndex = 0; arrayIndex < intentFilters.size(); arrayIndex++) {
+                        array[arrayIndex] = Pair.create(activity, intentFilters.get(arrayIndex));
+                    }
+                    listCut.add(array);
+                }
+            }
+            return super.queryIntentFromList(computer, intent, resolvedType,
+                    defaultOnly, listCut, userId, flags);
+        }
+
         protected void addActivity(@NonNull Computer computer, ParsedActivity a, String type,
                 List<Pair<ParsedActivity, ParsedIntentInfo>> newIntents) {
             mActivities.put(a.getComponentName(), a);
@@ -1105,6 +1072,18 @@
             return true;
         }
 
+        @Override
+        protected Pair<ParsedActivity, ParsedIntentInfo>[] newArray(int size) {
+            //noinspection unchecked
+            return (Pair<ParsedActivity, ParsedIntentInfo>[]) new Pair<?, ?>[size];
+        }
+
+        @Override
+        protected boolean isPackageForFilter(String packageName,
+                Pair<ParsedActivity, ParsedIntentInfo> info) {
+            return packageName.equals(info.first.getPackageName());
+        }
+
         private void log(String reason, ParsedIntentInfo info, int match,
                 int userId) {
             Slog.w(TAG, reason
@@ -1220,6 +1199,11 @@
         }
 
         @Override
+        protected void sortResults(List<ResolveInfo> results) {
+            results.sort(RESOLVE_PRIORITY_SORTER);
+        }
+
+        @Override
         protected void dumpFilter(PrintWriter out, String prefix,
                 Pair<ParsedActivity, ParsedIntentInfo> pair) {
             ParsedActivity activity = pair.first;
@@ -1253,6 +1237,12 @@
             out.println();
         }
 
+        @Override
+        protected IntentFilter getIntentFilter(
+                @NonNull Pair<ParsedActivity, ParsedIntentInfo> input) {
+            return input.second.getIntentFilter();
+        }
+
         protected List<ParsedActivity> getResolveList(AndroidPackage pkg) {
             return pkg.getActivities();
         }
@@ -1288,7 +1278,7 @@
     }
 
     public static final class ProviderIntentResolver
-            extends MimeGroupsAwareIntentResolver<ParsedProvider> {
+            extends MimeGroupsAwareIntentResolver<Pair<ParsedProvider, ParsedIntentInfo>, ResolveInfo> {
         // Default constructor
         ProviderIntentResolver(@NonNull UserManagerService userManager) {
             super(userManager);
@@ -1301,6 +1291,57 @@
             mProviders.putAll(orig.mProviders);
         }
 
+        @Override
+        public List<ResolveInfo> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
+                String resolvedType, boolean defaultOnly, @UserIdInt int userId) {
+            if (!mUserManager.exists(userId)) {
+                return null;
+            }
+            long flags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
+            return super.queryIntent(snapshot, intent, resolvedType, defaultOnly, userId, flags);
+        }
+
+        @Nullable
+        List<ResolveInfo> queryIntent(@NonNull Computer computer, Intent intent,
+                String resolvedType, long flags, int userId) {
+            if (!mUserManager.exists(userId)) {
+                return null;
+            }
+            return super.queryIntent(computer, intent, resolvedType,
+                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId, flags);
+        }
+
+        @Nullable
+        List<ResolveInfo> queryIntentForPackage(@NonNull Computer computer, Intent intent,
+                String resolvedType, long flags, List<ParsedProvider> packageProviders,
+                int userId) {
+            if (!mUserManager.exists(userId)) {
+                return null;
+            }
+            if (packageProviders == null) {
+                return Collections.emptyList();
+            }
+            final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
+            final int providersSize = packageProviders.size();
+            ArrayList<Pair<ParsedProvider, ParsedIntentInfo>[]> listCut =
+                    new ArrayList<>(providersSize);
+
+            List<ParsedIntentInfo> intentFilters;
+            for (int i = 0; i < providersSize; ++i) {
+                ParsedProvider provider = packageProviders.get(i);
+                intentFilters = provider.getIntents();
+                if (!intentFilters.isEmpty()) {
+                    Pair<ParsedProvider, ParsedIntentInfo>[] array = newArray(intentFilters.size());
+                    for (int arrayIndex = 0; arrayIndex < intentFilters.size(); arrayIndex++) {
+                        array[arrayIndex] = Pair.create(provider, intentFilters.get(arrayIndex));
+                    }
+                    listCut.add(array);
+                }
+            }
+            return super.queryIntentFromList(computer, intent, resolvedType,
+                    defaultOnly, listCut, userId, flags);
+        }
+
         void addProvider(@NonNull Computer computer, ParsedProvider p) {
             if (mProviders.containsKey(p.getComponentName())) {
                 Slog.w(TAG, "Provider " + p.getComponentName() + " already defined; ignoring");
@@ -1361,6 +1402,18 @@
         }
 
         @Override
+        protected Pair<ParsedProvider, ParsedIntentInfo>[] newArray(int size) {
+            //noinspection unchecked
+            return (Pair<ParsedProvider, ParsedIntentInfo>[]) new Pair<?, ?>[size];
+        }
+
+        @Override
+        protected boolean isPackageForFilter(String packageName,
+                Pair<ParsedProvider, ParsedIntentInfo> info) {
+            return packageName.equals(info.first.getPackageName());
+        }
+
+        @Override
         protected ResolveInfo newResult(@NonNull Computer computer,
                 Pair<ParsedProvider, ParsedIntentInfo> pair, int match, int userId,
                 long customFlags) {
@@ -1426,6 +1479,11 @@
         }
 
         @Override
+        protected void sortResults(List<ResolveInfo> results) {
+            results.sort(RESOLVE_PRIORITY_SORTER);
+        }
+
+        @Override
         protected void dumpFilter(PrintWriter out, String prefix,
                 Pair<ParsedProvider, ParsedIntentInfo> pair) {
             ParsedProvider provider = pair.first;
@@ -1460,11 +1518,17 @@
             out.println();
         }
 
+        @Override
+        protected IntentFilter getIntentFilter(
+                @NonNull Pair<ParsedProvider, ParsedIntentInfo> input) {
+            return input.second.getIntentFilter();
+        }
+
         final ArrayMap<ComponentName, ParsedProvider> mProviders = new ArrayMap<>();
     }
 
     public static final class ServiceIntentResolver
-            extends MimeGroupsAwareIntentResolver<ParsedService> {
+            extends MimeGroupsAwareIntentResolver<Pair<ParsedService, ParsedIntentInfo>, ResolveInfo> {
         // Default constructor
         ServiceIntentResolver(@NonNull UserManagerService userManager) {
             super(userManager);
@@ -1477,6 +1541,50 @@
             mServices.putAll(orig.mServices);
         }
 
+        @Override
+        public List<ResolveInfo> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
+                String resolvedType, boolean defaultOnly, @UserIdInt int userId) {
+            if (!mUserManager.exists(userId)) {
+                return null;
+            }
+            long flags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
+            return super.queryIntent(snapshot, intent, resolvedType, defaultOnly, userId, flags);
+        }
+
+        List<ResolveInfo> queryIntent(@NonNull Computer computer, Intent intent,
+                String resolvedType, long flags, int userId) {
+            if (!mUserManager.exists(userId)) return null;
+            return super.queryIntent(computer, intent, resolvedType,
+                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId, flags);
+        }
+
+        List<ResolveInfo> queryIntentForPackage(@NonNull Computer computer, Intent intent,
+                String resolvedType, long flags, List<ParsedService> packageServices, int userId) {
+            if (!mUserManager.exists(userId)) return null;
+            if (packageServices == null) {
+                return Collections.emptyList();
+            }
+            final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
+            final int servicesSize = packageServices.size();
+            ArrayList<Pair<ParsedService, ParsedIntentInfo>[]> listCut =
+                    new ArrayList<>(servicesSize);
+
+            List<ParsedIntentInfo> intentFilters;
+            for (int i = 0; i < servicesSize; ++i) {
+                ParsedService service = packageServices.get(i);
+                intentFilters = service.getIntents();
+                if (intentFilters.size() > 0) {
+                    Pair<ParsedService, ParsedIntentInfo>[] array = newArray(intentFilters.size());
+                    for (int arrayIndex = 0; arrayIndex < intentFilters.size(); arrayIndex++) {
+                        array[arrayIndex] = Pair.create(service, intentFilters.get(arrayIndex));
+                    }
+                    listCut.add(array);
+                }
+            }
+            return super.queryIntentFromList(computer, intent, resolvedType,
+                    defaultOnly, listCut, userId, flags);
+        }
+
         void addService(@NonNull Computer computer, ParsedService s) {
             mServices.put(s.getComponentName(), s);
             if (DEBUG_SHOW_INFO) {
@@ -1532,6 +1640,18 @@
         }
 
         @Override
+        protected Pair<ParsedService, ParsedIntentInfo>[] newArray(int size) {
+            //noinspection unchecked
+            return (Pair<ParsedService, ParsedIntentInfo>[]) new Pair<?, ?>[size];
+        }
+
+        @Override
+        protected boolean isPackageForFilter(String packageName,
+                Pair<ParsedService, ParsedIntentInfo> info) {
+            return packageName.equals(info.first.getPackageName());
+        }
+
+        @Override
         protected ResolveInfo newResult(@NonNull Computer computer,
                 Pair<ParsedService, ParsedIntentInfo> pair, int match, int userId,
                 long customFlags) {
@@ -1590,6 +1710,11 @@
         }
 
         @Override
+        protected void sortResults(List<ResolveInfo> results) {
+            results.sort(RESOLVE_PRIORITY_SORTER);
+        }
+
+        @Override
         protected void dumpFilter(PrintWriter out, String prefix,
                 Pair<ParsedService, ParsedIntentInfo> pair) {
             ParsedService service = pair.first;
@@ -1627,6 +1752,12 @@
             out.println();
         }
 
+        @Override
+        protected IntentFilter getIntentFilter(
+                @NonNull Pair<ParsedService, ParsedIntentInfo> input) {
+            return input.second.getIntentFilter();
+        }
+
         // Keys are String (activity class name), values are Activity.
         final ArrayMap<ComponentName, ParsedService> mServices = new ArrayMap<>();
     }
@@ -1690,8 +1821,7 @@
         }
 
         @Override
-        protected void filterResults(@NonNull Computer computer,
-                @NonNull Intent intent, List<AuxiliaryResolveInfo.AuxiliaryFilter> results) {
+        protected void filterResults(List<AuxiliaryResolveInfo.AuxiliaryFilter> results) {
             // only do work if ordering is enabled [most of the time it won't be]
             if (mOrderResult.size() == 0) {
                 return;
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolverApi.java b/services/core/java/com/android/server/pm/resolution/ComponentResolverApi.java
index 7f88660..b8e4c8d 100644
--- a/services/core/java/com/android/server/pm/resolution/ComponentResolverApi.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolverApi.java
@@ -55,12 +55,12 @@
 
     @Nullable
     List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
-            @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId);
+            @Nullable String resolvedType, long flags, @UserIdInt int userId);
 
     @Nullable
     List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
             @Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> activities,
-            int callingUid, @UserIdInt int userId);
+            @UserIdInt int userId);
 
     @Nullable
     ProviderInfo queryProvider(@NonNull Computer computer, @NonNull String authority, long flags,
@@ -68,12 +68,12 @@
 
     @Nullable
     List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
-            @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId);
+            @Nullable String resolvedType, long flags, @UserIdInt int userId);
 
     @Nullable
     List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
             @Nullable String resolvedType, long flags, @NonNull List<ParsedProvider> providers,
-            int callingUid, @UserIdInt int userId);
+            @UserIdInt int userId);
 
     @Nullable
     List<ProviderInfo> queryProviders(@NonNull Computer computer, @Nullable String processName,
@@ -81,21 +81,21 @@
 
     @Nullable
     List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
-            @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId);
+            @Nullable String resolvedType, long flags, @UserIdInt int userId);
 
     @Nullable
     List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
             @Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> receivers,
-            int callingUid, @UserIdInt int userId);
+            @UserIdInt int userId);
 
     @Nullable
     List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
-            @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId);
+            @Nullable String resolvedType, long flags, @UserIdInt int userId);
 
     @Nullable
     List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
             @Nullable String resolvedType, long flags, @NonNull List<ParsedService> services,
-            int callingUid, @UserIdInt int userId);
+            @UserIdInt int userId);
 
     void querySyncProviders(@NonNull Computer computer, @NonNull List<String> outNames,
             @NonNull List<ProviderInfo> outInfo, boolean safeMode, @UserIdInt int userId);
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java b/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java
index 6899924..9115775 100644
--- a/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java
@@ -126,17 +126,17 @@
     @Nullable
     @Override
     public List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
-            @Nullable String resolvedType, long flags, int callingUid, int userId) {
-        return mActivities.queryIntent(computer, intent, resolvedType, flags, callingUid, userId);
+            @Nullable String resolvedType, long flags, int userId) {
+        return mActivities.queryIntent(computer, intent, resolvedType, flags, userId);
     }
 
     @Nullable
     @Override
     public List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
             @Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> activities,
-            int callingUid, int userId) {
+            int userId) {
         return mActivities.queryIntentForPackage(computer, intent, resolvedType, flags, activities,
-                callingUid, userId);
+                userId);
     }
 
     @Nullable
@@ -168,17 +168,17 @@
     @Nullable
     @Override
     public List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
-            @Nullable String resolvedType, long flags, int callingUid, int userId) {
-        return mProviders.queryIntent(computer, intent, resolvedType, flags, callingUid, userId);
+            @Nullable String resolvedType, long flags, int userId) {
+        return mProviders.queryIntent(computer, intent, resolvedType, flags, userId);
     }
 
     @Nullable
     @Override
     public List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
             @Nullable String resolvedType, long flags, @NonNull List<ParsedProvider> providers,
-            int callingUid, @UserIdInt int userId) {
+            @UserIdInt int userId) {
         return mProviders.queryIntentForPackage(computer, intent, resolvedType, flags, providers,
-                callingUid, userId);
+                userId);
     }
 
     @Nullable
@@ -241,33 +241,33 @@
     @Nullable
     @Override
     public List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
-            @Nullable String resolvedType, long flags, int callingUid, int userId) {
-        return mReceivers.queryIntent(computer, intent, resolvedType, flags, callingUid, userId);
+            @Nullable String resolvedType, long flags, int userId) {
+        return mReceivers.queryIntent(computer, intent, resolvedType, flags, userId);
     }
 
     @Nullable
     @Override
     public List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
             @Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> receivers,
-            int callingUid, @UserIdInt int userId) {
+            @UserIdInt int userId) {
         return mReceivers.queryIntentForPackage(computer, intent, resolvedType, flags, receivers,
-                callingUid, userId);
+                userId);
     }
 
     @Nullable
     @Override
     public List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
-            @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId) {
-        return mServices.queryIntent(computer, intent, resolvedType, flags, callingUid, userId);
+            @Nullable String resolvedType, long flags, @UserIdInt int userId) {
+        return mServices.queryIntent(computer, intent, resolvedType, flags, userId);
     }
 
     @Nullable
     @Override
     public List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
             @Nullable String resolvedType, long flags, @NonNull List<ParsedService> services,
-            int callingUid, @UserIdInt int userId) {
+            @UserIdInt int userId) {
         return mServices.queryIntentForPackage(computer, intent, resolvedType, flags, services,
-                callingUid, userId);
+                userId);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolverLocked.java b/services/core/java/com/android/server/pm/resolution/ComponentResolverLocked.java
index 5bfb135..0c84f4c 100644
--- a/services/core/java/com/android/server/pm/resolution/ComponentResolverLocked.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolverLocked.java
@@ -92,9 +92,9 @@
     @Nullable
     @Override
     public List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
-            @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId) {
+            @Nullable String resolvedType, long flags, @UserIdInt int userId) {
         synchronized (mLock) {
-            return super.queryActivities(computer, intent, resolvedType, flags, callingUid, userId);
+            return super.queryActivities(computer, intent, resolvedType, flags, userId);
         }
     }
 
@@ -102,10 +102,9 @@
     @Override
     public List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
             @Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> activities,
-            int callingUid, @UserIdInt int userId) {
+            @UserIdInt int userId) {
         synchronized (mLock) {
-            return super.queryActivities(computer, intent, resolvedType, flags, activities,
-                    callingUid, userId);
+            return super.queryActivities(computer, intent, resolvedType, flags, activities, userId);
         }
     }
 
@@ -121,9 +120,9 @@
     @Nullable
     @Override
     public List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
-            @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId) {
+            @Nullable String resolvedType, long flags, @UserIdInt int userId) {
         synchronized (mLock) {
-            return super.queryProviders(computer, intent, resolvedType, flags, callingUid, userId);
+            return super.queryProviders(computer, intent, resolvedType, flags, userId);
         }
     }
 
@@ -131,10 +130,9 @@
     @Override
     public List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
             @Nullable String resolvedType, long flags, @NonNull List<ParsedProvider> providers,
-            int callingUid, @UserIdInt int userId) {
+            @UserIdInt int userId) {
         synchronized (mLock) {
-            return super.queryProviders(computer, intent, resolvedType, flags, providers,
-                    callingUid, userId);
+            return super.queryProviders(computer, intent, resolvedType, flags, providers, userId);
         }
     }
 
@@ -151,9 +149,9 @@
     @Nullable
     @Override
     public List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
-            @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId) {
+            @Nullable String resolvedType, long flags, @UserIdInt int userId) {
         synchronized (mLock) {
-            return super.queryReceivers(computer, intent, resolvedType, flags, callingUid, userId);
+            return super.queryReceivers(computer, intent, resolvedType, flags, userId);
         }
     }
 
@@ -161,19 +159,18 @@
     @Override
     public List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
             @Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> receivers,
-            int callingUid, @UserIdInt int userId) {
+            @UserIdInt int userId) {
         synchronized (mLock) {
-            return super.queryReceivers(computer, intent, resolvedType, flags, receivers,
-                    callingUid, userId);
+            return super.queryReceivers(computer, intent, resolvedType, flags, receivers, userId);
         }
     }
 
     @Nullable
     @Override
     public List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
-            @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId) {
+            @Nullable String resolvedType, long flags, @UserIdInt int userId) {
         synchronized (mLock) {
-            return super.queryServices(computer, intent, resolvedType, flags, callingUid, userId);
+            return super.queryServices(computer, intent, resolvedType, flags, userId);
         }
     }
 
@@ -181,10 +178,9 @@
     @Override
     public List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
             @Nullable String resolvedType, long flags, @NonNull List<ParsedService> services,
-            int callingUid, @UserIdInt int userId) {
+            @UserIdInt int userId) {
         synchronized (mLock) {
-            return super.queryServices(computer, intent, resolvedType, flags, services, callingUid,
-                    userId);
+            return super.queryServices(computer, intent, resolvedType, flags, services, userId);
         }
     }
 
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 37877cf..ea53ea5 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -332,6 +332,10 @@
     static final int TRIPLE_PRESS_PRIMARY_NOTHING = 0;
     static final int TRIPLE_PRESS_PRIMARY_TOGGLE_ACCESSIBILITY = 1;
 
+    // Must match: config_searchKeyBehavior in config.xml
+    static final int SEARCH_BEHAVIOR_DEFAULT_SEARCH = 0;
+    static final int SEARCH_BEHAVIOR_TARGET_ACTIVITY = 1;
+
     static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
     static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
     static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
@@ -540,6 +544,8 @@
     boolean mWakeOnAssistKeyPress;
     boolean mWakeOnBackKeyPress;
     long mWakeUpToLastStateTimeout;
+    int mSearchKeyBehavior;
+    ComponentName mSearchKeyTargetActivity;
 
     private boolean mHandleVolumeKeysInWM;
 
@@ -641,6 +647,9 @@
 
     private boolean mLockNowPending = false;
 
+    // Timeout for showing the keyguard after the screen is on, in case no "ready" is received.
+    private int mKeyguardDrawnTimeout = 1000;
+
     private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
     private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4;
     private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5;
@@ -1241,6 +1250,11 @@
             case LONG_PRESS_POWER_SHUT_OFF:
             case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
                 mPowerKeyHandled = true;
+                // don't actually trigger the shutdown if we are running stability
+                // tests via monkey
+                if (ActivityManager.isUserAMonkey()) {
+                    break;
+                }
                 performHapticFeedback(HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, false,
                         "Power - Long Press - Shut Off");
                 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
@@ -2139,6 +2153,12 @@
         mWakeUpToLastStateTimeout = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_wakeUpToLastStateTimeoutMillis);
 
+        mSearchKeyBehavior = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_searchKeyBehavior);
+
+        mSearchKeyTargetActivity = ComponentName.unflattenFromString(
+            mContext.getResources().getString(
+                com.android.internal.R.string.config_searchKeyTargetActivity));
         readConfigurationDependentBehaviors();
 
         mDisplayFoldController = DisplayFoldController.create(mContext, DEFAULT_DISPLAY);
@@ -2219,6 +2239,8 @@
             }
         });
 
+        mKeyguardDrawnTimeout = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_keyguardDrawnTimeout);
         mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
                 new StateCallback() {
                     @Override
@@ -2965,7 +2987,7 @@
                 }
                 break;
             case KeyEvent.KEYCODE_H:
-                if (down && event.isMetaPressed()) {
+                if (event.isMetaPressed()) {
                     return handleHomeShortcuts(displayId, focusedToken, event);
                 }
                 break;
@@ -3006,11 +3028,6 @@
                 if (down && event.isMetaPressed() && event.isCtrlPressed() && repeatCount == 0) {
                     enterStageSplitFromRunningApp(true /* leftOrTop */);
                     return key_consumed;
-                } else if (!down && event.isMetaPressed()) {
-                    boolean backKeyHandled = backKeyPress();
-                    if (backKeyHandled) {
-                        return key_consumed;
-                    }
                 }
                 break;
             case KeyEvent.KEYCODE_DPAD_RIGHT:
@@ -3019,14 +3036,6 @@
                     return key_consumed;
                 }
                 break;
-            case KeyEvent.KEYCODE_GRAVE:
-                if (!down && event.isMetaPressed()) {
-                    boolean backKeyHandled = backKeyPress();
-                    if (backKeyHandled) {
-                        return key_consumed;
-                    }
-                }
-                break;
             case KeyEvent.KEYCODE_SLASH:
                 if (down && repeatCount == 0 && event.isMetaPressed() && !keyguardOn) {
                     toggleKeyboardShortcutsMenu(event.getDeviceId());
@@ -3161,7 +3170,19 @@
                     toggleNotificationPanel();
                 }
                 return key_consumed;
-
+            case KeyEvent.KEYCODE_SEARCH:
+                if (down && repeatCount == 0 && !keyguardOn()) {
+                    switch(mSearchKeyBehavior) {
+                        case SEARCH_BEHAVIOR_TARGET_ACTIVITY: {
+                            launchTargetSearchActivity();
+                            return key_consumed;
+                        }
+                        case SEARCH_BEHAVIOR_DEFAULT_SEARCH:
+                        default:
+                            break;
+                    }
+                }
+                break;
             case KeyEvent.KEYCODE_SPACE:
                 // Handle keyboard layout switching. (META + SPACE)
                 if ((metaState & KeyEvent.META_META_MASK) == 0) {
@@ -4507,25 +4528,6 @@
      */
     private boolean isWakeKeyWhenScreenOff(int keyCode) {
         switch (keyCode) {
-            case KeyEvent.KEYCODE_VOLUME_UP:
-            case KeyEvent.KEYCODE_VOLUME_DOWN:
-            case KeyEvent.KEYCODE_VOLUME_MUTE:
-                return mDefaultDisplayPolicy.getDockMode() != Intent.EXTRA_DOCK_STATE_UNDOCKED;
-
-            case KeyEvent.KEYCODE_MUTE:
-            case KeyEvent.KEYCODE_HEADSETHOOK:
-            case KeyEvent.KEYCODE_MEDIA_PLAY:
-            case KeyEvent.KEYCODE_MEDIA_PAUSE:
-            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
-            case KeyEvent.KEYCODE_MEDIA_STOP:
-            case KeyEvent.KEYCODE_MEDIA_NEXT:
-            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
-            case KeyEvent.KEYCODE_MEDIA_REWIND:
-            case KeyEvent.KEYCODE_MEDIA_RECORD:
-            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
-            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
-                return false;
-
             case KeyEvent.KEYCODE_DPAD_UP:
             case KeyEvent.KEYCODE_DPAD_DOWN:
             case KeyEvent.KEYCODE_DPAD_LEFT:
@@ -4984,7 +4986,7 @@
         final boolean bootCompleted =
                 LocalServices.getService(SystemServiceManager.class).isBootCompleted();
         // Set longer timeout if it has not booted yet to prevent showing empty window.
-        return bootCompleted ? 1000 : 5000;
+        return bootCompleted ? mKeyguardDrawnTimeout : 5000;
     }
 
     // Called on the DisplayManager's DisplayPowerController thread.
@@ -6344,4 +6346,22 @@
         }
     }
 
+    private void launchTargetSearchActivity() {
+        Intent intent;
+        if (mSearchKeyTargetActivity != null) {
+            intent = new Intent();
+            intent.setComponent(mSearchKeyTargetActivity);
+        } else {
+            intent = new Intent(Intent.ACTION_WEB_SEARCH);
+        }
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+        try {
+            startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
+        } catch (ActivityNotFoundException ignore) {
+            Slog.e(TAG, "Could not resolve activity with : "
+                    + intent.getComponent().flattenToString()
+                    + " name.");
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/policy/PowerAction.java b/services/core/java/com/android/server/policy/PowerAction.java
index d2de58e..deb86b5 100644
--- a/services/core/java/com/android/server/policy/PowerAction.java
+++ b/services/core/java/com/android/server/policy/PowerAction.java
@@ -15,6 +15,7 @@
  */
 package com.android.server.policy;
 
+import android.app.ActivityManager;
 import android.content.Context;
 import android.os.UserManager;
 import com.android.internal.globalactions.LongPressAction;
@@ -35,6 +36,11 @@
 
     @Override
     public boolean onLongPress() {
+        // don't actually trigger the reboot if we are running stability
+        // tests via monkey
+        if (ActivityManager.isUserAMonkey()) {
+            return false;
+        }
         UserManager um = mContext.getSystemService(UserManager.class);
         if (!um.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
             mWindowManagerFuncs.rebootSafeMode(true);
@@ -55,6 +61,11 @@
 
     @Override
     public void onPress() {
+        // don't actually trigger the shutdown if we are running stability
+        // tests via monkey
+        if (ActivityManager.isUserAMonkey()) {
+            return;
+        }
         // shutdown by making sure radio and power are handled accordingly.
         mWindowManagerFuncs.shutdown(false /* confirm */);
     }
diff --git a/services/core/java/com/android/server/policy/RestartAction.java b/services/core/java/com/android/server/policy/RestartAction.java
index 0f13da8..24c921e 100644
--- a/services/core/java/com/android/server/policy/RestartAction.java
+++ b/services/core/java/com/android/server/policy/RestartAction.java
@@ -15,6 +15,7 @@
  */
 package com.android.server.policy;
 
+import android.app.ActivityManager;
 import android.content.Context;
 import android.os.UserManager;
 import com.android.internal.globalactions.LongPressAction;
@@ -35,6 +36,11 @@
 
     @Override
     public boolean onLongPress() {
+        // don't actually trigger the reboot if we are running stability
+        // tests via monkey
+        if (ActivityManager.isUserAMonkey()) {
+            return false;
+        }
         UserManager um = mContext.getSystemService(UserManager.class);
         if (!um.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
             mWindowManagerFuncs.rebootSafeMode(true);
@@ -55,6 +61,11 @@
 
     @Override
     public void onPress() {
+        // don't actually trigger the reboot if we are running stability
+        // tests via monkey
+        if (ActivityManager.isUserAMonkey()) {
+            return;
+        }
         mWindowManagerFuncs.reboot(false /* confirm */);
     }
 }
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index 85f1357..646dc4e 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -29,6 +29,7 @@
 import com.android.internal.policy.IKeyguardService;
 import com.android.server.UiThread;
 import com.android.server.policy.WindowManagerPolicy.OnKeyguardExitResult;
+import com.android.server.wm.EventLogTags;
 
 import java.io.PrintWriter;
 
@@ -255,6 +256,11 @@
     public void setOccluded(boolean isOccluded, boolean notify) {
         if (mKeyguardService != null && notify) {
             if (DEBUG) Log.v(TAG, "setOccluded(" + isOccluded + ")");
+            EventLogTags.writeWmSetKeyguardOccluded(
+                    isOccluded ? 1 : 0,
+                    0 /* animate */,
+                    0 /* transit */,
+                    "setOccluded");
             mKeyguardService.setOccluded(isOccluded, false /* animate */);
         }
         mKeyguardState.occluded = isOccluded;
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index b83d509..2e8a150 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -40,7 +40,6 @@
 import android.annotation.RequiresPermission;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
-import android.app.ActivityManagerInternal;
 import android.app.AppOpsManager;
 import android.app.SynchronousUserSwitchObserver;
 import android.content.BroadcastReceiver;
@@ -317,7 +316,6 @@
     private SettingsObserver mSettingsObserver;
     private DreamManagerInternal mDreamManager;
     private LogicalLight mAttentionLight;
-    private ActivityManagerInternal mAmInternal;
 
     private final InattentiveSleepWarningController mInattentiveSleepWarningOverlayController;
     private final AmbientDisplaySuppressionController mAmbientDisplaySuppressionController;
@@ -1244,7 +1242,6 @@
             mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);
             mPolicy = getLocalService(WindowManagerPolicy.class);
             mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);
-            mAmInternal = getLocalService(ActivityManagerInternal.class);
             mAttentionDetector.systemReady(mContext);
 
             SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());
@@ -4088,8 +4085,9 @@
                     final UidState state = wakeLock.mUidState;
                     if (Arrays.binarySearch(mDeviceIdleWhitelist, appid) < 0 &&
                             Arrays.binarySearch(mDeviceIdleTempWhitelist, appid) < 0 &&
-                            (mAmInternal != null && !mAmInternal.canHoldWakeLocksInDeepDoze(
-                                    state.mUid, state.mProcState))) {
+                            state.mProcState != ActivityManager.PROCESS_STATE_NONEXISTENT &&
+                            state.mProcState >
+                                    ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
                         disabled = true;
                     }
                 }
@@ -5695,6 +5693,7 @@
             }
 
             if (eventTime > now) {
+                Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now);
                 throw new IllegalArgumentException("event time must not be in the future");
             }
 
@@ -5710,7 +5709,9 @@
         @Override // Binder call
         public void wakeUp(long eventTime, @WakeReason int reason, String details,
                 String opPackageName) {
-            if (eventTime > mClock.uptimeMillis()) {
+            final long now = mClock.uptimeMillis();
+            if (eventTime > now) {
+                Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now);
                 throw new IllegalArgumentException("event time must not be in the future");
             }
 
@@ -5762,7 +5763,9 @@
 
         @Override // Binder call
         public void nap(long eventTime) {
-            if (eventTime > mClock.uptimeMillis()) {
+            final long now = mClock.uptimeMillis();
+            if (eventTime > now) {
+                Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now);
                 throw new IllegalArgumentException("event time must not be in the future");
             }
 
@@ -6527,7 +6530,9 @@
 
         @Override // Binder call
         public void boostScreenBrightness(long eventTime) {
+            final long now = mClock.uptimeMillis();
             if (eventTime > mClock.uptimeMillis()) {
+                Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now);
                 throw new IllegalArgumentException("event time must not be in the future");
             }
 
@@ -6686,7 +6691,9 @@
 
     @RequiresPermission(android.Manifest.permission.DEVICE_POWER)
     private void goToSleepInternal(IntArray groupIds, long eventTime, int reason, int flags) {
-        if (eventTime > mClock.uptimeMillis()) {
+        final long now = mClock.uptimeMillis();
+        if (eventTime > now) {
+            Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now);
             throw new IllegalArgumentException("event time must not be in the future");
         }
 
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index 5096ad1..c2d4ac6 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -17,6 +17,7 @@
 
 package com.android.server.power;
 
+import android.app.ActivityManagerInternal;
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.IActivityManager;
@@ -25,10 +26,12 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.DialogInterface;
+import android.content.IIntentReceiver;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManagerInternal;
 import android.media.AudioAttributes;
+import android.os.Bundle;
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.PowerManager;
@@ -51,7 +54,6 @@
 
 import com.android.server.LocalServices;
 import com.android.server.RescueParty;
-import com.android.server.pm.PackageManagerService;
 import com.android.server.statusbar.StatusBarManagerInternal;
 
 import java.io.File;
@@ -448,13 +450,6 @@
                 new File(CHECK_POINTS_FILE_BASENAME));
         dumpCheckPointsThread.start();
 
-        BroadcastReceiver br = new BroadcastReceiver() {
-            @Override public void onReceive(Context context, Intent intent) {
-                // We don't allow apps to cancel this, so ignore the result.
-                actionDone();
-            }
-        };
-
         /*
          * Write a system property in case the system_server reboots before we
          * get to the actual hardware restart. If that happens, we'll retry at
@@ -490,8 +485,16 @@
         mActionDone = false;
         Intent intent = new Intent(Intent.ACTION_SHUTDOWN);
         intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_REGISTERED_ONLY);
-        mContext.sendOrderedBroadcastAsUser(intent,
-                UserHandle.ALL, null, br, mHandler, 0, null, null);
+        final ActivityManagerInternal activityManagerInternal = LocalServices.getService(
+                ActivityManagerInternal.class);
+        activityManagerInternal.broadcastIntentWithCallback(intent,
+                new IIntentReceiver.Stub() {
+                    @Override
+                    public void performReceive(Intent intent, int resultCode, String data,
+                            Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
+                        mHandler.post(ShutdownThread.this::actionDone);
+                    }
+                }, null, UserHandle.USER_ALL, null, null, null);
 
         final long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME;
         synchronized (mActionDoneSync) {
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 f11c864..661715c 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -26,6 +26,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.app.AlarmManager;
 import android.app.usage.NetworkStatsManager;
 import android.bluetooth.BluetoothActivityEnergyInfo;
 import android.bluetooth.UidTraffic;
@@ -500,14 +501,6 @@
 
     }
 
-    /** Handles calls to AlarmManager */
-    public interface AlarmInterface {
-        /** Schedule an RTC alarm */
-        void schedule(long rtcTimeMs, long windowLengthMs);
-        /** Cancel the previously scheduled alarm */
-        void cancel();
-    }
-
     private final PlatformIdleStateCallback mPlatformIdleStateCallback;
 
     private final Runnable mDeferSetCharging = new Runnable() {
@@ -1569,8 +1562,15 @@
     @GuardedBy("this")
     protected BatteryStatsConfig mBatteryStatsConfig = new BatteryStatsConfig.Builder().build();
 
-    @VisibleForTesting
-    protected AlarmInterface mLongPlugInAlarmInterface = null;
+    @GuardedBy("this")
+    private AlarmManager mAlarmManager = null;
+
+    private final AlarmManager.OnAlarmListener mLongPlugInAlarmHandler = () ->
+            mHandler.post(() -> {
+                synchronized (BatteryStatsImpl.this) {
+                    maybeResetWhilePluggedInLocked();
+                }
+            });
 
     /*
      * Holds a SamplingTimer associated with each Resource Power Manager state and voter,
@@ -11061,18 +11061,6 @@
     }
 
     /**
-     * Injects an AlarmInterface for the long plug in alarm.
-     */
-    public void setLongPlugInAlarmInterface(AlarmInterface longPlugInAlarmInterface) {
-        synchronized (this) {
-            mLongPlugInAlarmInterface = longPlugInAlarmInterface;
-            if (mBatteryPluggedIn) {
-                scheduleNextResetWhilePluggedInCheck();
-            }
-        }
-    }
-
-    /**
      * Starts tracking CPU time-in-state for threads of the system server process,
      * keeping a separate account of threads receiving incoming binder calls.
      */
@@ -12688,8 +12676,8 @@
             energy = info.getControllerEnergyUsed();
             if (!info.getUidTraffic().isEmpty()) {
                 for (UidTraffic traffic : info.getUidTraffic()) {
-                    uidRxBytes.incrementValue(traffic.getUid(), traffic.getRxBytes());
-                    uidTxBytes.incrementValue(traffic.getUid(), traffic.getTxBytes());
+                    uidRxBytes.put(traffic.getUid(), traffic.getRxBytes());
+                    uidTxBytes.put(traffic.getUid(), traffic.getTxBytes());
                 }
             }
         }
@@ -14173,6 +14161,7 @@
     /**
      * Might reset battery stats if conditions are met. Assumed the device is currently plugged in.
      */
+    @VisibleForTesting
     @GuardedBy("this")
     public void maybeResetWhilePluggedInLocked() {
         final long elapsedRealtimeMs = mClock.elapsedRealtime();
@@ -14189,28 +14178,31 @@
 
     @GuardedBy("this")
     private void scheduleNextResetWhilePluggedInCheck() {
-        if (mLongPlugInAlarmInterface != null) {
-            final long timeoutMs = mClock.currentTimeMillis()
-                    + mConstants.RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS
-                    * DateUtils.HOUR_IN_MILLIS;
-            Calendar nextAlarm = Calendar.getInstance();
-            nextAlarm.setTimeInMillis(timeoutMs);
+        if (mAlarmManager == null) return;
+        final long timeoutMs = mClock.currentTimeMillis()
+                + mConstants.RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS
+                * DateUtils.HOUR_IN_MILLIS;
+        Calendar nextAlarm = Calendar.getInstance();
+        nextAlarm.setTimeInMillis(timeoutMs);
 
-            // Find the 2 AM the same day as the end of the minimum duration.
-            // This logic does not handle a Daylight Savings transition, or a timezone change
-            // while the alarm has been set. The need to reset after a long period while plugged
-            // in is not strict enough to warrant a well architected out solution.
-            nextAlarm.set(Calendar.MILLISECOND, 0);
-            nextAlarm.set(Calendar.SECOND, 0);
-            nextAlarm.set(Calendar.MINUTE, 0);
-            nextAlarm.set(Calendar.HOUR_OF_DAY, 2);
-            long nextTimeMs = nextAlarm.getTimeInMillis();
-            if (nextTimeMs < timeoutMs) {
-                // The 2AM on the day of the timeout, move on the next day.
-                nextTimeMs += DateUtils.DAY_IN_MILLIS;
-            }
-            mLongPlugInAlarmInterface.schedule(nextTimeMs, DateUtils.HOUR_IN_MILLIS);
+        // Find the 2 AM the same day as the end of the minimum duration.
+        // This logic does not handle a Daylight Savings transition, or a timezone change
+        // while the alarm has been set. The need to reset after a long period while plugged
+        // in is not strict enough to warrant a well architected out solution.
+        nextAlarm.set(Calendar.MILLISECOND, 0);
+        nextAlarm.set(Calendar.SECOND, 0);
+        nextAlarm.set(Calendar.MINUTE, 0);
+        nextAlarm.set(Calendar.HOUR_OF_DAY, 2);
+        long possibleNextTimeMs = nextAlarm.getTimeInMillis();
+        if (possibleNextTimeMs < timeoutMs) {
+            // The 2AM on the day of the timeout, move on the next day.
+            possibleNextTimeMs += DateUtils.DAY_IN_MILLIS;
         }
+        final long nextTimeMs = possibleNextTimeMs;
+        final AlarmManager am = mAlarmManager;
+        mHandler.post(() -> am.setWindow(AlarmManager.RTC, nextTimeMs,
+                DateUtils.HOUR_IN_MILLIS,
+                TAG, mLongPlugInAlarmHandler, mHandler));
     }
 
 
@@ -14339,8 +14331,12 @@
                 initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
             }
             mBatteryPluggedIn = false;
-            if (mLongPlugInAlarmInterface != null) {
-                mLongPlugInAlarmInterface.cancel();
+            if (mAlarmManager != null) {
+                final AlarmManager am = mAlarmManager;
+                mHandler.post(() -> {
+                    // No longer plugged in. Cancel the long plug in alarm.
+                    am.cancel(mLongPlugInAlarmHandler);
+                });
             }
             mHistory.recordBatteryState(mSecRealtime, mSecUptime, level, mBatteryPluggedIn);
             mDischargeCurrentLevel = mDischargeUnplugLevel = level;
@@ -15178,6 +15174,14 @@
     public void systemServicesReady(Context context) {
         mConstants.startObserving(context.getContentResolver());
         registerUsbStateReceiver(context);
+
+        synchronized (this) {
+            mAlarmManager = context.getSystemService(AlarmManager.class);
+            if (mBatteryPluggedIn) {
+                // Already plugged in. Schedule the long plug in alarm.
+                scheduleNextResetWhilePluggedInCheck();
+            }
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/power/stats/CpuWakeupStats.java b/services/core/java/com/android/server/power/stats/CpuWakeupStats.java
index 54f3476..b05b662 100644
--- a/services/core/java/com/android/server/power/stats/CpuWakeupStats.java
+++ b/services/core/java/com/android/server/power/stats/CpuWakeupStats.java
@@ -18,10 +18,13 @@
 
 import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_ALARM;
 import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_UNKNOWN;
+import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_WIFI;
 
 import android.content.Context;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.UserHandle;
+import android.provider.DeviceConfig;
 import android.util.IndentingPrintWriter;
 import android.util.IntArray;
 import android.util.LongSparseArray;
@@ -39,6 +42,8 @@
 
 import java.util.Arrays;
 import java.util.List;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -49,14 +54,15 @@
     private static final String TAG = "CpuWakeupStats";
 
     private static final String SUBSYSTEM_ALARM_STRING = "Alarm";
-    @VisibleForTesting
-    static final long WAKEUP_RETENTION_MS = 3 * 24 * 60 * 60_000; // 3 days.
+    private static final String SUBSYSTEM_ALARM_WIFI = "Wifi";
     @VisibleForTesting
     static final long WAKEUP_REASON_HALF_WINDOW_MS = 500;
-    private static final long WAKEUP_WRITE_DELAY_MS = 2 * 60 * 1000;  // 2 minutes.
+    private static final long WAKEUP_WRITE_DELAY_MS = TimeUnit.MINUTES.toMillis(2);
 
     private final Handler mHandler;
     private final IrqDeviceMap mIrqDeviceMap;
+    @VisibleForTesting
+    final Config mConfig = new Config();
     private final WakingActivityHistory mRecentWakingActivity = new WakingActivityHistory();
 
     @VisibleForTesting
@@ -70,10 +76,20 @@
         mHandler = handler;
     }
 
+    /**
+     * Called on the boot phase SYSTEM_SERVICES_READY.
+     * This ensures that DeviceConfig is ready for calls to read properties.
+     */
+    public synchronized void systemServicesReady() {
+        mConfig.register(new HandlerExecutor(mHandler));
+    }
+
     private static int subsystemToStatsReason(int subsystem) {
         switch (subsystem) {
             case CPU_WAKEUP_SUBSYSTEM_ALARM:
                 return FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED__REASON__ALARM;
+            case CPU_WAKEUP_SUBSYSTEM_WIFI:
+                return FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED__REASON__WIFI;
         }
         return FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED__REASON__UNKNOWN;
     }
@@ -122,21 +138,25 @@
     /** Notes a wakeup reason as reported by SuspendControlService to battery stats. */
     public synchronized void noteWakeupTimeAndReason(long elapsedRealtime, long uptime,
             String rawReason) {
-        final Wakeup parsedWakeup = new Wakeup(rawReason, elapsedRealtime, uptime);
+        final Wakeup parsedWakeup = Wakeup.parseWakeup(rawReason, elapsedRealtime, uptime);
+        if (parsedWakeup == null) {
+            return;
+        }
         mWakeupEvents.put(elapsedRealtime, parsedWakeup);
         attemptAttributionFor(parsedWakeup);
         // Assuming that wakeups always arrive in monotonically increasing elapsedRealtime order,
         // we can delete all history that will not be useful in attributing future wakeups.
         mRecentWakingActivity.clearAllBefore(elapsedRealtime - WAKEUP_REASON_HALF_WINDOW_MS);
 
-        // Limit history of wakeups and their attribution to the last WAKEUP_RETENTION_MS. Note that
+        // Limit history of wakeups and their attribution to the last retentionDuration. Note that
         // the last wakeup and its attribution (if computed) is always stored, even if that wakeup
-        // had occurred before WAKEUP_RETENTION_MS.
-        int lastIdx = mWakeupEvents.closestIndexOnOrBefore(elapsedRealtime - WAKEUP_RETENTION_MS);
+        // had occurred before retentionDuration.
+        final long retentionDuration = mConfig.WAKEUP_STATS_RETENTION_MS;
+        int lastIdx = mWakeupEvents.closestIndexOnOrBefore(elapsedRealtime - retentionDuration);
         for (int i = lastIdx; i >= 0; i--) {
             mWakeupEvents.removeAt(i);
         }
-        lastIdx = mWakeupAttribution.closestIndexOnOrBefore(elapsedRealtime - WAKEUP_RETENTION_MS);
+        lastIdx = mWakeupAttribution.closestIndexOnOrBefore(elapsedRealtime - retentionDuration);
         for (int i = lastIdx; i >= 0; i--) {
             mWakeupAttribution.removeAt(i);
         }
@@ -219,6 +239,9 @@
         pw.println("CPU wakeup stats:");
         pw.increaseIndent();
 
+        mConfig.dump(pw);
+        pw.println();
+
         mIrqDeviceMap.dump(pw);
         pw.println();
 
@@ -289,7 +312,8 @@
     }
 
     private static final class WakingActivityHistory {
-        private static final long WAKING_ACTIVITY_RETENTION_MS = 3 * 60 * 60_000; // 3 hours.
+        private static final long WAKING_ACTIVITY_RETENTION_MS = TimeUnit.MINUTES.toMillis(10);
+
         private SparseArray<TimeSparseArray<SparseBooleanArray>> mWakingActivity =
                 new SparseArray<>();
 
@@ -425,6 +449,8 @@
         switch (rawSubsystem) {
             case SUBSYSTEM_ALARM_STRING:
                 return CPU_WAKEUP_SUBSYSTEM_ALARM;
+            case SUBSYSTEM_ALARM_WIFI:
+                return CPU_WAKEUP_SUBSYSTEM_WIFI;
         }
         return CPU_WAKEUP_SUBSYSTEM_UNKNOWN;
     }
@@ -433,6 +459,8 @@
         switch (subsystem) {
             case CPU_WAKEUP_SUBSYSTEM_ALARM:
                 return SUBSYSTEM_ALARM_STRING;
+            case CPU_WAKEUP_SUBSYSTEM_WIFI:
+                return SUBSYSTEM_ALARM_WIFI;
             case CPU_WAKEUP_SUBSYSTEM_UNKNOWN:
                 return "Unknown";
         }
@@ -443,28 +471,25 @@
         private static final String PARSER_TAG = "CpuWakeupStats.Wakeup";
         private static final String ABORT_REASON_PREFIX = "Abort";
         private static final Pattern sIrqPattern = Pattern.compile("^(\\d+)\\s+(\\S+)");
-
-        String mRawReason;
         long mElapsedMillis;
         long mUptimeMillis;
         IrqDevice[] mDevices;
 
-        Wakeup(String rawReason, long elapsedMillis, long uptimeMillis) {
-            mRawReason = rawReason;
+        private Wakeup(IrqDevice[] devices, long elapsedMillis, long uptimeMillis) {
             mElapsedMillis = elapsedMillis;
             mUptimeMillis = uptimeMillis;
-            mDevices = parseIrqDevices(rawReason);
+            mDevices = devices;
         }
 
-        private static IrqDevice[] parseIrqDevices(String rawReason) {
+        static Wakeup parseWakeup(String rawReason, long elapsedMillis, long uptimeMillis) {
             final String[] components = rawReason.split(":");
             if (ArrayUtils.isEmpty(components) || components[0].startsWith(ABORT_REASON_PREFIX)) {
-                // We don't support parsing aborts yet.
+                // Accounting of aborts is not supported yet.
                 return null;
             }
 
             int parsedDeviceCount = 0;
-            IrqDevice[] parsedDevices = new IrqDevice[components.length];
+            final IrqDevice[] parsedDevices = new IrqDevice[components.length];
 
             for (String component : components) {
                 final Matcher matcher = sIrqPattern.matcher(component.trim());
@@ -482,14 +507,17 @@
                     parsedDevices[parsedDeviceCount++] = new IrqDevice(line, device);
                 }
             }
-            return (parsedDeviceCount > 0) ? Arrays.copyOf(parsedDevices, parsedDeviceCount) : null;
+            if (parsedDeviceCount == 0) {
+                return null;
+            }
+            return new Wakeup(Arrays.copyOf(parsedDevices, parsedDeviceCount), elapsedMillis,
+                    uptimeMillis);
         }
 
         @Override
         public String toString() {
             return "Wakeup{"
-                    + "mRawReason='" + mRawReason + '\''
-                    + ", mElapsedMillis=" + mElapsedMillis
+                    + "mElapsedMillis=" + mElapsedMillis
                     + ", mUptimeMillis=" + TimeUtils.formatDuration(mUptimeMillis)
                     + ", mDevices=" + Arrays.toString(mDevices)
                     + '}';
@@ -506,8 +534,56 @@
 
             @Override
             public String toString() {
-                return "IrqDevice{" + "mLine=" + mLine + ", mDevice='" + mDevice + '\'' + '}';
+                return "IrqDevice{" + "mLine=" + mLine + ", mDevice=\'" + mDevice + '\'' + '}';
             }
         }
     }
+
+    static final class Config implements DeviceConfig.OnPropertiesChangedListener {
+        static final String KEY_WAKEUP_STATS_RETENTION_MS = "wakeup_stats_retention_ms";
+
+        private static final String[] PROPERTY_NAMES = {
+                KEY_WAKEUP_STATS_RETENTION_MS,
+        };
+
+        static final long DEFAULT_WAKEUP_STATS_RETENTION_MS = TimeUnit.DAYS.toMillis(3);
+
+        /**
+         * Wakeup stats are retained only for this duration.
+         */
+        public volatile long WAKEUP_STATS_RETENTION_MS = DEFAULT_WAKEUP_STATS_RETENTION_MS;
+
+        void register(Executor executor) {
+            DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_BATTERY_STATS,
+                    executor, this);
+            onPropertiesChanged(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_BATTERY_STATS,
+                    PROPERTY_NAMES));
+        }
+
+        @Override
+        public void onPropertiesChanged(DeviceConfig.Properties properties) {
+            for (String name : properties.getKeyset()) {
+                if (name == null) {
+                    continue;
+                }
+                switch (name) {
+                    case KEY_WAKEUP_STATS_RETENTION_MS:
+                        WAKEUP_STATS_RETENTION_MS = properties.getLong(
+                                KEY_WAKEUP_STATS_RETENTION_MS, DEFAULT_WAKEUP_STATS_RETENTION_MS);
+                        break;
+                }
+            }
+        }
+
+        void dump(IndentingPrintWriter pw) {
+            pw.println("Config:");
+
+            pw.increaseIndent();
+
+            pw.print(KEY_WAKEUP_STATS_RETENTION_MS, WAKEUP_STATS_RETENTION_MS);
+            pw.println();
+
+            pw.decreaseIndent();
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/sensors/SensorManagerInternal.java b/services/core/java/com/android/server/sensors/SensorManagerInternal.java
index 41c2fbf..6c32ec2 100644
--- a/services/core/java/com/android/server/sensors/SensorManagerInternal.java
+++ b/services/core/java/com/android/server/sensors/SensorManagerInternal.java
@@ -17,6 +17,8 @@
 package com.android.server.sensors;
 
 import android.annotation.NonNull;
+import android.hardware.SensorDirectChannel;
+import android.os.ParcelFileDescriptor;
 
 import java.util.concurrent.Executor;
 
@@ -58,7 +60,7 @@
      * @return The sensor handle.
      */
     public abstract int createRuntimeSensor(int deviceId, int type, @NonNull String name,
-            @NonNull String vendor, @NonNull RuntimeSensorCallback callback);
+            @NonNull String vendor, int flags, @NonNull RuntimeSensorCallback callback);
 
     /**
      * Unregisters the sensor with the given handle from the framework.
@@ -98,9 +100,31 @@
     public interface RuntimeSensorCallback {
         /**
          * Invoked when the listeners of the runtime sensor have changed.
-         * Returns an error code if the invocation was unsuccessful, zero otherwise.
+         * Returns zero on success, negative error code otherwise.
          */
         int onConfigurationChanged(int handle, boolean enabled, int samplingPeriodMicros,
                 int batchReportLatencyMicros);
+
+        /**
+         * Invoked when a direct sensor channel has been created.
+         * Wraps the file descriptor in a {@link android.os.SharedMemory} object and passes it to
+         * the client process.
+         * Returns a positive identifier of the channel on success, negative error code otherwise.
+         */
+        int onDirectChannelCreated(ParcelFileDescriptor fd);
+
+        /**
+         * Invoked when a direct sensor channel has been destroyed.
+         */
+        void onDirectChannelDestroyed(int channelHandle);
+
+        /**
+         * Invoked when a direct sensor channel has been configured for a sensor.
+         * If the invocation is unsuccessful, a negative error code is returned.
+         * On success, the return value is zero if the rate level is {@code RATE_STOP}, and a
+         * positive report token otherwise.
+         */
+        int onDirectChannelConfigured(int channelHandle, int sensorHandle,
+                @SensorDirectChannel.RateLevel int rateLevel);
     }
 }
diff --git a/services/core/java/com/android/server/sensors/SensorService.java b/services/core/java/com/android/server/sensors/SensorService.java
index 9790659..1baa0a6 100644
--- a/services/core/java/com/android/server/sensors/SensorService.java
+++ b/services/core/java/com/android/server/sensors/SensorService.java
@@ -56,7 +56,8 @@
     private static native void unregisterProximityActiveListenerNative(long ptr);
 
     private static native int registerRuntimeSensorNative(long ptr, int deviceId, int type,
-            String name, String vendor, SensorManagerInternal.RuntimeSensorCallback callback);
+            String name, String vendor, int flags,
+            SensorManagerInternal.RuntimeSensorCallback callback);
     private static native void unregisterRuntimeSensorNative(long ptr, int handle);
     private static native boolean sendRuntimeSensorEventNative(long ptr, int handle, int type,
             long timestampNanos, float[] values);
@@ -95,9 +96,9 @@
     class LocalService extends SensorManagerInternal {
         @Override
         public int createRuntimeSensor(int deviceId, int type, @NonNull String name,
-                @NonNull String vendor, @NonNull RuntimeSensorCallback callback) {
+                @NonNull String vendor, int flags, @NonNull RuntimeSensorCallback callback) {
             synchronized (mLock) {
-                int handle = registerRuntimeSensorNative(mPtr, deviceId, type, name, vendor,
+                int handle = registerRuntimeSensorNative(mPtr, deviceId, type, name, vendor, flags,
                         callback);
                 mRuntimeSensorHandles.add(handle);
                 return handle;
diff --git a/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java b/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java
index 8e8abf6..96f4a01 100644
--- a/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java
+++ b/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java
@@ -250,15 +250,7 @@
                 service.checkRecognitionSupport(recognizerIntent, attributionSource, callback));
     }
 
-    void triggerModelDownload(Intent recognizerIntent, AttributionSource attributionSource) {
-        if (!mConnected) {
-            Slog.e(TAG, "#downloadModel failed due to connection.");
-            return;
-        }
-        run(service -> service.triggerModelDownload(recognizerIntent, attributionSource));
-    }
-
-    void setModelDownloadListener(
+    void triggerModelDownload(
             Intent recognizerIntent,
             AttributionSource attributionSource,
             IModelDownloadListener listener) {
@@ -266,25 +258,12 @@
             try {
                 listener.onError(SpeechRecognizer.ERROR_SERVER_DISCONNECTED);
             } catch (RemoteException e) {
-                Slog.w(TAG, "Failed to report the connection broke to the caller.", e);
+                Slog.w(TAG, "#downloadModel failed due to connection.", e);
                 e.printStackTrace();
             }
             return;
         }
-
-        run(service ->
-                service.setModelDownloadListener(recognizerIntent, attributionSource, listener));
-    }
-
-    void clearModelDownloadListener(
-            Intent recognizerIntent,
-            AttributionSource attributionSource) {
-        if (!mConnected) {
-            return;
-        }
-
-        run(service ->
-                service.clearModelDownloadListener(recognizerIntent, attributionSource));
+        run(service -> service.triggerModelDownload(recognizerIntent, attributionSource, listener));
     }
 
     void shutdown(IBinder clientToken) {
diff --git a/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java b/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java
index bc73db1..bff6d50 100644
--- a/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java
@@ -193,25 +193,11 @@
                         @Override
                         public void triggerModelDownload(
                                 Intent recognizerIntent,
-                                AttributionSource attributionSource) {
-                            service.triggerModelDownload(recognizerIntent, attributionSource);
-                        }
-
-                        @Override
-                        public void setModelDownloadListener(
-                                Intent recognizerIntent,
                                 AttributionSource attributionSource,
-                                IModelDownloadListener listener) throws RemoteException {
-                            service.setModelDownloadListener(
+                                IModelDownloadListener listener) {
+                            service.triggerModelDownload(
                                     recognizerIntent, attributionSource, listener);
                         }
-
-                        @Override
-                        public void clearModelDownloadListener(
-                                Intent recognizerIntent,
-                                AttributionSource attributionSource) throws RemoteException {
-                            service.clearModelDownloadListener(recognizerIntent, attributionSource);
-                        }
                     });
                 } catch (RemoteException e) {
                     Slog.e(TAG, "Error creating a speech recognition session", e);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 5bace0e..88d64df 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -151,6 +151,13 @@
     @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S_V2)
     static final long REQUEST_LISTENING_MUST_MATCH_PACKAGE = 172251878L;
 
+    /**
+     * @hide
+     */
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+    static final long REQUEST_LISTENING_OTHER_USER_NOOP = 242194868L;
+
     private final Context mContext;
 
     private final Handler mHandler = new Handler();
@@ -1888,7 +1895,12 @@
 
             // Check current user
             if (userId != currentUser) {
-                throw new IllegalArgumentException("User " + userId + " is not the current user.");
+                if (CompatChanges.isChangeEnabled(REQUEST_LISTENING_OTHER_USER_NOOP, callingUid)) {
+                    return;
+                } else {
+                    throw new IllegalArgumentException(
+                            "User " + userId + " is not the current user.");
+                }
             }
         }
         if (mBar != null) {
diff --git a/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java b/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java
index de631bb..e7c073c 100644
--- a/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java
@@ -30,7 +30,6 @@
 import android.content.IntentFilter;
 import android.database.ContentObserver;
 import android.net.ConnectivityManager;
-import android.net.ConnectivityManager.NetworkCallback;
 import android.net.Network;
 import android.os.Binder;
 import android.os.Handler;
@@ -140,20 +139,12 @@
     /** Initialize the receivers and initiate the first NTP request */
     public void systemRunning() {
         // Listen for scheduled refreshes.
-        mContext.registerReceiver(
-                new BroadcastReceiver() {
-                    @Override
-                    public void onReceive(Context context, Intent intent) {
-                        onPollNetworkTime("scheduled refresh");
-                    }
-                },
-                new IntentFilter(ACTION_POLL),
-                /*broadcastPermission=*/ null,
-                mHandler);
+        ScheduledRefreshBroadcastReceiver receiver = new ScheduledRefreshBroadcastReceiver();
+        mContext.registerReceiver(receiver, new IntentFilter(ACTION_POLL));
 
         // Listen for network connectivity changes.
-        NetworkTimeUpdateCallback networkTimeUpdateCallback = new NetworkTimeUpdateCallback();
-        mCM.registerDefaultNetworkCallback(networkTimeUpdateCallback, mHandler);
+        NetworkConnectivityCallback networkConnectivityCallback = new NetworkConnectivityCallback();
+        mCM.registerDefaultNetworkCallback(networkConnectivityCallback, mHandler);
 
         // Listen for user settings changes.
         ContentResolver resolver = mContext.getContentResolver();
@@ -223,8 +214,25 @@
         }
     }
 
+    private class ScheduledRefreshBroadcastReceiver extends BroadcastReceiver implements Runnable {
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            // The BroadcastReceiver has to complete quickly or an ANR will be triggered by the
+            // platform regardless of the receiver thread used. Instead of blocking the receiver
+            // thread, the long-running / blocking work is posted to mHandler to allow onReceive()
+            // to return immediately.
+            mHandler.post(this);
+        }
+
+        @Override
+        public void run() {
+            onPollNetworkTime("scheduled refresh");
+        }
+    }
+
     // All callbacks will be invoked using mHandler because of how the callback is registered.
-    private class NetworkTimeUpdateCallback extends NetworkCallback {
+    private class NetworkConnectivityCallback extends ConnectivityManager.NetworkCallback {
         @Override
         public void onAvailable(@NonNull Network network) {
             Log.d(TAG, String.format("New default network %s; checking time.", network));
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 404ca01..5442b6d 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -2125,6 +2125,26 @@
         }
 
         @Override
+        public void notifyTvMessage(IBinder sessionToken, int type, Bundle data, int userId) {
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+                    userId, "timeShiftEnablePositionTracking");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        getSessionLocked(sessionToken, callingUid, resolvedUserId)
+                                .notifyTvMessage(type, data);
+                    } catch (RemoteException | SessionNotFoundException e) {
+                        Slog.e(TAG, "error in timeShiftEnablePositionTracking", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
         public void startRecording(IBinder sessionToken, @Nullable Uri programUri,
                 @Nullable Bundle params, int userId) {
             final int callingUid = Binder.getCallingUid();
@@ -2570,7 +2590,7 @@
         }
 
         @Override
-        public void notifyAdBuffer(
+        public void notifyAdBufferReady(
                 IBinder sessionToken, AdBuffer buffer, int userId) {
             final int callingUid = Binder.getCallingUid();
             final int callingPid = Binder.getCallingPid();
@@ -2582,7 +2602,7 @@
                     try {
                         SessionState sessionState = getSessionStateLocked(sessionToken, callingUid,
                                 resolvedUserId);
-                        getSessionLocked(sessionState).notifyAdBuffer(buffer);
+                        getSessionLocked(sessionState).notifyAdBufferReady(buffer);
                     } catch (RemoteException | SessionNotFoundException e) {
                         Slog.e(TAG, "error in notifyAdBuffer", e);
                     }
@@ -3745,7 +3765,7 @@
         }
 
         @Override
-        public void onTvMessage(String type, Bundle data) {
+        public void onTvMessage(int type, Bundle data) {
             synchronized (mLock) {
                 if (DEBUG) {
                     Slog.d(TAG, "onTvMessage(type=" + type + ", data=" + data + ")");
diff --git a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
index 61c137e..0d4a76e 100644
--- a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
+++ b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
@@ -1117,7 +1117,7 @@
         }
 
         @Override
-        public void notifyTvMessage(IBinder sessionToken, String type, Bundle data, int userId) {
+        public void notifyTvMessage(IBinder sessionToken, int type, Bundle data, int userId) {
             final int callingUid = Binder.getCallingUid();
             final int callingPid = Binder.getCallingPid();
             final int resolvedUserId = resolveCallingUserId(callingPid, callingUid, userId,
@@ -3047,16 +3047,16 @@
         }
 
         @Override
-        public void onAdBuffer(AdBuffer buffer) {
+        public void onAdBufferReady(AdBuffer buffer) {
             synchronized (mLock) {
                 if (DEBUG) {
-                    Slogf.d(TAG, "onAdBuffer(buffer=" + buffer + ")");
+                    Slogf.d(TAG, "onAdBufferReady(buffer=" + buffer + ")");
                 }
                 if (mSessionState.mSession == null || mSessionState.mClient == null) {
                     return;
                 }
                 try {
-                    mSessionState.mClient.onAdBuffer(buffer, mSessionState.mSeq);
+                    mSessionState.mClient.onAdBufferReady(buffer, mSessionState.mSeq);
                 } catch (RemoteException e) {
                     Slogf.e(TAG, "error in onAdBuffer", e);
                 }
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index ac03808..c9eef38 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -923,6 +923,8 @@
             if (DEBUG) Slog.v(TAG, "Adding window token: " + mToken);
             mWindowManagerInternal.addWindowToken(mToken, TYPE_WALLPAPER, mDisplayId,
                     null /* options */);
+            mWindowManagerInternal.setWallpaperShowWhenLocked(
+                    mToken, (wallpaper.mWhich & FLAG_LOCK) != 0);
             final DisplayData wpdData =
                     mWallpaperDisplayHelper.getDisplayDataOrCreate(mDisplayId);
             try {
@@ -945,7 +947,9 @@
             mWindowManagerInternal.removeWindowToken(mToken, false/* removeWindows */,
                     mDisplayId);
             try {
-                connection.mService.detach(mToken);
+                if (connection.mService != null) {
+                    connection.mService.detach(mToken);
+                }
             } catch (RemoteException e) {
                 Slog.w(TAG, "connection.mService.destroy() threw a RemoteException");
             }
@@ -1413,12 +1417,13 @@
                         try {
                             if (connector.mEngine != null) {
                                 connector.mEngine.setWallpaperFlags(which);
+                                mWindowManagerInternal.setWallpaperShowWhenLocked(
+                                        connector.mToken, (which & FLAG_LOCK) != 0);
                             }
                         } catch (RemoteException e) {
                             Slog.e(TAG, "Failed to update wallpaper engine flags", e);
                         }
-                    }
-            );
+                    });
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 9aa7e56..fa3a186 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -702,8 +702,8 @@
                         + AppTransition.appTransitionOldToString(transition)
                         + " displayId: " + displayId);
             }
-            final boolean magnifying = mMagnifedViewport.isMagnifying();
-            if (magnifying) {
+            final boolean isMagnifierActivated = isForceShowingMagnifiableBounds();
+            if (isMagnifierActivated) {
                 switch (transition) {
                     case WindowManager.TRANSIT_OLD_ACTIVITY_OPEN:
                     case WindowManager.TRANSIT_OLD_TASK_FRAGMENT_OPEN:
@@ -727,8 +727,8 @@
                 Slog.i(LOG_TAG, "Window transition: " + WindowManager.transitTypeToString(type)
                         + " displayId: " + displayId);
             }
-            final boolean magnifying = mMagnifedViewport.isMagnifying();
-            if (magnifying) {
+            final boolean isMagnifierActivated = isForceShowingMagnifiableBounds();
+            if (isMagnifierActivated) {
                 // All opening/closing situations.
                 switch (type) {
                     case WindowManager.TRANSIT_OPEN:
@@ -751,12 +751,12 @@
                         + AppTransition.appTransitionOldToString(transition)
                         + " displayId: " + windowState.getDisplayId());
             }
-            final boolean magnifying = mMagnifedViewport.isMagnifying();
+            final boolean isMagnifierActivated = isForceShowingMagnifiableBounds();
             final int type = windowState.mAttrs.type;
             switch (transition) {
                 case WindowManagerPolicy.TRANSIT_ENTER:
                 case WindowManagerPolicy.TRANSIT_SHOW: {
-                    if (!magnifying) {
+                    if (!isMagnifierActivated) {
                         break;
                     }
                     switch (type) {
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index 01e9522..f14a432 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -251,11 +251,6 @@
                     // {@link #restartActivityProcessIfVisible}.
                     restartingName = r.app.mName;
                     restartingUid = r.app.mUid;
-                    // Make EnsureActivitiesVisibleHelper#makeVisibleAndRestartIfNeeded not skip
-                    // restarting non-top activity.
-                    if (r != r.getTask().topRunningActivity()) {
-                        r.setVisibleRequested(false);
-                    }
                 }
                 r.activityStopped(icicle, persistentState, description);
             }
@@ -1714,4 +1709,20 @@
             }
         }
     }
+
+    /**
+     * Returns {@code true} if the activity was explicitly requested to be launched in its
+     * current TaskFragment.
+     *
+     * @see ActivityRecord#mRequestedLaunchingTaskFragmentToken
+     */
+    public boolean isRequestedToLaunchInTaskFragment(IBinder activityToken,
+            IBinder taskFragmentToken) {
+        synchronized (mGlobalLock) {
+            final ActivityRecord r = ActivityRecord.isInRootTaskLocked(activityToken);
+            if (r == null) return false;
+
+            return r.mRequestedLaunchingTaskFragmentToken == taskFragmentToken;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index e62d305..d249f8c 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -565,12 +565,16 @@
     volatile boolean inHistory;
     final ActivityTaskSupervisor mTaskSupervisor;
     final RootWindowContainer mRootWindowContainer;
+    // The token of the TaskFragment that this activity was requested to be launched into.
+    IBinder mRequestedLaunchingTaskFragmentToken;
 
     // Tracking splash screen status from previous activity
     boolean mSplashScreenStyleSolidColor = false;
 
     Drawable mEnterpriseThumbnailDrawable;
 
+    boolean mPauseSchedulePendingForPip = false;
+
     private void updateEnterpriseThumbnailDrawable(Context context) {
         DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
         mEnterpriseThumbnailDrawable = dpm.getResources().getDrawable(
@@ -1500,6 +1504,12 @@
             mLastReportedMultiWindowMode = inPictureInPictureMode;
             ensureActivityConfiguration(0 /* globalChanges */, PRESERVE_WINDOWS,
                     true /* ignoreVisibility */);
+            if (inPictureInPictureMode && findMainWindow() == null) {
+                // Prevent malicious app entering PiP without valid WindowState, which can in turn
+                // result a non-touchable PiP window since the InputConsumer for PiP requires it.
+                EventLog.writeEvent(0x534e4554, "265293293", -1, "");
+                removeImmediately();
+            }
         }
     }
 
@@ -1605,6 +1615,8 @@
 
         if (oldParent != null) {
             oldParent.cleanUpActivityReferences(this);
+            // Clear the state as this activity is removed from its old parent.
+            mRequestedLaunchingTaskFragmentToken = null;
         }
 
         if (newParent != null) {
@@ -1722,7 +1734,7 @@
                 : null;
     }
 
-    private void clearLastParentBeforePip() {
+    void clearLastParentBeforePip() {
         if (mLastParentBeforePip != null) {
             mLastParentBeforePip.mChildPipActivity = null;
             mLastParentBeforePip = null;
@@ -2086,7 +2098,7 @@
         mTaskSupervisor = supervisor;
 
         info.taskAffinity = computeTaskAffinity(info.taskAffinity, info.applicationInfo.uid,
-                launchMode);
+                info.launchMode, mActivityComponent);
         taskAffinity = info.taskAffinity;
         final String uid = Integer.toString(info.applicationInfo.uid);
         if (info.windowLayout != null && info.windowLayout.windowLayoutAffinity != null
@@ -2187,12 +2199,18 @@
      * @param affinity The affinity of the activity.
      * @param uid The user-ID that has been assigned to this application.
      * @param launchMode The activity launch mode
+     * @param componentName The activity component name. This is only useful when the given
+     *                      launchMode is {@link ActivityInfo#LAUNCH_SINGLE_INSTANCE}
      * @return The task affinity
      */
-    static String computeTaskAffinity(String affinity, int uid, int launchMode) {
+    static String computeTaskAffinity(String affinity, int uid, int launchMode,
+            ComponentName componentName) {
         final String uidStr = Integer.toString(uid);
         if (affinity != null && !affinity.startsWith(uidStr)) {
-            affinity = uidStr + (launchMode == LAUNCH_SINGLE_INSTANCE ? "-si:" : ":") + affinity;
+            affinity = uidStr + ":" + affinity;
+            if (launchMode == LAUNCH_SINGLE_INSTANCE && componentName != null) {
+                affinity += ":" + componentName.hashCode();
+            }
         }
         return affinity;
     }
@@ -4117,9 +4135,7 @@
         } else if (!mVisibleRequested && launchCount > 2
                 && lastLaunchTime > (SystemClock.uptimeMillis() - 60000)) {
             // We have launched this activity too many times since it was able to run, so give up
-            // and remove it. (Note if the activity is visible, we don't remove the record. We leave
-            // the dead window on the screen but the process will not be restarted unless user
-            // explicitly tap on it.)
+            // and remove it.
             remove = true;
         } else {
             // The process may be gone, but the activity lives on!
@@ -4141,11 +4157,6 @@
             if (DEBUG_APP) {
                 Slog.v(TAG_APP, "Keeping entry during removeHistory for activity " + this);
             }
-            // Set nowVisible to previous visible state. If the app was visible while it died, we
-            // leave the dead window on screen so it's basically visible. This is needed when user
-            // later tap on the dead window, we need to stop other apps when user transfers focus
-            // to the restarted activity.
-            nowVisible = mVisibleRequested;
         }
         // upgrade transition trigger to task if this is the last activity since it means we are
         // closing the task.
@@ -5224,8 +5235,7 @@
         mTaskSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
     }
 
-    @VisibleForTesting
-    void setVisibility(boolean visible, boolean deferHidingClient) {
+    private void setVisibility(boolean visible, boolean deferHidingClient) {
         final AppTransition appTransition = getDisplayContent().mAppTransition;
 
         // Don't set visibility to false if we were already not visible. This prevents WM from
@@ -5273,10 +5283,6 @@
         mLastDeferHidingClient = deferHidingClient;
 
         if (!visible) {
-            // If the app is dead while it was visible, we kept its dead window on screen.
-            // Now that the app is going invisible, we can remove it. It will be restarted
-            // if made visible again.
-            removeDeadWindows();
             // If this activity is about to finish/stopped and now becomes invisible, remove it
             // from the unknownApp list in case the activity does not want to draw anything, which
             // keep the user waiting for the next transition to start.
@@ -6625,9 +6631,6 @@
         // stop tracking
         mSplashScreenStyleSolidColor = true;
 
-        // We now have a good window to show, remove dead placeholders
-        removeDeadWindows();
-
         if (mStartingWindow != null) {
             ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Finish starting %s"
                     + ": first real window is shown, no animation", win.mToken);
@@ -7363,20 +7366,6 @@
         }
     }
 
-    void removeDeadWindows() {
-        for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
-            WindowState win = mChildren.get(winNdx);
-            if (win.mAppDied) {
-                ProtoLog.w(WM_DEBUG_ADD_REMOVE,
-                        "removeDeadWindows: %s", win);
-                // Set mDestroying, we don't want any animation or delayed removal here.
-                win.mDestroying = true;
-                // Also removes child windows.
-                win.removeIfPossible();
-            }
-        }
-    }
-
     void setWillReplaceWindows(boolean animate) {
         ProtoLog.d(WM_DEBUG_ADD_REMOVE,
                 "Marking app token %s with replacing windows.", this);
@@ -7813,25 +7802,35 @@
 
     /**
      * Returns the requested {@link Configuration.Orientation} for the current activity.
-     *
-     * <p>When The current orientation is set to {@link SCREEN_ORIENTATION_BEHIND} it returns the
-     * requested orientation for the activity below which is the first activity with an explicit
-     * (different from {@link SCREEN_ORIENTATION_UNSET}) orientation which is not {@link
-     * SCREEN_ORIENTATION_BEHIND}.
      */
     @Configuration.Orientation
     @Override
     int getRequestedConfigurationOrientation(boolean forDisplay) {
+        return getRequestedConfigurationOrientation(forDisplay, getOverrideOrientation());
+    }
+
+    /**
+     * Returns the requested {@link Configuration.Orientation} for the requested
+     * {@link ActivityInfo.ScreenOrientation}.
+     *
+     * <p>When the current screen orientation is set to {@link SCREEN_ORIENTATION_BEHIND} it returns
+     * the requested orientation for the activity below which is the first activity with an explicit
+     * (different from {@link SCREEN_ORIENTATION_UNSET}) orientation which is not {@link
+     * SCREEN_ORIENTATION_BEHIND}.
+     */
+    @Configuration.Orientation
+    int getRequestedConfigurationOrientation(boolean forDisplay,
+            @ActivityInfo.ScreenOrientation int requestedOrientation) {
         if (mLetterboxUiController.hasInheritedOrientation()) {
             final RootDisplayArea root = getRootDisplayArea();
             if (forDisplay && root != null && root.isOrientationDifferentFromDisplay()) {
-                return ActivityInfo.reverseOrientation(
+                return reverseConfigurationOrientation(
                         mLetterboxUiController.getInheritedOrientation());
             } else {
                 return mLetterboxUiController.getInheritedOrientation();
             }
         }
-        if (task != null && getOverrideOrientation() == SCREEN_ORIENTATION_BEHIND) {
+        if (task != null && requestedOrientation == SCREEN_ORIENTATION_BEHIND) {
             // We use Task here because we want to be consistent with what happens in
             // multi-window mode where other tasks orientations are ignored.
             final ActivityRecord belowCandidate = task.getActivity(
@@ -7842,7 +7841,23 @@
                 return belowCandidate.getRequestedConfigurationOrientation(forDisplay);
             }
         }
-        return super.getRequestedConfigurationOrientation(forDisplay);
+        return super.getRequestedConfigurationOrientation(forDisplay, requestedOrientation);
+    }
+
+    /**
+     * Returns the reversed configuration orientation.
+     * @hide
+     */
+    @Configuration.Orientation
+    public static int reverseConfigurationOrientation(@Configuration.Orientation int orientation) {
+        switch (orientation) {
+            case ORIENTATION_LANDSCAPE:
+                return ORIENTATION_PORTRAIT;
+            case ORIENTATION_PORTRAIT:
+                return ORIENTATION_LANDSCAPE;
+            default:
+                return orientation;
+        }
     }
 
     /**
@@ -7888,6 +7903,19 @@
         if (mLetterboxUiController.shouldIgnoreRequestedOrientation(requestedOrientation)) {
             return;
         }
+        // This is necessary in order to avoid going into size compat mode when the orientation
+        // change request comes from the app
+        if (mWmService.mLetterboxConfiguration
+                    .isSizeCompatModeDisabledAfterOrientationChangeFromApp()
+                && getRequestedConfigurationOrientation(false, requestedOrientation)
+                    != getRequestedConfigurationOrientation(false /*forDisplay */)) {
+            // Do not change the requested configuration now, because this will be done when setting
+            // the orientation below with the new mCompatDisplayInsets
+            clearSizeCompatModeAttributes();
+        }
+        ProtoLog.v(WM_DEBUG_ORIENTATION,
+                "Setting requested orientation %s for %s",
+                ActivityInfo.screenOrientationToString(requestedOrientation), this);
         setOrientation(requestedOrientation, this);
 
         // Push the new configuration to the requested app in case where it's not pushed, e.g. when
@@ -7933,7 +7961,7 @@
         }
 
         return getTask().getConfiguration().smallestScreenWidthDp
-                >= mAtmService.mLargeScreenSmallestScreenWidthDp;
+                >= WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP;
     }
 
     /**
@@ -8080,11 +8108,7 @@
                 return false;
             }
         }
-        // Activity should be resizable if the task is.
-        final boolean isResizeable = task != null
-                ? task.isResizeable() || isResizeable()
-                : isResizeable();
-        return !isResizeable && (info.isFixedOrientation() || hasFixedAspectRatio())
+        return !isResizeable() && (info.isFixedOrientation() || hasFixedAspectRatio())
                 // The configuration of non-standard type should be enforced by system.
                 // {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD} is set when this activity is
                 // added to a task, but this function is called when resolving the launch params, at
@@ -8119,9 +8143,7 @@
         // The smallest screen width is the short side of screen bounds. Because the bounds
         // and density won't be changed, smallestScreenWidthDp is also fixed.
         overrideConfig.smallestScreenWidthDp = fullConfig.smallestScreenWidthDp;
-        // TODO(b/264276741): Check whether the runtime orietnation request is fixed rather than
-        // the manifest orientation which may be obsolete.
-        if (info.isFixedOrientation()) {
+        if (ActivityInfo.isFixedOrientation(getOverrideOrientation())) {
             // lock rotation too. When in size-compat, onConfigurationChanged will watch for and
             // apply runtime rotation changes.
             overrideConfig.windowConfiguration.setRotation(
@@ -8134,19 +8156,28 @@
                         mDisplayContent, this, mLetterboxBoundsForFixedOrientationAndAspectRatio);
     }
 
-    @VisibleForTesting
-    void clearSizeCompatMode() {
-        final float lastSizeCompatScale = mSizeCompatScale;
+    private void clearSizeCompatModeAttributes() {
         mInSizeCompatModeForBounds = false;
         mSizeCompatScale = 1f;
         mSizeCompatBounds = null;
         mCompatDisplayInsets = null;
+    }
+
+    @VisibleForTesting
+    void clearSizeCompatMode() {
+        final float lastSizeCompatScale = mSizeCompatScale;
+        clearSizeCompatModeAttributes();
         if (mSizeCompatScale != lastSizeCompatScale) {
             forAllWindows(WindowState::updateGlobalScale, false /* traverseTopToBottom */);
         }
-
         // Clear config override in #updateCompatDisplayInsets().
-        onRequestedOverrideConfigurationChanged(EMPTY);
+        final int activityType = getActivityType();
+        final Configuration overrideConfig = getRequestedOverrideConfiguration();
+        overrideConfig.unset();
+        // Keep the activity type which was set when attaching to a task to prevent leaving it
+        // undefined.
+        overrideConfig.windowConfiguration.setActivityType(activityType);
+        onRequestedOverrideConfigurationChanged(overrideConfig);
     }
 
     @Override
@@ -8209,9 +8240,9 @@
         if (isFixedOrientationLetterboxAllowed) {
             resolveFixedOrientationConfiguration(newParentConfiguration);
         }
-
-        if (getCompatDisplayInsets() != null) {
-            resolveSizeCompatModeConfiguration(newParentConfiguration);
+        final CompatDisplayInsets compatDisplayInsets = getCompatDisplayInsets();
+        if (compatDisplayInsets != null) {
+            resolveSizeCompatModeConfiguration(newParentConfiguration, compatDisplayInsets);
         } else if (inMultiWindowMode() && !isFixedOrientationLetterboxAllowed) {
             // We ignore activities' requested orientation in multi-window modes. They may be
             // taken into consideration in resolveFixedOrientationConfiguration call above.
@@ -8228,7 +8259,7 @@
             resolveAspectRatioRestriction(newParentConfiguration);
         }
 
-        if (isFixedOrientationLetterboxAllowed || getCompatDisplayInsets() != null
+        if (isFixedOrientationLetterboxAllowed || compatDisplayInsets != null
                 // In fullscreen, can be letterboxed for aspect ratio.
                 || !inMultiWindowMode()) {
             updateResolvedBoundsPosition(newParentConfiguration);
@@ -8236,7 +8267,7 @@
 
         boolean isIgnoreOrientationRequest = mDisplayContent != null
                 && mDisplayContent.getIgnoreOrientationRequest();
-        if (getCompatDisplayInsets() == null
+        if (compatDisplayInsets == null
                 // for size compat mode set in updateCompatDisplayInsets
                 // Fixed orientation letterboxing is possible on both large screen devices
                 // with ignoreOrientationRequest enabled and on phones in split screen even with
@@ -8283,7 +8314,7 @@
                         info.neverSandboxDisplayApis(sConstrainDisplayApisConfig),
                         info.alwaysSandboxDisplayApis(sConstrainDisplayApisConfig),
                         !matchParentBounds(),
-                        getCompatDisplayInsets() != null,
+                        compatDisplayInsets != null,
                         shouldCreateCompatDisplayInsets());
             }
             resolvedConfig.windowConfiguration.setMaxBounds(mTmpBounds);
@@ -8295,7 +8326,7 @@
     /**
      * @return The orientation to use to understand if reachability is enabled.
      */
-    @ActivityInfo.ScreenOrientation
+    @Configuration.Orientation
     int getOrientationForReachability() {
         return mLetterboxUiController.hasInheritedLetterboxBehavior()
                 ? mLetterboxUiController.getInheritedOrientation()
@@ -8699,7 +8730,8 @@
      * Resolves consistent screen configuration for orientation and rotation changes without
      * inheriting the parent bounds.
      */
-    private void resolveSizeCompatModeConfiguration(Configuration newParentConfiguration) {
+    private void resolveSizeCompatModeConfiguration(Configuration newParentConfiguration,
+            @NonNull CompatDisplayInsets compatDisplayInsets) {
         final Configuration resolvedConfig = getResolvedOverrideConfiguration();
         final Rect resolvedBounds = resolvedConfig.windowConfiguration.getBounds();
 
@@ -8720,13 +8752,13 @@
                 ? requestedOrientation
                 // We should use the original orientation of the activity when possible to avoid
                 // forcing the activity in the opposite orientation.
-                : getCompatDisplayInsets().mOriginalRequestedOrientation != ORIENTATION_UNDEFINED
-                        ? getCompatDisplayInsets().mOriginalRequestedOrientation
+                : compatDisplayInsets.mOriginalRequestedOrientation != ORIENTATION_UNDEFINED
+                        ? compatDisplayInsets.mOriginalRequestedOrientation
                         : newParentConfiguration.orientation;
         int rotation = newParentConfiguration.windowConfiguration.getRotation();
         final boolean isFixedToUserRotation = mDisplayContent == null
                 || mDisplayContent.getDisplayRotation().isFixedToUserRotation();
-        if (!isFixedToUserRotation && !getCompatDisplayInsets().mIsFloating) {
+        if (!isFixedToUserRotation && !compatDisplayInsets.mIsFloating) {
             // Use parent rotation because the original display can be rotated.
             resolvedConfig.windowConfiguration.setRotation(rotation);
         } else {
@@ -8742,11 +8774,11 @@
         // rely on them to contain the original and unchanging width and height of the app.
         final Rect containingAppBounds = new Rect();
         final Rect containingBounds = mTmpBounds;
-        getCompatDisplayInsets().getContainerBounds(containingAppBounds, containingBounds, rotation,
+        compatDisplayInsets.getContainerBounds(containingAppBounds, containingBounds, rotation,
                 orientation, orientationRequested, isFixedToUserRotation);
         resolvedBounds.set(containingBounds);
         // The size of floating task is fixed (only swap), so the aspect ratio is already correct.
-        if (!getCompatDisplayInsets().mIsFloating) {
+        if (!compatDisplayInsets.mIsFloating) {
             mIsAspectRatioApplied =
                     applyAspectRatio(resolvedBounds, containingAppBounds, containingBounds);
         }
@@ -8755,7 +8787,7 @@
         // are calculated in compat container space. The actual position on screen will be applied
         // later, so the calculation is simpler that doesn't need to involve offset from parent.
         getTaskFragment().computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
-                getCompatDisplayInsets());
+                compatDisplayInsets);
         // Use current screen layout as source because the size of app is independent to parent.
         resolvedConfig.screenLayout = computeScreenLayout(
                 getConfiguration().screenLayout, resolvedConfig.screenWidthDp,
@@ -9014,6 +9046,7 @@
 
         final boolean wasInPictureInPicture = inPinnedWindowingMode();
         final DisplayContent display = mDisplayContent;
+        final int activityType = getActivityType();
         if (wasInPictureInPicture && attachedToProcess() && display != null) {
             // If the PIP activity is changing to fullscreen with display orientation change, the
             // fixed rotation will take effect that requires to send fixed rotation adjustments
@@ -9038,6 +9071,11 @@
         } else {
             super.onConfigurationChanged(newParentConfig);
         }
+        if (activityType != ACTIVITY_TYPE_UNDEFINED
+                && activityType != getActivityType()) {
+            Slog.w(TAG, "Can't change activity type once set: " + this
+                    + " activityType=" + activityTypeToString(getActivityType()));
+        }
 
         // Configuration's equality doesn't consider seq so if only seq number changes in resolved
         // override configuration. Therefore ConfigurationContainer doesn't change merged override
diff --git a/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java b/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java
index 8a4fc0db..19d8129 100644
--- a/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java
+++ b/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java
@@ -43,7 +43,7 @@
     static final String DOC_LINK = "go/android-asm";
 
     /** Used to determine which version of the ASM logic was used in logs while we iterate */
-    static final int ASM_VERSION = 5;
+    static final int ASM_VERSION = 7;
 
     private static final String NAMESPACE = NAMESPACE_WINDOW_MANAGER;
     private static final String KEY_ASM_PREFIX = "ActivitySecurity__";
@@ -89,6 +89,9 @@
 
         if (flagEnabled) {
             String[] packageNames = sPm.getPackagesForUid(uid);
+            if (packageNames == null) {
+                return true;
+            }
             for (int i = 0; i < packageNames.length; i++) {
                 if (sExcludedPackageNames.contains(packageNames[i])) {
                     return false;
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index e990460..211c230 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -172,6 +172,12 @@
     private static final int INVALID_LAUNCH_MODE = -1;
 
     /**
+     * Avoid problematical apps from occupying system resources (e.g. the amount of surface) by
+     * launching too many activities in a task.
+     */
+    private static final long MAX_TASK_WEIGHT_FOR_ADDING_ACTIVITY = 300;
+
+    /**
      * Feature flag to protect PendingIntent being abused to start background activity.
      */
     @ChangeId
@@ -400,6 +406,8 @@
         PendingIntentRecord originatingPendingIntent;
         BackgroundStartPrivileges backgroundStartPrivileges;
 
+        final StringBuilder logMessage = new StringBuilder();
+
         /**
          * The error callback token passed in {@link android.window.WindowContainerTransaction}
          * for TaskFragment operation error handling via
@@ -728,7 +736,14 @@
                 if (res != START_SUCCESS) {
                     return res;
                 }
-                res = executeRequest(mRequest);
+
+                try {
+                    res = executeRequest(mRequest);
+                } finally {
+                    mRequest.logMessage.append(" result code=").append(res);
+                    Slog.i(TAG, mRequest.logMessage.toString());
+                    mRequest.logMessage.setLength(0);
+                }
 
                 Binder.restoreCallingIdentity(origId);
 
@@ -927,8 +942,14 @@
                 ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
         final int launchMode = aInfo != null ? aInfo.launchMode : 0;
         if (err == ActivityManager.START_SUCCESS) {
-            Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
-                    + "} with " + launchModeToString(launchMode) + " from uid " + callingUid);
+            request.logMessage.append("START u").append(userId).append(" {")
+                    .append(intent.toShortString(true, true, true, false))
+                    .append("} with ").append(launchModeToString(launchMode))
+                    .append(" from uid ").append(callingUid);
+            if (callingUid != realCallingUid
+                    && realCallingUid != Request.DEFAULT_REAL_CALLING_UID) {
+                request.logMessage.append(" (realCallingUid=").append(realCallingUid).append(")");
+            }
         }
 
         ActivityRecord sourceRecord = null;
@@ -1097,6 +1118,11 @@
                                 request.backgroundStartPrivileges,
                                 intent,
                                 checkedOptions);
+                if (balCode != BAL_ALLOW_DEFAULT) {
+                    request.logMessage.append(" (").append(
+                                    BackgroundActivityStartController.balCodeToString(balCode))
+                            .append(")");
+                }
             } finally {
                 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
             }
@@ -1647,6 +1673,13 @@
         }
 
         if (targetTask != null) {
+            if (targetTask.getTreeWeight() > MAX_TASK_WEIGHT_FOR_ADDING_ACTIVITY) {
+                Slog.e(TAG, "Remove " + targetTask + " because it has contained too many"
+                        + " activities or windows (abort starting " + r
+                        + " from uid=" + mCallingUid);
+                targetTask.removeImmediately("bulky-task");
+                return START_ABORTED;
+            }
             mPriorAboveTask = TaskDisplayArea.getRootTaskAbove(targetTask.getRootTask());
         }
 
@@ -1948,9 +1981,13 @@
             boolean passesAsmChecks = true;
             Task sourceTask = mSourceRecord.getTask();
 
-            // Don't allow launches into a new task if the current task is not foreground.
+            // Allow launching into a new task (or a task matching the launched activity's
+            // affinity) only if the current task is foreground or mutating its own task.
+            // The latter can happen eg. if caller uses NEW_TASK flag and the activity being
+            // launched matches affinity of source task.
             if (taskToFront) {
-                passesAsmChecks = sourceTask != null && sourceTask.isVisible();
+                passesAsmChecks = sourceTask != null
+                        && (sourceTask.isVisible() || sourceTask == targetTask);
             }
 
             if (passesAsmChecks) {
@@ -2232,13 +2269,14 @@
      */
     private void clearTopIfNeeded(@NonNull Task targetTask, int callingUid, int realCallingUid,
             int startingUid, int launchFlags) {
-        if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) != FLAG_ACTIVITY_NEW_TASK) {
-            // Launch is from the same task, so must be a top or privileged UID
+        if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) != FLAG_ACTIVITY_NEW_TASK
+                || mBalCode == BAL_ALLOW_ALLOWLISTED_UID) {
+            // Launch is from the same task, (a top or privileged UID), or is directly privileged.
             return;
         }
 
-        Predicate<ActivityRecord> isLaunchingOrLaunched = ar -> !ar.finishing
-                && (ar.isUid(startingUid) || ar.isUid(callingUid) || ar.isUid(realCallingUid));
+        Predicate<ActivityRecord> isLaunchingOrLaunched = ar ->
+                ar.isUid(startingUid) || ar.isUid(callingUid) || ar.isUid(realCallingUid);
 
         // Return early if we know for sure we won't need to clear any activities by just checking
         // the top activity.
@@ -3032,6 +3070,8 @@
             int embeddingCheckResult = canEmbedActivity(mInTaskFragment, mStartActivity, task);
             if (embeddingCheckResult == EMBEDDING_ALLOWED) {
                 newParent = mInTaskFragment;
+                mStartActivity.mRequestedLaunchingTaskFragmentToken =
+                        mInTaskFragment.getFragmentToken();
             } else {
                 // Start mStartActivity to task instead if it can't be embedded to mInTaskFragment.
                 sendCanNotEmbedActivityError(mInTaskFragment, embeddingCheckResult);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index 2bd9052..bfb735d 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -473,9 +473,10 @@
     /** Writes current activity states to the proto stream. */
     public abstract void writeActivitiesToProto(ProtoOutputStream proto);
 
-    /** Dump the current state based on the command. */
+    /** Dump the current state based on the command and filters. */
     public abstract void dump(String cmd, FileDescriptor fd, PrintWriter pw, String[] args,
-            int opti, boolean dumpAll, boolean dumpClient, String dumpPackage);
+            int opti, boolean dumpAll, boolean dumpClient, String dumpPackage,
+            int displayIdFilter);
 
     /** Dump the current state for inclusion in process dump. */
     public abstract boolean dumpForProcesses(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
@@ -489,7 +490,7 @@
     /** Dump the current activities state. */
     public abstract boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name,
             String[] args, int opti, boolean dumpAll, boolean dumpVisibleRootTasksOnly,
-            boolean dumpFocusedRootTaskOnly, @UserIdInt int userId);
+            boolean dumpFocusedRootTaskOnly, int displayIdFilter, @UserIdInt int userId);
 
     /** Dump the current state for inclusion in oom dump. */
     public abstract void dumpForOom(PrintWriter pw);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 18be2a3..992743a 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -45,6 +45,7 @@
 import static android.content.pm.ConfigurationInfo.GL_ES_VERSION_UNDEFINED;
 import static android.content.pm.PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS;
 import static android.content.pm.PackageManager.FEATURE_CANT_SAVE_STATE;
+import static android.content.pm.PackageManager.FEATURE_COMPANION_DEVICE_SETUP;
 import static android.content.pm.PackageManager.FEATURE_EXPANDED_PICTURE_IN_PICTURE;
 import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
 import static android.content.pm.PackageManager.FEATURE_LEANBACK;
@@ -228,6 +229,7 @@
 import android.util.SparseArray;
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
+import android.view.Display;
 import android.view.IRecentsAnimationRunner;
 import android.view.RemoteAnimationAdapter;
 import android.view.RemoteAnimationDefinition;
@@ -401,6 +403,7 @@
     volatile WindowProcessController mHeavyWeightProcess;
     boolean mHasHeavyWeightFeature;
     boolean mHasLeanbackFeature;
+    boolean mHasCompanionDeviceSetupFeature;
     /** The process of the top most activity. */
     volatile WindowProcessController mTopApp;
     /**
@@ -607,7 +610,7 @@
      * Whether the device supports non-resizable in multi windowing modes.
      * -1: The device doesn't support non-resizable in multi windowing modes.
      *  0: The device supports non-resizable in multi windowing modes only if this is a large
-     *     screen (smallest width >= {@link #mLargeScreenSmallestScreenWidthDp}).
+     *     screen (smallest width >= {@link WindowManager#LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP}).
      *  1: The device always supports non-resizable in multi windowing modes.
      */
     int mSupportsNonResizableMultiWindow;
@@ -617,7 +620,8 @@
      * windowing modes.
      * -1: The device ignores activity min width/height when determining if it can be shown in multi
      *     windowing modes.
-     *  0: If it is a small screen (smallest width < {@link #mLargeScreenSmallestScreenWidthDp}),
+     *  0: If it is a small screen (smallest width <
+     *     {@link WindowManager#LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP}),
      *     the device compares the activity min width/height with the min multi windowing modes
      *     dimensions {@link #mMinPercentageMultiWindowSupportHeight} the device supports to
      *     determine whether the activity can be shown in multi windowing modes
@@ -645,13 +649,6 @@
      */
     float mMinPercentageMultiWindowSupportWidth;
 
-    /**
-     * If the display {@link Configuration#smallestScreenWidthDp} is greater or equal to this value,
-     * we will treat it as a large screen device, which will have some multi window features enabled
-     * by default.
-     */
-    int mLargeScreenSmallestScreenWidthDp;
-
     final List<ActivityTaskManagerInternal.ScreenObserver> mScreenObservers = new ArrayList<>();
 
     // VR Vr2d Display Id.
@@ -859,6 +856,7 @@
             final PackageManager pm = mContext.getPackageManager();
             mHasHeavyWeightFeature = pm.hasSystemFeature(FEATURE_CANT_SAVE_STATE);
             mHasLeanbackFeature = pm.hasSystemFeature(FEATURE_LEANBACK);
+            mHasCompanionDeviceSetupFeature = pm.hasSystemFeature(FEATURE_COMPANION_DEVICE_SETUP);
             mVrController.onSystemReady();
             mRecentTasks.onSystemReadyLocked();
             mTaskSupervisor.onSystemReady();
@@ -911,8 +909,6 @@
                 com.android.internal.R.dimen.config_minPercentageMultiWindowSupportHeight);
         final float minPercentageMultiWindowSupportWidth = mContext.getResources().getFloat(
                 com.android.internal.R.dimen.config_minPercentageMultiWindowSupportWidth);
-        final int largeScreenSmallestScreenWidthDp = mContext.getResources().getInteger(
-                com.android.internal.R.integer.config_largeScreenSmallestScreenWidthDp);
 
         // Transfer any global setting for forcing RTL layout, into a System Property
         DisplayProperties.debug_force_rtl(forceRtl);
@@ -931,7 +927,6 @@
             mRespectsActivityMinWidthHeightMultiWindow = respectsActivityMinWidthHeightMultiWindow;
             mMinPercentageMultiWindowSupportHeight = minPercentageMultiWindowSupportHeight;
             mMinPercentageMultiWindowSupportWidth = minPercentageMultiWindowSupportWidth;
-            mLargeScreenSmallestScreenWidthDp = largeScreenSmallestScreenWidthDp;
             final boolean multiWindowFormEnabled = freeformWindowManagement
                     || supportsSplitScreenMultiWindow
                     || supportsPictureInPicture
@@ -1501,7 +1496,7 @@
         a.persistableMode = ActivityInfo.PERSIST_NEVER;
         a.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
         a.colorMode = ActivityInfo.COLOR_MODE_DEFAULT;
-        a.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS | ActivityInfo.FLAG_NO_HISTORY;
+        a.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
         a.resizeMode = RESIZE_MODE_UNRESIZEABLE;
         a.configChanges = 0xffffffff;
 
@@ -3631,7 +3626,7 @@
                         null /* launchIntoPipHostActivity */, "enterPictureInPictureMode",
                         transition);
                 // Continue the pausing process after entering pip.
-                if (r.isState(PAUSING)) {
+                if (r.isState(PAUSING) && r.mPauseSchedulePendingForPip) {
                     r.getTask().schedulePauseActivity(r, false /* userLeaving */,
                             false /* pauseImmediately */, true /* autoEnteringPip */, "auto-pip");
                 }
@@ -4109,42 +4104,50 @@
         }
     }
 
-    void dumpVisibleActivitiesLocked(PrintWriter pw) {
+    void dumpVisibleActivitiesLocked(PrintWriter pw, int displayIdFilter) {
         pw.println("ACTIVITY MANAGER VISIBLE ACTIVITIES (dumpsys activity visible)");
         ArrayList<ActivityRecord> activities =
                 mRootWindowContainer.getDumpActivities("all", /* dumpVisibleRootTasksOnly */ true,
                         /* dumpFocusedRootTaskOnly */ false, UserHandle.USER_ALL);
         boolean needSeparator = false;
+        boolean printedAnything = false;
         for (int i = activities.size() - 1; i >= 0; i--) {
             ActivityRecord activity = activities.get(i);
-            if (!activity.isVisible()) {
+            if (!activity.isVisible() || (displayIdFilter != INVALID_DISPLAY
+                    && activity.getDisplayId() != displayIdFilter)) {
                 continue;
             }
             if (needSeparator) {
                 pw.println();
             }
+            printedAnything = true;
             activity.dump(pw, "", true);
             needSeparator = true;
         }
+        if (!printedAnything) {
+            pw.println("(nothing)");
+        }
     }
 
     void dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
-            int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
-        dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage,
+            int opti, boolean dumpAll, boolean dumpClient, String dumpPackage,
+            int displayIdFilter) {
+        dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage, displayIdFilter,
                 "ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)");
     }
 
     void dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
-            int opti, boolean dumpAll, boolean dumpClient, String dumpPackage, String header) {
+            int opti, boolean dumpAll, boolean dumpClient, String dumpPackage, int displayIdFilter,
+            String header) {
         pw.println(header);
 
         boolean printedAnything = mRootWindowContainer.dumpActivities(fd, pw, dumpAll, dumpClient,
-                dumpPackage);
+                dumpPackage, displayIdFilter);
         boolean needSep = printedAnything;
 
         boolean printed = ActivityTaskSupervisor.printThisActivity(pw,
-                mRootWindowContainer.getTopResumedActivity(), dumpPackage, needSep,
-                "  ResumedActivity: ", null);
+                mRootWindowContainer.getTopResumedActivity(), dumpPackage, displayIdFilter, needSep,
+                "  ResumedActivity: ", /* header= */ null);
         if (printed) {
             printedAnything = true;
             needSep = false;
@@ -4202,7 +4205,7 @@
      */
     protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
             int opti, boolean dumpAll, boolean dumpVisibleRootTasksOnly,
-            boolean dumpFocusedRootTaskOnly, @UserIdInt int userId) {
+            boolean dumpFocusedRootTaskOnly, int displayIdFilter, @UserIdInt int userId) {
         ArrayList<ActivityRecord> activities;
 
         synchronized (mGlobalLock) {
@@ -4219,6 +4222,7 @@
 
         Task lastTask = null;
         boolean needSep = false;
+        boolean printedAnything = false;
         for (int i = activities.size() - 1; i >= 0; i--) {
             ActivityRecord r = activities.get(i);
             if (needSep) {
@@ -4226,15 +4230,21 @@
             }
             needSep = true;
             synchronized (mGlobalLock) {
-                final Task task = r.getTask();
+                Task task = r.getTask();
+                int displayId = task.getDisplayId();
+                if (displayIdFilter != INVALID_DISPLAY && displayId != displayIdFilter) {
+                    continue;
+                }
                 if (lastTask != task) {
+                    printedAnything = true;
                     lastTask = task;
                     pw.print("TASK ");
                     pw.print(lastTask.affinity);
                     pw.print(" id=");
                     pw.print(lastTask.mTaskId);
                     pw.print(" userId=");
-                    pw.println(lastTask.mUserId);
+                    pw.print(lastTask.mUserId);
+                    printDisplayInfoAndNewLine(pw, r);
                     if (dumpAll) {
                         lastTask.dump(pw, "  ");
                     }
@@ -4242,6 +4252,10 @@
             }
             dumpActivity("  ", fd, pw, activities.get(i), newArgs, dumpAll);
         }
+        if (!printedAnything) {
+            // Typically happpens when no task matches displayIdFilter
+            pw.println("(nothing)");
+        }
         return true;
     }
 
@@ -4250,7 +4264,7 @@
      * there is a thread associated with the activity.
      */
     private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
-            final ActivityRecord r, String[] args, boolean dumpAll) {
+            ActivityRecord r, String[] args, boolean dumpAll) {
         String innerPrefix = prefix + "  ";
         IApplicationThread appThread = null;
         synchronized (mGlobalLock) {
@@ -4261,13 +4275,18 @@
             pw.print(Integer.toHexString(System.identityHashCode(r)));
             pw.print(" pid=");
             if (r.hasProcess()) {
-                pw.println(r.app.getPid());
+                pw.print(r.app.getPid());
                 appThread = r.app.getThread();
             } else {
-                pw.println("(not running)");
+                pw.print("(not running)");
             }
+            pw.print(" userId=");
+            pw.print(r.mUserId);
+            pw.print(" uid=");
+            pw.print(r.getUid());
+            printDisplayInfoAndNewLine(pw, r);
             if (dumpAll) {
-                r.dump(pw, innerPrefix, true /* dumpAll */);
+                r.dump(pw, innerPrefix, /* dumpAll= */ true);
             }
         }
         if (appThread != null) {
@@ -4285,6 +4304,20 @@
         }
     }
 
+    private void printDisplayInfoAndNewLine(PrintWriter pw, ActivityRecord r) {
+        pw.print(" displayId=");
+        DisplayContent displayContent = r.getDisplayContent();
+        if (displayContent == null) {
+            pw.println("N/A");
+            return;
+        }
+        Display display = displayContent.getDisplay();
+        pw.print(display.getDisplayId());
+        pw.print("(type=");
+        pw.print(Display.typeToString(display.getType()));
+        pw.println(")");
+    }
+
     private void writeSleepStateToProto(ProtoOutputStream proto, int wakeFullness,
             boolean testPssMode) {
         final long sleepToken = proto.start(ActivityManagerServiceDumpProcessesProto.SLEEP_STATUS);
@@ -5314,7 +5347,7 @@
                 + "------------");
         dumpActivitiesLocked(null /* fd */, pw, null /* args */, 0 /* opti */,
                 true /* dumpAll */, false /* dumpClient */, null /* dumpPackage */,
-                "" /* header */);
+                INVALID_DISPLAY, "" /* header */);
         pw.println();
         pw.close();
 
@@ -6365,10 +6398,11 @@
 
         @Override
         public void dump(String cmd, FileDescriptor fd, PrintWriter pw, String[] args, int opti,
-                boolean dumpAll, boolean dumpClient, String dumpPackage) {
+                boolean dumpAll, boolean dumpClient, String dumpPackage, int displayIdFilter) {
             synchronized (mGlobalLock) {
                 if (DUMP_ACTIVITIES_CMD.equals(cmd) || DUMP_ACTIVITIES_SHORT_CMD.equals(cmd)) {
-                    dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
+                    dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage,
+                            displayIdFilter);
                 } else if (DUMP_LASTANR_CMD.equals(cmd)) {
                     dumpLastANRLocked(pw);
                 } else if (DUMP_LASTANR_TRACES_CMD.equals(cmd)) {
@@ -6384,7 +6418,7 @@
                 } else if (DUMP_TOP_RESUMED_ACTIVITY.equals(cmd)) {
                     dumpTopResumedActivityLocked(pw);
                 } else if (DUMP_VISIBLE_ACTIVITIES.equals(cmd)) {
-                    dumpVisibleActivitiesLocked(pw);
+                    dumpVisibleActivitiesLocked(pw, displayIdFilter);
                 }
             }
         }
@@ -6579,9 +6613,10 @@
         @Override
         public boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name,
                 String[] args, int opti, boolean dumpAll, boolean dumpVisibleRootTasksOnly,
-                boolean dumpFocusedRootTaskOnly, @UserIdInt int userId) {
+                boolean dumpFocusedRootTaskOnly, int displayIdFilter,
+                @UserIdInt int userId) {
             return ActivityTaskManagerService.this.dumpActivity(fd, pw, name, args, opti, dumpAll,
-                    dumpVisibleRootTasksOnly, dumpFocusedRootTaskOnly, userId);
+                    dumpVisibleRootTasksOnly, dumpFocusedRootTaskOnly, displayIdFilter, userId);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index e463358..eaf5583 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -1239,8 +1239,13 @@
             return Context.DEVICE_ID_DEFAULT;
         }
         if (mVirtualDeviceManager == null) {
-            mVirtualDeviceManager =
-                    mService.mContext.getSystemService(VirtualDeviceManager.class);
+            if (mService.mHasCompanionDeviceSetupFeature) {
+                mVirtualDeviceManager =
+                        mService.mContext.getSystemService(VirtualDeviceManager.class);
+            }
+            if (mVirtualDeviceManager == null) {
+                return Context.DEVICE_ID_DEFAULT;
+            }
         }
         return mVirtualDeviceManager.getDeviceIdForDisplayId(displayId);
     }
@@ -1661,7 +1666,7 @@
             String callerActivityClassName) {
         // We may have already checked that the callingUid has additional clearTask privileges, and
         // cleared the calling identify. If so, we infer we do not need further restrictions here.
-        if (callingUid == SYSTEM_UID) {
+        if (callingUid == SYSTEM_UID || !task.isVisible() || task.inMultiWindowMode()) {
             return;
         }
 
@@ -1724,14 +1729,11 @@
         }
 
         if (ActivitySecurityModelFeatureFlags.shouldShowToast(callingUid)) {
-            Toast toast = Toast.makeText(mService.mContext,
+            UiThread.getHandler().post(() -> Toast.makeText(mService.mContext,
                     (ActivitySecurityModelFeatureFlags.DOC_LINK
-                            + (restrictActivitySwitch
-                            ? "returned home due to "
-                            : "would return home due to ")
-                            + callingLabel),
-                    Toast.LENGTH_LONG);
-            UiThread.getHandler().post(toast::show);
+                            + (restrictActivitySwitch ? " returned home due to "
+                                    : " would return home due to ")
+                            + callingLabel), Toast.LENGTH_LONG).show());
         }
 
         // If the activity switch should be restricted, return home rather than the
@@ -1770,13 +1772,19 @@
             return new Pair<>(true, true);
         }
 
+        // Always allow actual top activity to clear task
+        ActivityRecord topActivity = task.getTopMostActivity();
+        if (topActivity != null && topActivity.isUid(uid)) {
+            return new Pair<>(true, true);
+        }
+
         // Consider the source activity, whether or not it is finishing. Do not consider any other
         // finishing activity.
         Predicate<ActivityRecord> topOfStackPredicate = (ar) -> ar.equals(sourceRecord)
                 || (!ar.finishing && !ar.isAlwaysOnTop());
 
         // Check top of stack (or the first task fragment for embedding).
-        ActivityRecord topActivity = task.getActivity(topOfStackPredicate);
+        topActivity = task.getActivity(topOfStackPredicate);
         if (topActivity == null) {
             return new Pair<>(false, false);
         }
@@ -2216,7 +2224,14 @@
 
     static boolean printThisActivity(PrintWriter pw, ActivityRecord activity, String dumpPackage,
             boolean needSep, String prefix, Runnable header) {
-        if (activity != null) {
+        return printThisActivity(pw, activity, dumpPackage, INVALID_DISPLAY, needSep, prefix,
+                header);
+    }
+
+    static boolean printThisActivity(PrintWriter pw, ActivityRecord activity, String dumpPackage,
+            int displayIdFilter, boolean needSep, String prefix, Runnable header) {
+        if (activity != null && (displayIdFilter == INVALID_DISPLAY
+                || displayIdFilter == activity.getDisplayId())) {
             if (dumpPackage == null || dumpPackage.equals(activity.packageName)) {
                 if (needSep) {
                     pw.println();
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index f73c68a..939cf1a 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -888,8 +888,11 @@
         } else {
             int animAttr = mapOpenCloseTransitTypes(transit, enter);
             if (animAttr != 0) {
-                a = loadCustomActivityAnimation(animAttr, enter, container);
-                if (a == null) {
+                final CustomAppTransition customAppTransition =
+                        getCustomAppTransition(animAttr, container);
+                if (customAppTransition != null) {
+                    a = loadCustomActivityAnimation(customAppTransition, enter, container);
+                } else {
                     if (canCustomizeAppTransition) {
                         a = loadAnimationAttr(lp, animAttr, transit);
                     } else {
@@ -911,7 +914,7 @@
         return a;
     }
 
-    Animation loadCustomActivityAnimation(int animAttr, boolean enter, WindowContainer container) {
+    CustomAppTransition getCustomAppTransition(int animAttr, WindowContainer container) {
         ActivityRecord customAnimationSource = container.asActivityRecord();
         if (customAnimationSource == null) {
             return null;
@@ -927,31 +930,28 @@
                 return null;
             }
         }
-        final CustomAppTransition custom;
         switch (animAttr) {
             case WindowAnimation_activityOpenEnterAnimation:
             case WindowAnimation_activityOpenExitAnimation:
-                custom = customAnimationSource.getCustomAnimation(true /* open */);
-                break;
+                return customAnimationSource.getCustomAnimation(true /* open */);
             case WindowAnimation_activityCloseEnterAnimation:
             case WindowAnimation_activityCloseExitAnimation:
-                custom = customAnimationSource.getCustomAnimation(false /* open */);
-                break;
-            default:
-                return null;
-        }
-        if (custom != null) {
-            final Animation a = mTransitionAnimation.loadAppTransitionAnimation(
-                    customAnimationSource.packageName, enter
-                            ? custom.mEnterAnim : custom.mExitAnim);
-            if (a != null && custom.mBackgroundColor != 0) {
-                a.setBackdropColor(custom.mBackgroundColor);
-                a.setShowBackdrop(true);
-            }
-            return a;
+                return customAnimationSource.getCustomAnimation(false /* open */);
         }
         return null;
     }
+    private Animation loadCustomActivityAnimation(@NonNull CustomAppTransition custom,
+            boolean enter, WindowContainer container) {
+        final ActivityRecord customAnimationSource = container.asActivityRecord();
+        final Animation a = mTransitionAnimation.loadAppTransitionAnimation(
+                customAnimationSource.packageName, enter
+                        ? custom.mEnterAnim : custom.mExitAnim);
+        if (a != null && custom.mBackgroundColor != 0) {
+            a.setBackdropColor(custom.mBackgroundColor);
+            a.setShowBackdrop(true);
+        }
+        return a;
+    }
 
     int getAppRootTaskClipMode() {
         return mNextAppTransitionRequests.contains(TRANSIT_RELAUNCH)
diff --git a/services/core/java/com/android/server/wm/AsyncRotationController.java b/services/core/java/com/android/server/wm/AsyncRotationController.java
index 0dc6e0f..7a11120 100644
--- a/services/core/java/com/android/server/wm/AsyncRotationController.java
+++ b/services/core/java/com/android/server/wm/AsyncRotationController.java
@@ -93,6 +93,9 @@
     /** Whether the start transaction of the transition is committed (by shell). */
     private boolean mIsStartTransactionCommitted;
 
+    /** Whether all windows should wait for the start transaction. */
+    private boolean mAlwaysWaitForStartTransaction;
+
     /** Whether the target windows have been requested to sync their draw transactions. */
     private boolean mIsSyncDrawRequested;
 
@@ -144,6 +147,15 @@
         if (mTransitionOp == OP_LEGACY) {
             mIsStartTransactionCommitted = true;
         } else if (displayContent.mTransitionController.isCollecting(displayContent)) {
+            final Transition transition =
+                    mDisplayContent.mTransitionController.getCollectingTransition();
+            if (transition != null) {
+                final BLASTSyncEngine.SyncGroup syncGroup =
+                        mDisplayContent.mWmService.mSyncEngine.getSyncSet(transition.getSyncId());
+                if (syncGroup != null && syncGroup.mSyncMethod == BLASTSyncEngine.METHOD_BLAST) {
+                    mAlwaysWaitForStartTransaction = true;
+                }
+            }
             keepAppearanceInPreviousRotation();
         }
     }
@@ -202,7 +214,7 @@
         // target windows. But the windows still need to use sync transaction to keep the appearance
         // in previous rotation, so request a no-op sync to keep the state.
         for (int i = mTargetWindowTokens.size() - 1; i >= 0; i--) {
-            if (mTargetWindowTokens.valueAt(i).canDrawBeforeStartTransaction()) {
+            if (canDrawBeforeStartTransaction(mTargetWindowTokens.valueAt(i))) {
                 // Expect a screenshot layer will cover the non seamless windows.
                 continue;
             }
@@ -364,6 +376,7 @@
 
     /** Hides the window immediately until it is drawn in new rotation. */
     void hideImmediately(WindowToken windowToken) {
+        if (isTargetToken(windowToken)) return;
         final boolean original = mHideImmediately;
         mHideImmediately = true;
         final Operation op = new Operation(Operation.ACTION_FADE);
@@ -520,7 +533,7 @@
         if (op == null) return false;
         if (DEBUG) Slog.d(TAG, "handleFinishDrawing " + w);
         if (postDrawTransaction == null || !mIsSyncDrawRequested
-                || op.canDrawBeforeStartTransaction()) {
+                || canDrawBeforeStartTransaction(op)) {
             mDisplayContent.finishAsyncRotation(w.mToken);
             return false;
         }
@@ -562,6 +575,14 @@
         return super.getFadeOutAnimation();
     }
 
+    /**
+     * Returns {@code true} if the corresponding window can draw its latest content before the
+     * start transaction of rotation transition is applied.
+     */
+    private boolean canDrawBeforeStartTransaction(Operation op) {
+        return !mAlwaysWaitForStartTransaction && op.mAction != Operation.ACTION_SEAMLESS;
+    }
+
     /** The operation to control the rotation appearance associated with window token. */
     private static class Operation {
         @Retention(RetentionPolicy.SOURCE)
@@ -587,14 +608,5 @@
         Operation(@Action int action) {
             mAction = action;
         }
-
-        /**
-         * Returns {@code true} if the corresponding window can draw its latest content before the
-         * start transaction of rotation transition is applied.
-         */
-        boolean canDrawBeforeStartTransaction() {
-            return TransitionController.SYNC_METHOD != BLASTSyncEngine.METHOD_BLAST
-                    && mAction != ACTION_SEAMLESS;
-        }
     }
 }
diff --git a/services/core/java/com/android/server/wm/BLASTSyncEngine.java b/services/core/java/com/android/server/wm/BLASTSyncEngine.java
index cd26e2e..48cf567 100644
--- a/services/core/java/com/android/server/wm/BLASTSyncEngine.java
+++ b/services/core/java/com/android/server/wm/BLASTSyncEngine.java
@@ -95,7 +95,7 @@
      */
     class SyncGroup {
         final int mSyncId;
-        final int mSyncMethod;
+        int mSyncMethod = METHOD_BLAST;
         final TransactionReadyListener mListener;
         final Runnable mOnTimeout;
         boolean mReady = false;
@@ -103,9 +103,8 @@
         private SurfaceControl.Transaction mOrphanTransaction = null;
         private String mTraceName;
 
-        private SyncGroup(TransactionReadyListener listener, int id, String name, int method) {
+        private SyncGroup(TransactionReadyListener listener, int id, String name) {
             mSyncId = id;
-            mSyncMethod = method;
             mListener = listener;
             mOnTimeout = () -> {
                 Slog.w(TAG, "Sync group " + mSyncId + " timeout");
@@ -288,13 +287,12 @@
      * Prepares a {@link SyncGroup} that is not active yet. Caller must call {@link #startSyncSet}
      * before calling {@link #addToSyncSet(int, WindowContainer)} on any {@link WindowContainer}.
      */
-    SyncGroup prepareSyncSet(TransactionReadyListener listener, String name, int method) {
-        return new SyncGroup(listener, mNextSyncId++, name, method);
+    SyncGroup prepareSyncSet(TransactionReadyListener listener, String name) {
+        return new SyncGroup(listener, mNextSyncId++, name);
     }
 
-    int startSyncSet(TransactionReadyListener listener, long timeoutMs, String name,
-            int method) {
-        final SyncGroup s = prepareSyncSet(listener, name, method);
+    int startSyncSet(TransactionReadyListener listener, long timeoutMs, String name) {
+        final SyncGroup s = prepareSyncSet(listener, name);
         startSyncSet(s, timeoutMs);
         return s.mSyncId;
     }
@@ -334,6 +332,15 @@
         getSyncGroup(id).addToSync(wc);
     }
 
+    void setSyncMethod(int id, int method) {
+        final SyncGroup syncGroup = getSyncGroup(id);
+        if (!syncGroup.mRootMembers.isEmpty()) {
+            throw new IllegalStateException(
+                    "Not allow to change sync method after adding group member, id=" + id);
+        }
+        syncGroup.mSyncMethod = method;
+    }
+
     void setReady(int id, boolean ready) {
         getSyncGroup(id).setReady(ready);
     }
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index a229fc5..f9f972c 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -21,6 +21,7 @@
 import static android.view.RemoteAnimationTarget.MODE_OPENING;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_NONE;
 import static android.view.WindowManager.TRANSIT_TO_BACK;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BACK_PREVIEW;
@@ -31,6 +32,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.res.ResourceId;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.Bundle;
@@ -51,12 +53,14 @@
 import android.window.TaskSnapshot;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.policy.TransitionAnimation;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.server.LocalServices;
 import com.android.server.wm.utils.InsetUtils;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Objects;
 import java.util.function.Consumer;
 
 /**
@@ -75,6 +79,13 @@
     private final ArrayList<WindowContainer> mTmpOpenApps = new ArrayList<>();
     private final ArrayList<WindowContainer> mTmpCloseApps = new ArrayList<>();
 
+    // This will be set if the back navigation is in progress and the current transition is still
+    // running. The pending animation builder will do the animation stuff includes creating leashes,
+    // re-parenting leashes and set launch behind, etc. Will be handled when transition finished.
+    private AnimationHandler.ScheduleAnimationBuilder mPendingAnimationBuilder;
+
+    private static int sDefaultAnimationResId;
+
     /**
      * true if the back predictability feature is enabled
      */
@@ -250,9 +261,19 @@
             } else if (prevActivity != null) {
                 if (!isOccluded || prevActivity.canShowWhenLocked()) {
                     // We have another Activity in the same currentTask to go to
-                    backType = BackNavigationInfo.TYPE_CROSS_ACTIVITY;
+                    final WindowContainer parent = currentActivity.getParent();
+                    final boolean isCustomize = parent != null
+                            && (parent.asTask() != null
+                            || (parent.asTaskFragment() != null
+                            && parent.canCustomizeAppTransition()))
+                            && isCustomizeExitAnimation(window);
+                    if (isCustomize) {
+                        infoBuilder.setWindowAnimations(
+                                window.mAttrs.packageName, window.mAttrs.windowAnimations);
+                    }
                     removedWindowContainer = currentActivity;
                     prevTask = prevActivity.getTask();
+                    backType = BackNavigationInfo.TYPE_CROSS_ACTIVITY;
                 } else {
                     backType = BackNavigationInfo.TYPE_CALLBACK;
                 }
@@ -305,25 +326,26 @@
                             || backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY)
                     && adapter != null;
 
-            // Only prepare animation if no leash has been created (no animation is running).
-            // TODO(b/241808055): Cancel animation when preparing back animation.
-            if (prepareAnimation
-                    && (removedWindowContainer.hasCommittedReparentToAnimationLeash()
-                            || removedWindowContainer.mTransitionController.inTransition())) {
-                Slog.w(TAG, "Can't prepare back animation due to another animation is running.");
-                prepareAnimation = false;
-            }
-
             if (prepareAnimation) {
-                mPendingAnimation = mAnimationHandler.scheduleAnimation(backType, adapter,
-                        currentTask, prevTask, currentActivity, prevActivity);
-                prepareAnimation = mPendingAnimation != null;
-                mBackAnimationInProgress = prepareAnimation;
-                if (prepareAnimation) {
-                    mWindowManagerService.mWindowPlacerLocked.requestTraversal();
-                    if (mShowWallpaper) {
-                        currentTask.getDisplayContent().mWallpaperController
-                                .adjustWallpaperWindows();
+                final AnimationHandler.ScheduleAnimationBuilder builder =
+                        mAnimationHandler.prepareAnimation(backType, adapter,
+                                currentTask, prevTask, currentActivity, prevActivity);
+                mBackAnimationInProgress = builder != null;
+                if (mBackAnimationInProgress) {
+                    if (removedWindowContainer.hasCommittedReparentToAnimationLeash()
+                            || removedWindowContainer.mTransitionController.inTransition()
+                            || mWindowManagerService.mSyncEngine.hasPendingSyncSets()) {
+                        ProtoLog.w(WM_DEBUG_BACK_PREVIEW,
+                                "Pending back animation due to another animation is running");
+                        mPendingAnimationBuilder = builder;
+                        // Current transition is still running, we have to defer the hiding to the
+                        // client process to prevent the unexpected relayout when handling the back
+                        // animation.
+                        if (prevActivity != null) {
+                            prevActivity.setDeferHidingClient(true);
+                        }
+                    } else {
+                        scheduleAnimation(builder);
                     }
                 }
             }
@@ -345,6 +367,15 @@
         return isWaitBackTransition() || mNavigationMonitor.isMonitoring();
     }
 
+    private void scheduleAnimation(@NonNull AnimationHandler.ScheduleAnimationBuilder builder) {
+        mPendingAnimation = builder.build();
+        mWindowManagerService.mWindowPlacerLocked.requestTraversal();
+        if (mShowWallpaper) {
+            mWindowManagerService.getDefaultDisplayContentLocked().mWallpaperController
+                    .adjustWallpaperWindows();
+        }
+    }
+
     private boolean isWaitBackTransition() {
         return mAnimationHandler.mComposed && mAnimationHandler.mWaitTransition;
     }
@@ -355,6 +386,37 @@
         return kc.isKeyguardLocked(displayId) && kc.isDisplayOccluded(displayId);
     }
 
+    /**
+     * There are two ways to customize activity exit animation, one is to provide the
+     * windowAnimationStyle by Activity#setTheme, another one is to set resId by
+     * Window#setWindowAnimations.
+     * Not all run-time customization methods can be checked from here, such as
+     * overridePendingTransition, which the animation resource will be set just before the
+     * transition is about to happen.
+     */
+    private static boolean isCustomizeExitAnimation(WindowState window) {
+        // The default animation ResId is loaded from system package, so the result must match.
+        if (Objects.equals(window.mAttrs.packageName, "android")) {
+            return false;
+        }
+        if (window.mAttrs.windowAnimations != 0) {
+            final TransitionAnimation transitionAnimation = window.getDisplayContent()
+                    .mAppTransition.mTransitionAnimation;
+            final int attr = com.android.internal.R.styleable
+                    .WindowAnimation_activityCloseExitAnimation;
+            final int appResId = transitionAnimation.getAnimationResId(
+                    window.mAttrs, attr, TRANSIT_OLD_NONE);
+            if (ResourceId.isValid(appResId)) {
+                if (sDefaultAnimationResId == 0) {
+                    sDefaultAnimationResId = transitionAnimation.getDefaultAnimationResId(attr,
+                            TRANSIT_OLD_NONE);
+                }
+                return sDefaultAnimationResId != appResId;
+            }
+        }
+        return false;
+    }
+
     // For legacy transition.
     /**
      *  Once we find the transition targets match back animation targets, remove the target from
@@ -526,6 +588,57 @@
         mAnimationHandler.clearBackAnimateTarget(cleanupTransaction);
     }
 
+     /**
+     * Handle the pending animation when the running transition finished.
+     * @param targets The final animation targets derived in transition.
+     */
+    boolean handleDeferredBackAnimation(@NonNull ArrayList<Transition.ChangeInfo> targets) {
+        if (!mBackAnimationInProgress || mPendingAnimationBuilder == null) {
+            return false;
+        }
+
+        ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
+                "Handling the deferred animation after transition finished");
+
+        // Show the target surface and its parents to prevent it or its parents hidden when
+        // the transition finished.
+        // The target could be affected by transition when :
+        // Open transition -> the open target in back navigation
+        // Close transition -> the close target in back navigation.
+        boolean hasTarget = false;
+        final SurfaceControl.Transaction t =
+                mPendingAnimationBuilder.mCloseTarget.getPendingTransaction();
+        for (int i = 0; i < targets.size(); i++) {
+            final WindowContainer wc = targets.get(i).mContainer;
+            if (wc.asActivityRecord() == null && wc.asTask() == null) {
+                continue;
+            } else if (!mPendingAnimationBuilder.containTarget(wc)) {
+                continue;
+            }
+
+            hasTarget = true;
+            t.show(wc.getSurfaceControl());
+        }
+
+        if (!hasTarget) {
+            // Skip if no target participated in current finished transition.
+            Slog.w(TAG, "Finished transition didn't include the targets"
+                    + " open: " + mPendingAnimationBuilder.mOpenTarget
+                    + " close: " + mPendingAnimationBuilder.mCloseTarget);
+            try {
+                mPendingAnimationBuilder.mBackAnimationAdapter.getRunner().onAnimationCancelled();
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+            mPendingAnimationBuilder = null;
+            return false;
+        }
+
+        scheduleAnimation(mPendingAnimationBuilder);
+        mPendingAnimationBuilder = null;
+        return true;
+    }
+
     /**
      * Create and handling animations status for an open/close animation targets.
      */
@@ -638,6 +751,7 @@
             if (open) {
                 return wc == mOpenAdaptor.mTarget || mOpenAdaptor.mTarget.hasChild(wc);
             }
+
             if (mSwitchType == TASK_SWITCH) {
                 return  wc == mCloseAdaptor.mTarget
                         || (wc.asTask() != null && wc.hasChild(mCloseAdaptor.mTarget));
@@ -841,23 +955,22 @@
             }
         }
 
-        Runnable scheduleAnimation(int backType, BackAnimationAdapter adapter,
+        ScheduleAnimationBuilder prepareAnimation(int backType, BackAnimationAdapter adapter,
                 Task currentTask, Task previousTask, ActivityRecord currentActivity,
                 ActivityRecord previousActivity) {
             switch (backType) {
                 case BackNavigationInfo.TYPE_RETURN_TO_HOME:
                     return new ScheduleAnimationBuilder(backType, adapter)
                             .setIsLaunchBehind(true)
-                            .setComposeTarget(currentTask, previousTask)
-                            .build();
+                            .setComposeTarget(currentTask, previousTask);
                 case BackNavigationInfo.TYPE_CROSS_ACTIVITY:
                     return new ScheduleAnimationBuilder(backType, adapter)
                             .setComposeTarget(currentActivity, previousActivity)
-                            .setOpeningSnapshot(getActivitySnapshot(previousActivity)).build();
+                            .setOpeningSnapshot(getActivitySnapshot(previousActivity));
                 case BackNavigationInfo.TYPE_CROSS_TASK:
                     return new ScheduleAnimationBuilder(backType, adapter)
                             .setComposeTarget(currentTask, previousTask)
-                            .setOpeningSnapshot(getTaskSnapshot(previousTask)).build();
+                            .setOpeningSnapshot(getTaskSnapshot(previousTask));
             }
             return null;
         }
@@ -891,6 +1004,11 @@
                 return this;
             }
 
+            boolean containTarget(@NonNull WindowContainer wc) {
+                return wc == mOpenTarget || wc == mCloseTarget
+                        || wc.hasChild(mOpenTarget) || wc.hasChild(mCloseTarget);
+            }
+
             Runnable build() {
                 if (mOpenTarget == null || mCloseTarget == null) {
                     return null;
@@ -926,7 +1044,7 @@
 
                 return () -> {
                     try {
-                        mBackAnimationAdapter.getRunner().onAnimationStart(mType,
+                        mBackAnimationAdapter.getRunner().onAnimationStart(
                                 targets, null, null, callback);
                     } catch (RemoteException e) {
                         e.printStackTrace();
@@ -967,49 +1085,43 @@
                     }
                 };
             }
-
-            private void setLaunchBehind(ActivityRecord activity) {
-                if (activity == null) {
-                    return;
-                }
-                if (!activity.isVisibleRequested()) {
-                    activity.setVisibility(true);
-                }
-                activity.mLaunchTaskBehind = true;
-
-                // Handle fixed rotation launching app.
-                final DisplayContent dc = activity.mDisplayContent;
-                dc.rotateInDifferentOrientationIfNeeded(activity);
-                if (activity.hasFixedRotationTransform()) {
-                    // Set the record so we can recognize it to continue to update display
-                    // orientation if the previous activity becomes the top later.
-                    dc.setFixedRotationLaunchingApp(activity,
-                            activity.getWindowConfiguration().getRotation());
-                }
-
-                ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
-                        "Setting Activity.mLauncherTaskBehind to true. Activity=%s", activity);
-                activity.mTaskSupervisor.mStoppingActivities.remove(activity);
-                activity.getDisplayContent().ensureActivitiesVisible(null /* starting */,
-                        0 /* configChanges */, false /* preserveWindows */, true);
-            }
-            private void restoreLaunchBehind(ActivityRecord activity) {
-                if (activity == null) {
-                    return;
-                }
-
-                activity.mDisplayContent.continueUpdateOrientationForDiffOrienLaunchingApp();
-
-                // Restore the launch-behind state.
-                activity.mTaskSupervisor.scheduleLaunchTaskBehindComplete(activity.token);
-                activity.mLaunchTaskBehind = false;
-                ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
-                        "Setting Activity.mLauncherTaskBehind to false. Activity=%s",
-                        activity);
-            }
         }
     }
 
+    private static void setLaunchBehind(@NonNull ActivityRecord activity) {
+        if (!activity.isVisibleRequested()) {
+            activity.setVisibility(true);
+        }
+        activity.mLaunchTaskBehind = true;
+
+        // Handle fixed rotation launching app.
+        final DisplayContent dc = activity.mDisplayContent;
+        dc.rotateInDifferentOrientationIfNeeded(activity);
+        if (activity.hasFixedRotationTransform()) {
+            // Set the record so we can recognize it to continue to update display
+            // orientation if the previous activity becomes the top later.
+            dc.setFixedRotationLaunchingApp(activity,
+                    activity.getWindowConfiguration().getRotation());
+        }
+
+        ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
+                "Setting Activity.mLauncherTaskBehind to true. Activity=%s", activity);
+        activity.mTaskSupervisor.mStoppingActivities.remove(activity);
+        activity.getDisplayContent().ensureActivitiesVisible(null /* starting */,
+                0 /* configChanges */, false /* preserveWindows */, true);
+    }
+
+    private static void restoreLaunchBehind(@NonNull ActivityRecord activity) {
+        activity.mDisplayContent.continueUpdateOrientationForDiffOrienLaunchingApp();
+
+        // Restore the launch-behind state.
+        activity.mTaskSupervisor.scheduleLaunchTaskBehindComplete(activity.token);
+        activity.mLaunchTaskBehind = false;
+        ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
+                "Setting Activity.mLauncherTaskBehind to false. Activity=%s",
+                activity);
+    }
+
     void checkAnimationReady(WallpaperController wallpaperController) {
         if (!mBackAnimationInProgress) {
             return;
@@ -1039,6 +1151,7 @@
         mNavigationMonitor.stopMonitor();
         mBackAnimationInProgress = false;
         mShowWallpaper = false;
+        mPendingAnimationBuilder = null;
     }
 
     private static TaskSnapshot getActivitySnapshot(@NonNull ActivityRecord r) {
diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
index 8fc3797..2344739596 100644
--- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
+++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
@@ -430,7 +430,7 @@
         // anything that has fallen through would currently be aborted
         Slog.w(
                 TAG,
-                "Background activity start [callingPackage: "
+                "Background activity launch blocked [callingPackage: "
                         + callingPackage
                         + "; callingUid: "
                         + callingUid
@@ -502,7 +502,7 @@
             }
             builder.append("Activity start allowed: " + msg + ". callingUid: " + callingUid + ". ");
             builder.append("BAL Code: ");
-            builder.append(code);
+            builder.append(balCodeToString(code));
             Slog.d(TAG,  builder.toString());
         }
         return code;
diff --git a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
index 5e44d6c..e91c9d4 100644
--- a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
@@ -41,7 +41,8 @@
 
     // Desktop mode feature flag.
     static final boolean DESKTOP_MODE_SUPPORTED = SystemProperties.getBoolean(
-            "persist.wm.debug.desktop_mode", false);
+            "persist.wm.debug.desktop_mode", false) || SystemProperties.getBoolean(
+            "persist.wm.debug.desktop_mode_2", false);
     // Override default freeform task width when desktop mode is enabled. In dips.
     private static final int DESKTOP_MODE_DEFAULT_WIDTH_DP = SystemProperties.getInt(
             "persist.wm.debug.desktop_mode.default_width", 840);
@@ -79,8 +80,8 @@
             appendLog("not in bounds phase, skipping");
             return RESULT_SKIP;
         }
-        if (!task.inFreeformWindowingMode()) {
-            appendLog("not a freeform task, skipping");
+        if (!task.isActivityTypeStandard()) {
+            appendLog("not standard activity type, skipping");
             return RESULT_SKIP;
         }
         if (!currentParams.mBounds.isEmpty()) {
diff --git a/services/core/java/com/android/server/wm/DeviceStateController.java b/services/core/java/com/android/server/wm/DeviceStateController.java
index f5313cb..270b2f8 100644
--- a/services/core/java/com/android/server/wm/DeviceStateController.java
+++ b/services/core/java/com/android/server/wm/DeviceStateController.java
@@ -24,6 +24,7 @@
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 
 import java.util.ArrayList;
@@ -51,7 +52,8 @@
     private final int[] mReverseRotationAroundZAxisStates;
     @GuardedBy("this")
     @NonNull
-    private final List<Consumer<DeviceState>> mDeviceStateCallbacks = new ArrayList<>();
+    @VisibleForTesting
+    final List<Consumer<DeviceState>> mDeviceStateCallbacks = new ArrayList<>();
 
     private final boolean mMatchBuiltInDisplayOrientationToDefaultDisplay;
 
@@ -98,6 +100,12 @@
         }
     }
 
+    void unregisterDeviceStateCallback(@NonNull Consumer<DeviceState> callback) {
+        synchronized (this) {
+            mDeviceStateCallbacks.remove(callback);
+        }
+    }
+
     /**
      * @return true if the rotation direction on the Z axis should be reversed.
      */
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 86c4e0f..a4d475f 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -38,6 +38,9 @@
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.util.DisplayMetrics.DENSITY_DEFAULT;
 import static android.util.RotationUtils.deltaRotation;
+import static android.util.TypedValue.COMPLEX_UNIT_DIP;
+import static android.util.TypedValue.COMPLEX_UNIT_MASK;
+import static android.util.TypedValue.COMPLEX_UNIT_SHIFT;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
 import static android.view.Display.FLAG_PRIVATE;
@@ -170,6 +173,7 @@
 import android.content.pm.ActivityInfo.ScreenOrientation;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.ColorSpace;
 import android.graphics.Insets;
@@ -206,6 +210,7 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
+import android.util.TypedValue;
 import android.util.proto.ProtoOutputStream;
 import android.view.ContentRecordingSession;
 import android.view.Display;
@@ -596,6 +601,7 @@
 
     @VisibleForTesting
     final DeviceStateController mDeviceStateController;
+    final Consumer<DeviceStateController.DeviceState> mDeviceStateConsumer;
     private final PhysicalDisplaySwitchTransitionLauncher mDisplaySwitchTransitionLauncher;
     final RemoteDisplayChangeController mRemoteDisplayChangeController;
 
@@ -1161,12 +1167,12 @@
         mDisplayRotation = new DisplayRotation(mWmService, this, mDisplayInfo.address,
                 mDeviceStateController, root.getDisplayRotationCoordinator());
 
-        final Consumer<DeviceStateController.DeviceState> deviceStateConsumer =
+        mDeviceStateConsumer =
                 (@NonNull DeviceStateController.DeviceState newFoldState) -> {
                     mDisplaySwitchTransitionLauncher.foldStateChanged(newFoldState);
                     mDisplayRotation.foldStateChanged(newFoldState);
                 };
-        mDeviceStateController.registerDeviceStateCallback(deviceStateConsumer);
+        mDeviceStateController.registerDeviceStateCallback(mDeviceStateConsumer);
 
         mCloseToSquareMaxAspectRatio = mWmService.mContext.getResources().getFloat(
                 R.dimen.config_closeToSquareDisplayMaxAspectRatio);
@@ -1684,14 +1690,16 @@
     private int getMinimalTaskSizeDp() {
         final Context displayConfigurationContext =
                 mAtmService.mContext.createConfigurationContext(getConfiguration());
-        final float minimalSize =
-                displayConfigurationContext.getResources().getDimension(
-                        R.dimen.default_minimal_size_resizable_task);
-        if (Double.compare(mDisplayMetrics.density, 0.0) == 0) {
-            throw new IllegalArgumentException("Display with ID=" + getDisplayId() + "has invalid "
-                + "DisplayMetrics.density= 0.0");
+        final Resources res = displayConfigurationContext.getResources();
+        final TypedValue value = new TypedValue();
+        res.getValue(R.dimen.default_minimal_size_resizable_task, value, true /* resolveRefs */);
+        final int valueUnit = ((value.data >> COMPLEX_UNIT_SHIFT) & COMPLEX_UNIT_MASK);
+        if (value.type != TypedValue.TYPE_DIMENSION || valueUnit != COMPLEX_UNIT_DIP) {
+            throw new IllegalArgumentException(
+                "Resource ID #0x" + Integer.toHexString(R.dimen.default_minimal_size_resizable_task)
+                    + " is not in valid type or unit");
         }
-        return (int) (minimalSize / mDisplayMetrics.density);
+        return (int) TypedValue.complexToFloat(value.data);
     }
 
     private boolean updateOrientation(boolean forceUpdate) {
@@ -3276,6 +3284,7 @@
             handleAnimatingStoppedAndTransition();
             mWmService.stopFreezingDisplayLocked();
             mDisplayRotation.removeDefaultDisplayRotationChangedCallback();
+            mDeviceStateController.unregisterDeviceStateCallback(mDeviceStateConsumer);
             super.removeImmediately();
             if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
             mPointerEventDispatcher.dispose();
@@ -4151,13 +4160,13 @@
 
     /** @see WindowManagerInternal#onToggleImeRequested */
     void onShowImeRequested() {
-        if (mImeLayeringTarget == null || mInputMethodWindow == null) {
+        if (mInputMethodWindow == null) {
             return;
         }
         // If IME window will be shown on the rotated activity, share the transformed state to
         // IME window so it can compute rotated frame with rotated configuration.
-        if (mImeLayeringTarget.mToken.isFixedRotationTransforming()) {
-            mInputMethodWindow.mToken.linkFixedRotationTransform(mImeLayeringTarget.mToken);
+        if (mFixedRotationLaunchingApp != null) {
+            mInputMethodWindow.mToken.linkFixedRotationTransform(mFixedRotationLaunchingApp);
             // Hide the window until the rotation is done to avoid intermediate artifacts if the
             // parent surface of IME container is changed.
             if (mAsyncRotationController != null) {
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index ce3379e..389c908 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -20,11 +20,6 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 import static android.view.Display.TYPE_INTERNAL;
 import static android.view.InsetsFrameProvider.SOURCE_FRAME;
-import static android.view.InsetsState.ITYPE_CAPTION_BAR;
-import static android.view.InsetsState.ITYPE_CLIMATE_BAR;
-import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
 import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
 import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
 import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
@@ -198,6 +193,11 @@
 
     private boolean mCanSystemBarsBeShownByUser;
 
+    /**
+     * Let remote insets controller control system bars regardless of other settings.
+     */
+    private boolean mRemoteInsetsControllerControlsSystemBars;
+
     StatusBarManagerInternal getStatusBarManagerInternal() {
         synchronized (mServiceAcquireLock) {
             if (mStatusBarManagerInternal == null) {
@@ -781,6 +781,17 @@
         return mScreenOnListener;
     }
 
+
+    boolean isRemoteInsetsControllerControllingSystemBars() {
+        return mRemoteInsetsControllerControlsSystemBars;
+    }
+
+    @VisibleForTesting
+    void setRemoteInsetsControllerControlsSystemBars(
+            boolean remoteInsetsControllerControlsSystemBars) {
+        mRemoteInsetsControllerControlsSystemBars = remoteInsetsControllerControlsSystemBars;
+    }
+
     public void screenTurnedOn(ScreenOnListener screenOnListener) {
         synchronized (mLock) {
             mScreenOnEarly = true;
@@ -1029,7 +1040,6 @@
                         android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
                         "DisplayPolicy");
             }
-            enforceSingleInsetsTypeCorrespondingToWindowType(attrs.providedInsets);
         }
         return ADD_OKAY;
     }
@@ -1061,7 +1071,7 @@
                 final TriConsumer<DisplayFrames, WindowContainer, Rect> frameProvider =
                         getFrameProvider(win, provider, i);
                 final InsetsFrameProvider.InsetsSizeOverride[] overrides =
-                        provider.insetsSizeOverrides;
+                        provider.getInsetsSizeOverrides();
                 final SparseArray<TriConsumer<DisplayFrames, WindowContainer, Rect>>
                         overrideProviders;
                 if (overrides != null) {
@@ -1070,19 +1080,14 @@
                         final TriConsumer<DisplayFrames, WindowContainer, Rect>
                                 overrideFrameProvider =
                                 getOverrideFrameProvider(win, i, j);
-                        overrideProviders.put(overrides[j].windowType, overrideFrameProvider);
+                        overrideProviders.put(overrides[j].getWindowType(), overrideFrameProvider);
                     }
                 } else {
                     overrideProviders = null;
                 }
-                // TODO (b/234093736): Let InsetsFrameProvider have the following fields:
-                //                     - IBinder owner.
-                //                     - int index.
-                //                     - @InsetsType int type.
-                //                     So we can create the id by using InsetsSource#createId.
-                //                     And we won't need toPublicType anymore.
-                final int id = provider.type;
-                final @InsetsType int type = InsetsState.toPublicType(id);
+                final @InsetsType int type = provider.getType();
+                final int id = InsetsSource.createId(
+                        provider.getOwner(), provider.getIndex(), type);
                 mDisplayContent.getInsetsStateController().getOrCreateSourceProvider(id, type)
                         .setWindowContainer(win, frameProvider, overrideProviders);
                 mInsetsSourceWindowsExceptIme.add(win);
@@ -1093,7 +1098,7 @@
     @Nullable
     private TriConsumer<DisplayFrames, WindowContainer, Rect> getFrameProvider(WindowState win,
             InsetsFrameProvider provider, int index) {
-        if (provider.insetsSize == null && provider.source == SOURCE_FRAME) {
+        if (provider.getInsetsSize() == null && provider.getSource() == SOURCE_FRAME) {
             return null;
         }
         return (displayFrames, windowContainer, inOutFrame) -> {
@@ -1101,8 +1106,8 @@
             final InsetsFrameProvider ifp = lp.providedInsets[index];
             InsetsFrameProvider.calculateInsetsFrame(displayFrames.mUnrestricted,
                     windowContainer.getBounds(), displayFrames.mDisplayCutoutSafe, inOutFrame,
-                    ifp.source, ifp.insetsSize, lp.privateFlags,
-                    ifp.minimalInsetsSizeInDisplayCutoutSafe);
+                    ifp.getSource(), ifp.getInsetsSize(), lp.privateFlags,
+                    ifp.getMinimalInsetsSizeInDisplayCutoutSafe());
         };
     }
 
@@ -1114,8 +1119,8 @@
             final InsetsFrameProvider ifp = lp.providedInsets[index];
             InsetsFrameProvider.calculateInsetsFrame(displayFrames.mUnrestricted,
                     windowContainer.getBounds(), displayFrames.mDisplayCutoutSafe, inOutFrame,
-                    ifp.source, ifp.insetsSizeOverrides[overrideIndex].insetsSize, lp.privateFlags,
-                    null);
+                    ifp.getSource(), ifp.getInsetsSizeOverrides()[overrideIndex].getInsetsSize(),
+                    lp.privateFlags, null /* displayCutoutSafeInsetsSize */);
         };
     }
 
@@ -1141,24 +1146,6 @@
         };
     }
 
-    private static void enforceSingleInsetsTypeCorrespondingToWindowType(
-            InsetsFrameProvider[] providers) {
-        int count = 0;
-        for (InsetsFrameProvider provider : providers) {
-            switch (provider.type) {
-                case ITYPE_NAVIGATION_BAR:
-                case ITYPE_STATUS_BAR:
-                case ITYPE_CLIMATE_BAR:
-                case ITYPE_EXTRA_NAVIGATION_BAR:
-                case ITYPE_CAPTION_BAR:
-                    if (++count > 1) {
-                        throw new IllegalArgumentException(
-                                "Multiple InsetsTypes corresponding to Window type");
-                    }
-            }
-        }
-    }
-
     /**
      * Called when a window is being removed from a window manager.  Must not
      * throw an exception -- clean up as much as possible.
@@ -1664,6 +1651,8 @@
         mRightGestureInset = mGestureNavigationSettingsObserver.getRightSensitivity(res);
         mNavigationBarAlwaysShowOnSideGesture =
                 res.getBoolean(R.bool.config_navBarAlwaysShowOnSideEdgeGesture);
+        mRemoteInsetsControllerControlsSystemBars = res.getBoolean(
+                R.bool.config_remoteInsetsControllerControlsSystemBars);
 
         updateConfigurationAndScreenSizeDependentBehaviors();
 
@@ -2553,7 +2542,7 @@
         pw.print(mForceShowNavigationBarEnabled);
         pw.print(" mAllowLockscreenWhenOn="); pw.println(mAllowLockscreenWhenOn);
         pw.print(prefix); pw.print("mRemoteInsetsControllerControlsSystemBars=");
-        pw.println(mDisplayContent.getInsetsPolicy().getRemoteInsetsControllerControlsSystemBars());
+        pw.println(mRemoteInsetsControllerControlsSystemBars);
         pw.print(prefix); pw.println("mDecorInsetsInfo:");
         for (int rotation = 0; rotation < mDecorInsets.mInfoForRotation.length; rotation++) {
             final DecorInsets.Info info = mDecorInsets.mInfoForRotation[rotation];
@@ -2662,10 +2651,9 @@
      */
     private static boolean intersectsAnyInsets(Rect bounds, InsetsState insetsState,
             @InsetsType int insetsType) {
-        final ArraySet<Integer> internalTypes = InsetsState.toInternalType(insetsType);
-        for (int i = 0; i < internalTypes.size(); i++) {
-            final InsetsSource source = insetsState.peekSource(internalTypes.valueAt(i));
-            if (source == null || !source.isVisible()) {
+        for (int i = insetsState.sourceSize() - 1; i >= 0; i--) {
+            final InsetsSource source = insetsState.sourceAt(i);
+            if ((source.getType() & insetsType) == 0 || !source.isVisible()) {
                 continue;
             }
             if (Rect.intersects(bounds, source.getFrame())) {
diff --git a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
index 47bdba3..41eb2c9 100644
--- a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
@@ -359,12 +359,6 @@
                 CAMERA_OPENED_ROTATION_UPDATE_DELAY_MS);
     }
 
-    private void updateOrientationWithWmLock() {
-        synchronized (mWmService.mGlobalLock) {
-            mDisplayContent.updateOrientation();
-        }
-    }
-
     private void delayedUpdateOrientationWithWmLock(
             @NonNull String cameraId, @NonNull String packageName) {
         synchronized (this) {
@@ -375,25 +369,28 @@
             }
             mCameraIdPackageBiMap.put(packageName, cameraId);
         }
-        ActivityRecord topActivity = mDisplayContent.topRunningActivity(
-                    /* considerKeyguardState= */ true);
-        if (topActivity == null || topActivity.getTask() == null) {
-            return;
-        }
-        // Checking whether an activity in fullscreen rather than the task as this camera compat
-        // treatment doesn't cover activity embedding.
-        if (topActivity.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
-            if (topActivity.mLetterboxUiController.isOverrideOrientationOnlyForCameraEnabled()) {
-                topActivity.recomputeConfiguration();
+        synchronized (mWmService.mGlobalLock) {
+            ActivityRecord topActivity = mDisplayContent.topRunningActivity(
+                        /* considerKeyguardState= */ true);
+            if (topActivity == null || topActivity.getTask() == null) {
+                return;
             }
-            updateOrientationWithWmLock();
-            return;
-        }
-        // Checking that the whole app is in multi-window mode as we shouldn't show toast
-        // for the activity embedding case.
-        if (topActivity.getTask().getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW
-                && isTreatmentEnabledForActivity(topActivity, /* mustBeFullscreen */ false)) {
-            showToast(R.string.display_rotation_camera_compat_toast_in_split_screen);
+            // Checking whether an activity in fullscreen rather than the task as this camera
+            // compat treatment doesn't cover activity embedding.
+            if (topActivity.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
+                if (topActivity.mLetterboxUiController
+                        .isOverrideOrientationOnlyForCameraEnabled()) {
+                    topActivity.recomputeConfiguration();
+                }
+                mDisplayContent.updateOrientation();
+                return;
+            }
+            // Checking that the whole app is in multi-window mode as we shouldn't show toast
+            // for the activity embedding case.
+            if (topActivity.getTask().getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW
+                    && isTreatmentEnabledForActivity(topActivity, /* mustBeFullscreen */ false)) {
+                showToast(R.string.display_rotation_camera_compat_toast_in_split_screen);
+            }
         }
     }
 
@@ -441,18 +438,20 @@
         ProtoLog.v(WM_DEBUG_ORIENTATION,
                 "Display id=%d is notified that Camera %s is closed, updating rotation.",
                 mDisplayContent.mDisplayId, cameraId);
-        ActivityRecord topActivity = mDisplayContent.topRunningActivity(
-                /* considerKeyguardState= */ true);
-        if (topActivity == null
-                // Checking whether an activity in fullscreen rather than the task as this camera
-                // compat treatment doesn't cover activity embedding.
-                || topActivity.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
-            return;
+        synchronized (mWmService.mGlobalLock) {
+            ActivityRecord topActivity = mDisplayContent.topRunningActivity(
+                    /* considerKeyguardState= */ true);
+            if (topActivity == null
+                    // Checking whether an activity in fullscreen rather than the task as this
+                    // camera compat treatment doesn't cover activity embedding.
+                    || topActivity.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
+                return;
+            }
+            if (topActivity.mLetterboxUiController.isOverrideOrientationOnlyForCameraEnabled()) {
+                topActivity.recomputeConfiguration();
+            }
+            mDisplayContent.updateOrientation();
         }
-        if (topActivity.mLetterboxUiController.isOverrideOrientationOnlyForCameraEnabled()) {
-            topActivity.recomputeConfiguration();
-        }
-        updateOrientationWithWmLock();
     }
 
     private boolean isActivityForCameraIdRefreshing(String cameraId) {
diff --git a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
index dde89e9..9cc311d 100644
--- a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
+++ b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
@@ -193,7 +193,7 @@
             }
 
             if (!r.attachedToProcess()) {
-                makeVisibleAndRestartIfNeeded(mStarting, mConfigChanges, isTop,
+                makeVisibleAndRestartIfNeeded(mStarting, mConfigChanges,
                         resumeTopActivity && isTop, r);
             } else if (r.isVisibleRequested()) {
                 // If this activity is already visible, then there is nothing to do here.
@@ -243,15 +243,7 @@
     }
 
     private void makeVisibleAndRestartIfNeeded(ActivityRecord starting, int configChanges,
-            boolean isTop, boolean andResume, ActivityRecord r) {
-        // We need to make sure the app is running if it's the top, or it is just made visible from
-        // invisible. If the app is already visible, it must have died while it was visible. In this
-        // case, we'll show the dead window but will not restart the app. Otherwise we could end up
-        // thrashing.
-        if (!isTop && r.isVisibleRequested() && !r.isState(INITIALIZING)) {
-            return;
-        }
-
+            boolean andResume, ActivityRecord r) {
         // This activity needs to be visible, but isn't even running...
         // get it started and resume if no other root task in this root task is resumed.
         if (DEBUG_VISIBILITY) {
diff --git a/services/core/java/com/android/server/wm/EventLogTags.logtags b/services/core/java/com/android/server/wm/EventLogTags.logtags
index 594929b..244656c 100644
--- a/services/core/java/com/android/server/wm/EventLogTags.logtags
+++ b/services/core/java/com/android/server/wm/EventLogTags.logtags
@@ -49,7 +49,7 @@
 30066 wm_add_to_stopping (User|1|5),(Token|1|5),(Component Name|3),(Reason|3)
 
 # Keyguard status changed
-30067 wm_set_keyguard_shown (Display Id|1|5),(keyguardShowing|1),(aodShowing|1),(keyguardGoingAway|1),(Reason|3)
+30067 wm_set_keyguard_shown (Display Id|1|5),(keyguardShowing|1),(aodShowing|1),(keyguardGoingAway|1),(occluded|1),(Reason|3)
 
 # Out of memory for surfaces.
 31000 wm_no_surface_memory (Window|3),(PID|1|5),(Operation|3)
@@ -65,6 +65,8 @@
 
 # bootanim finished:
 31007 wm_boot_animation_done (time|2|3)
+# Notify keyguard occlude statuc change to SysUI.
+31008 wm_set_keyguard_occluded (occluded|1),(animate|1),(transit|1),(Channel|3)
 
 # Back navigation.
 31100 wm_back_navi_canceled (Reason|3)
diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java
index 1e9d451..0a47fe0 100644
--- a/services/core/java/com/android/server/wm/InputManagerCallback.java
+++ b/services/core/java/com/android/server/wm/InputManagerCallback.java
@@ -25,7 +25,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.graphics.PointF;
 import android.os.Debug;
 import android.os.IBinder;
 import android.util.Slog;
@@ -221,11 +220,6 @@
     }
 
     @Override
-    public PointF getCursorPosition() {
-        return mService.getLatestMousePosition();
-    }
-
-    @Override
     public void onPointerDownOutsideFocus(IBinder touchedToken) {
         mService.mH.obtainMessage(ON_POINTER_DOWN_OUTSIDE_FOCUS, touchedToken).sendToTarget();
     }
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 25ce569..868a15d 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -116,11 +116,6 @@
     private @InsetsType int mShowingTransientTypes;
     private boolean mAnimatingShown;
 
-    /**
-     * Let remote insets controller control system bars regardless of other settings.
-     */
-    private boolean mRemoteInsetsControllerControlsSystemBars;
-
     private final boolean mHideNavBarForKeyboard;
     private final float[] mTmpFloat9 = new float[9];
 
@@ -129,22 +124,9 @@
         mDisplayContent = displayContent;
         mPolicy = displayContent.getDisplayPolicy();
         final Resources r = mPolicy.getContext().getResources();
-        mRemoteInsetsControllerControlsSystemBars = r.getBoolean(
-                R.bool.config_remoteInsetsControllerControlsSystemBars);
         mHideNavBarForKeyboard = r.getBoolean(R.bool.config_hideNavBarForKeyboard);
     }
 
-    boolean getRemoteInsetsControllerControlsSystemBars() {
-        return mRemoteInsetsControllerControlsSystemBars;
-    }
-
-    /**
-     * Used only for testing.
-     */
-    @VisibleForTesting
-    void setRemoteInsetsControllerControlsSystemBars(boolean controlsSystemBars) {
-        mRemoteInsetsControllerControlsSystemBars = controlsSystemBars;
-    }
 
     /** Updates the target which can control system bars. */
     void updateBarControlTarget(@Nullable WindowState focusedWin) {
@@ -329,21 +311,32 @@
             state.removeSource(ID_IME);
         } else if (attrs.providedInsets != null) {
             for (InsetsFrameProvider provider : attrs.providedInsets) {
-                // TODO(b/234093736): Let InsetsFrameProvider return the public type and the ID.
-                final int sourceId = provider.type;
-                final @InsetsType int type = sourceId == ID_IME
-                        ? WindowInsets.Type.ime()
-                        : InsetsState.toPublicType(sourceId);
+                final int id = InsetsSource.createId(
+                        provider.getOwner(), provider.getIndex(), provider.getType());
+                final @InsetsType int type = provider.getType();
                 if ((type & WindowInsets.Type.systemBars()) == 0) {
                     continue;
                 }
                 if (state == originalState) {
                     state = new InsetsState(state);
                 }
-                state.removeSource(sourceId);
+                state.removeSource(id);
             }
         }
 
+        if (!attrs.isFullscreen() || attrs.getFitInsetsTypes() != 0) {
+            if (state == originalState) {
+                state = new InsetsState(originalState);
+            }
+            // Explicitly exclude floating windows from receiving caption insets. This is because we
+            // hard code caption insets for windows due to a synchronization issue that leads to
+            // flickering that bypasses insets frame calculation, which consequently needs us to
+            // remove caption insets from floating windows.
+            // TODO(b/254128050): Remove this workaround after we find a way to update window frames
+            //  and caption insets frames simultaneously.
+            state.removeSource(InsetsState.ITYPE_CAPTION_BAR);
+        }
+
         final SparseArray<WindowContainerInsetsSourceProvider> providers =
                 mStateController.getSourceProviders();
         final int windowType = attrs.type;
@@ -567,6 +560,13 @@
             // Notification shade has control anyways, no reason to force anything.
             return focusedWin;
         }
+        if (focusedWin != null) {
+            final InsetsSourceProvider provider = focusedWin.getControllableInsetProvider();
+            if (provider != null && provider.getSource().getType() == Type.navigationBars()) {
+                // Navigation bar has control if it is focused.
+                return focusedWin;
+            }
+        }
         if (mPolicy.isForceShowNavigationBarEnabled() && focusedWin != null
                 && focusedWin.getActivityType() == ACTIVITY_TYPE_STANDARD) {
             // When "force show navigation bar" is enabled, it means both force visible is true, and
@@ -612,7 +612,8 @@
         if (focusedWin == null) {
             return false;
         }
-        if (!mRemoteInsetsControllerControlsSystemBars) {
+
+        if (!mPolicy.isRemoteInsetsControllerControllingSystemBars()) {
             return false;
         }
         if (mDisplayContent == null || mDisplayContent.mRemoteInsetsControlTarget == null) {
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 2b7a451..0953604 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -16,8 +16,6 @@
 
 package com.android.server.wm;
 
-import static android.view.InsetsSource.ID_IME;
-
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_INSETS;
 import static com.android.server.wm.InsetsSourceProviderProto.CAPTURED_LEASH;
 import static com.android.server.wm.InsetsSourceProviderProto.CLIENT_VISIBLE;
@@ -41,7 +39,6 @@
 import android.graphics.Rect;
 import android.util.SparseArray;
 import android.util.proto.ProtoOutputStream;
-import android.view.InsetsFrameProvider;
 import android.view.InsetsSource;
 import android.view.InsetsSourceControl;
 import android.view.SurfaceControl;
@@ -514,33 +511,13 @@
     }
 
     protected void updateVisibility() {
-        mSource.setVisible(mServerVisible && (isMirroredSource() || mClientVisible));
+        mSource.setVisible(mServerVisible && mClientVisible);
         ProtoLog.d(WM_DEBUG_WINDOW_INSETS,
                 "InsetsSource updateVisibility for %s, serverVisible: %s clientVisible: %s",
                 WindowInsets.Type.toString(mSource.getType()),
                 mServerVisible, mClientVisible);
     }
 
-    private boolean isMirroredSource() {
-        if (mWindowContainer == null) {
-            return false;
-        }
-        if (mWindowContainer.asWindowState() == null) {
-            return false;
-        }
-        final InsetsFrameProvider[] providers =
-                ((WindowState) mWindowContainer).mAttrs.providedInsets;
-        if (providers == null) {
-            return false;
-        }
-        for (int i = 0; i < providers.length; i++) {
-            if (providers[i].type == ID_IME) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     InsetsSourceControl getControl(InsetsControlTarget target) {
         if (target == mControlTarget) {
             if (!mIsLeashReadyForDispatching && mControl != null) {
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index 0e1e63e..e4ffb8d 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -138,14 +138,6 @@
     }
 
     /**
-     * @return The provider of a source ID or null if we don't have it.
-     */
-    @Nullable
-    WindowContainerInsetsSourceProvider peekSourceProvider(int id) {
-        return mProviders.get(id);
-    }
-
-    /**
      * Called when a layout pass has occurred.
      */
     void onPostLayout() {
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 32b3ccf..08a6358 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -188,6 +188,7 @@
                 keyguardShowing ? 1 : 0,
                 aodShowing ? 1 : 0,
                 state.mKeyguardGoingAway ? 1 : 0,
+                state.mOccluded ? 1 : 0,
                 "setKeyguardShown");
 
         // Update the task snapshot if the screen will not be turned off. To make sure that the
@@ -253,9 +254,10 @@
         try {
             EventLogTags.writeWmSetKeyguardShown(
                     displayId,
-                    1 /* keyguardShowing */,
+                    state.mKeyguardShowing ? 1 : 0,
                     state.mAodShowing ? 1 : 0,
                     1 /* keyguardGoingAway */,
+                    state.mOccluded ? 1 : 0,
                     "keyguardGoingAway");
             final int transitFlags = convertTransitFlags(flags);
             final DisplayContent dc = mRootWindowContainer.getDefaultDisplay();
@@ -669,6 +671,15 @@
 
             boolean hasChange = false;
             if (lastOccluded != mOccluded) {
+                if (mDisplayId == DEFAULT_DISPLAY) {
+                    EventLogTags.writeWmSetKeyguardShown(
+                            mDisplayId,
+                            mKeyguardShowing ? 1 : 0,
+                            mAodShowing ? 1 : 0,
+                            mKeyguardGoingAway ? 1 : 0,
+                            mOccluded ? 1 : 0,
+                            "updateVisibility");
+                }
                 controller.handleOccludedChanged(mDisplayId, mTopOccludesActivity);
                 hasChange = true;
             } else if (!lastKeyguardGoingAway && mKeyguardGoingAway) {
diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
index fa49a6ba..37cf5bc 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
@@ -19,6 +19,7 @@
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ALLOW_IGNORE_ORIENTATION_REQUEST;
+import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP;
 import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_CAMERA_COMPAT_TREATMENT;
 import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_COMPAT_FAKE_FOCUS;
 import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY;
@@ -314,6 +315,10 @@
         mDeviceConfig.updateFlagActiveStatus(
                 /* isActive */ mTranslucentLetterboxingEnabled,
                 /* key */ KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY);
+        mDeviceConfig.updateFlagActiveStatus(
+                /* isActive */ true,
+                /* key */ KEY_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP);
+
         mLetterboxConfigurationPersister = letterboxConfigurationPersister;
         mLetterboxConfigurationPersister.start();
     }
@@ -327,6 +332,16 @@
     }
 
     /**
+     * Whether size compat mode is disabled after an orientation change request comes from the app.
+     * This value is controlled via {@link android.provider.DeviceConfig}.
+     */
+    // TODO(b/270356567) Clean up this flag
+    boolean isSizeCompatModeDisabledAfterOrientationChangeFromApp() {
+        return mDeviceConfig.getFlag(
+                KEY_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP);
+    }
+
+    /**
      * Overrides the aspect ratio of letterbox for fixed orientation. If given value is <= {@link
      * #MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO}, both it and a value of {@link
      * com.android.internal.R.dimen.config_fixedOrientationLetterboxAspectRatio} will be ignored and
diff --git a/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java b/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java
index df3c8f0..1651af3 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java
@@ -20,7 +20,6 @@
 import android.provider.DeviceConfig;
 import android.util.ArraySet;
 
-
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.util.Map;
@@ -53,6 +52,11 @@
 
     private static final boolean DEFAULT_VALUE_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY = true;
 
+    static final String KEY_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP =
+            "disable_size_compat_mode_after_orientation_change_from_app";
+    private static final boolean
+            DEFAULT_VALUE_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP = true;
+
     @VisibleForTesting
     static final Map<String, Boolean> sKeyToDefaultValueMap = Map.of(
             KEY_ENABLE_CAMERA_COMPAT_TREATMENT,
@@ -64,7 +68,9 @@
             KEY_ENABLE_COMPAT_FAKE_FOCUS,
             DEFAULT_VALUE_ENABLE_COMPAT_FAKE_FOCUS,
             KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY,
-            DEFAULT_VALUE_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY
+            DEFAULT_VALUE_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY,
+            KEY_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP,
+            DEFAULT_VALUE_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP
     );
 
     // Whether camera compatibility treatment is enabled.
@@ -93,6 +99,10 @@
     private boolean mIsTranslucentLetterboxingAllowed =
             DEFAULT_VALUE_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY;
 
+    // Whether size compat mode is disabled after an orientation change request comes from the app
+    private boolean mIsSizeCompatModeDisabledAfterOrientationChangeFromApp =
+            DEFAULT_VALUE_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP;
+
     // Set of active device configs that need to be updated in
     // DeviceConfig.OnPropertiesChangedListener#onPropertiesChanged.
     private final ArraySet<String> mActiveDeviceConfigsSet = new ArraySet<>();
@@ -142,6 +152,8 @@
                 return mIsCompatFakeFocusAllowed;
             case KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY:
                 return mIsTranslucentLetterboxingAllowed;
+            case KEY_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP:
+                return mIsSizeCompatModeDisabledAfterOrientationChangeFromApp;
             default:
                 throw new AssertionError("Unexpected flag name: " + key);
         }
@@ -169,6 +181,10 @@
             case KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY:
                 mIsTranslucentLetterboxingAllowed = getDeviceConfig(key, defaultValue);
                 break;
+            case KEY_DISABLE_SIZE_COMPAT_MODE_AFTER_ORIENTATION_CHANGE_FROM_APP:
+                mIsSizeCompatModeDisabledAfterOrientationChangeFromApp =
+                        getDeviceConfig(key, defaultValue);
+                break;
             default:
                 throw new AssertionError("Unexpected flag name: " + key);
         }
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index dc674c2..f355f08 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -862,10 +862,9 @@
         return mActivityRecord.mWmService.mContext.getResources();
     }
 
-    private void handleHorizontalDoubleTap(int x) {
-        // TODO(b/260857308): Investigate if enabling reachability for translucent activity
-        if (hasInheritedLetterboxBehavior() || !isHorizontalReachabilityEnabled()
-                || mActivityRecord.isInTransition()) {
+    @VisibleForTesting
+    void handleHorizontalDoubleTap(int x) {
+        if (!isHorizontalReachabilityEnabled() || mActivityRecord.isInTransition()) {
             return;
         }
 
@@ -903,10 +902,9 @@
         mActivityRecord.recomputeConfiguration();
     }
 
-    private void handleVerticalDoubleTap(int y) {
-        // TODO(b/260857308): Investigate if enabling reachability for translucent activity
-        if (hasInheritedLetterboxBehavior() || !isVerticalReachabilityEnabled()
-                || mActivityRecord.isInTransition()) {
+    @VisibleForTesting
+    void handleVerticalDoubleTap(int y) {
+        if (!isVerticalReachabilityEnabled() || mActivityRecord.isInTransition()) {
             return;
         }
 
@@ -1397,9 +1395,9 @@
                 FIRST_OPAQUE_NOT_FINISHING_ACTIVITY_PREDICATE /* callback */,
                 mActivityRecord /* boundary */, false /* includeBoundary */,
                 true /* traverseTopToBottom */);
-        if (firstOpaqueActivityBeneath == null) {
+        if (firstOpaqueActivityBeneath == null || firstOpaqueActivityBeneath.isEmbedded()) {
             // We skip letterboxing if the translucent activity doesn't have any opaque
-            // activities beneath
+            // activities beneath or the activity below is embedded which never has letterbox.
             return;
         }
         inheritConfiguration(firstOpaqueActivityBeneath);
@@ -1429,7 +1427,7 @@
      * the first opaque activity beneath.
      */
     boolean hasInheritedLetterboxBehavior() {
-        return mLetterboxConfigListener != null && !mActivityRecord.matchParentBounds();
+        return mLetterboxConfigListener != null;
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index 14b845c..cb94146 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -37,6 +37,7 @@
 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS;
+import static com.android.server.wm.ActivityRecord.State.RESUMED;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS_TRIM_TASKS;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS;
@@ -1221,7 +1222,7 @@
     void onActivityIdle(ActivityRecord r) {
         // Clean up the hidden tasks when going to home because the user may not be unable to return
         // to the task from recents.
-        if (!mHiddenTasks.isEmpty() && r.isActivityTypeHome()) {
+        if (!mHiddenTasks.isEmpty() && r.isActivityTypeHome() && r.isState(RESUMED)) {
             removeUnreachableHiddenTasks(r.getWindowingMode());
         }
         if (mCheckTrimmableTasksOnIdle) {
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index 3635ebb..b879d1a 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -16,6 +16,8 @@
 
 package com.android.server.wm;
 
+import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_UNOCCLUDE;
+
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_REMOTE_ANIMATIONS;
 import static com.android.server.wm.AnimationAdapterProto.REMOTE;
 import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET;
@@ -195,6 +197,13 @@
                                 + " transit=%s, apps=%d, wallpapers=%d, nonApps=%d",
                         AppTransition.appTransitionOldToString(transit), appTargets.length,
                         wallpaperTargets.length, nonAppTargets.length);
+                if (AppTransition.isKeyguardOccludeTransitOld(transit)) {
+                    EventLogTags.writeWmSetKeyguardOccluded(
+                            transit == TRANSIT_OLD_KEYGUARD_UNOCCLUDE ? 0 : 1,
+                            1 /* animate */,
+                            transit,
+                            "onAnimationStart");
+                }
                 mRemoteAnimationAdapter.getRunner().onAnimationStart(transit, appTargets,
                         wallpaperTargets, nonAppTargets, mFinishedCallback);
             } catch (RemoteException e) {
@@ -356,6 +365,11 @@
         final boolean isKeyguardOccluded = mDisplayContent.isKeyguardOccluded();
 
         try {
+            EventLogTags.writeWmSetKeyguardOccluded(
+                    isKeyguardOccluded ? 1 : 0,
+                    0 /* animate */,
+                    0 /* transit */,
+                    "onAnimationCancelled");
             mRemoteAnimationAdapter.getRunner().onAnimationCancelled(isKeyguardOccluded);
         } catch (RemoteException e) {
             Slog.e(TAG, "Failed to notify cancel", e);
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index b3b56f2..b2a4df1 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -33,6 +33,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
 import static android.view.WindowManager.TRANSIT_NONE;
 import static android.view.WindowManager.TRANSIT_PIP;
+import static android.view.WindowManager.TRANSIT_SLEEP;
 import static android.view.WindowManager.TRANSIT_TO_BACK;
 import static android.view.WindowManager.TRANSIT_WAKE;
 
@@ -2329,6 +2330,7 @@
     }
 
     void applySleepTokens(boolean applyToRootTasks) {
+        boolean builtSleepTransition = false;
         for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
             // Set the sleeping state of the display.
             final DisplayContent display = getChildAt(displayNdx);
@@ -2338,6 +2340,30 @@
             }
             display.setIsSleeping(displayShouldSleep);
 
+            if (display.mTransitionController.isShellTransitionsEnabled() && !builtSleepTransition
+                    // Only care if there are actual sleep tokens.
+                    && displayShouldSleep && !display.mAllSleepTokens.isEmpty()) {
+                builtSleepTransition = true;
+                // We don't actually care about collecting anything here. We really just want
+                // this as a signal to the transition-player.
+                final Transition transition = new Transition(TRANSIT_SLEEP, 0 /* flags */,
+                        display.mTransitionController, mWmService.mSyncEngine);
+                final Runnable sendSleepTransition = () -> {
+                    display.mTransitionController.requestStartTransition(transition,
+                            null /* trigger */, null /* remote */, null /* display */);
+                    // Force playing immediately so that unrelated ops can't be collected.
+                    transition.playNow();
+                };
+                if (display.mTransitionController.isCollecting()) {
+                    mWmService.mSyncEngine.queueSyncSet(
+                            () -> display.mTransitionController.moveToCollecting(transition),
+                            sendSleepTransition);
+                } else {
+                    display.mTransitionController.moveToCollecting(transition);
+                    sendSleepTransition.run();
+                }
+            }
+
             if (!applyToRootTasks) {
                 continue;
             }
@@ -3446,7 +3472,7 @@
     }
 
     boolean dumpActivities(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient,
-            String dumpPackage) {
+            String dumpPackage, int displayIdFilter) {
         boolean[] printed = {false};
         boolean[] needSep = {false};
         for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
@@ -3454,6 +3480,10 @@
             if (printed[0]) {
                 pw.println();
             }
+            if (displayIdFilter != Display.INVALID_DISPLAY
+                    && displayContent.mDisplayId != displayIdFilter) {
+                continue;
+            }
             pw.print("Display #");
             pw.print(displayContent.mDisplayId);
             pw.println(" (activities from top to bottom):");
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 97e0b1e..ce9bff8 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -948,7 +948,7 @@
         synchronized (mService.mGlobalLock) {
             WindowState windowState = mService.windowForClientLocked(this, window, false);
             if (windowState == null) {
-                Slog.e(TAG_WM,
+                Slog.i(TAG_WM,
                         "setOnBackInvokedCallback(): No window state for package:" + mPackageName);
             } else {
                 windowState.setOnBackInvokedCallbackInfo(callbackInfo);
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index cc81d52..969f65c 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -2035,6 +2035,10 @@
         Rect outOverrideBounds = getResolvedOverrideConfiguration().windowConfiguration.getBounds();
 
         if (windowingMode == WINDOWING_MODE_FULLSCREEN) {
+            if (!mCreatedByOrganizer) {
+                // Use empty bounds to indicate "fill parent".
+                outOverrideBounds.setEmpty();
+            }
             // The bounds for fullscreen mode shouldn't be adjusted by minimal size. Otherwise if
             // the parent or display is smaller than the size, the content may be cropped.
             return;
@@ -2580,6 +2584,9 @@
 
         EventLogTags.writeWmTaskRemoved(mTaskId, getRootTaskId(), getDisplayId(), reason);
         clearPinnedTaskIfNeed();
+        if (mChildPipActivity != null) {
+            mChildPipActivity.clearLastParentBeforePip();
+        }
         // If applicable let the TaskOrganizer know the Task is vanishing.
         setTaskOrganizer(null);
 
@@ -5325,7 +5332,7 @@
         // the task if the affinity has changed.
 
         final String affinity = ActivityRecord.computeTaskAffinity(destAffinity, srec.getUid(),
-                srec.launchMode);
+                srec.launchMode, srec.mActivityComponent);
         if (srec == null || srec.getTask().affinity == null
                 || !srec.getTask().affinity.equals(affinity)) {
             return true;
@@ -5774,8 +5781,11 @@
             final int taskId = activity != null
                     ? mTaskSupervisor.getNextTaskIdForUser(activity.mUserId)
                     : mTaskSupervisor.getNextTaskIdForUser();
+            final int activityType = getActivityType();
             task = new Task.Builder(mAtmService)
                     .setTaskId(taskId)
+                    .setActivityType(activityType != ACTIVITY_TYPE_UNDEFINED ? activityType
+                            : ACTIVITY_TYPE_STANDARD)
                     .setActivityInfo(info)
                     .setActivityOptions(options)
                     .setIntent(intent)
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 3cec3aa..76759ba 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -49,6 +49,7 @@
 import android.util.Slog;
 import android.view.RemoteAnimationTarget;
 import android.view.SurfaceControl;
+import android.view.WindowManager;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.protolog.common.ProtoLog;
@@ -1486,7 +1487,7 @@
      */
     private boolean isLargeEnoughForMultiWindow() {
         return getConfiguration().smallestScreenWidthDp
-                >= mAtmService.mLargeScreenSmallestScreenWidthDp;
+                >= WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP;
     }
 
     boolean isTopRootTask(Task rootTask) {
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 808e79d..2ddb307 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -1637,6 +1637,7 @@
 
         if (prev.attachedToProcess()) {
             if (shouldAutoPip) {
+                prev.mPauseSchedulePendingForPip = true;
                 boolean didAutoPip = mAtmService.enterPictureInPictureMode(
                         prev, prev.pictureInPictureArgs, false /* fromClient */);
                 ProtoLog.d(WM_DEBUG_STATES, "Auto-PIP allowed, entering PIP mode "
@@ -1700,6 +1701,7 @@
             boolean pauseImmediately, boolean autoEnteringPip, String reason) {
         ProtoLog.v(WM_DEBUG_STATES, "Enqueueing pending pause: %s", prev);
         try {
+            prev.mPauseSchedulePendingForPip = false;
             EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev),
                     prev.shortComponentName, "userLeaving=" + userLeaving, reason);
 
@@ -2574,6 +2576,7 @@
      */
     TaskFragmentInfo getTaskFragmentInfo() {
         List<IBinder> childActivities = new ArrayList<>();
+        List<IBinder> inRequestedTaskFragmentActivities = new ArrayList<>();
         for (int i = 0; i < getChildCount(); i++) {
             final WindowContainer<?> wc = getChildAt(i);
             final ActivityRecord ar = wc.asActivityRecord();
@@ -2582,6 +2585,9 @@
                     && ar.getUid() == mTaskFragmentOrganizerUid && !ar.finishing) {
                 // Only includes Activities that belong to the organizer process for security.
                 childActivities.add(ar.token);
+                if (ar.mRequestedLaunchingTaskFragmentToken == mFragmentToken) {
+                    inRequestedTaskFragmentActivities.add(ar.token);
+                }
             }
         }
         final Point positionInParent = new Point();
@@ -2593,6 +2599,7 @@
                 getNonFinishingActivityCount(),
                 shouldBeVisible(null /* starting */),
                 childActivities,
+                inRequestedTaskFragmentActivities,
                 positionInParent,
                 mClearedTaskForReuse,
                 mClearedTaskFragmentForPip,
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index a68b3cb..4e0f120 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -53,6 +53,7 @@
 import static android.window.TransitionInfo.FLAG_NO_ANIMATION;
 import static android.window.TransitionInfo.FLAG_OCCLUDES_KEYGUARD;
 import static android.window.TransitionInfo.FLAG_SHOW_WALLPAPER;
+import static android.window.TransitionInfo.FLAG_TASK_LAUNCHING_BEHIND;
 import static android.window.TransitionInfo.FLAG_TRANSLUCENT;
 import static android.window.TransitionInfo.FLAG_WILL_IME_SHOWN;
 
@@ -218,6 +219,9 @@
 
     final TransitionController.Logger mLogger = new TransitionController.Logger();
 
+    /** Whether this transition was forced to play early (eg for a SLEEP signal). */
+    private boolean mForcePlaying = false;
+
     /**
      * {@code false} if this transition runs purely in WMCore (meaning Shell is completely unaware
      * of it). Currently, this happens before the display is ready since nothing can be seen yet.
@@ -365,7 +369,6 @@
         return mState;
     }
 
-    @VisibleForTesting
     int getSyncId() {
         return mSyncId;
     }
@@ -389,6 +392,10 @@
         return mState == STATE_COLLECTING || mState == STATE_STARTED;
     }
 
+    boolean isAborted() {
+        return mState == STATE_ABORT;
+    }
+
     boolean isStarted() {
         return mState == STATE_STARTED;
     }
@@ -401,18 +408,14 @@
         return mState == STATE_FINISHED;
     }
 
-    @VisibleForTesting
-    void startCollecting(long timeoutMs) {
-        startCollecting(timeoutMs, TransitionController.SYNC_METHOD);
-    }
-
     /** Starts collecting phase. Once this starts, all relevant surface operations are sync. */
-    void startCollecting(long timeoutMs, int method) {
+    void startCollecting(long timeoutMs) {
         if (mState != STATE_PENDING) {
             throw new IllegalStateException("Attempting to re-use a transition");
         }
         mState = STATE_COLLECTING;
-        mSyncId = mSyncEngine.startSyncSet(this, timeoutMs, TAG, method);
+        mSyncId = mSyncEngine.startSyncSet(this, timeoutMs, TAG);
+        mSyncEngine.setSyncMethod(mSyncId, TransitionController.SYNC_METHOD);
 
         mLogger.mSyncId = mSyncId;
         mLogger.mCollectTimeNs = SystemClock.elapsedRealtimeNanos();
@@ -672,7 +675,7 @@
      * needs to be passed/applied in shell because until finish is called, shell owns the surfaces.
      * Additionally, this gives shell the ability to better deal with merged transitions.
      */
-    private void buildFinishTransaction(SurfaceControl.Transaction t, SurfaceControl rootLeash) {
+    private void buildFinishTransaction(SurfaceControl.Transaction t, TransitionInfo info) {
         final Point tmpPos = new Point();
         // usually only size 1
         final ArraySet<DisplayContent> displays = new ArraySet<>();
@@ -725,8 +728,8 @@
         } finally {
             mController.mBuildingFinishLayers = false;
         }
-        if (rootLeash.isValid()) {
-            t.reparent(rootLeash, null);
+        for (int i = 0; i < info.getRootCount(); ++i) {
+            t.reparent(info.getRoot(i).getLeash(), null);
         }
     }
 
@@ -813,7 +816,7 @@
         }
 
         boolean hasParticipatedDisplay = false;
-        boolean reportTaskStackChanged = false;
+        boolean hasVisibleTransientLaunch = false;
         // Commit all going-invisible containers
         for (int i = 0; i < mParticipants.size(); ++i) {
             final WindowContainer<?> participant = mParticipants.valueAt(i);
@@ -856,7 +859,7 @@
                         && ar.isVisible()) {
                     // Transient launch was committed, so report enteringAnimation
                     ar.mEnteringAnimation = true;
-                    reportTaskStackChanged = true;
+                    hasVisibleTransientLaunch = true;
 
                     // Since transient launches don't automatically take focus, make sure we
                     // synchronize focus since we committed to the launch.
@@ -900,8 +903,14 @@
             }
         }
 
-        if (reportTaskStackChanged) {
+        if (hasVisibleTransientLaunch) {
+            // Notify the change about the transient-below task that becomes invisible.
             mController.mAtm.getTaskChangeNotificationController().notifyTaskStackChanged();
+            // Prevent spurious background app switches.
+            mController.mAtm.stopAppSwitches();
+            // The end of transient launch may not reorder task, so make sure to compute the latest
+            // task rank according to the current visibility.
+            mController.mAtm.mRootWindowContainer.rankTaskLayers();
         }
 
         // dispatch legacy callback in a different loop. This is because multiple legacy handlers
@@ -983,11 +992,19 @@
         cleanUpInternal();
         mController.updateAnimatingState(mTmpTransaction);
         mTmpTransaction.apply();
+
+        // Handle back animation if it's already started.
+        mController.mAtm.mBackNavigationController.handleDeferredBackAnimation(mTargets);
     }
 
     void abort() {
         // This calls back into itself via controller.abort, so just early return here.
         if (mState == STATE_ABORT) return;
+        if (mState == STATE_PENDING) {
+            // hasn't started collecting, so can jump directly to aborted state.
+            mState = STATE_ABORT;
+            return;
+        }
         if (mState != STATE_COLLECTING && mState != STATE_STARTED) {
             throw new IllegalStateException("Too late to abort. state=" + mState);
         }
@@ -998,6 +1015,27 @@
         mController.dispatchLegacyAppTransitionCancelled();
     }
 
+    /** Immediately moves this to playing even if it isn't started yet. */
+    void playNow() {
+        if (!(mState == STATE_COLLECTING || mState == STATE_STARTED)) {
+            return;
+        }
+        ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Force Playing Transition: %d",
+                mSyncId);
+        mForcePlaying = true;
+        setAllReady();
+        if (mState == STATE_COLLECTING) {
+            start();
+        }
+        // Don't wait for actual surface-placement. We don't want anything else collected in this
+        // transition.
+        mSyncEngine.onSurfacePlacement();
+    }
+
+    boolean isForcePlaying() {
+        return mForcePlaying;
+    }
+
     void setRemoteTransition(RemoteTransition remoteTransition) {
         mRemoteTransition = remoteTransition;
     }
@@ -1028,13 +1066,6 @@
             Slog.e(TAG, "Unexpected Sync ID " + syncId + ". Expected " + mSyncId);
             return;
         }
-        if (mTargetDisplays.isEmpty()) {
-            mTargetDisplays.add(mController.mAtm.mRootWindowContainer.getDefaultDisplay());
-        }
-        // While there can be multiple DC's involved. For now, we just use the first one as
-        // the "primary" one for most things. Eventually, this will need to change, but, for the
-        // time being, we don't have full cross-display transitions so it isn't a problem.
-        final DisplayContent dc = mTargetDisplays.get(0);
 
         // Commit the visibility of visible activities before calculateTransitionInfo(), so the
         // TaskInfo can be visible. Also it needs to be done before moveToPlaying(), otherwise
@@ -1044,6 +1075,9 @@
 
         if (mState == STATE_ABORT) {
             mController.abort(this);
+            // Fall-back to the default display if there isn't one participating.
+            final DisplayContent dc = !mTargetDisplays.isEmpty() ? mTargetDisplays.get(0)
+                    : mController.mAtm.mRootWindowContainer.getDefaultDisplay();
             dc.getPendingTransaction().merge(transaction);
             mSyncId = -1;
             mOverrideOptions = null;
@@ -1056,16 +1090,24 @@
         mFinishTransaction = mController.mAtm.mWindowManager.mTransactionFactory.get();
         mController.moveToPlaying(this);
 
-        if (dc.isKeyguardLocked()) {
-            mFlags |= TRANSIT_FLAG_KEYGUARD_LOCKED;
-        }
-
         // Check whether the participants were animated from back navigation.
         final boolean markBackAnimated = mController.mAtm.mBackNavigationController
                 .containsBackAnimationTargets(this);
-        // Resolve the animating targets from the participants
+        // Resolve the animating targets from the participants.
         mTargets = calculateTargets(mParticipants, mChanges);
         final TransitionInfo info = calculateTransitionInfo(mType, mFlags, mTargets, transaction);
+
+        // Repopulate the displays based on the resolved targets.
+        mTargetDisplays.clear();
+        for (int i = 0; i < info.getRootCount(); ++i) {
+            final DisplayContent dc = mController.mAtm.mRootWindowContainer.getDisplayContent(
+                    info.getRoot(i).getDisplayId());
+            mTargetDisplays.add(dc);
+            if (dc.isKeyguardLocked()) {
+                mFlags |= TRANSIT_FLAG_KEYGUARD_LOCKED;
+            }
+        }
+
         if (markBackAnimated) {
             mController.mAtm.mBackNavigationController.clearBackAnimations(mStartTransaction);
         }
@@ -1087,9 +1129,12 @@
         }
 
         // TODO(b/188669821): Move to animation impl in shell.
-        handleLegacyRecentsStartBehavior(dc, info);
+        for (int i = 0; i < mTargetDisplays.size(); ++i) {
+            handleLegacyRecentsStartBehavior(mTargetDisplays.get(i), info);
+            if (mRecentsDisplayId != INVALID_DISPLAY) break;
+        }
 
-        handleNonAppWindowsInTransition(dc, mType, mFlags);
+        handleNonAppWindowsInTransition(mType, mFlags);
 
         // The callback is only populated for custom activity-level client animations
         sendRemoteCallback(mClientAnimationStartCallback);
@@ -1153,11 +1198,14 @@
 
         // This is non-null only if display has changes. It handles the visible windows that don't
         // need to be participated in the transition.
-        final AsyncRotationController controller = dc.getAsyncRotationController();
-        if (controller != null && containsChangeFor(dc, mTargets)) {
-            controller.setupStartTransaction(transaction);
+        for (int i = 0; i < mTargetDisplays.size(); ++i) {
+            final DisplayContent dc = mTargetDisplays.get(i);
+            final AsyncRotationController controller = dc.getAsyncRotationController();
+            if (controller != null && containsChangeFor(dc, mTargets)) {
+                controller.setupStartTransaction(transaction);
+            }
         }
-        buildFinishTransaction(mFinishTransaction, info.getRootLeash());
+        buildFinishTransaction(mFinishTransaction, info);
         if (mController.getTransitionPlayer() != null && mIsPlayerEnabled) {
             mController.dispatchLegacyAppTransitionStarting(info, mStatusBarTransitionDelay);
             try {
@@ -1178,10 +1226,13 @@
                 // client, we should finish and apply it here so the transactions aren't lost.
                 postCleanupOnFailure();
             }
-            final AccessibilityController accessibilityController =
-                    dc.mWmService.mAccessibilityController;
-            if (accessibilityController.hasCallbacks()) {
-                accessibilityController.onWMTransition(dc.getDisplayId(), mType);
+            for (int i = 0; i < mTargetDisplays.size(); ++i) {
+                final DisplayContent dc = mTargetDisplays.get(i);
+                final AccessibilityController accessibilityController =
+                        dc.mWmService.mAccessibilityController;
+                if (accessibilityController.hasCallbacks()) {
+                    accessibilityController.onWMTransition(dc.getDisplayId(), mType);
+                }
             }
         } else {
             // No player registered or it's not enabled, so just finish/apply immediately
@@ -1258,16 +1309,15 @@
         if ((mFlags & TRANSIT_FLAG_IS_RECENTS) == 0) {
             return;
         }
-        mRecentsDisplayId = dc.mDisplayId;
 
         // Recents has an input-consumer to grab input from the "live tile" app. Set that up here
         final InputConsumerImpl recentsAnimationInputConsumer =
                 dc.getInputMonitor().getInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION);
+        ActivityRecord recentsActivity = null;
         if (recentsAnimationInputConsumer != null) {
             // find the top-most going-away activity and the recents activity. The top-most
             // is used as layer reference while the recents is used for registering the consumer
             // override.
-            ActivityRecord recentsActivity = null;
             ActivityRecord topActivity = null;
             for (int i = 0; i < info.getChanges().size(); ++i) {
                 final TransitionInfo.Change change = info.getChanges().get(i);
@@ -1291,6 +1341,12 @@
             }
         }
 
+        if (recentsActivity == null) {
+            // No recents activity on `dc`, its probably on a different display.
+            return;
+        }
+        mRecentsDisplayId = dc.mDisplayId;
+
         // The rest of this function handles nav-bar reparenting
 
         if (!dc.getDisplayPolicy().shouldAttachNavBarToAppDuringTransition()
@@ -1385,7 +1441,7 @@
         }
     }
 
-    private void handleNonAppWindowsInTransition(@NonNull DisplayContent dc,
+    private void handleNonAppWindowsInTransition(
             @TransitionType int transit, @TransitionFlags int flags) {
         if ((flags & TRANSIT_FLAG_KEYGUARD_LOCKED) != 0) {
             // If the occlusion changed but the transition isn't an occlude/unocclude transition,
@@ -1763,6 +1819,41 @@
         return wc instanceof DisplayContent;
     }
 
+    private static int getDisplayId(@NonNull WindowContainer wc) {
+        return wc.getDisplayContent() != null
+                ? wc.getDisplayContent().getDisplayId() : INVALID_DISPLAY;
+    }
+
+    @VisibleForTesting
+    static void calculateTransitionRoots(@NonNull TransitionInfo outInfo,
+            ArrayList<ChangeInfo> sortedTargets,
+            @NonNull SurfaceControl.Transaction startT) {
+        // There needs to be a root on each display.
+        for (int i = 0; i < sortedTargets.size(); ++i) {
+            final WindowContainer<?> wc = sortedTargets.get(i).mContainer;
+            // Don't include wallpapers since they are in a different DA.
+            if (isWallpaper(wc)) continue;
+            final int endDisplayId = getDisplayId(wc);
+            if (endDisplayId < 0) continue;
+
+            // Check if Root was already created for this display with a higher-Z window
+            if (outInfo.findRootIndex(endDisplayId) >= 0) continue;
+
+            WindowContainer<?> ancestor = findCommonAncestor(sortedTargets, wc);
+
+            // Make leash based on highest (z-order) direct child of ancestor with a participant.
+            WindowContainer leashReference = wc;
+            while (leashReference.getParent() != ancestor) {
+                leashReference = leashReference.getParent();
+            }
+            final SurfaceControl rootLeash = leashReference.makeAnimationLeash().setName(
+                    "Transition Root: " + leashReference.getName()).build();
+            startT.setLayer(rootLeash, leashReference.getLastLayer());
+            outInfo.addRootLeash(endDisplayId, rootLeash,
+                    ancestor.getBounds().left, ancestor.getBounds().top);
+        }
+    }
+
     /**
      * Construct a TransitionInfo object from a set of targets and changes. Also populates the
      * root surface.
@@ -1773,37 +1864,13 @@
     @NonNull
     static TransitionInfo calculateTransitionInfo(@TransitionType int type, int flags,
             ArrayList<ChangeInfo> sortedTargets,
-            @Nullable SurfaceControl.Transaction startT) {
+            @NonNull SurfaceControl.Transaction startT) {
         final TransitionInfo out = new TransitionInfo(type, flags);
-
-        WindowContainer<?> topApp = null;
-        for (int i = 0; i < sortedTargets.size(); i++) {
-            final WindowContainer<?> wc = sortedTargets.get(i).mContainer;
-            if (!isWallpaper(wc)) {
-                topApp = wc;
-                break;
-            }
-        }
-        if (topApp == null) {
-            out.setRootLeash(new SurfaceControl(), 0, 0);
+        calculateTransitionRoots(out, sortedTargets, startT);
+        if (out.getRootCount() == 0) {
             return out;
         }
 
-        WindowContainer<?> ancestor = findCommonAncestor(sortedTargets, topApp);
-
-        // Make leash based on highest (z-order) direct child of ancestor with a participant.
-        // TODO(b/261418859): Handle the case when the target contains window containers which
-        // belong to a different display. As a workaround we use topApp, from which wallpaper
-        // window container is removed, instead of sortedTargets here.
-        WindowContainer leashReference = topApp;
-        while (leashReference.getParent() != ancestor) {
-            leashReference = leashReference.getParent();
-        }
-        final SurfaceControl rootLeash = leashReference.makeAnimationLeash().setName(
-                "Transition Root: " + leashReference.getName()).build();
-        startT.setLayer(rootLeash, leashReference.getLastLayer());
-        out.setRootLeash(rootLeash, ancestor.getBounds().left, ancestor.getBounds().top);
-
         // Convert all the resolved ChangeInfos into TransactionInfo.Change objects in order.
         final int count = sortedTargets.size();
         for (int i = 0; i < count; ++i) {
@@ -1823,6 +1890,7 @@
             change.setMode(info.getTransitMode(target));
             change.setStartAbsBounds(info.mAbsoluteBounds);
             change.setFlags(info.getChangeFlags(target));
+            change.setDisplayId(info.mDisplayId, getDisplayId(target));
 
             final Task task = target.asTask();
             final TaskFragment taskFragment = target.asTaskFragment();
@@ -1909,6 +1977,15 @@
         }
 
         TransitionInfo.AnimationOptions animOptions = null;
+
+        // Check if the top-most app is an activity (ie. activity->activity). If so, make sure to
+        // honor its custom transition options.
+        WindowContainer<?> topApp = null;
+        for (int i = 0; i < sortedTargets.size(); i++) {
+            if (isWallpaper(sortedTargets.get(i).mContainer)) continue;
+            topApp = sortedTargets.get(i).mContainer;
+            break;
+        }
         if (topApp.asActivityRecord() != null) {
             final ActivityRecord topActivity = topApp.asActivityRecord();
             animOptions = addCustomActivityTransition(topActivity, true/* open */, null);
@@ -1959,14 +2036,15 @@
     private static WindowContainer<?> findCommonAncestor(
             @NonNull ArrayList<ChangeInfo> targets,
             @NonNull WindowContainer<?> topApp) {
+        final int displayId = getDisplayId(topApp);
         WindowContainer<?> ancestor = topApp.getParent();
         // Go up ancestor parent chain until all targets are descendants. Ancestor should never be
         // null because all targets are attached.
         for (int i = targets.size() - 1; i >= 0; i--) {
             final ChangeInfo change = targets.get(i);
             final WindowContainer wc = change.mContainer;
-            if (isWallpaper(wc)) {
-                // Skip the non-app window.
+            if (isWallpaper(wc) || getDisplayId(wc) != displayId) {
+                // Skip the non-app window or windows on a different display
                 continue;
             }
             while (!wc.isDescendantOf(ancestor)) {
@@ -2142,6 +2220,7 @@
         final Rect mAbsoluteBounds = new Rect();
         boolean mShowWallpaper;
         int mRotation = ROTATION_UNDEFINED;
+        int mDisplayId = -1;
         @ActivityInfo.Config int mKnownConfigChanges;
 
         /** These are just extra info. They aren't used for change-detection. */
@@ -2159,6 +2238,7 @@
             mShowWallpaper = origState.showWallpaper();
             mRotation = origState.getWindowConfiguration().getRotation();
             mStartParent = origState.getParent();
+            mDisplayId = getDisplayId(origState);
         }
 
         @VisibleForTesting
@@ -2190,7 +2270,8 @@
                     // assume no change in windowing-mode.
                     || (mWindowingMode != 0 && mContainer.getWindowingMode() != mWindowingMode)
                     || !mContainer.getBounds().equals(mAbsoluteBounds)
-                    || mRotation != mContainer.getWindowConfiguration().getRotation();
+                    || mRotation != mContainer.getWindowConfiguration().getRotation()
+                    || mDisplayId != getDisplayId(mContainer);
         }
 
         @TransitionInfo.TransitionMode
@@ -2230,6 +2311,10 @@
                             .isMonitorTransitionTarget(topActivity)) {
                         flags |= TransitionInfo.FLAG_BACK_GESTURE_ANIMATED;
                     }
+                    if (topActivity != null && topActivity.mLaunchTaskBehind) {
+                        Slog.e(TAG, "Unexpected launch-task-behind operation in shell transition");
+                        flags |= FLAG_TASK_LAUNCHING_BEHIND;
+                    }
                 } else {
                     if (task.mAtmService.mBackNavigationController
                             .isMonitorTransitionTarget(task)) {
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index 79eb634..bacc6e6 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -51,7 +51,6 @@
 import android.window.WindowContainerTransaction;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.protolog.ProtoLogGroup;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.server.FgThread;
@@ -200,20 +199,20 @@
 
     /** Starts Collecting */
     void moveToCollecting(@NonNull Transition transition) {
-        moveToCollecting(transition, SYNC_METHOD);
-    }
-
-    /** Starts Collecting */
-    @VisibleForTesting
-    void moveToCollecting(@NonNull Transition transition, int method) {
         if (mCollectingTransition != null) {
             throw new IllegalStateException("Simultaneous transition collection not supported.");
         }
+        if (mTransitionPlayer == null) {
+            // If sysui has been killed (by a test) or crashed, we can temporarily have no player
+            // In this case, abort the transition.
+            transition.abort();
+            return;
+        }
         mCollectingTransition = transition;
         // Distinguish change type because the response time is usually expected to be not too long.
         final long timeoutMs =
                 transition.mType == TRANSIT_CHANGE ? CHANGE_TIMEOUT_MS : DEFAULT_TIMEOUT_MS;
-        mCollectingTransition.startCollecting(timeoutMs, method);
+        mCollectingTransition.startCollecting(timeoutMs);
         ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Start collecting in Transition: %s",
                 mCollectingTransition);
         dispatchLegacyAppTransitionPending();
@@ -486,6 +485,15 @@
         } else {
             newTransition = requestStartTransition(createTransition(type, flags),
                     trigger != null ? trigger.asTask() : null, remoteTransition, displayChange);
+            if (newTransition != null && displayChange != null && (displayChange.getStartRotation()
+                    + displayChange.getEndRotation()) % 2 == 0) {
+                // 180 degrees rotation change may not change screen size. So the clients may draw
+                // some frames before and after the display projection transaction is applied by the
+                // remote player. That may cause some buffers to show in different rotation. So use
+                // sync method to pause clients drawing until the projection transaction is applied.
+                mAtm.mWindowManager.mSyncEngine.setSyncMethod(newTransition.getSyncId(),
+                        BLASTSyncEngine.METHOD_BLAST);
+            }
         }
         if (trigger != null) {
             if (isExistenceType(type)) {
@@ -511,6 +519,14 @@
                     transition.getToken(), null));
             return transition;
         }
+        if (mTransitionPlayer == null || transition.isAborted()) {
+            // Apparently, some tests will kill(and restart) systemui, so there is a chance that
+            // the player might be transiently null.
+            if (transition.isCollecting()) {
+                transition.abort();
+            }
+            return transition;
+        }
         try {
             ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
                     "Requesting StartTransition: %s", transition);
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 16541c1..2b848d5 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -37,6 +37,7 @@
 import static com.android.server.wm.WindowManagerService.H.WALLPAPER_DRAW_PENDING_TIMEOUT;
 
 import android.annotation.Nullable;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -55,6 +56,7 @@
 import android.view.animation.Animation;
 import android.window.ScreenCapture;
 
+import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.protolog.ProtoLogImpl;
 import com.android.internal.protolog.common.ProtoLog;
@@ -72,7 +74,7 @@
 class WallpaperController {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "WallpaperController" : TAG_WM;
     private WindowManagerService mService;
-    private final DisplayContent mDisplayContent;
+    private DisplayContent mDisplayContent;
 
     private final ArrayList<WallpaperWindowToken> mWallpaperTokens = new ArrayList<>();
 
@@ -120,9 +122,19 @@
 
     private boolean mShouldOffsetWallpaperCenter;
 
+    final boolean mEnableSeparateLockScreenEngine;
+
     private final ToBooleanFunction<WindowState> mFindWallpaperTargetFunction = w -> {
         if ((w.mAttrs.type == TYPE_WALLPAPER)) {
             if (mFindResults.topWallpaper == null || mFindResults.resetTopWallpaper) {
+                WallpaperWindowToken token = w.mToken.asWallpaperToken();
+                if (token == null) {
+                    Slog.w(TAG, "Window " + w + " has wallpaper type but not wallpaper token");
+                    return false;
+                }
+                if (!token.canShowWhenLocked() && mDisplayContent.isKeyguardLocked()) {
+                    return false;
+                }
                 mFindResults.setTopWallpaper(w);
                 mFindResults.resetTopWallpaper = false;
             }
@@ -249,11 +261,14 @@
     WallpaperController(WindowManagerService service, DisplayContent displayContent) {
         mService = service;
         mDisplayContent = displayContent;
-        mMaxWallpaperScale = service.mContext.getResources()
-                .getFloat(com.android.internal.R.dimen.config_wallpaperMaxScale);
-        mShouldOffsetWallpaperCenter = service.mContext.getResources()
-                .getBoolean(
+        Resources resources = service.mContext.getResources();
+        mMaxWallpaperScale =
+                resources.getFloat(com.android.internal.R.dimen.config_wallpaperMaxScale);
+        mShouldOffsetWallpaperCenter =
+                resources.getBoolean(
                         com.android.internal.R.bool.config_offsetWallpaperToCenterOfLargestDisplay);
+        mEnableSeparateLockScreenEngine =
+                resources.getBoolean(R.bool.config_independentLockscreenLiveWallpaper);
     }
 
     void resetLargestDisplay(Display display) {
@@ -753,10 +768,10 @@
         result.setWallpaperTarget(wallpaperTarget);
     }
 
-    private void updateWallpaperTokens(boolean visible) {
+    private void updateWallpaperTokens(boolean visibility, boolean locked) {
         for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
             final WallpaperWindowToken token = mWallpaperTokens.get(curTokenNdx);
-            token.updateWallpaperWindows(visible);
+            token.updateWallpaperWindows(visibility && (!locked || token.canShowWhenLocked()));
         }
     }
 
@@ -794,7 +809,13 @@
             }
         }
 
-        updateWallpaperTokens(visible);
+        // Keep both wallpapers visible unless the keyguard is locked (then hide private wp)
+        updateWallpaperTokens(visible, mDisplayContent.isKeyguardLocked());
+
+        if (DEBUG_WALLPAPER) {
+            Slog.v(TAG, "adjustWallpaperWindows: wallpaper visibility " + visible
+                    + ", lock visibility " + mDisplayContent.isKeyguardLocked());
+        }
 
         if (visible && mLastFrozen != mFindResults.isWallpaperTargetForLetterbox) {
             mLastFrozen = mFindResults.isWallpaperTargetForLetterbox;
@@ -896,7 +917,6 @@
         mWallpaperTokens.remove(token);
     }
 
-
     @VisibleForTesting
     boolean canScreenshotWallpaper() {
         return canScreenshotWallpaper(getTopVisibleWallpaper());
diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
index 8708f73..17ab551 100644
--- a/services/core/java/com/android/server/wm/WallpaperWindowToken.java
+++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
@@ -76,14 +76,18 @@
             return;
         }
         mShowWhenLocked = showWhenLocked;
+        if (mDisplayContent.mWallpaperController.mEnableSeparateLockScreenEngine) {
+            // Move the window token to the front (private) or back (showWhenLocked). This is
+            // possible
+            // because the DisplayArea underneath TaskDisplayArea only contains TYPE_WALLPAPER
+            // windows.
+            final int position = showWhenLocked ? POSITION_BOTTOM : POSITION_TOP;
 
-        // Move the window token to the front (private) or back (showWhenLocked). This is possible
-        // because the DisplayArea underneath TaskDisplayArea only contains TYPE_WALLPAPER windows.
-        final int position = showWhenLocked ? POSITION_BOTTOM : POSITION_TOP;
-
-        // Note: Moving all the way to the front or back breaks ordering based on addition times.
-        // We should never have more than one non-animating token of each type.
-        getParent().positionChildAt(position, this /* child */, false  /*includingParents */);
+            // Note: Moving all the way to the front or back breaks ordering based on addition
+            // times.
+            // We should never have more than one non-animating token of each type.
+            getParent().positionChildAt(position, this /* child */, false /*includingParents */);
+        }
     }
 
     boolean canShowWhenLocked() {
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index da7400c..d42a629 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -1473,7 +1473,7 @@
      *         {@link Configuration#ORIENTATION_PORTRAIT},
      *         {@link Configuration#ORIENTATION_UNDEFINED}).
      */
-    @ScreenOrientation
+    @Configuration.Orientation
     int getRequestedConfigurationOrientation() {
         return getRequestedConfigurationOrientation(false /* forDisplay */);
     }
@@ -1491,9 +1491,28 @@
      *         {@link Configuration#ORIENTATION_PORTRAIT},
      *         {@link Configuration#ORIENTATION_UNDEFINED}).
      */
-    @ScreenOrientation
+    @Configuration.Orientation
     int getRequestedConfigurationOrientation(boolean forDisplay) {
-        int requestedOrientation = getOverrideOrientation();
+        return getRequestedConfigurationOrientation(forDisplay, getOverrideOrientation());
+    }
+
+    /**
+     * Gets the configuration orientation by the requested screen orientation
+     *
+     * @param forDisplay whether it is the requested config orientation for display.
+     *                   If {@code true}, we may reverse the requested orientation if the root is
+     *                   different from the display, so that when the display rotates to the
+     *                   reversed orientation, the requested app will be in the requested
+     *                   orientation.
+     * @param requestedOrientation the screen orientation({@link ScreenOrientation}) that is
+     *                   requested
+     * @return orientation in ({@link Configuration#ORIENTATION_LANDSCAPE},
+     *         {@link Configuration#ORIENTATION_PORTRAIT},
+     *         {@link Configuration#ORIENTATION_UNDEFINED}).
+     */
+    @Configuration.Orientation
+    int getRequestedConfigurationOrientation(boolean forDisplay,
+            @ScreenOrientation int requestedOrientation) {
         final RootDisplayArea root = getRootDisplayArea();
         if (forDisplay && root != null && root.isOrientationDifferentFromDisplay()) {
             // Reverse the requested orientation if the orientation of its root is different from
@@ -1503,7 +1522,7 @@
             // (portrait).
             // When an app below the DAG is requesting landscape, it should actually request the
             // display to be portrait, so that the DAG and the app will be in landscape.
-            requestedOrientation = reverseOrientation(getOverrideOrientation());
+            requestedOrientation = reverseOrientation(requestedOrientation);
         }
 
         if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 98563f6..42d23e7 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -186,7 +186,6 @@
 import android.graphics.Bitmap;
 import android.graphics.Matrix;
 import android.graphics.Point;
-import android.graphics.PointF;
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.hardware.configstore.V1_0.OptionalBool;
@@ -2267,19 +2266,18 @@
                     if (win.mAttrs.providedInsets == null || attrs.providedInsets == null
                             || (win.mAttrs.providedInsets.length != attrs.providedInsets.length)) {
                         throw new IllegalArgumentException(
-                                "Insets types can not be changed after the window is added.");
+                                "Insets amount can not be changed after the window is added.");
                     } else {
                         final int insetsTypes = attrs.providedInsets.length;
                         for (int i = 0; i < insetsTypes; i++) {
-                            if (win.mAttrs.providedInsets[i].type != attrs.providedInsets[i].type) {
+                            if (!win.mAttrs.providedInsets[i].idEquals(attrs.providedInsets[i])) {
                                 throw new IllegalArgumentException(
-                                        "Insets types can not be changed after the window is "
-                                                + "added.");
+                                        "Insets ID can not be changed after the window is added.");
                             }
                             final InsetsFrameProvider.InsetsSizeOverride[] overrides =
-                                    win.mAttrs.providedInsets[i].insetsSizeOverrides;
+                                    win.mAttrs.providedInsets[i].getInsetsSizeOverrides();
                             final InsetsFrameProvider.InsetsSizeOverride[] newOverrides =
-                                    attrs.providedInsets[i].insetsSizeOverrides;
+                                    attrs.providedInsets[i].getInsetsSizeOverrides();
                             if (!(overrides == null && newOverrides == null)) {
                                 if (overrides == null || newOverrides == null
                                         || (overrides.length != newOverrides.length)) {
@@ -2289,7 +2287,8 @@
                                 } else {
                                     final int overrideTypes = overrides.length;
                                     for (int j = 0; j < overrideTypes; j++) {
-                                        if (overrides[j].windowType != newOverrides[j].windowType) {
+                                        if (overrides[j].getWindowType()
+                                                != newOverrides[j].getWindowType()) {
                                             throw new IllegalArgumentException(
                                                     "Insets override types can not be changed after"
                                                             + " the window is added.");
@@ -7361,14 +7360,6 @@
                     .setPointerIconType(PointerIcon.TYPE_DEFAULT);
         }
     }
-
-    PointF getLatestMousePosition() {
-        synchronized (mMousePositionTracker) {
-            return new PointF(mMousePositionTracker.mLatestMouseX,
-                    mMousePositionTracker.mLatestMouseY);
-        }
-    }
-
     void setMousePointerDisplayId(int displayId) {
         mMousePositionTracker.setPointerDisplayId(displayId);
     }
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index cfb3c6c..8c2dd2d 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -42,6 +42,7 @@
 import android.util.DisplayMetrics;
 import android.util.Pair;
 import android.view.Display;
+import android.view.IWindow;
 import android.view.IWindowManager;
 import android.view.ViewDebug;
 
@@ -569,6 +570,22 @@
         return 0;
     }
 
+    private void dumpLocalWindowAsync(IWindow client, ParcelFileDescriptor pfd) {
+        // Make it asynchronous to avoid writer from being blocked
+        // by waiting for the buffer to be consumed in the same process.
+        IoThread.getExecutor().execute(() -> {
+            synchronized (mInternal.mGlobalLock) {
+                try {
+                    client.executeCommand(ViewDebug.REMOTE_COMMAND_DUMP_ENCODED, null, pfd);
+                } catch (Exception e) {
+                    // Ignore RemoteException for local call. Just print trace for other
+                    // exceptions caused by RC with tolerable low possibility.
+                    e.printStackTrace();
+                }
+            }
+        });
+    }
+
     private int runDumpVisibleWindowViews(PrintWriter pw) {
         if (!mInternal.checkCallingPermission(android.Manifest.permission.DUMP,
                 "runDumpVisibleWindowViews()")) {
@@ -591,16 +608,7 @@
                             pipe = new ByteTransferPipe();
                             final ParcelFileDescriptor pfd = pipe.getWriteFd();
                             if (w.isClientLocal()) {
-                                // Make it asynchronous to avoid writer from being blocked
-                                // by waiting for the buffer to be consumed in the same process.
-                                IoThread.getExecutor().execute(() -> {
-                                    try {
-                                        w.mClient.executeCommand(
-                                                ViewDebug.REMOTE_COMMAND_DUMP_ENCODED, null, pfd);
-                                    } catch (RemoteException e) {
-                                        // Ignore for local call.
-                                    }
-                                });
+                                dumpLocalWindowAsync(w.mClient, pfd);
                             } else {
                                 w.mClient.executeCommand(
                                         ViewDebug.REMOTE_COMMAND_DUMP_ENCODED, null, pfd);
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 8e22821..c3c87af 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -74,7 +74,9 @@
 import android.graphics.Rect;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.Parcel;
 import android.os.RemoteException;
 import android.util.AndroidRuntimeException;
@@ -315,7 +317,7 @@
                     }
                     transition = mTransitionController.createTransition(type);
                 }
-                if (!transition.isCollecting()) {
+                if (!transition.isCollecting() && !transition.isForcePlaying()) {
                     Slog.e(TAG, "Trying to start a transition that isn't collecting. This probably"
                             + " means Shell took too long to respond to a request. WM State may be"
                             + " incorrect now, please file a bug");
@@ -998,11 +1000,14 @@
                     activityOptions.setCallerDisplayId(DEFAULT_DISPLAY);
                 }
                 final Bundle options = activityOptions != null ? activityOptions.toBundle() : null;
-                waitAsyncStart(() -> mService.mAmInternal.sendIntentSender(
+                int res = waitAsyncStart(() -> mService.mAmInternal.sendIntentSender(
                         hop.getPendingIntent().getTarget(),
                         hop.getPendingIntent().getWhitelistToken(), 0 /* code */,
                         hop.getActivityIntent(), resolvedType, null /* finishReceiver */,
                         null /* requiredPermission */, options));
+                if (ActivityManager.isStartResultSuccessful(res)) {
+                    effects |= TRANSACT_EFFECTS_LIFECYCLE;
+                }
                 break;
             }
             case HIERARCHY_OP_TYPE_START_SHORTCUT: {
@@ -1353,9 +1358,16 @@
      * Post and wait for the result of the activity start to prevent potential deadlock against
      * {@link WindowManagerGlobalLock}.
      */
-    private void waitAsyncStart(IntSupplier startActivity) {
+    private int waitAsyncStart(IntSupplier startActivity) {
         final Integer[] starterResult = {null};
-        mService.mH.post(() -> {
+        final Handler handler = (Looper.myLooper() == mService.mH.getLooper())
+                // uncommon case where a queued transaction is trying to start an activity. We can't
+                // post to our own thread and wait (otherwise we deadlock), so use anim thread
+                // instead (which is 1 higher priority).
+                ? mService.mWindowManager.mAnimationHandler
+                // Otherwise just put it on main handler
+                : mService.mH;
+        handler.post(() -> {
             try {
                 starterResult[0] = startActivity.getAsInt();
             } catch (Throwable t) {
@@ -1372,6 +1384,7 @@
             } catch (InterruptedException ignored) {
             }
         }
+        return starterResult[0];
     }
 
     private int sanitizeAndApplyHierarchyOp(WindowContainer container,
@@ -1635,7 +1648,7 @@
     private BLASTSyncEngine.SyncGroup prepareSyncWithOrganizer(
             IWindowContainerTransactionCallback callback) {
         final BLASTSyncEngine.SyncGroup s = mService.mWindowManager.mSyncEngine
-                .prepareSyncSet(this, "", BLASTSyncEngine.METHOD_BLAST);
+                .prepareSyncSet(this, "Organizer");
         mTransactionCallbacksByPendingSyncId.put(s.mSyncId, callback);
         return s;
     }
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 7c0318d..834b708 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -210,7 +210,7 @@
     /** Whether {@link #mLastReportedConfiguration} is deferred by the cached state. */
     private volatile boolean mHasCachedConfiguration;
 
-    private int mTopActivityDeviceId = Context.DEVICE_ID_DEFAULT;
+    private int mLastTopActivityDeviceId = Context.DEVICE_ID_DEFAULT;
     /**
      * Registered {@link DisplayArea} as a listener to override config changes. {@code null} if not
      * registered.
@@ -1381,6 +1381,13 @@
     }
 
     /**
+     * Destroys the WindwoProcessController, after the process has been removed.
+     */
+    void destroy() {
+        unregisterConfigurationListeners();
+    }
+
+    /**
      * Check if activity configuration override for the activity process needs an update and perform
      * if needed. By default we try to override the process configuration to match the top activity
      * config to increase app compatibility with multi-window and multi-display. The process will
@@ -1411,8 +1418,9 @@
         // If deviceId for the top-activity changed, schedule passing it to the app process.
         boolean topActivityDeviceChanged = false;
         int deviceId = getTopActivityDeviceId();
-        if (deviceId != mTopActivityDeviceId) {
+        if (deviceId != mLastTopActivityDeviceId) {
             topActivityDeviceChanged = true;
+            mLastTopActivityDeviceId = deviceId;
         }
 
         final Configuration config = getConfiguration();
@@ -1431,15 +1439,12 @@
             return;
         }
 
-        // TODO(b/263402938): Add tests that capture the deviceId dispatch to the client.
-        mTopActivityDeviceId = deviceId;
-        dispatchConfiguration(config, topActivityDeviceChanged ? mTopActivityDeviceId
-                : Context.DEVICE_ID_INVALID);
+        dispatchConfiguration(config);
     }
 
     private int getTopActivityDeviceId() {
         ActivityRecord topActivity = getTopNonFinishingActivity();
-        int updatedDeviceId = mTopActivityDeviceId;
+        int updatedDeviceId = Context.DEVICE_ID_DEFAULT;
         if (topActivity != null && topActivity.mDisplayContent != null) {
             updatedDeviceId = mAtm.mTaskSupervisor.getDeviceIdForDisplayId(
                     topActivity.mDisplayContent.mDisplayId);
@@ -1484,10 +1489,6 @@
     }
 
     void dispatchConfiguration(Configuration config) {
-        dispatchConfiguration(config, getTopActivityDeviceId());
-    }
-
-    void dispatchConfiguration(Configuration config, int deviceId) {
         mHasPendingConfigurationChange = false;
         if (mThread == null) {
             if (Build.IS_DEBUGGABLE && mHasImeService) {
@@ -1514,16 +1515,10 @@
             }
         }
 
-        scheduleConfigurationChange(mThread, config, deviceId);
+        scheduleConfigurationChange(mThread, config);
     }
 
     private void scheduleConfigurationChange(IApplicationThread thread, Configuration config) {
-        // By default send invalid deviceId as no-op signal so it's not updated on the client side.
-        scheduleConfigurationChange(thread, config, Context.DEVICE_ID_INVALID);
-    }
-
-    private void scheduleConfigurationChange(IApplicationThread thread, Configuration config,
-            int deviceId) {
         ProtoLog.v(WM_DEBUG_CONFIGURATION, "Sending to proc %s new config %s", mName,
                 config);
         if (Build.IS_DEBUGGABLE && mHasImeService) {
@@ -1533,7 +1528,7 @@
         mHasCachedConfiguration = false;
         try {
             mAtm.getLifecycleManager().scheduleTransaction(thread,
-                    ConfigurationChangeItem.obtain(config, deviceId));
+                    ConfigurationChangeItem.obtain(config, mLastTopActivityDeviceId));
         } catch (Exception e) {
             Slog.e(TAG_CONFIGURATION, "Failed to schedule configuration change: " + mOwner, e);
         }
@@ -1838,6 +1833,9 @@
                     pw.print("F|");
                 }
             }
+            if ((stateFlags & ACTIVITY_STATE_FLAG_HAS_ACTIVITY_IN_VISIBLE_TASK) != 0) {
+                pw.print("VT|");
+            }
             final int taskLayer = stateFlags & ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER;
             if (taskLayer != ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER) {
                 pw.print("taskLayer=" + taskLayer);
diff --git a/services/core/java/com/android/server/wm/WindowProcessControllerMap.java b/services/core/java/com/android/server/wm/WindowProcessControllerMap.java
index 2767972..424b043 100644
--- a/services/core/java/com/android/server/wm/WindowProcessControllerMap.java
+++ b/services/core/java/com/android/server/wm/WindowProcessControllerMap.java
@@ -19,8 +19,8 @@
 import android.util.ArraySet;
 import android.util.SparseArray;
 
-import java.util.Map;
 import java.util.HashMap;
+import java.util.Map;
 
 final class WindowProcessControllerMap {
 
@@ -67,6 +67,7 @@
             mPidMap.remove(pid);
             // remove process from mUidMap
             removeProcessFromUidMap(proc);
+            proc.destroy();
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 87e87b9..d6c0311 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -221,8 +221,6 @@
 import android.view.IWindowFocusObserver;
 import android.view.IWindowId;
 import android.view.InputChannel;
-import android.view.InputEvent;
-import android.view.InputEventReceiver;
 import android.view.InputWindowHandle;
 import android.view.InsetsSource;
 import android.view.InsetsState;
@@ -572,12 +570,6 @@
     boolean mRemoveOnExit;
 
     /**
-     * Whether the app died while it was visible, if true we might need
-     * to continue to show it until it's restarted.
-     */
-    boolean mAppDied;
-
-    /**
      * Set when the orientation is changing and this window has not yet
      * been updated for the new orientation.
      */
@@ -760,7 +752,6 @@
      */
     private InsetsState mFrozenInsetsState;
 
-    private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f;
     private KeyInterceptionInfo mKeyInterceptionInfo;
 
     /**
@@ -1504,13 +1495,6 @@
                 }
             }
 
-            // If it's a dead window left on screen, and the configuration changed, there is nothing
-            // we can do about it. Remove the window now.
-            if (mActivityRecord != null && mAppDied) {
-                mActivityRecord.removeDeadWindows();
-                return;
-            }
-
             onResizeHandled();
             mWmService.makeWindowFreezingScreenIfNeededLocked(this);
 
@@ -2009,7 +1993,7 @@
     boolean isInteresting() {
         final RecentsAnimationController recentsAnimationController =
                 mWmService.getRecentsAnimationController();
-        return mActivityRecord != null && !mAppDied
+        return mActivityRecord != null
                 && (!mActivityRecord.isFreezingScreen() || !mAppFreezing)
                 && mViewVisibility == View.VISIBLE
                 && (recentsAnimationController == null
@@ -2018,16 +2002,19 @@
 
     /**
      * Like isOnScreen(), but we don't return true if the window is part
-     * of a transition that has not yet been started.
+     * of a transition but has not yet started animating.
      */
     boolean isReadyForDisplay() {
-        if (mToken.waitingToShow && getDisplayContent().mAppTransition.isTransitionSet()) {
+        if (!mHasSurface || mDestroying || !isVisibleByPolicy()) {
+            return false;
+        }
+        if (mToken.waitingToShow && getDisplayContent().mAppTransition.isTransitionSet()
+                && !isAnimating(TRANSITION | PARENTS, ANIMATION_TYPE_APP_TRANSITION)) {
             return false;
         }
         final boolean parentAndClientVisible = !isParentWindowHidden()
                 && mViewVisibility == View.VISIBLE && mToken.isVisible();
-        return mHasSurface && isVisibleByPolicy() && !mDestroying
-                && (parentAndClientVisible || isAnimating(TRANSITION | PARENTS));
+        return parentAndClientVisible || isAnimating(TRANSITION | PARENTS, ANIMATION_TYPE_ALL);
     }
 
     boolean isFullyTransparent() {
@@ -2342,9 +2329,11 @@
 
     @Override
     public void onConfigurationChanged(Configuration newParentConfig) {
-        mTempConfiguration.setTo(getConfiguration());
+        // Get from super to avoid using the updated global config from the override method.
+        final Configuration selfConfiguration = super.getConfiguration();
+        mTempConfiguration.setTo(selfConfiguration);
         super.onConfigurationChanged(newParentConfig);
-        final int diff = getConfiguration().diff(mTempConfiguration);
+        final int diff = selfConfiguration.diff(mTempConfiguration);
         if (diff != 0) {
             mLastConfigReportedToClient = false;
         }
@@ -2443,11 +2432,6 @@
 
     @Override
     void removeIfPossible() {
-        super.removeIfPossible();
-        removeIfPossible(false /*keepVisibleDeadWindow*/);
-    }
-
-    private void removeIfPossible(boolean keepVisibleDeadWindow) {
         mWindowRemovalAllowed = true;
         ProtoLog.v(WM_DEBUG_ADD_REMOVE,
                 "removeIfPossible: %s callers=%s", this, Debug.getCallers(5));
@@ -2522,21 +2506,6 @@
                 // If we are not currently running the exit animation, we need to see about starting one
                 wasVisible = isVisible();
 
-                if (keepVisibleDeadWindow) {
-                    ProtoLog.v(WM_DEBUG_ADD_REMOVE,
-                            "Not removing %s because app died while it's visible", this);
-
-                    mAppDied = true;
-                    setDisplayLayoutNeeded();
-                    mWmService.mWindowPlacerLocked.performSurfacePlacement();
-
-                    // Set up a replacement input channel since the app is now dead.
-                    // We need to catch tapping on the dead window to restart the app.
-                    openInputChannel(null);
-                    displayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);
-                    return;
-                }
-
                 // Remove immediately if there is display transition because the animation is
                 // usually unnoticeable (e.g. covered by rotation animation) and the animation
                 // bounds could be inconsistent, such as depending on when the window applies
@@ -2710,19 +2679,7 @@
                 || (isVisible() && mActivityRecord != null && mActivityRecord.isVisible());
     }
 
-    private final class DeadWindowEventReceiver extends InputEventReceiver {
-        DeadWindowEventReceiver(InputChannel inputChannel) {
-            super(inputChannel, mWmService.mH.getLooper());
-        }
-        @Override
-        public void onInputEvent(InputEvent event) {
-            finishInputEvent(event, true);
-        }
-    }
-    /** Fake event receiver for windows that died visible. */
-    private DeadWindowEventReceiver mDeadWindowEventReceiver;
-
-    void openInputChannel(InputChannel outInputChannel) {
+    void openInputChannel(@NonNull InputChannel outInputChannel) {
         if (mInputChannel != null) {
             throw new IllegalStateException("Window already has an input channel.");
         }
@@ -2731,14 +2688,7 @@
         mInputChannelToken = mInputChannel.getToken();
         mInputWindowHandle.setToken(mInputChannelToken);
         mWmService.mInputToWindowMap.put(mInputChannelToken, this);
-        if (outInputChannel != null) {
-            mInputChannel.copyTo(outInputChannel);
-        } else {
-            // If the window died visible, we setup a fake input channel, so that taps
-            // can still detected by input monitor channel, and we can relaunch the app.
-            // Create fake event receiver that simply reports all events as handled.
-            mDeadWindowEventReceiver = new DeadWindowEventReceiver(mInputChannel);
-        }
+        mInputChannel.copyTo(outInputChannel);
     }
 
     /**
@@ -2749,10 +2699,6 @@
     }
 
     void disposeInputChannel() {
-        if (mDeadWindowEventReceiver != null) {
-            mDeadWindowEventReceiver.dispose();
-            mDeadWindowEventReceiver = null;
-        }
         if (mInputChannelToken != null) {
             // Unregister server channel first otherwise it complains about broken channel.
             mWmService.mInputManager.removeInputChannel(mInputChannelToken);
@@ -3079,11 +3025,10 @@
                             .windowForClientLocked(mSession, mClient, false);
                     Slog.i(TAG, "WIN DEATH: " + win);
                     if (win != null) {
-                        final DisplayContent dc = getDisplayContent();
                         if (win.mActivityRecord != null && win.mActivityRecord.findMainWindow() == win) {
                             mWmService.mTaskSnapshotController.onAppDied(win.mActivityRecord);
                         }
-                        win.removeIfPossible(shouldKeepVisibleDeadAppWindow());
+                        win.removeIfPossible();
                     } else if (mHasSurface) {
                         Slog.e(TAG, "!!! LEAK !!! Window removed but surface still valid.");
                         WindowState.this.removeIfPossible();
@@ -3095,32 +3040,6 @@
         }
     }
 
-    /**
-     * Returns true if this window is visible and belongs to a dead app and shouldn't be removed,
-     * because we want to preserve its location on screen to be re-activated later when the user
-     * interacts with it.
-     */
-    private boolean shouldKeepVisibleDeadAppWindow() {
-        if (!isVisible() || mActivityRecord == null || !mActivityRecord.isClientVisible()) {
-            // Not a visible app window or the app isn't dead.
-            return false;
-        }
-
-        if (mAttrs.token != mClient.asBinder()) {
-            // The window was add by a client using another client's app token. We don't want to
-            // keep the dead window around for this case since this is meant for 'real' apps.
-            return false;
-        }
-
-        if (mAttrs.type == TYPE_APPLICATION_STARTING) {
-            // We don't keep starting windows since they were added by the window manager before
-            // the app even launched.
-            return false;
-        }
-
-        return getWindowConfiguration().keepVisibleDeadAppWindowOnScreen();
-    }
-
     /** Returns {@code true} if this window desires key events. */
     boolean canReceiveKeys() {
         return canReceiveKeys(false /* fromUserTouch */);
@@ -3967,7 +3886,7 @@
     @Override
     public void notifyInsetsControlChanged() {
         ProtoLog.d(WM_DEBUG_WINDOW_INSETS, "notifyInsetsControlChanged for %s ", this);
-        if (mAppDied || mRemoved) {
+        if (mRemoved) {
             return;
         }
         final InsetsStateController stateController =
@@ -4273,7 +4192,6 @@
             pw.println(prefix + "mToken=" + mToken);
             if (mActivityRecord != null) {
                 pw.println(prefix + "mActivityRecord=" + mActivityRecord);
-                pw.print(prefix + "mAppDied=" + mAppDied);
                 pw.print(prefix + "drawnStateEvaluated=" + getDrawnStateEvaluated());
                 pw.println(prefix + "mightAffectAllDrawn=" + mightAffectAllDrawn());
             }
@@ -4518,7 +4436,7 @@
 
     void requestUpdateWallpaperIfNeeded() {
         final DisplayContent dc = getDisplayContent();
-        if (dc != null && hasWallpaper()) {
+        if (dc != null && ((mIsWallpaper && !mLastConfigReportedToClient) || hasWallpaper())) {
             dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
             dc.setLayoutNeeded();
             mWmService.mWindowPlacerLocked.requestTraversal();
@@ -5402,10 +5320,7 @@
     }
 
     private void applyDims() {
-        if (!mAnimatingExit && mAppDied) {
-            mIsDimming = true;
-            getDimmer().dimAbove(getSyncTransaction(), this, DEFAULT_DIM_AMOUNT_DEAD_WINDOW);
-        } else if (((mAttrs.flags & FLAG_DIM_BEHIND) != 0 || shouldDrawBlurBehind())
+        if (((mAttrs.flags & FLAG_DIM_BEHIND) != 0 || shouldDrawBlurBehind())
                    && isVisibleNow() && !mHidden) {
             // Only show the Dimmer when the following is satisfied:
             // 1. The window has the flag FLAG_DIM_BEHIND or blur behind is requested
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index e2bdcdd..2ce86ad 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -179,6 +179,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.tv.input@1.0",
         "android.hardware.tv.input-V1-ndk",
         "android.hardware.vibrator-V2-cpp",
diff --git a/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp b/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
index ed79352..7e0bb68 100644
--- a/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
+++ b/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
@@ -16,27 +16,28 @@
 
 #define LOG_TAG "HardwarePropertiesManagerService-JNI"
 
-#include <nativehelper/JNIHelp.h>
-#include "jni.h"
-
-#include <math.h>
-#include <stdlib.h>
-
+#include <aidl/android/hardware/thermal/IThermal.h>
+#include <android/binder_manager.h>
 #include <android/hardware/thermal/1.0/IThermal.h>
+#include <math.h>
+#include <nativehelper/JNIHelp.h>
 #include <utils/Log.h>
 #include <utils/String8.h>
 
 #include "core_jni_helpers.h"
+#include "jni.h"
 
 namespace android {
 
+using ::aidl::android::hardware::thermal::CoolingDevice;
+using ::aidl::android::hardware::thermal::IThermal;
+using ::aidl::android::hardware::thermal::Temperature;
+using ::aidl::android::hardware::thermal::TemperatureThreshold;
+using ::aidl::android::hardware::thermal::TemperatureType;
+using ::aidl::android::hardware::thermal::ThrottlingSeverity;
 using android::hidl::base::V1_0::IBase;
 using hardware::hidl_death_recipient;
 using hardware::hidl_vec;
-using hardware::thermal::V1_0::CoolingDevice;
-using hardware::thermal::V1_0::CpuUsage;
-using hardware::thermal::V1_0::IThermal;
-using hardware::thermal::V1_0::Temperature;
 using hardware::thermal::V1_0::ThermalStatus;
 using hardware::thermal::V1_0::ThermalStatusCode;
 template<typename T>
@@ -62,20 +63,28 @@
 
 static void getThermalHalLocked();
 static std::mutex gThermalHalMutex;
-static sp<IThermal> gThermalHal = nullptr;
+static sp<hardware::thermal::V1_0::IThermal> gThermalHidlHal = nullptr;
+static std::shared_ptr<IThermal> gThermalAidlHal = nullptr;
 
-// struct ThermalHalDeathRecipient;
-struct ThermalHalDeathRecipient : virtual public hidl_death_recipient {
-      // hidl_death_recipient interface
-      virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override {
-          std::lock_guard<std::mutex> lock(gThermalHalMutex);
-          ALOGE("ThermalHAL just died");
-          gThermalHal = nullptr;
-          getThermalHalLocked();
-      }
+struct ThermalHidlHalDeathRecipient : virtual public hidl_death_recipient {
+    // hidl_death_recipient interface
+    virtual void serviceDied(uint64_t cookie, const wp<IBase> &who) override {
+        std::lock_guard<std::mutex> lock(gThermalHalMutex);
+        ALOGE("Thermal HAL just died");
+        gThermalHidlHal = nullptr;
+        getThermalHalLocked();
+    }
 };
 
-sp<ThermalHalDeathRecipient> gThermalHalDeathRecipient = nullptr;
+static void onThermalAidlBinderDied(void *cookie) {
+    std::lock_guard<std::mutex> lock(gThermalHalMutex);
+    ALOGE("Thermal AIDL HAL just died");
+    gThermalAidlHal = nullptr;
+    getThermalHalLocked();
+}
+
+sp<ThermalHidlHalDeathRecipient> gThermalHidlHalDeathRecipient = nullptr;
+ndk::ScopedAIBinder_DeathRecipient gThermalAidlDeathRecipient;
 
 // ----------------------------------------------------------------------------
 
@@ -85,27 +94,49 @@
 
 // The caller must be holding gThermalHalMutex.
 static void getThermalHalLocked() {
-    if (gThermalHal != nullptr) {
+    if (gThermalAidlHal || gThermalHidlHal) {
+        return;
+    }
+    const std::string thermalInstanceName = std::string(IThermal::descriptor) + "/default";
+    if (AServiceManager_isDeclared(thermalInstanceName.c_str())) {
+        auto binder = AServiceManager_waitForService(thermalInstanceName.c_str());
+        auto thermalAidlService = IThermal::fromBinder(ndk::SpAIBinder(binder));
+        if (thermalAidlService) {
+            gThermalAidlHal = thermalAidlService;
+            if (gThermalAidlDeathRecipient.get() == nullptr) {
+                gThermalAidlDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(
+                        AIBinder_DeathRecipient_new(onThermalAidlBinderDied));
+            }
+            auto linked = AIBinder_linkToDeath(thermalAidlService->asBinder().get(),
+                                               gThermalAidlDeathRecipient.get(), nullptr);
+            if (linked != STATUS_OK) {
+                ALOGW("Failed to link to death (AIDL): %d", linked);
+                gThermalAidlHal = nullptr;
+            }
+        } else {
+            ALOGE("Unable to get Thermal AIDL service");
+        }
         return;
     }
 
-    gThermalHal = IThermal::getService();
+    ALOGI("Thermal AIDL service is not declared, trying HIDL");
+    gThermalHidlHal = hardware::thermal::V1_0::IThermal::getService();
 
-    if (gThermalHal == nullptr) {
+    if (gThermalHidlHal == nullptr) {
         ALOGE("Unable to get Thermal service.");
     } else {
-        if (gThermalHalDeathRecipient == nullptr) {
-            gThermalHalDeathRecipient = new ThermalHalDeathRecipient();
+        if (gThermalHidlHalDeathRecipient == nullptr) {
+            gThermalHidlHalDeathRecipient = new ThermalHidlHalDeathRecipient();
         }
-        hardware::Return<bool> linked = gThermalHal->linkToDeath(
-            gThermalHalDeathRecipient, 0x451F /* cookie */);
+        hardware::Return<bool> linked =
+                gThermalHidlHal->linkToDeath(gThermalHidlHalDeathRecipient, 0x451F /* cookie */);
         if (!linked.isOk()) {
             ALOGE("Transaction error in linking to ThermalHAL death: %s",
-            linked.description().c_str());
-            gThermalHal = nullptr;
+                  linked.description().c_str());
+            gThermalHidlHal = nullptr;
         } else if (!linked) {
             ALOGW("Unable to link to ThermalHal death notifications");
-            gThermalHal = nullptr;
+            gThermalHidlHal = nullptr;
         } else {
             ALOGD("Link to death notification successful");
         }
@@ -117,17 +148,27 @@
     getThermalHalLocked();
 }
 
-static jfloatArray nativeGetFanSpeeds(JNIEnv *env, jclass /* clazz */) {
-    std::lock_guard<std::mutex> lock(gThermalHalMutex);
-    getThermalHalLocked();
-    if (gThermalHal == nullptr) {
-        ALOGE("Couldn't get fan speeds because of HAL error.");
+static jfloatArray getFanSpeedsAidl(JNIEnv *env) {
+    std::vector<CoolingDevice> list;
+    auto status = gThermalAidlHal->getCoolingDevices(&list);
+    if (!status.isOk()) {
+        ALOGE("getFanSpeeds failed status: %s", status.getMessage());
         return env->NewFloatArray(0);
     }
+    float values[list.size()];
+    for (size_t i = 0; i < list.size(); ++i) {
+        values[i] = list[i].value;
+    }
+    jfloatArray fanSpeeds = env->NewFloatArray(list.size());
+    env->SetFloatArrayRegion(fanSpeeds, 0, list.size(), values);
+    return fanSpeeds;
+}
 
-    hidl_vec<CoolingDevice> list;
-    Return<void> ret = gThermalHal->getCoolingDevices(
-            [&list](ThermalStatus status, hidl_vec<CoolingDevice> devices) {
+static jfloatArray getFanSpeedsHidl(JNIEnv *env) {
+    hidl_vec<hardware::thermal::V1_0::CoolingDevice> list;
+    Return<void> ret = gThermalHidlHal->getCoolingDevices(
+            [&list](ThermalStatus status,
+                    hidl_vec<hardware::thermal::V1_0::CoolingDevice> devices) {
                 if (status.code == ThermalStatusCode::SUCCESS) {
                     list = std::move(devices);
                 } else {
@@ -137,9 +178,9 @@
             });
 
     if (!ret.isOk()) {
-        ALOGE("getCoolingDevices failed status: %s", ret.description().c_str());
+        ALOGE("getFanSpeeds failed status: %s", ret.description().c_str());
+        return env->NewFloatArray(0);
     }
-
     float values[list.size()];
     for (size_t i = 0; i < list.size(); ++i) {
         values[i] = list[i].currentValue;
@@ -149,17 +190,79 @@
     return fanSpeeds;
 }
 
-static jfloatArray nativeGetDeviceTemperatures(JNIEnv *env, jclass /* clazz */, int type,
-                                               int source) {
+static jfloatArray nativeGetFanSpeeds(JNIEnv *env, jclass /* clazz */) {
     std::lock_guard<std::mutex> lock(gThermalHalMutex);
     getThermalHalLocked();
-    if (gThermalHal == nullptr) {
-        ALOGE("Couldn't get device temperatures because of HAL error.");
+    if (!gThermalHidlHal && !gThermalAidlHal) {
+        ALOGE("Couldn't get fan speeds because of HAL error.");
         return env->NewFloatArray(0);
     }
-    hidl_vec<Temperature> list;
-    Return<void> ret = gThermalHal->getTemperatures(
-            [&list](ThermalStatus status, hidl_vec<Temperature> temperatures) {
+    if (gThermalAidlHal) {
+        return getFanSpeedsAidl(env);
+    }
+    return getFanSpeedsHidl(env);
+}
+
+static jfloatArray getDeviceTemperaturesAidl(JNIEnv *env, int type, int source) {
+    jfloat *values;
+    size_t length = 0;
+    if (source == TEMPERATURE_CURRENT) {
+        std::vector<Temperature> list;
+        auto status =
+                gThermalAidlHal->getTemperaturesWithType(static_cast<TemperatureType>(type), &list);
+
+        if (!status.isOk()) {
+            ALOGE("getDeviceTemperatures failed status: %s", status.getMessage());
+            return env->NewFloatArray(0);
+        }
+        values = new jfloat[list.size()];
+        for (const auto &temp : list) {
+            if (static_cast<int>(temp.type) == type) {
+                values[length++] = finalizeTemperature(temp.value);
+            }
+        }
+    } else if (source == TEMPERATURE_THROTTLING_BELOW_VR_MIN) {
+        values = new jfloat[1];
+        values[length++] = gUndefinedTemperature;
+    } else {
+        std::vector<TemperatureThreshold> list;
+        auto status =
+                gThermalAidlHal->getTemperatureThresholdsWithType(static_cast<TemperatureType>(
+                                                                          type),
+                                                                  &list);
+
+        if (!status.isOk()) {
+            ALOGE("getDeviceTemperatures failed status: %s", status.getMessage());
+            return env->NewFloatArray(0);
+        }
+        values = new jfloat[list.size()];
+        for (auto &t : list) {
+            if (static_cast<int>(t.type) == type) {
+                switch (source) {
+                    case TEMPERATURE_THROTTLING:
+                        values[length++] =
+                                finalizeTemperature(t.hotThrottlingThresholds[static_cast<int>(
+                                        ThrottlingSeverity::SEVERE)]);
+                        break;
+                    case TEMPERATURE_SHUTDOWN:
+                        values[length++] =
+                                finalizeTemperature(t.hotThrottlingThresholds[static_cast<int>(
+                                        ThrottlingSeverity::SHUTDOWN)]);
+                        break;
+                }
+            }
+        }
+    }
+    jfloatArray deviceTemps = env->NewFloatArray(length);
+    env->SetFloatArrayRegion(deviceTemps, 0, length, values);
+    return deviceTemps;
+}
+
+static jfloatArray getDeviceTemperaturesHidl(JNIEnv *env, int type, int source) {
+    hidl_vec<hardware::thermal::V1_0::Temperature> list;
+    Return<void> ret = gThermalHidlHal->getTemperatures(
+            [&list](ThermalStatus status,
+                    hidl_vec<hardware::thermal::V1_0::Temperature> temperatures) {
                 if (status.code == ThermalStatusCode::SUCCESS) {
                     list = std::move(temperatures);
                 } else {
@@ -170,9 +273,9 @@
 
     if (!ret.isOk()) {
         ALOGE("getDeviceTemperatures failed status: %s", ret.description().c_str());
+        return env->NewFloatArray(0);
     }
-
-    jfloat values[list.size()];
+    float values[list.size()];
     size_t length = 0;
     for (size_t i = 0; i < list.size(); ++i) {
         if (static_cast<int>(list[i].type) == type) {
@@ -197,16 +300,34 @@
     return deviceTemps;
 }
 
+static jfloatArray nativeGetDeviceTemperatures(JNIEnv *env, jclass /* clazz */, int type,
+                                               int source) {
+    std::lock_guard<std::mutex> lock(gThermalHalMutex);
+    getThermalHalLocked();
+    if (!gThermalHidlHal && !gThermalAidlHal) {
+        ALOGE("Couldn't get device temperatures because of HAL error.");
+        return env->NewFloatArray(0);
+    }
+    if (gThermalAidlHal) {
+        return getDeviceTemperaturesAidl(env, type, source);
+    }
+    return getDeviceTemperaturesHidl(env, type, source);
+}
+
 static jobjectArray nativeGetCpuUsages(JNIEnv *env, jclass /* clazz */) {
     std::lock_guard<std::mutex> lock(gThermalHalMutex);
     getThermalHalLocked();
-    if (gThermalHal == nullptr || !gCpuUsageInfoClassInfo.initMethod) {
+    if (gThermalAidlHal) {
+        ALOGW("getCpuUsages is not supported");
+        return env->NewObjectArray(0, gCpuUsageInfoClassInfo.clazz, nullptr);
+    }
+    if (gThermalHidlHal == nullptr || !gCpuUsageInfoClassInfo.initMethod) {
         ALOGE("Couldn't get CPU usages because of HAL error.");
         return env->NewObjectArray(0, gCpuUsageInfoClassInfo.clazz, nullptr);
     }
-    hidl_vec<CpuUsage> list;
-    Return<void> ret = gThermalHal->getCpuUsages(
-            [&list](ThermalStatus status, hidl_vec<CpuUsage> cpuUsages) {
+    hidl_vec<hardware::thermal::V1_0::CpuUsage> list;
+    Return<void> ret = gThermalHidlHal->getCpuUsages(
+            [&list](ThermalStatus status, hidl_vec<hardware::thermal::V1_0::CpuUsage> cpuUsages) {
                 if (status.code == ThermalStatusCode::SUCCESS) {
                     list = std::move(cpuUsages);
                 } else {
@@ -217,6 +338,7 @@
 
     if (!ret.isOk()) {
         ALOGE("getCpuUsages failed status: %s", ret.description().c_str());
+        return env->NewObjectArray(0, gCpuUsageInfoClassInfo.clazz, nullptr);
     }
 
     jobjectArray cpuUsages = env->NewObjectArray(list.size(), gCpuUsageInfoClassInfo.clazz,
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index b4e2fb6..da44da4 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -308,6 +308,7 @@
     void setMotionClassifierEnabled(bool enabled);
     std::optional<std::string> getBluetoothAddress(int32_t deviceId);
     void setStylusButtonMotionEventsEnabled(bool enabled);
+    FloatPoint getMouseCursorPosition();
 
     /* --- InputReaderPolicyInterface implementation --- */
 
@@ -366,7 +367,7 @@
     virtual PointerIconStyle getDefaultPointerIconId();
     virtual PointerIconStyle getDefaultStylusIconId();
     virtual PointerIconStyle getCustomPointerIconId();
-    virtual void onPointerDisplayIdChanged(int32_t displayId, float xPos, float yPos);
+    virtual void onPointerDisplayIdChanged(int32_t displayId, const FloatPoint& position);
 
     /* --- If touch mode is enabled per display or global --- */
 
@@ -730,11 +731,11 @@
     return controller;
 }
 
-void NativeInputManager::onPointerDisplayIdChanged(int32_t pointerDisplayId, float xPos,
-                                                   float yPos) {
+void NativeInputManager::onPointerDisplayIdChanged(int32_t pointerDisplayId,
+                                                   const FloatPoint& position) {
     JNIEnv* env = jniEnv();
     env->CallVoidMethod(mServiceObj, gServiceClassInfo.onPointerDisplayIdChanged, pointerDisplayId,
-                        xPos, yPos);
+                        position.x, position.y);
     checkAndClearExceptionFromCallback(env, "onPointerDisplayIdChanged");
 }
 
@@ -1655,6 +1656,14 @@
     return static_cast<bool>(enabled);
 }
 
+FloatPoint NativeInputManager::getMouseCursorPosition() {
+    AutoMutex _l(mLock);
+    const auto pc = mLocked.pointerController.lock();
+    if (!pc) return {AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION};
+
+    return pc->getPosition();
+}
+
 // ----------------------------------------------------------------------------
 
 static NativeInputManager* getNativeInputManager(JNIEnv* env, jobject clazz) {
@@ -2547,6 +2556,15 @@
     im->setStylusButtonMotionEventsEnabled(enabled);
 }
 
+static jfloatArray nativeGetMouseCursorPosition(JNIEnv* env, jobject nativeImplObj) {
+    NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
+    const auto p = im->getMouseCursorPosition();
+    const std::array<float, 2> arr = {{p.x, p.y}};
+    jfloatArray outArr = env->NewFloatArray(2);
+    env->SetFloatArrayRegion(outArr, 0, arr.size(), arr.data());
+    return outArr;
+}
+
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod gInputManagerMethods[] = {
@@ -2640,6 +2658,7 @@
         {"getBluetoothAddress", "(I)Ljava/lang/String;", (void*)nativeGetBluetoothAddress},
         {"setStylusButtonMotionEventsEnabled", "(Z)V",
          (void*)nativeSetStylusButtonMotionEventsEnabled},
+        {"getMouseCursorPosition", "()[F", (void*)nativeGetMouseCursorPosition},
 };
 
 #define FIND_CLASS(var, className) \
diff --git a/services/core/jni/com_android_server_sensor_SensorService.cpp b/services/core/jni/com_android_server_sensor_SensorService.cpp
index 356e9a9..a916b64 100644
--- a/services/core/jni/com_android_server_sensor_SensorService.cpp
+++ b/services/core/jni/com_android_server_sensor_SensorService.cpp
@@ -17,10 +17,13 @@
 #define LOG_TAG "NativeSensorService"
 
 #include <android-base/properties.h>
+#include <android_os_NativeHandle.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <core_jni_helpers.h>
+#include <cutils/native_handle.h>
 #include <cutils/properties.h>
 #include <jni.h>
+#include <nativehelper/JNIPlatformHelp.h>
 #include <sensorservice/SensorService.h>
 #include <string.h>
 #include <utils/Log.h>
@@ -28,6 +31,8 @@
 
 #include <mutex>
 
+#include "android_util_Binder.h"
+
 #define PROXIMITY_ACTIVE_CLASS \
     "com/android/server/sensors/SensorManagerInternal$ProximityActiveListener"
 
@@ -38,7 +43,10 @@
 
 static JavaVM* sJvm = nullptr;
 static jmethodID sMethodIdOnProximityActive;
-static jmethodID sMethodIdOnConfigurationChanged;
+static jmethodID sMethodIdRuntimeSensorOnConfigurationChanged;
+static jmethodID sMethodIdRuntimeSensorOnDirectChannelCreated;
+static jmethodID sMethodIdRuntimeSensorOnDirectChannelDestroyed;
+static jmethodID sMethodIdRuntimeSensorOnDirectChannelConfigured;
 
 class NativeSensorService {
 public:
@@ -47,7 +55,7 @@
     void registerProximityActiveListener();
     void unregisterProximityActiveListener();
     jint registerRuntimeSensor(JNIEnv* env, jint deviceId, jint type, jstring name, jstring vendor,
-                               jobject callback);
+                               jint flags, jobject callback);
     void unregisterRuntimeSensor(jint handle);
     jboolean sendRuntimeSensorEvent(JNIEnv* env, jint handle, jint type, jlong timestamp,
                                     jfloatArray values);
@@ -74,6 +82,9 @@
 
         status_t onConfigurationChanged(int32_t handle, bool enabled, int64_t samplingPeriodNs,
                                         int64_t batchReportLatencyNs) override;
+        int onDirectChannelCreated(int fd) override;
+        void onDirectChannelDestroyed(int channelHandle) override;
+        int onDirectChannelConfigured(int channelHandle, int sensorHandle, int rateLevel) override;
 
     private:
         jobject mCallback;
@@ -108,7 +119,7 @@
 }
 
 jint NativeSensorService::registerRuntimeSensor(JNIEnv* env, jint deviceId, jint type, jstring name,
-                                                jstring vendor, jobject callback) {
+                                                jstring vendor, jint flags, jobject callback) {
     if (mService == nullptr) {
         ALOGD("Dropping registerRuntimeSensor, sensor service not available.");
         return -1;
@@ -119,6 +130,11 @@
             .vendor = env->GetStringUTFChars(vendor, 0),
             .version = sizeof(sensor_t),
             .type = type,
+#ifdef __LP64__
+            .flags = static_cast<uint64_t>(flags),
+#else
+            .flags = static_cast<uint32_t>(flags),
+#endif
     };
 
     sp<RuntimeSensorCallbackDelegate> callbackDelegate(
@@ -234,12 +250,39 @@
 status_t NativeSensorService::RuntimeSensorCallbackDelegate::onConfigurationChanged(
         int32_t handle, bool enabled, int64_t samplingPeriodNs, int64_t batchReportLatencyNs) {
     auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
-    return jniEnv->CallIntMethod(mCallback, sMethodIdOnConfigurationChanged,
+    return jniEnv->CallIntMethod(mCallback, sMethodIdRuntimeSensorOnConfigurationChanged,
                                  static_cast<jint>(handle), static_cast<jboolean>(enabled),
                                  static_cast<jint>(ns2us(samplingPeriodNs)),
                                  static_cast<jint>(ns2us(batchReportLatencyNs)));
 }
 
+int NativeSensorService::RuntimeSensorCallbackDelegate::onDirectChannelCreated(int fd) {
+    if (fd <= 0) {
+        return 0;
+    }
+    auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
+    jobject jfd = jniCreateFileDescriptor(jniEnv, fd);
+    jobject parcelFileDescriptor = newParcelFileDescriptor(jniEnv, jfd);
+    return jniEnv->CallIntMethod(mCallback, sMethodIdRuntimeSensorOnDirectChannelCreated,
+                                 parcelFileDescriptor);
+}
+
+void NativeSensorService::RuntimeSensorCallbackDelegate::onDirectChannelDestroyed(
+        int channelHandle) {
+    auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
+    return jniEnv->CallVoidMethod(mCallback, sMethodIdRuntimeSensorOnDirectChannelDestroyed,
+                                  static_cast<jint>(channelHandle));
+}
+
+int NativeSensorService::RuntimeSensorCallbackDelegate::onDirectChannelConfigured(int channelHandle,
+                                                                                  int sensorHandle,
+                                                                                  int rateLevel) {
+    auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
+    return jniEnv->CallIntMethod(mCallback, sMethodIdRuntimeSensorOnDirectChannelConfigured,
+                                 static_cast<jint>(channelHandle), static_cast<jint>(sensorHandle),
+                                 static_cast<jint>(rateLevel));
+}
+
 static jlong startSensorServiceNative(JNIEnv* env, jclass, jobject listener) {
     NativeSensorService* service = new NativeSensorService(env, listener);
     return reinterpret_cast<jlong>(service);
@@ -256,9 +299,10 @@
 }
 
 static jint registerRuntimeSensorNative(JNIEnv* env, jclass, jlong ptr, jint deviceId, jint type,
-                                        jstring name, jstring vendor, jobject callback) {
+                                        jstring name, jstring vendor, jint flags,
+                                        jobject callback) {
     auto* service = reinterpret_cast<NativeSensorService*>(ptr);
-    return service->registerRuntimeSensor(env, deviceId, type, name, vendor, callback);
+    return service->registerRuntimeSensor(env, deviceId, type, name, vendor, flags, callback);
 }
 
 static void unregisterRuntimeSensorNative(JNIEnv* env, jclass, jlong ptr, jint handle) {
@@ -280,7 +324,7 @@
         {"unregisterProximityActiveListenerNative", "(J)V",
          reinterpret_cast<void*>(unregisterProximityActiveListenerNative)},
         {"registerRuntimeSensorNative",
-         "(JIILjava/lang/String;Ljava/lang/String;L" RUNTIME_SENSOR_CALLBACK_CLASS ";)I",
+         "(JIILjava/lang/String;Ljava/lang/String;IL" RUNTIME_SENSOR_CALLBACK_CLASS ";)I",
          reinterpret_cast<void*>(registerRuntimeSensorNative)},
         {"unregisterRuntimeSensorNative", "(JI)V",
          reinterpret_cast<void*>(unregisterRuntimeSensorNative)},
@@ -293,8 +337,17 @@
     jclass listenerClass = FindClassOrDie(env, PROXIMITY_ACTIVE_CLASS);
     sMethodIdOnProximityActive = GetMethodIDOrDie(env, listenerClass, "onProximityActive", "(Z)V");
     jclass runtimeSensorCallbackClass = FindClassOrDie(env, RUNTIME_SENSOR_CALLBACK_CLASS);
-    sMethodIdOnConfigurationChanged =
+    sMethodIdRuntimeSensorOnConfigurationChanged =
             GetMethodIDOrDie(env, runtimeSensorCallbackClass, "onConfigurationChanged", "(IZII)I");
+    sMethodIdRuntimeSensorOnDirectChannelCreated =
+            GetMethodIDOrDie(env, runtimeSensorCallbackClass, "onDirectChannelCreated",
+                             "(Landroid/os/ParcelFileDescriptor;)I");
+    sMethodIdRuntimeSensorOnDirectChannelDestroyed =
+            GetMethodIDOrDie(env, runtimeSensorCallbackClass, "onDirectChannelDestroyed", "(I)V");
+    sMethodIdRuntimeSensorOnDirectChannelConfigured =
+            GetMethodIDOrDie(env, runtimeSensorCallbackClass, "onDirectChannelConfigured",
+                             "(III)I");
+
     return jniRegisterNativeMethods(env, "com/android/server/sensors/SensorService", methods,
                                     NELEM(methods));
 }
diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd
index 9260d2b..981844c 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -26,6 +26,10 @@
     <xs:element name="displayConfiguration">
         <xs:complexType>
             <xs:sequence>
+                <xs:element type ="xs:string" name="name">
+                    <xs:annotation name="nullable"/>
+                    <xs:annotation name="final"/>
+                </xs:element>
                 <xs:element type="densityMapping" name="densityMapping" minOccurs="0" maxOccurs="1">
                     <xs:annotation name="nullable"/>
                     <xs:annotation name="final"/>
@@ -211,6 +215,32 @@
             <xs:element type="brightnessThrottlingMap" name="brightnessThrottlingMap" maxOccurs="unbounded">
                 <xs:annotation name="final"/>
             </xs:element>
+            <xs:element type="refreshRateThrottlingMap" name="refreshRateThrottlingMap" maxOccurs="unbounded">
+                <xs:annotation name="final"/>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:complexType name="refreshRateThrottlingMap">
+        <xs:attribute name="id" type="xs:string" />
+        <xs:sequence>
+            <xs:element name="refreshRateThrottlingPoint" type="refreshRateThrottlingPoint" maxOccurs="unbounded">
+                <xs:annotation name="nonnull"/>
+                <xs:annotation name="final"/>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:complexType name="refreshRateThrottlingPoint">
+        <xs:sequence>
+            <xs:element type="thermalStatus" name="thermalStatus">
+                <xs:annotation name="nonnull"/>
+                <xs:annotation name="final"/>
+            </xs:element>
+            <xs:element type="refreshRateRange" name="refreshRateRange">
+                <xs:annotation name="nonnull"/>
+                <xs:annotation name="final"/>
+            </xs:element>
         </xs:sequence>
     </xs:complexType>
 
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index e81c27d..8cb4837 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -89,6 +89,7 @@
     method public final com.android.server.display.config.Thresholds getDisplayBrightnessChangeThresholdsIdle();
     method public com.android.server.display.config.HighBrightnessMode getHighBrightnessMode();
     method public final com.android.server.display.config.SensorDetails getLightSensor();
+    method @Nullable public final String getName();
     method public final com.android.server.display.config.SensorDetails getProxSensor();
     method public com.android.server.display.config.DisplayQuirks getQuirks();
     method public com.android.server.display.config.RefreshRateConfigs getRefreshRate();
@@ -114,6 +115,7 @@
     method public final void setDisplayBrightnessChangeThresholdsIdle(com.android.server.display.config.Thresholds);
     method public void setHighBrightnessMode(com.android.server.display.config.HighBrightnessMode);
     method public final void setLightSensor(com.android.server.display.config.SensorDetails);
+    method public final void setName(@Nullable String);
     method public final void setProxSensor(com.android.server.display.config.SensorDetails);
     method public void setQuirks(com.android.server.display.config.DisplayQuirks);
     method public void setRefreshRate(com.android.server.display.config.RefreshRateConfigs);
@@ -214,6 +216,21 @@
     method public final void setMinimum(java.math.BigInteger);
   }
 
+  public class RefreshRateThrottlingMap {
+    ctor public RefreshRateThrottlingMap();
+    method public String getId();
+    method @NonNull public final java.util.List<com.android.server.display.config.RefreshRateThrottlingPoint> getRefreshRateThrottlingPoint();
+    method public void setId(String);
+  }
+
+  public class RefreshRateThrottlingPoint {
+    ctor public RefreshRateThrottlingPoint();
+    method @NonNull public final com.android.server.display.config.RefreshRateRange getRefreshRateRange();
+    method @NonNull public final com.android.server.display.config.ThermalStatus getThermalStatus();
+    method public final void setRefreshRateRange(@NonNull com.android.server.display.config.RefreshRateRange);
+    method public final void setThermalStatus(@NonNull com.android.server.display.config.ThermalStatus);
+  }
+
   public class RefreshRateZone {
     ctor public RefreshRateZone();
     method public String getId();
@@ -264,6 +281,7 @@
   public class ThermalThrottling {
     ctor public ThermalThrottling();
     method public final java.util.List<com.android.server.display.config.BrightnessThrottlingMap> getBrightnessThrottlingMap();
+    method public final java.util.List<com.android.server.display.config.RefreshRateThrottlingMap> getRefreshRateThrottlingMap();
   }
 
   public class ThresholdPoint {
diff --git a/services/core/xsd/display-layout-config/display-layout-config.xsd b/services/core/xsd/display-layout-config/display-layout-config.xsd
index d4556d7..ce022e9 100644
--- a/services/core/xsd/display-layout-config/display-layout-config.xsd
+++ b/services/core/xsd/display-layout-config/display-layout-config.xsd
@@ -52,6 +52,7 @@
             <xs:element name="address" type="xs:nonNegativeInteger"/>
             <xs:element name="position" type="xs:string" minOccurs="0" maxOccurs="1" />
             <xs:element name="brightnessThrottlingMapId" type="xs:string" minOccurs="0" maxOccurs="1" />
+            <xs:element name="refreshRateThermalThrottlingMapId" type="xs:string" minOccurs="0" />
         </xs:sequence>
         <xs:attribute name="enabled" type="xs:boolean" use="optional" />
         <xs:attribute name="defaultDisplay" type="xs:boolean" use="optional" />
diff --git a/services/core/xsd/display-layout-config/schema/current.txt b/services/core/xsd/display-layout-config/schema/current.txt
index 52133ab..42a800d 100644
--- a/services/core/xsd/display-layout-config/schema/current.txt
+++ b/services/core/xsd/display-layout-config/schema/current.txt
@@ -7,6 +7,7 @@
     method public String getBrightnessThrottlingMapId();
     method public String getDisplayGroup();
     method public String getPosition();
+    method public String getRefreshRateThermalThrottlingMapId();
     method public String getRefreshRateZoneId();
     method public boolean isDefaultDisplay();
     method public boolean isEnabled();
@@ -16,6 +17,7 @@
     method public void setDisplayGroup(String);
     method public void setEnabled(boolean);
     method public void setPosition(String);
+    method public void setRefreshRateThermalThrottlingMapId(String);
     method public void setRefreshRateZoneId(String);
   }
 
diff --git a/services/credentials/java/com/android/server/credentials/ClearRequestSession.java b/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
index f8b1e6fc..e09c0a2 100644
--- a/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
@@ -20,15 +20,19 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.credentials.ClearCredentialStateRequest;
+import android.credentials.CredentialProviderInfo;
 import android.credentials.IClearCredentialStateCallback;
 import android.credentials.ui.ProviderData;
 import android.credentials.ui.RequestInfo;
 import android.os.CancellationSignal;
 import android.os.RemoteException;
 import android.service.credentials.CallingAppInfo;
-import android.service.credentials.CredentialProviderInfo;
 import android.util.Log;
 
+import com.android.server.credentials.metrics.ApiName;
+import com.android.server.credentials.metrics.ApiStatus;
+import com.android.server.credentials.metrics.ProviderStatusForMetrics;
+
 import java.util.ArrayList;
 
 /**
@@ -42,9 +46,11 @@
 
     public ClearRequestSession(Context context, int userId, int callingUid,
             IClearCredentialStateCallback callback, ClearCredentialStateRequest request,
-            CallingAppInfo callingAppInfo, CancellationSignal cancellationSignal) {
+            CallingAppInfo callingAppInfo, CancellationSignal cancellationSignal,
+            long startedTimestamp) {
         super(context, userId, callingUid, request, callback, RequestInfo.TYPE_UNDEFINED,
-                callingAppInfo, cancellationSignal);
+                callingAppInfo, cancellationSignal, startedTimestamp);
+        setupInitialPhaseMetric(ApiName.CLEAR_CREDENTIAL.getMetricCode(), MetricUtilities.ZERO);
     }
 
     /**
@@ -116,21 +122,23 @@
     private void respondToClientWithResponseAndFinish() {
         Log.i(TAG, "respondToClientWithResponseAndFinish");
         if (isSessionCancelled()) {
-            // TODO: Differentiate btw cancelled and false
-            mChosenProviderMetric.setChosenProviderStatus(
-                    MetricUtilities.METRICS_PROVIDER_STATUS_FINAL_SUCCESS);
-            logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ true);
+            mChosenProviderFinalPhaseMetric.setChosenProviderStatus(
+                    ProviderStatusForMetrics.FINAL_SUCCESS.getMetricCode());
+            logApiCall(ApiName.CLEAR_CREDENTIAL, /* apiStatus */
+                    ApiStatus.CLIENT_CANCELED);
             finishSession(/*propagateCancellation=*/true);
             return;
         }
         try {
             mClientCallback.onSuccess();
-            logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ true);
+            logApiCall(ApiName.CLEAR_CREDENTIAL, /* apiStatus */
+                    ApiStatus.SUCCESS);
         } catch (RemoteException e) {
-            mChosenProviderMetric.setChosenProviderStatus(
-                    MetricUtilities.METRICS_PROVIDER_STATUS_FINAL_FAILURE);
+            mChosenProviderFinalPhaseMetric.setChosenProviderStatus(
+                    ProviderStatusForMetrics.FINAL_FAILURE.getMetricCode());
             Log.i(TAG, "Issue while propagating the response to the client");
-            logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ false);
+            logApiCall(ApiName.CLEAR_CREDENTIAL, /* apiStatus */
+                    ApiStatus.FAILURE);
         }
         finishSession(/*propagateCancellation=*/false);
     }
@@ -138,8 +146,8 @@
     private void respondToClientWithErrorAndFinish(String errorType, String errorMsg) {
         Log.i(TAG, "respondToClientWithErrorAndFinish");
         if (isSessionCancelled()) {
-            // TODO: Differentiate btw cancelled and false
-            logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ true);
+            logApiCall(ApiName.CLEAR_CREDENTIAL, /* apiStatus */
+                    ApiStatus.CLIENT_CANCELED);
             finishSession(/*propagateCancellation=*/true);
             return;
         }
@@ -148,7 +156,8 @@
         } catch (RemoteException e) {
             e.printStackTrace();
         }
-        logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ false);
+        logApiCall(ApiName.CLEAR_CREDENTIAL, /* apiStatus */
+                ApiStatus.FAILURE);
         finishSession(/*propagateCancellation=*/false);
     }
 
diff --git a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
index 4dd0c84..793d83e 100644
--- a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
@@ -16,9 +16,6 @@
 
 package com.android.server.credentials;
 
-import static com.android.server.credentials.MetricUtilities.METRICS_PROVIDER_STATUS_FINAL_FAILURE;
-import static com.android.server.credentials.MetricUtilities.METRICS_PROVIDER_STATUS_FINAL_SUCCESS;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.ComponentName;
@@ -27,15 +24,19 @@
 import android.credentials.CreateCredentialRequest;
 import android.credentials.CreateCredentialResponse;
 import android.credentials.CredentialManager;
+import android.credentials.CredentialProviderInfo;
 import android.credentials.ICreateCredentialCallback;
 import android.credentials.ui.ProviderData;
 import android.credentials.ui.RequestInfo;
 import android.os.CancellationSignal;
 import android.os.RemoteException;
 import android.service.credentials.CallingAppInfo;
-import android.service.credentials.CredentialProviderInfo;
 import android.util.Log;
 
+import com.android.server.credentials.metrics.ApiName;
+import com.android.server.credentials.metrics.ApiStatus;
+import com.android.server.credentials.metrics.ProviderStatusForMetrics;
+
 import java.util.ArrayList;
 
 /**
@@ -52,9 +53,11 @@
             CreateCredentialRequest request,
             ICreateCredentialCallback callback,
             CallingAppInfo callingAppInfo,
-            CancellationSignal cancellationSignal) {
+            CancellationSignal cancellationSignal,
+            long startedTimestamp) {
         super(context, userId, callingUid, request, callback, RequestInfo.TYPE_CREATE,
-                callingAppInfo, cancellationSignal);
+                callingAppInfo, cancellationSignal, startedTimestamp);
+        setupInitialPhaseMetric(ApiName.CREATE_CREDENTIAL.getMetricCode(), MetricUtilities.UNIT);
     }
 
     /**
@@ -80,6 +83,7 @@
 
     @Override
     protected void launchUiWithProviderData(ArrayList<ProviderData> providerDataList) {
+        mChosenProviderFinalPhaseMetric.setUiCallStartTimeNanoseconds(System.nanoTime());
         try {
             mClientCallback.onPendingIntent(mCredentialManagerUi.createPendingIntent(
                     RequestInfo.newCreateRequestInfo(
@@ -87,6 +91,7 @@
                             mClientAppInfo.getPackageName()),
                     providerDataList));
         } catch (RemoteException e) {
+            mChosenProviderFinalPhaseMetric.setUiReturned(false);
             respondToClientWithErrorAndFinish(
                     CreateCredentialException.TYPE_UNKNOWN,
                     "Unable to invoke selector");
@@ -96,15 +101,17 @@
     @Override
     public void onFinalResponseReceived(ComponentName componentName,
             @Nullable CreateCredentialResponse response) {
+        mChosenProviderFinalPhaseMetric.setUiReturned(true);
+        mChosenProviderFinalPhaseMetric.setUiCallEndTimeNanoseconds(System.nanoTime());
         Log.i(TAG, "onFinalCredentialReceived from: " + componentName.flattenToString());
         setChosenMetric(componentName);
         if (response != null) {
-            mChosenProviderMetric.setChosenProviderStatus(
-                    METRICS_PROVIDER_STATUS_FINAL_SUCCESS);
+            mChosenProviderFinalPhaseMetric.setChosenProviderStatus(
+                    ProviderStatusForMetrics.FINAL_SUCCESS.getMetricCode());
             respondToClientWithResponseAndFinish(response);
         } else {
-            mChosenProviderMetric.setChosenProviderStatus(
-                    METRICS_PROVIDER_STATUS_FINAL_FAILURE);
+            mChosenProviderFinalPhaseMetric.setChosenProviderStatus(
+                    ProviderStatusForMetrics.FINAL_FAILURE.getMetricCode());
             respondToClientWithErrorAndFinish(CreateCredentialException.TYPE_NO_CREATE_OPTIONS,
                     "Invalid response");
         }
@@ -135,35 +142,40 @@
 
     private void respondToClientWithResponseAndFinish(CreateCredentialResponse response) {
         Log.i(TAG, "respondToClientWithResponseAndFinish");
+        // TODO immediately add exception bit to chosen provider and do final emits across all
+        // including sequenceCounter!
         if (mRequestSessionStatus == RequestSessionStatus.COMPLETE) {
             Log.i(TAG, "Request has already been completed. This is strange.");
             return;
         }
         if (isSessionCancelled()) {
-            // TODO: Differentiate btw cancelled and false
-            logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ true);
+            logApiCall(ApiName.CREATE_CREDENTIAL, /* apiStatus */
+                    ApiStatus.CLIENT_CANCELED);
             finishSession(/*propagateCancellation=*/true);
             return;
         }
         try {
             mClientCallback.onResponse(response);
-            logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ true);
+            logApiCall(ApiName.CREATE_CREDENTIAL, /* apiStatus */
+                    ApiStatus.SUCCESS);
         } catch (RemoteException e) {
             Log.i(TAG, "Issue while responding to client: " + e.getMessage());
-            logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ false);
+            logApiCall(ApiName.CREATE_CREDENTIAL, /* apiStatus */
+                    ApiStatus.FAILURE);
         }
         finishSession(/*propagateCancellation=*/false);
     }
 
     private void respondToClientWithErrorAndFinish(String errorType, String errorMsg) {
         Log.i(TAG, "respondToClientWithErrorAndFinish");
+
         if (mRequestSessionStatus == RequestSessionStatus.COMPLETE) {
             Log.i(TAG, "Request has already been completed. This is strange.");
             return;
         }
         if (isSessionCancelled()) {
-            // TODO: Differentiate btw cancelled and false
-            logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ true);
+            logApiCall(ApiName.CREATE_CREDENTIAL, /* apiStatus */
+                    ApiStatus.CLIENT_CANCELED);
             finishSession(/*propagateCancellation=*/true);
             return;
         }
@@ -172,10 +184,20 @@
         } catch (RemoteException e) {
             Log.i(TAG, "Issue while responding to client: " + e.getMessage());
         }
-        logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ false);
+        logFailureOrUserCancel(errorType);
         finishSession(/*propagateCancellation=*/false);
     }
 
+    private void logFailureOrUserCancel(String errorType) {
+        if (CreateCredentialException.TYPE_USER_CANCELED.equals(errorType)) {
+            logApiCall(ApiName.CREATE_CREDENTIAL,
+                    /* apiStatus */ ApiStatus.USER_CANCELED);
+        } else {
+            logApiCall(ApiName.CREATE_CREDENTIAL,
+                    /* apiStatus */ ApiStatus.FAILURE);
+        }
+    }
+
     @Override
     public void onProviderStatusChanged(ProviderSession.Status status,
             ComponentName componentName) {
diff --git a/services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java b/services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java
index 9c50a5a..8ccc61b 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java
@@ -23,17 +23,21 @@
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 
+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.concurrent.locks.ReentrantLock;
+import java.util.stream.Collectors;
 
 /** Contains information on what CredentialProvider has what provisioned Credential. */
-public final class CredentialDescriptionRegistry {
+public class CredentialDescriptionRegistry {
 
+    private static final String FLAT_STRING_SPLIT_REGEX = ";";
     private static final int MAX_ALLOWED_CREDENTIAL_DESCRIPTIONS = 128;
     private static final int MAX_ALLOWED_ENTRIES_PER_PROVIDER = 16;
     @GuardedBy("sLock")
@@ -52,7 +56,8 @@
         final String mFlattenedRequest;
         final List<CredentialEntry> mCredentialEntries;
 
-        private FilterResult(String packageName,
+        @VisibleForTesting
+        FilterResult(String packageName,
                 String flattenedRequest,
                 List<CredentialEntry> credentialEntries) {
             mPackageName = packageName;
@@ -90,6 +95,31 @@
         }
     }
 
+    /** Clears an existing session for a given user identifier. Used when testing only. */
+    @GuardedBy("sLock")
+    @VisibleForTesting
+    static void clearAllSessions() {
+        sLock.lock();
+        try {
+            sCredentialDescriptionSessionPerUser.clear();
+        } finally {
+            sLock.unlock();
+        }
+    }
+
+    /** Sets an existing session for a given user identifier. Used when testing only. */
+    @GuardedBy("sLock")
+    @VisibleForTesting
+    static void setSession(int userId, CredentialDescriptionRegistry
+            credentialDescriptionRegistry) {
+        sLock.lock();
+        try {
+            sCredentialDescriptionSessionPerUser.put(userId, credentialDescriptionRegistry);
+        } finally {
+            sLock.unlock();
+        }
+    }
+
     private Map<String, Set<CredentialDescription>> mCredentialDescriptions;
     private int mTotalDescriptionCount;
 
@@ -136,11 +166,16 @@
     /** Returns package names and entries of a CredentialProviders that can satisfy a given
      * {@link CredentialDescription}. */
     public Set<FilterResult> getFilteredResultForProvider(String packageName,
-            String flatRequestStrings) {
+            String flatRequestString) {
         Set<FilterResult> result = new HashSet<>();
+        if (!mCredentialDescriptions.containsKey(packageName)) {
+            return result;
+        }
         Set<CredentialDescription> currentSet = mCredentialDescriptions.get(packageName);
+        Set<String> unflattenedRequestString = flatStringToSet(flatRequestString);
         for (CredentialDescription containedDescription: currentSet) {
-            if (flatRequestStrings.equals(containedDescription.getFlattenedRequestString())) {
+            if (checkForMatch(flatStringToSet(containedDescription.getFlattenedRequestString()),
+                    unflattenedRequestString)) {
                 result.add(new FilterResult(packageName,
                         containedDescription.getFlattenedRequestString(), containedDescription
                         .getCredentialEntries()));
@@ -151,12 +186,16 @@
 
     /** Returns package names of CredentialProviders that can satisfy a given
      * {@link CredentialDescription}. */
-    public Set<FilterResult> getMatchingProviders(Set<String> flatRequestString) {
+    public Set<FilterResult> getMatchingProviders(Set<String> flatRequestStrings) {
         Set<FilterResult> result = new HashSet<>();
+        Set<Set<String>> unflattenedRequestStrings = flatRequestStrings.stream().map(
+                CredentialDescriptionRegistry::flatStringToSet).collect(Collectors.toSet());
         for (String packageName: mCredentialDescriptions.keySet()) {
             Set<CredentialDescription> currentSet = mCredentialDescriptions.get(packageName);
             for (CredentialDescription containedDescription : currentSet) {
-                if (flatRequestString.contains(containedDescription.getFlattenedRequestString())) {
+                if (canProviderSatisfyAny(flatStringToSet(containedDescription
+                                .getFlattenedRequestString()),
+                        unflattenedRequestStrings)) {
                     result.add(new FilterResult(packageName,
                             containedDescription.getFlattenedRequestString(), containedDescription
                             .getCredentialEntries()));
@@ -172,4 +211,24 @@
         }
     }
 
+    private static boolean canProviderSatisfyAny(Set<String> registeredUnflattenedStrings,
+            Set<Set<String>> requestedUnflattenedStrings) {
+        for (Set<String> requestedUnflattenedString : requestedUnflattenedStrings) {
+            if (registeredUnflattenedStrings.containsAll(requestedUnflattenedString)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    static boolean checkForMatch(Set<String> registeredUnflattenedStrings,
+            Set<String> requestedUnflattenedString) {
+        return registeredUnflattenedStrings.containsAll(requestedUnflattenedString);
+    }
+
+    static Set<String> flatStringToSet(String flatString) {
+        return new HashSet<>(Arrays
+                .asList(flatString.split(FLAT_STRING_SPLIT_REGEX)));
+    }
+
 }
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
index 7a4e7df..4c5c366 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
@@ -29,22 +29,20 @@
 import android.content.Context;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.ServiceInfo;
 import android.credentials.ClearCredentialStateRequest;
 import android.credentials.CreateCredentialException;
 import android.credentials.CreateCredentialRequest;
-import android.credentials.CredentialDescription;
 import android.credentials.CredentialManager;
 import android.credentials.CredentialOption;
+import android.credentials.CredentialProviderInfo;
 import android.credentials.GetCredentialException;
 import android.credentials.GetCredentialRequest;
 import android.credentials.IClearCredentialStateCallback;
 import android.credentials.ICreateCredentialCallback;
 import android.credentials.ICredentialManager;
 import android.credentials.IGetCredentialCallback;
-import android.credentials.IListEnabledProvidersCallback;
+import android.credentials.IGetPendingCredentialCallback;
 import android.credentials.ISetEnabledProvidersCallback;
-import android.credentials.ListEnabledProvidersResponse;
 import android.credentials.RegisterCredentialDescriptionRequest;
 import android.credentials.UnregisterCredentialDescriptionRequest;
 import android.credentials.ui.IntentFactory;
@@ -56,7 +54,7 @@
 import android.provider.DeviceConfig;
 import android.provider.Settings;
 import android.service.credentials.CallingAppInfo;
-import android.service.credentials.CredentialProviderInfo;
+import android.service.credentials.CredentialProviderInfoFactory;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
@@ -64,6 +62,8 @@
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.server.credentials.metrics.ApiName;
+import com.android.server.credentials.metrics.ApiStatus;
 import com.android.server.infra.AbstractMasterSystemService;
 import com.android.server.infra.SecureSettingsServiceNameResolver;
 
@@ -84,7 +84,7 @@
  */
 public final class CredentialManagerService
         extends AbstractMasterSystemService<
-                CredentialManagerService, CredentialManagerServiceImpl> {
+        CredentialManagerService, CredentialManagerServiceImpl> {
 
     private static final String TAG = "CredManSysService";
     private static final String DEVICE_CONFIG_ENABLE_CREDENTIAL_DESC_API =
@@ -116,10 +116,11 @@
             int resolvedUserId) {
         List<CredentialManagerServiceImpl> services = new ArrayList<>();
         List<CredentialProviderInfo> serviceInfos =
-                CredentialProviderInfo.getAvailableSystemServices(
+                CredentialProviderInfoFactory.getAvailableSystemServices(
                         mContext,
                         resolvedUserId,
-                        /* disableSystemAppVerificationForTests= */ false);
+                        /* disableSystemAppVerificationForTests= */ false,
+                        new HashSet<>());
         serviceInfos.forEach(
                 info -> {
                     services.add(
@@ -220,10 +221,18 @@
         return hasPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS);
     }
 
-    private void verifyPermission(String permission) throws SecurityException {
-        if (!hasPermission(permission)) {
-            throw new SecurityException("Caller is missing permission: " + permission);
+    private void verifyGetProvidersPermission() throws SecurityException {
+        if (hasPermission(android.Manifest.permission.QUERY_ALL_PACKAGES)) {
+            return;
         }
+
+        if (hasPermission(android.Manifest.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS)) {
+            return;
+        }
+
+        throw new SecurityException(
+                "Caller is missing permission: QUERY_ALL_PACKAGES or "
+                        + "LIST_ENABLED_CREDENTIAL_PROVIDERS");
     }
 
     private boolean hasPermission(String permission) {
@@ -267,7 +276,8 @@
         final long origId = Binder.clearCallingIdentity();
         try {
             return DeviceConfig.getBoolean(
-                DeviceConfig.NAMESPACE_CREDENTIAL, DEVICE_CONFIG_ENABLE_CREDENTIAL_DESC_API, false);
+                    DeviceConfig.NAMESPACE_CREDENTIAL, DEVICE_CONFIG_ENABLE_CREDENTIAL_DESC_API,
+                    false);
         } finally {
             Binder.restoreCallingIdentity(origId);
         }
@@ -282,13 +292,15 @@
         List<ProviderSession> providerSessions = new ArrayList<>();
         for (Pair<CredentialOption, CredentialDescriptionRegistry.FilterResult> result :
                 activeCredentialContainers) {
-            providerSessions.add(
-                    ProviderRegistryGetSession.createNewSession(
-                            mContext,
-                            UserHandle.getCallingUserId(),
-                            session,
-                            result.second.mPackageName,
-                            result.first));
+            ProviderSession providerSession = ProviderRegistryGetSession.createNewSession(
+                    mContext,
+                    UserHandle.getCallingUserId(),
+                    session,
+                    session.mClientAppInfo,
+                    result.second.mPackageName,
+                    result.first);
+            providerSessions.add(providerSession);
+            session.addProviderSession(providerSession.getComponentName(), providerSession);
         }
         return providerSessions;
     }
@@ -317,11 +329,16 @@
         Set<Pair<CredentialOption, CredentialDescriptionRegistry.FilterResult>> result =
                 new HashSet<>();
 
-        for (CredentialDescriptionRegistry.FilterResult filterResult: filterResults) {
-            for (CredentialOption credentialOption: options) {
-                if (filterResult.mFlattenedRequest.equals(credentialOption
-                        .getCredentialRetrievalData()
-                        .getString(CredentialOption.FLATTENED_REQUEST))) {
+        for (CredentialDescriptionRegistry.FilterResult filterResult : filterResults) {
+            Set<String> registeredUnflattenedStrings = CredentialDescriptionRegistry
+                    .flatStringToSet(filterResult.mFlattenedRequest);
+            for (CredentialOption credentialOption : options) {
+                Set<String> requestedUnflattenedStrings = CredentialDescriptionRegistry
+                        .flatStringToSet(credentialOption
+                                .getCredentialRetrievalData()
+                                .getString(CredentialOption.FLATTENED_REQUEST));
+                if (CredentialDescriptionRegistry.checkForMatch(registeredUnflattenedStrings,
+                        requestedUnflattenedStrings)) {
                     result.add(new Pair<>(credentialOption, filterResult));
                 }
             }
@@ -349,6 +366,14 @@
         return providerSessions;
     }
 
+    private List<CredentialProviderInfo> getServicesForCredentialDescription(int userId) {
+        return CredentialProviderInfoFactory.getCredentialProviderServices(
+                mContext,
+                userId,
+                CredentialManager.PROVIDER_FILTER_ALL_PROVIDERS,
+                new HashSet<>());
+    }
+
     @Override
     @GuardedBy("CredentialDescriptionRegistry.sLock")
     public void onUserStopped(@NonNull TargetUser user) {
@@ -364,13 +389,13 @@
         CallingAppInfo callingAppInfo;
         try {
             packageInfo =
-                getContext()
-                    .getPackageManager()
-                    .getPackageInfoAsUser(
-                            realPackageName,
-                        PackageManager.PackageInfoFlags.of(
-                            PackageManager.GET_SIGNING_CERTIFICATES),
-                        userId);
+                    getContext()
+                            .getPackageManager()
+                            .getPackageInfoAsUser(
+                                    realPackageName,
+                                    PackageManager.PackageInfoFlags.of(
+                                            PackageManager.GET_SIGNING_CERTIFICATES),
+                                    userId);
             callingAppInfo = new CallingAppInfo(realPackageName, packageInfo.signingInfo, origin);
         } catch (PackageManager.NameNotFoundException e) {
             Log.i(TAG, "Issue while retrieving signatureInfo : " + e.getMessage());
@@ -385,6 +410,7 @@
                 GetCredentialRequest request,
                 IGetCredentialCallback callback,
                 final String callingPackage) {
+            final long timestampBegan = System.nanoTime();
             Log.i(TAG, "starting executeGetCredential with callingPackage: " + callingPackage);
             ICancellationSignal cancelTransport = CancellationSignal.createTransport();
 
@@ -406,12 +432,24 @@
                             callback,
                             request,
                             constructCallingAppInfo(callingPackage, userId, request.getOrigin()),
-                            CancellationSignal.fromTransport(cancelTransport));
+                            CancellationSignal.fromTransport(cancelTransport),
+                            timestampBegan);
 
             processGetCredential(request, callback, session);
             return cancelTransport;
         }
 
+        @Override
+        public ICancellationSignal executeGetPendingCredential(
+                GetCredentialRequest request,
+                IGetPendingCredentialCallback callback,
+                final String callingPackage) {
+            // TODO(b/273308895): implement
+
+            ICancellationSignal cancelTransport = CancellationSignal.createTransport();
+            return cancelTransport;
+        }
+
         private void processGetCredential(
                 GetCredentialRequest request,
                 IGetCredentialCallback callback,
@@ -421,41 +459,41 @@
             if (isCredentialDescriptionApiEnabled()) {
                 List<CredentialOption> optionsThatRequireActiveCredentials =
                         request.getCredentialOptions().stream()
-                        .filter(
-                            getCredentialOption ->
-                                !TextUtils.isEmpty(
-                                    getCredentialOption
-                                        .getCredentialRetrievalData()
-                                        .getString(
-                                            CredentialOption
-                                                .FLATTENED_REQUEST,
-                                            null)))
-                        .toList();
+                                .filter(
+                                        getCredentialOption ->
+                                                !TextUtils.isEmpty(
+                                                        getCredentialOption
+                                                                .getCredentialRetrievalData()
+                                                                .getString(
+                                                                        CredentialOption
+                                                                                .FLATTENED_REQUEST,
+                                                                        null)))
+                                .toList();
 
                 List<CredentialOption> optionsThatDoNotRequireActiveCredentials =
                         request.getCredentialOptions().stream()
-                        .filter(
-                            getCredentialOption ->
-                                TextUtils.isEmpty(
-                                    getCredentialOption
-                                        .getCredentialRetrievalData()
-                                        .getString(
-                                            CredentialOption
-                                                .FLATTENED_REQUEST,
-                                            null)))
-                        .toList();
+                                .filter(
+                                        getCredentialOption ->
+                                                TextUtils.isEmpty(
+                                                        getCredentialOption
+                                                                .getCredentialRetrievalData()
+                                                                .getString(
+                                                                        CredentialOption
+                                                                                .FLATTENED_REQUEST,
+                                                                        null)))
+                                .toList();
 
                 List<ProviderSession> sessionsWithoutRemoteService =
                         initiateProviderSessionsWithActiveContainers(
-                        session,
-                        getFilteredResultFromRegistry(optionsThatRequireActiveCredentials));
+                                session,
+                                getFilteredResultFromRegistry(optionsThatRequireActiveCredentials));
 
                 List<ProviderSession> sessionsWithRemoteService =
                         initiateProviderSessions(
-                        session,
-                        optionsThatDoNotRequireActiveCredentials.stream()
-                            .map(CredentialOption::getType)
-                            .collect(Collectors.toList()));
+                                session,
+                                optionsThatDoNotRequireActiveCredentials.stream()
+                                        .map(CredentialOption::getType)
+                                        .collect(Collectors.toList()));
 
                 Set<ProviderSession> all = new LinkedHashSet<>();
                 all.addAll(sessionsWithRemoteService);
@@ -465,11 +503,11 @@
             } else {
                 // Initiate all provider sessions
                 providerSessions =
-                    initiateProviderSessions(
-                        session,
-                        request.getCredentialOptions().stream()
-                            .map(CredentialOption::getType)
-                            .collect(Collectors.toList()));
+                        initiateProviderSessions(
+                                session,
+                                request.getCredentialOptions().stream()
+                                        .map(CredentialOption::getType)
+                                        .collect(Collectors.toList()));
             }
 
             if (providerSessions.isEmpty()) {
@@ -481,10 +519,13 @@
                     Log.i(
                             TAG,
                             "Issue invoking onError on IGetCredentialCallback "
-                                + "callback: "
-                                + e.getMessage());
+                                    + "callback: "
+                                    + e.getMessage());
                 }
             }
+
+            finalizeAndEmitInitialPhaseMetric(session);
+            // TODO(b/271135048) - May still be worth emitting in the empty cases above.
             providerSessions.forEach(ProviderSession::invokeSession);
         }
 
@@ -493,6 +534,7 @@
                 CreateCredentialRequest request,
                 ICreateCredentialCallback callback,
                 String callingPackage) {
+            final long timestampBegan = System.nanoTime();
             Log.i(TAG, "starting executeCreateCredential with callingPackage: "
                     + callingPackage);
             ICancellationSignal cancelTransport = CancellationSignal.createTransport();
@@ -515,7 +557,8 @@
                             request,
                             callback,
                             constructCallingAppInfo(callingPackage, userId, request.getOrigin()),
-                            CancellationSignal.fromTransport(cancelTransport));
+                            CancellationSignal.fromTransport(cancelTransport),
+                            timestampBegan);
 
             processCreateCredential(request, callback, session);
             return cancelTransport;
@@ -538,47 +581,20 @@
                     Log.i(
                             TAG,
                             "Issue invoking onError on ICreateCredentialCallback "
-                                + "callback: "
-                                + e.getMessage());
+                                    + "callback: "
+                                    + e.getMessage());
                 }
             }
 
+            finalizeAndEmitInitialPhaseMetric(session);
             // Iterate over all provider sessions and invoke the request
             providerSessions.forEach(ProviderSession::invokeSession);
         }
 
-        @SuppressWarnings("GuardedBy") // ErrorProne requires listEnabledProviders
-        // to be guarded by 'service.mLock', which is the same as mLock.
-        @Override
-        public ICancellationSignal listEnabledProviders(IListEnabledProvidersCallback callback) {
-            Log.i(TAG, "listEnabledProviders");
-            ICancellationSignal cancelTransport = CancellationSignal.createTransport();
-
-            if (!hasWriteSecureSettingsPermission()) {
-                try {
-                    callback.onError(
-                            PERMISSION_DENIED_ERROR, PERMISSION_DENIED_WRITE_SECURE_SETTINGS_ERROR);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Issue with invoking response: " + e.getMessage());
-                }
-                return cancelTransport;
-            }
-
-            List<String> enabledProviders = new ArrayList<>();
-            runForUser(
-                    (service) -> {
-                        enabledProviders.add(service.getComponentName().flattenToString());
-                    });
-
-            // Call the callback.
-            try {
-                callback.onResponse(ListEnabledProvidersResponse.create(enabledProviders));
-            } catch (RemoteException e) {
-                Log.i(TAG, "Issue with invoking response: " + e.getMessage());
-                // TODO: Propagate failure
-            }
-
-            return cancelTransport;
+        private void finalizeAndEmitInitialPhaseMetric(RequestSession session) {
+            var initMetric = session.mInitialPhaseMetric;
+            initMetric.setCredentialServiceBeginQueryTimeNanoseconds(System.nanoTime());
+            MetricUtilities.logApiCalled(initMetric);
         }
 
         @Override
@@ -654,13 +670,18 @@
                     if (serviceComponentName.equals(componentName)) {
                         if (!s.getServicePackageName().equals(callingPackage)) {
                             // The component name and the package name do not match.
+                            MetricUtilities.logApiCalled(
+                                    ApiName.IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE,
+                                    ApiStatus.FAILURE, callingUid);
                             Log.w(
                                     TAG,
                                     "isEnabledCredentialProviderService: Component name does not"
                                             + " match package name.");
                             return false;
                         }
-
+                        MetricUtilities.logApiCalled(ApiName.IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE,
+                                ApiStatus.SUCCESS, callingUid);
+                        // TODO(b/271135048) - Update asap to use the new logging types
                         return true;
                     }
                 }
@@ -670,20 +691,45 @@
         }
 
         @Override
-        public List<ServiceInfo> getCredentialProviderServices(
-                int userId, boolean disableSystemAppVerificationForTests, int providerFilter) {
+        public List<CredentialProviderInfo> getCredentialProviderServices(
+                int userId, int providerFilter) {
             Log.i(TAG, "getCredentialProviderServices");
-            verifyPermission(android.Manifest.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS);
+            verifyGetProvidersPermission();
 
-            List<ServiceInfo> services = new ArrayList<>();
-            List<CredentialProviderInfo> providers =
-                    CredentialProviderInfo.getCredentialProviderServices(
-                            mContext, userId, disableSystemAppVerificationForTests, providerFilter);
-            for (CredentialProviderInfo p : providers) {
-                services.add(p.getServiceInfo());
+            return CredentialProviderInfoFactory.getCredentialProviderServices(
+                    mContext, userId, providerFilter, getEnabledProviders());
+        }
+
+        @Override
+        public List<CredentialProviderInfo> getCredentialProviderServicesForTesting(
+                int providerFilter) {
+            Log.i(TAG, "getCredentialProviderServicesForTesting");
+            verifyGetProvidersPermission();
+
+            final int userId = UserHandle.getCallingUserId();
+            return CredentialProviderInfoFactory.getCredentialProviderServicesForTesting(
+                    mContext, userId, providerFilter, getEnabledProviders());
+        }
+
+        @SuppressWarnings("GuardedBy") // ErrorProne requires service.mLock which is the same
+        // this.mLock
+        private Set<ComponentName> getEnabledProviders() {
+            Set<ComponentName> enabledProviders = new HashSet<>();
+            synchronized (mLock) {
+                runForUser(
+                        (service) -> {
+                            try {
+                                enabledProviders.add(
+                                        service.getCredentialProviderInfo()
+                                                .getServiceInfo().getComponentName());
+                            } catch (NullPointerException e) {
+                                // Safe check
+                                Log.i(TAG, "Skipping provider as either the providerInfo"
+                                        + "or serviceInfo is null - weird");
+                            }
+                        });
             }
-
-            return services;
+            return enabledProviders;
         }
 
         @Override
@@ -691,6 +737,7 @@
                 ClearCredentialStateRequest request,
                 IClearCredentialStateCallback callback,
                 String callingPackage) {
+            final long timestampBegan = System.nanoTime();
             Log.i(TAG, "starting clearCredentialState with callingPackage: " + callingPackage);
             final int userId = UserHandle.getCallingUserId();
             int callingUid = Binder.getCallingUid();
@@ -708,7 +755,8 @@
                             callback,
                             request,
                             constructCallingAppInfo(callingPackage, userId, null),
-                            CancellationSignal.fromTransport(cancelTransport));
+                            CancellationSignal.fromTransport(cancelTransport),
+                            timestampBegan);
 
             // Initiate all provider sessions
             // TODO: Determine if provider needs to have clear capability in their manifest
@@ -727,6 +775,8 @@
                 }
             }
 
+            finalizeAndEmitInitialPhaseMetric(session);
+
             // Iterate over all provider sessions and invoke the request
             providerSessions.forEach(ProviderSession::invokeSession);
             return cancelTransport;
@@ -744,44 +794,6 @@
 
             enforceCallingPackage(callingPackage, Binder.getCallingUid());
 
-            List<CredentialProviderInfo> services =
-                getServicesForCredentialDescription(UserHandle.getCallingUserId());
-
-            List<String> providers =
-                    services.stream()
-                            .map(
-                                    credentialProviderInfo ->
-                                            credentialProviderInfo.getServiceInfo().packageName)
-                            .toList();
-
-            if (!providers.contains(callingPackage)) {
-                throw new NonCredentialProviderCallerException(callingPackage);
-            }
-
-            List<CredentialProviderInfo> matchingService =
-                    services.stream()
-                            .filter(
-                                    credentialProviderInfo ->
-                                            credentialProviderInfo
-                                                    .getServiceInfo()
-                                                    .packageName
-                                                    .equals(callingPackage))
-                            .toList();
-
-            CredentialProviderInfo credentialProviderInfo = matchingService.get(0);
-
-            Set<String> supportedTypes =
-                    request.getCredentialDescriptions().stream()
-                            .map(CredentialDescription::getType)
-                            .filter(credentialProviderInfo::hasCapability)
-                            .collect(Collectors.toSet());
-
-            if (supportedTypes.size() != request.getCredentialDescriptions().size()) {
-                throw new IllegalArgumentException(
-                        "CredentialProvider does not support one or more"
-                                + "of the registered types. Check your XML entry.");
-            }
-
             CredentialDescriptionRegistry session =
                     CredentialDescriptionRegistry.forUser(UserHandle.getCallingUserId());
 
@@ -800,33 +812,11 @@
 
             enforceCallingPackage(callingPackage, Binder.getCallingUid());
 
-            List<CredentialProviderInfo> services =
-                getServicesForCredentialDescription(UserHandle.getCallingUserId());
-
-            List<String> providers =
-                    services.stream()
-                            .map(
-                                    credentialProviderInfo ->
-                                            credentialProviderInfo.getServiceInfo().packageName)
-                            .toList();
-
-            if (!providers.contains(callingPackage)) {
-                throw new NonCredentialProviderCallerException(callingPackage);
-            }
-
             CredentialDescriptionRegistry session =
                     CredentialDescriptionRegistry.forUser(UserHandle.getCallingUserId());
 
             session.executeUnregisterRequest(request, callingPackage);
         }
-
-        private List<CredentialProviderInfo> getServicesForCredentialDescription(int userId) {
-            return CredentialProviderInfo.getCredentialProviderServices(
-                    mContext,
-                    userId,
-                    /* disableSystemAppVerificationForTests= */ false,
-                    CredentialManager.PROVIDER_FILTER_ALL_PROVIDERS);
-        }
     }
 
     private void enforceCallingPackage(String callingPackage, int callingUid) {
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java b/services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java
index 546c48f..ee55a1c 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java
@@ -21,7 +21,8 @@
 import android.content.ComponentName;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
-import android.service.credentials.CredentialProviderInfo;
+import android.credentials.CredentialProviderInfo;
+import android.service.credentials.CredentialProviderInfoFactory;
 import android.util.Log;
 import android.util.Slog;
 
@@ -82,7 +83,7 @@
             Log.i(TAG, "newServiceInfoLocked with null mInfo , "
                     + serviceComponent.getPackageName());
         }
-        mInfo = new CredentialProviderInfo(
+        mInfo = CredentialProviderInfoFactory.create(
                 getContext(), serviceComponent,
                 mUserId, /*isSystemProvider=*/false);
         return mInfo.getServiceInfo();
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java b/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java
index 2c6c0d8..546c37f 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java
@@ -22,6 +22,7 @@
 import android.content.Intent;
 import android.content.pm.ServiceInfo;
 import android.credentials.CredentialManager;
+import android.credentials.CredentialProviderInfo;
 import android.credentials.ui.DisabledProviderData;
 import android.credentials.ui.IntentFactory;
 import android.credentials.ui.ProviderData;
@@ -31,11 +32,12 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.ResultReceiver;
-import android.service.credentials.CredentialProviderInfo;
+import android.service.credentials.CredentialProviderInfoFactory;
 import android.util.Log;
 import android.util.Slog;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.Set;
 import java.util.UUID;
 import java.util.stream.Collectors;
@@ -118,11 +120,11 @@
                 .map(ProviderData::getProviderFlattenedComponentName)
                 .collect(Collectors.toUnmodifiableSet());
         Set<String> allProviders =
-                CredentialProviderInfo.getCredentialProviderServices(
+                CredentialProviderInfoFactory.getCredentialProviderServices(
                                 mContext,
                                 mUserId,
-                                /* disableSystemAppVerificationForTests= */ false,
-                                CredentialManager.PROVIDER_FILTER_USER_PROVIDERS_ONLY)
+                                CredentialManager.PROVIDER_FILTER_USER_PROVIDERS_ONLY,
+                                new HashSet<>())
                         .stream()
                         .map(CredentialProviderInfo::getServiceInfo)
                         .map(ServiceInfo::getComponentName)
diff --git a/services/credentials/java/com/android/server/credentials/GetRequestSession.java b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
index 32b14d7..00fbbba 100644
--- a/services/credentials/java/com/android/server/credentials/GetRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
@@ -16,12 +16,11 @@
 
 package com.android.server.credentials;
 
-import static com.android.server.credentials.MetricUtilities.METRICS_PROVIDER_STATUS_FINAL_FAILURE;
-import static com.android.server.credentials.MetricUtilities.METRICS_PROVIDER_STATUS_FINAL_SUCCESS;
-
 import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
+import android.credentials.CredentialOption;
+import android.credentials.CredentialProviderInfo;
 import android.credentials.GetCredentialException;
 import android.credentials.GetCredentialRequest;
 import android.credentials.GetCredentialResponse;
@@ -31,24 +30,33 @@
 import android.os.CancellationSignal;
 import android.os.RemoteException;
 import android.service.credentials.CallingAppInfo;
-import android.service.credentials.CredentialProviderInfo;
 import android.util.Log;
 
+import com.android.server.credentials.metrics.ApiName;
+import com.android.server.credentials.metrics.ApiStatus;
+import com.android.server.credentials.metrics.ProviderStatusForMetrics;
+
 import java.util.ArrayList;
+import java.util.stream.Collectors;
 
 /**
  * Central session for a single getCredentials request. This class listens to the
  * responses from providers, and the UX app, and updates the provider(S) state.
  */
-public final class GetRequestSession extends RequestSession<GetCredentialRequest,
+public class GetRequestSession extends RequestSession<GetCredentialRequest,
         IGetCredentialCallback>
         implements ProviderSession.ProviderInternalCallback<GetCredentialResponse> {
     private static final String TAG = "GetRequestSession";
     public GetRequestSession(Context context, int userId, int callingUid,
             IGetCredentialCallback callback, GetCredentialRequest request,
-            CallingAppInfo callingAppInfo, CancellationSignal cancellationSignal) {
+            CallingAppInfo callingAppInfo, CancellationSignal cancellationSignal,
+            long startedTimestamp) {
         super(context, userId, callingUid, request, callback, RequestInfo.TYPE_GET,
-                callingAppInfo, cancellationSignal);
+                callingAppInfo, cancellationSignal, startedTimestamp);
+        int numTypes = (request.getCredentialOptions().stream()
+                .map(CredentialOption::getType).collect(
+                Collectors.toSet())).size(); // Dedupe type strings
+        setupInitialPhaseMetric(ApiName.GET_CREDENTIAL.getMetricCode(), numTypes);
     }
 
     /**
@@ -74,12 +82,14 @@
 
     @Override
     protected void launchUiWithProviderData(ArrayList<ProviderData> providerDataList) {
+        mChosenProviderFinalPhaseMetric.setUiCallStartTimeNanoseconds(System.nanoTime());
         try {
             mClientCallback.onPendingIntent(mCredentialManagerUi.createPendingIntent(
                     RequestInfo.newGetRequestInfo(
                     mRequestId, mClientRequest, mClientAppInfo.getPackageName()),
                     providerDataList));
         } catch (RemoteException e) {
+            mChosenProviderFinalPhaseMetric.setUiReturned(false);
             respondToClientWithErrorAndFinish(
                     GetCredentialException.TYPE_UNKNOWN, "Unable to instantiate selector");
         }
@@ -88,15 +98,17 @@
     @Override
     public void onFinalResponseReceived(ComponentName componentName,
             @Nullable GetCredentialResponse response) {
+        mChosenProviderFinalPhaseMetric.setUiReturned(true);
+        mChosenProviderFinalPhaseMetric.setUiCallEndTimeNanoseconds(System.nanoTime());
         Log.i(TAG, "onFinalCredentialReceived from: " + componentName.flattenToString());
         setChosenMetric(componentName);
         if (response != null) {
-            mChosenProviderMetric.setChosenProviderStatus(
-                    METRICS_PROVIDER_STATUS_FINAL_SUCCESS);
+            mChosenProviderFinalPhaseMetric.setChosenProviderStatus(
+                    ProviderStatusForMetrics.FINAL_SUCCESS.getMetricCode());
             respondToClientWithResponseAndFinish(response);
         } else {
-            mChosenProviderMetric.setChosenProviderStatus(
-                    METRICS_PROVIDER_STATUS_FINAL_FAILURE);
+            mChosenProviderFinalPhaseMetric.setChosenProviderStatus(
+                    ProviderStatusForMetrics.FINAL_FAILURE.getMetricCode());
             respondToClientWithErrorAndFinish(GetCredentialException.TYPE_NO_CREDENTIAL,
                     "Invalid response from provider");
         }
@@ -116,17 +128,19 @@
             return;
         }
         if (isSessionCancelled()) {
-            // TODO: Differentiate btw cancelled and false
-            logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
+            logApiCall(ApiName.GET_CREDENTIAL, /* apiStatus */
+                    ApiStatus.CLIENT_CANCELED);
             finishSession(/*propagateCancellation=*/true);
             return;
         }
         try {
             mClientCallback.onResponse(response);
-            logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ true);
+            logApiCall(ApiName.GET_CREDENTIAL, /* apiStatus */
+                    ApiStatus.SUCCESS);
         } catch (RemoteException e) {
             Log.i(TAG, "Issue while responding to client with a response : " + e.getMessage());
-            logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
+            logApiCall(ApiName.GET_CREDENTIAL, /* apiStatus */
+                    ApiStatus.FAILURE);
         }
         finishSession(/*propagateCancellation=*/false);
     }
@@ -137,7 +151,8 @@
             return;
         }
         if (isSessionCancelled()) {
-            logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
+            logApiCall(ApiName.GET_CREDENTIAL, /* apiStatus */
+                    ApiStatus.CLIENT_CANCELED);
             finishSession(/*propagateCancellation=*/true);
             return;
         }
@@ -147,10 +162,20 @@
         } catch (RemoteException e) {
             Log.i(TAG, "Issue while responding to client with error : " + e.getMessage());
         }
-        logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
+        logFailureOrUserCancel(errorType);
         finishSession(/*propagateCancellation=*/false);
     }
 
+    private void logFailureOrUserCancel(String errorType) {
+        if (GetCredentialException.TYPE_USER_CANCELED.equals(errorType)) {
+            logApiCall(ApiName.GET_CREDENTIAL,
+                    /* apiStatus */ ApiStatus.USER_CANCELED);
+        } else {
+            logApiCall(ApiName.GET_CREDENTIAL,
+                    /* apiStatus */ ApiStatus.FAILURE);
+        }
+    }
+
     @Override
     public void onUiCancellation(boolean isUserCancellation) {
         if (isUserCancellation) {
diff --git a/services/credentials/java/com/android/server/credentials/MetricUtilities.java b/services/credentials/java/com/android/server/credentials/MetricUtilities.java
index 27d9836d..ed139b5 100644
--- a/services/credentials/java/com/android/server/credentials/MetricUtilities.java
+++ b/services/credentials/java/com/android/server/credentials/MetricUtilities.java
@@ -16,25 +16,20 @@
 
 package com.android.server.credentials;
 
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CLEAR_CREDENTIAL;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CREATE_CREDENTIAL;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_GET_CREDENTIAL;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_UNKNOWN;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_CLIENT_CANCELED;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_FAILURE;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_SUCCESS;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_USER_CANCELED;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_FINAL_FAILURE;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_FINAL_SUCCESS;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_QUERY_FAILURE;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_QUERY_SUCCESS;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_UNKNOWN;
-
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.util.Log;
 
+import com.android.internal.util.FrameworkStatsLog;
+import com.android.server.credentials.metrics.ApiName;
+import com.android.server.credentials.metrics.ApiStatus;
+import com.android.server.credentials.metrics.CandidatePhaseMetric;
+import com.android.server.credentials.metrics.ChosenProviderFinalPhaseMetric;
+import com.android.server.credentials.metrics.InitialPhaseMetric;
+
+import java.util.Map;
+
 /**
  * For all future metric additions, this will contain their names for local usage after importing
  * from {@link com.android.internal.util.FrameworkStatsLog}.
@@ -43,40 +38,18 @@
 
     private static final String TAG = "MetricUtilities";
 
-    // Metrics constants
-    protected static final int METRICS_API_NAME_UNKNOWN =
-            CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_UNKNOWN;
-    protected static final int METRICS_API_NAME_GET_CREDENTIAL =
-            CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_GET_CREDENTIAL;
-    protected static final int METRICS_API_NAME_CREATE_CREDENTIAL =
-            CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CREATE_CREDENTIAL;
-    protected static final int METRICS_API_NAME_CLEAR_CREDENTIAL =
-            CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CLEAR_CREDENTIAL;
-    // TODO add isEnabled
-    protected static final int METRICS_API_STATUS_SUCCESS =
-            CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_SUCCESS;
-    protected static final int METRICS_API_STATUS_FAILURE =
-            CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_FAILURE;
-    protected static final int METRICS_API_STATUS_CLIENT_CANCEL =
-            CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_CLIENT_CANCELED;
-    protected static final int METRICS_API_STATUS_USER_CANCEL =
-            CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_USER_CANCELED;
-    protected static final int METRICS_PROVIDER_STATUS_FINAL_FAILURE =
-            CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_FINAL_FAILURE;
-    protected static final int METRICS_PROVIDER_STATUS_QUERY_FAILURE =
-            CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_QUERY_FAILURE;
-    protected static final int METRICS_PROVIDER_STATUS_FINAL_SUCCESS =
-            CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_FINAL_SUCCESS;
-    protected static final int METRICS_PROVIDER_STATUS_QUERY_SUCCESS =
-            CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_QUERY_SUCCESS;
-    protected static final int METRICS_PROVIDER_STATUS_UNKNOWN =
-            CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_UNKNOWN;
-
+    public static final int DEFAULT_INT_32 = -1;
+    public static final int[] DEFAULT_REPEATED_INT_32 = new int[0];
+    // Used for single count metric emits, such as singular amounts of various types
+    public static final int UNIT = 1;
+    // Used for zero count metric emits, such as zero amounts of various types
+    public static final int ZERO = 0;
 
     /**
      * This retrieves the uid of any package name, given a context and a component name for the
      * package. By default, if the desired package uid cannot be found, it will fall back to a
      * bogus uid.
+     *
      * @return the uid of a given package
      */
     protected static int getPackageUid(Context context, ComponentName componentName) {
@@ -92,4 +65,113 @@
         return sessUid;
     }
 
+    /**
+     * Given any two timestamps in nanoseconds, this gets the difference and converts to
+     * milliseconds. Assumes the difference is not larger than the maximum int size.
+     *
+     * @param t2 the final timestamp
+     * @param t1 the initial timestamp
+     * @return the timestamp difference converted to microseconds
+     */
+    protected static int getMetricTimestampDifferenceMicroseconds(long t2, long t1) {
+        if (t2 - t1 > Integer.MAX_VALUE) {
+            throw new ArithmeticException("Input timestamps are too far apart and unsupported");
+        }
+        return (int) ((t2 - t1) / 1000);
+    }
+
+    /**
+     * The most common logging helper, handles the overall status of the API request with the
+     * provider status and latencies. Other versions of this method may be more useful depending
+     * on the situation, as this is geared towards the logging of {@link ProviderSession} types.
+     *
+     * @param apiName              the api type to log
+     * @param apiStatus            the api status to log
+     * @param providers            a map with known providers
+     * @param callingUid           the calling UID of the client app
+     * @param chosenProviderFinalPhaseMetric the metric data type of the final chosen provider
+     */
+    protected static void logApiCalled(ApiName apiName, ApiStatus apiStatus,
+            Map<String, ProviderSession> providers, int callingUid,
+            ChosenProviderFinalPhaseMetric chosenProviderFinalPhaseMetric) {
+        try {
+            var providerSessions = providers.values();
+            int providerSize = providerSessions.size();
+            int[] candidateUidList = new int[providerSize];
+            int[] candidateQueryRoundTripTimeList = new int[providerSize];
+            int[] candidateStatusList = new int[providerSize];
+            int index = 0;
+            for (var session : providerSessions) {
+                CandidatePhaseMetric metric = session.mCandidatePhasePerProviderMetric;
+                candidateUidList[index] = metric.getCandidateUid();
+                candidateQueryRoundTripTimeList[index] = metric.getQueryLatencyMicroseconds();
+                candidateStatusList[index] = metric.getProviderQueryStatus();
+                index++;
+            }
+            FrameworkStatsLog.write(FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED,
+                    /* api_name */apiName.getMetricCode(),
+                    /* caller_uid */ callingUid,
+                    /* api_status */ apiStatus.getMetricCode(),
+                    /* repeated_candidate_provider_uid */ candidateUidList,
+                    /* repeated_candidate_provider_round_trip_time_query_microseconds */
+                    candidateQueryRoundTripTimeList,
+                    /* repeated_candidate_provider_status */ candidateStatusList,
+                    /* chosen_provider_uid */ chosenProviderFinalPhaseMetric.getChosenUid(),
+                    /* chosen_provider_round_trip_time_overall_microseconds */
+                    chosenProviderFinalPhaseMetric.getEntireProviderLatencyMicroseconds(),
+                    /* chosen_provider_final_phase_microseconds (backwards compat only) */
+                    DEFAULT_INT_32,
+                    /* chosen_provider_status */ chosenProviderFinalPhaseMetric
+                            .getChosenProviderStatus());
+        } catch (Exception e) {
+            Log.w(TAG, "Unexpected error during metric logging: " + e);
+        }
+    }
+
+    /**
+     * This is useful just to record an API calls' final event, and for no other purpose. It will
+     * contain default values for all other optional parameters.
+     *
+     * TODO(b/271135048) - given space requirements, this may be a good candidate for another atom
+     *
+     * @param apiName    the api name to log
+     * @param apiStatus  the status to log
+     * @param callingUid the calling uid
+     */
+    protected static void logApiCalled(ApiName apiName, ApiStatus apiStatus,
+            int callingUid) {
+        try {
+            FrameworkStatsLog.write(FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED,
+                    /* api_name */apiName.getMetricCode(),
+                    /* caller_uid */ callingUid,
+                    /* api_status */ apiStatus.getMetricCode(),
+                    /* repeated_candidate_provider_uid */  DEFAULT_REPEATED_INT_32,
+                    /* repeated_candidate_provider_round_trip_time_query_microseconds */
+                    DEFAULT_REPEATED_INT_32,
+                    /* repeated_candidate_provider_status */ DEFAULT_REPEATED_INT_32,
+                    /* chosen_provider_uid */ DEFAULT_INT_32,
+                    /* chosen_provider_round_trip_time_overall_microseconds */
+                    DEFAULT_INT_32,
+                    /* chosen_provider_final_phase_microseconds */
+                    DEFAULT_INT_32,
+                    /* chosen_provider_status */ DEFAULT_INT_32);
+        } catch (Exception e) {
+            Log.w(TAG, "Unexpected error during metric logging: " + e);
+        }
+    }
+
+    /**
+     * Handles the metric emit for the initial phase.
+     *
+     * @param initialPhaseMetric contains all the data for this emit
+     */
+    protected static void logApiCalled(InitialPhaseMetric initialPhaseMetric) {
+        /*
+        FrameworkStatsLog.write(FrameworkStatsLog.INITIAL_PHASE,
+        .. session_id .. initialPhaseMetric.getSessionId(),
+        ...
+        TODO Immediately - Fill in asap now that the split atom is checked in.
+         */
+    }
+
 }
diff --git a/services/credentials/java/com/android/server/credentials/ProviderClearSession.java b/services/credentials/java/com/android/server/credentials/ProviderClearSession.java
index ce9fca7..950cf4f 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderClearSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderClearSession.java
@@ -20,11 +20,11 @@
 import android.annotation.UserIdInt;
 import android.content.Context;
 import android.credentials.ClearCredentialStateException;
+import android.credentials.CredentialProviderInfo;
 import android.credentials.ui.ProviderData;
 import android.credentials.ui.ProviderPendingIntentResponse;
 import android.service.credentials.CallingAppInfo;
 import android.service.credentials.ClearCredentialStateRequest;
-import android.service.credentials.CredentialProviderInfo;
 import android.util.Log;
 import android.util.Slog;
 
@@ -72,7 +72,8 @@
             ProviderInternalCallback callbacks,
             int userId, RemoteCredentialService remoteCredentialService,
             ClearCredentialStateRequest providerRequest) {
-        super(context, info, providerRequest, callbacks, userId, remoteCredentialService);
+        super(context, providerRequest, callbacks, info.getComponentName(),
+                userId, remoteCredentialService);
         setStatus(Status.PENDING);
     }
 
@@ -95,7 +96,7 @@
     /** Called when provider service dies. */
     @Override // Callback from the remote provider
     public void onProviderServiceDied(RemoteCredentialService service) {
-        if (service.getComponentName().equals(mProviderInfo.getServiceInfo().getComponentName())) {
+        if (service.getComponentName().equals(mComponentName)) {
             updateStatusAndInvokeCallback(Status.SERVICE_DEAD);
         } else {
             Slog.i(TAG, "Component names different in onProviderServiceDied - "
@@ -119,8 +120,15 @@
     @Override
     protected void invokeSession() {
         if (mRemoteCredentialService != null) {
+            /*
+            InitialPhaseMetric initMetric = ((RequestSession)mCallbacks).initMetric;
+            TODO immediately once the other change patched through
+            mCandidateProviderMetric.setSessionId(initMetric
+            .mInitialPhaseMetric.getSessionId());
+            mCandidateProviderMetric.setStartTime(initMetric.getStartTime())
+             */
+            mCandidatePhasePerProviderMetric.setStartQueryTimeNanoseconds(System.nanoTime());
             mRemoteCredentialService.onClearCredentialState(mProviderRequest, this);
-            mCandidateProviderMetric.setStartTimeNanoseconds(System.nanoTime());
         }
     }
 }
diff --git a/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java b/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
index 3245c91..3ec0fc0 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
@@ -24,6 +24,7 @@
 import android.content.Intent;
 import android.credentials.CreateCredentialException;
 import android.credentials.CreateCredentialResponse;
+import android.credentials.CredentialProviderInfo;
 import android.credentials.ui.CreateCredentialProviderData;
 import android.credentials.ui.Entry;
 import android.credentials.ui.ProviderPendingIntentResponse;
@@ -33,8 +34,8 @@
 import android.service.credentials.CallingAppInfo;
 import android.service.credentials.CreateCredentialRequest;
 import android.service.credentials.CreateEntry;
-import android.service.credentials.CredentialProviderInfo;
 import android.service.credentials.CredentialProviderService;
+import android.service.credentials.RemoteEntry;
 import android.util.Log;
 import android.util.Pair;
 import android.util.Slog;
@@ -132,11 +133,12 @@
             @NonNull BeginCreateCredentialRequest beginCreateRequest,
             @NonNull CreateCredentialRequest completeCreateRequest,
             String hybridService) {
-        super(context, info, beginCreateRequest, callbacks, userId,
+        super(context, beginCreateRequest, callbacks, info.getComponentName(), userId,
                 remoteCredentialService);
         mCompleteRequest = completeCreateRequest;
         setStatus(Status.PENDING);
-        mProviderResponseDataHandler = new ProviderResponseDataHandler(hybridService);
+        mProviderResponseDataHandler = new ProviderResponseDataHandler(
+                ComponentName.unflattenFromString(hybridService));
     }
 
     @Override
@@ -159,7 +161,7 @@
     /** Called when provider service dies. */
     @Override
     public void onProviderServiceDied(RemoteCredentialService service) {
-        if (service.getComponentName().equals(mProviderInfo.getServiceInfo().getComponentName())) {
+        if (service.getComponentName().equals(mComponentName)) {
             updateStatusAndInvokeCallback(Status.SERVICE_DEAD);
         } else {
             Slog.i(TAG, "Component names different in onProviderServiceDied - "
@@ -224,8 +226,15 @@
     @Override
     protected void invokeSession() {
         if (mRemoteCredentialService != null) {
+            /*
+            InitialPhaseMetric initMetric = ((RequestSession)mCallbacks).initMetric;
+            TODO immediately once the other change patched through
+            mCandidateProviderMetric.setSessionId(initMetric
+            .mInitialPhaseMetric.getSessionId());
+            mCandidateProviderMetric.setStartTime(initMetric.getStartTime())
+             */
+            mCandidatePhasePerProviderMetric.setStartQueryTimeNanoseconds(System.nanoTime());
             mRemoteCredentialService.onCreateCredential(mProviderRequest, this);
-            mCandidateProviderMetric.setStartTimeNanoseconds(System.nanoTime());
         }
     }
 
@@ -296,21 +305,23 @@
     }
 
     private class ProviderResponseDataHandler {
-        private final ComponentName mExpectedRemoteEntryProviderService;
+        @Nullable private final ComponentName mExpectedRemoteEntryProviderService;
 
         @NonNull
         private final Map<String, Pair<CreateEntry, Entry>> mUiCreateEntries = new HashMap<>();
 
-        @Nullable private Pair<String, Pair<CreateEntry, Entry>> mUiRemoteEntry = null;
+        @Nullable private Pair<String, Pair<RemoteEntry, Entry>> mUiRemoteEntry = null;
 
-        ProviderResponseDataHandler(String hybridService) {
-            mExpectedRemoteEntryProviderService = ComponentName.unflattenFromString(hybridService);
+        ProviderResponseDataHandler(@Nullable ComponentName expectedRemoteEntryProviderService) {
+            mExpectedRemoteEntryProviderService = expectedRemoteEntryProviderService;
         }
 
         public void addResponseContent(List<CreateEntry> createEntries,
-                CreateEntry remoteEntry) {
+                RemoteEntry remoteEntry) {
             createEntries.forEach(this::addCreateEntry);
-            setRemoteEntry(remoteEntry);
+            if (remoteEntry != null) {
+                setRemoteEntry(remoteEntry);
+            }
         }
         public void addCreateEntry(CreateEntry createEntry) {
             String id = generateUniqueId();
@@ -319,14 +330,14 @@
             mUiCreateEntries.put(id, new Pair<>(createEntry, entry));
         }
 
-        public void setRemoteEntry(@Nullable CreateEntry remoteEntry) {
-            if (remoteEntry == null) {
-                mUiRemoteEntry = null;
+        public void setRemoteEntry(@Nullable RemoteEntry remoteEntry) {
+            if (!enforceRemoteEntryRestrictions(mExpectedRemoteEntryProviderService)) {
+                Log.i(TAG, "Remote entry being dropped as it does not meet the restriction"
+                        + "checks.");
                 return;
             }
-            if (!mComponentName.equals(mExpectedRemoteEntryProviderService)) {
-                Log.i(TAG, "Remote entry being dropped as it is not from the service "
-                        + "configured by the OEM.");
+            if (remoteEntry == null) {
+                mUiRemoteEntry = null;
                 return;
             }
             String id = generateUniqueId();
@@ -363,7 +374,7 @@
             return mUiCreateEntries.isEmpty() && mUiRemoteEntry == null;
         }
         @Nullable
-        public CreateEntry getRemoteEntry(String entryKey) {
+        public RemoteEntry getRemoteEntry(String entryKey) {
             return mUiRemoteEntry == null || mUiRemoteEntry
                     .first == null || !mUiRemoteEntry.first.equals(entryKey)
                     || mUiRemoteEntry.second == null
diff --git a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
index 8c94b0a..ec8bf22 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.credentials.CredentialOption;
+import android.credentials.CredentialProviderInfo;
 import android.credentials.GetCredentialException;
 import android.credentials.GetCredentialResponse;
 import android.credentials.ui.AuthenticationEntry;
@@ -35,9 +36,9 @@
 import android.service.credentials.BeginGetCredentialResponse;
 import android.service.credentials.CallingAppInfo;
 import android.service.credentials.CredentialEntry;
-import android.service.credentials.CredentialProviderInfo;
 import android.service.credentials.CredentialProviderService;
 import android.service.credentials.GetCredentialRequest;
+import android.service.credentials.RemoteEntry;
 import android.util.Log;
 import android.util.Pair;
 import android.util.Slog;
@@ -60,13 +61,13 @@
         RemoteCredentialService.ProviderCallbacks<BeginGetCredentialResponse> {
     private static final String TAG = "ProviderGetSession";
     // Key to be used as the entry key for an action entry
-    private static final String ACTION_ENTRY_KEY = "action_key";
+    public static final String ACTION_ENTRY_KEY = "action_key";
     // Key to be used as the entry key for the authentication entry
-    private static final String AUTHENTICATION_ACTION_ENTRY_KEY = "authentication_action_key";
+    public static final String AUTHENTICATION_ACTION_ENTRY_KEY = "authentication_action_key";
     // Key to be used as an entry key for a remote entry
-    private static final String REMOTE_ENTRY_KEY = "remote_entry_key";
+    public static final String REMOTE_ENTRY_KEY = "remote_entry_key";
     // Key to be used as an entry key for a credential entry
-    private static final String CREDENTIAL_ENTRY_KEY = "credential_key";
+    public static final String CREDENTIAL_ENTRY_KEY = "credential_key";
 
     @NonNull
     private final Map<String, CredentialOption> mBeginGetOptionToCredentialOptionMap;
@@ -168,7 +169,8 @@
             CallingAppInfo callingAppInfo,
             Map<String, CredentialOption> beginGetOptionToCredentialOptionMap,
             String hybridService) {
-        super(context, info, beginGetRequest, callbacks, userId, remoteCredentialService);
+        super(context, beginGetRequest, callbacks, info.getComponentName() ,
+                userId, remoteCredentialService);
         mCompleteRequest = completeGetRequest;
         mCallingAppInfo = callingAppInfo;
         setStatus(Status.PENDING);
@@ -180,7 +182,6 @@
     /** Called when the provider response has been updated by an external source. */
     @Override // Callback from the remote provider
     public void onProviderResponseSuccess(@Nullable BeginGetCredentialResponse response) {
-        Log.i(TAG, "in onProviderResponseSuccess");
         onSetInitialRemoteResponse(response);
     }
 
@@ -196,7 +197,7 @@
     /** Called when provider service dies. */
     @Override // Callback from the remote provider
     public void onProviderServiceDied(RemoteCredentialService service) {
-        if (service.getComponentName().equals(mProviderInfo.getServiceInfo().getComponentName())) {
+        if (service.getComponentName().equals(mComponentName)) {
             updateStatusAndInvokeCallback(Status.SERVICE_DEAD);
         } else {
             Slog.i(TAG, "Component names different in onProviderServiceDied - "
@@ -268,8 +269,15 @@
     @Override
     protected void invokeSession() {
         if (mRemoteCredentialService != null) {
+            /*
+            InitialPhaseMetric initMetric = ((RequestSession)mCallbacks).initMetric;
+            TODO immediately once the other change patched through
+            mCandidateProviderMetric.setSessionId(initMetric
+            .mInitialPhaseMetric.getSessionId());
+            mCandidateProviderMetric.setStartTime(initMetric.getStartTime())
+             */
+            mCandidatePhasePerProviderMetric.setStartQueryTimeNanoseconds(System.nanoTime());
             mRemoteCredentialService.onBeginGetCredential(mProviderRequest, this);
-            mCandidateProviderMetric.setStartTimeNanoseconds(System.nanoTime());
         }
     }
 
@@ -299,7 +307,7 @@
         }
         return new Intent().putExtra(CredentialProviderService.EXTRA_GET_CREDENTIAL_REQUEST,
                 new GetCredentialRequest(
-                        mCallingAppInfo, mBeginGetOptionToCredentialOptionMap.get(id)));
+                        mCallingAppInfo, List.of(mBeginGetOptionToCredentialOptionMap.get(id))));
     }
 
     private Intent setUpFillInIntentWithQueryRequest() {
@@ -392,7 +400,7 @@
                 .extractResponseContent(providerPendingIntentResponse
                         .getResultData());
         if (response != null && !mProviderResponseDataHandler.isEmptyResponse(response)) {
-            addToInitialRemoteResponse(response);
+            addToInitialRemoteResponse(response, /*isInitialResponse=*/ false);
             // Additional content received is in the form of new response content.
             return true;
         }
@@ -400,7 +408,8 @@
         return false;
     }
 
-    private void addToInitialRemoteResponse(BeginGetCredentialResponse content) {
+    private void addToInitialRemoteResponse(BeginGetCredentialResponse content,
+            boolean isInitialResponse) {
         if (content == null) {
             return;
         }
@@ -408,53 +417,40 @@
                 content.getCredentialEntries(),
                 content.getActions(),
                 content.getAuthenticationActions(),
-                content.getRemoteCredentialEntry()
+                content.getRemoteCredentialEntry(),
+                isInitialResponse
         );
     }
 
     /** Returns true if either an exception or a response is found. */
     private void onActionEntrySelected(ProviderPendingIntentResponse
             providerPendingIntentResponse) {
-        // Action entry is expected to either contain the final GetCredentialResponse, or it is
-        // also acceptable if it does not contain anything. In the second case, we re-show this
-        // action on the UI.
-        if (providerPendingIntentResponse == null) {
-            Log.i(TAG, "providerPendingIntentResponse is null");
-            return;
-        }
-
-        GetCredentialException exception = maybeGetPendingIntentException(
-                providerPendingIntentResponse);
-        if (exception != null) {
-            invokeCallbackWithError(exception.getType(), exception.getMessage());
-        }
-        GetCredentialResponse response = PendingIntentResultHandler
-                .extractGetCredentialResponse(
-                        providerPendingIntentResponse.getResultData());
-        if (response != null) {
-            mCallbacks.onFinalResponseReceived(mComponentName, response);
-        }
+        Log.i(TAG, "onActionEntrySelected");
+        onCredentialEntrySelected(providerPendingIntentResponse);
     }
 
 
     /** Updates the response being maintained in state by this provider session. */
     private void onSetInitialRemoteResponse(BeginGetCredentialResponse response) {
         mProviderResponse = response;
-        addToInitialRemoteResponse(response);
+        addToInitialRemoteResponse(response, /*isInitialResponse=*/true);
+        // Log the data.
         if (mProviderResponseDataHandler.isEmptyResponse(response)) {
             updateStatusAndInvokeCallback(Status.EMPTY_RESPONSE);
             return;
         }
+        // TODO immediately, add to Candidate Phase counts, repeat across all sessions
+        // Use sets to dedup type counts
         updateStatusAndInvokeCallback(Status.CREDENTIALS_RECEIVED);
     }
 
     /**
      * When an invalid state occurs, e.g. entry mismatch or no response from provider,
-     * we send back a TYPE_UNKNOWN error as to the developer.
+     * we send back a TYPE_NO_CREDENTIAL error as to the developer.
      */
     private void invokeCallbackOnInternalInvalidState() {
         mCallbacks.onFinalErrorReceived(mComponentName,
-                GetCredentialException.TYPE_UNKNOWN, null);
+                GetCredentialException.TYPE_NO_CREDENTIAL, null);
     }
 
     /** Update auth entries status based on an auth entry selected from a different session. */
@@ -479,7 +475,7 @@
     }
 
     private class ProviderResponseDataHandler {
-        private final ComponentName mExpectedRemoteEntryProviderService;
+        @Nullable private final ComponentName mExpectedRemoteEntryProviderService;
         @NonNull
         private final Map<String, Pair<CredentialEntry, Entry>> mUiCredentialEntries =
                 new HashMap<>();
@@ -489,28 +485,35 @@
         private final Map<String, Pair<Action, AuthenticationEntry>> mUiAuthenticationEntries =
                 new HashMap<>();
 
-        @Nullable private Pair<String, Pair<CredentialEntry, Entry>> mUiRemoteEntry = null;
+        @Nullable private Pair<String, Pair<RemoteEntry, Entry>> mUiRemoteEntry = null;
 
-        ProviderResponseDataHandler(ComponentName expectedRemoteEntryProviderService) {
+        ProviderResponseDataHandler(@Nullable ComponentName expectedRemoteEntryProviderService) {
             mExpectedRemoteEntryProviderService = expectedRemoteEntryProviderService;
         }
 
         public void addResponseContent(List<CredentialEntry> credentialEntries,
                 List<Action> actions, List<Action> authenticationActions,
-                CredentialEntry remoteEntry) {
+                RemoteEntry remoteEntry, boolean isInitialResponse) {
             credentialEntries.forEach(this::addCredentialEntry);
             actions.forEach(this::addAction);
             authenticationActions.forEach(
                     authenticationAction -> addAuthenticationAction(authenticationAction,
                             AuthenticationEntry.STATUS_LOCKED));
-            setRemoteEntry(remoteEntry);
+            // In the query phase, it is likely most providers will return a null remote entry
+            // so no need to invoke the setter since it adds the overhead of checking for the
+            // hybrid permission, and then sets an already null value to null.
+            // If this is not the query phase, e.g. response after a locked entry is unlocked
+            // then it is valid for the provider to remove the remote entry, and so we allow
+            // them to set it to null.
+            if (remoteEntry != null || !isInitialResponse) {
+                setRemoteEntry(remoteEntry);
+            }
         }
         public void addCredentialEntry(CredentialEntry credentialEntry) {
             String id = generateUniqueId();
             Entry entry = new Entry(CREDENTIAL_ENTRY_KEY,
                     id, credentialEntry.getSlice(),
-                    setUpFillInIntent(credentialEntry
-                            .getBeginGetCredentialOption().getId()));
+                    setUpFillInIntent(credentialEntry.getBeginGetCredentialOptionId()));
             mUiCredentialEntries.put(id, new Pair<>(credentialEntry, entry));
         }
 
@@ -539,22 +542,24 @@
             mUiAuthenticationEntries.remove(id);
         }
 
-        public void setRemoteEntry(@Nullable CredentialEntry remoteEntry) {
-            if (remoteEntry == null) {
+        public void setRemoteEntry(@Nullable RemoteEntry remoteEntry) {
+            if (!enforceRemoteEntryRestrictions(mExpectedRemoteEntryProviderService)) {
+                Log.i(TAG, "Remote entry being dropped as it does not meet the restriction"
+                        + " checks.");
                 return;
             }
-            if (!mComponentName.equals(mExpectedRemoteEntryProviderService)) {
-                Log.i(TAG, "Remote entry being dropped as it is not from the service "
-                        + "configured by the OEM.");
+            if (remoteEntry == null) {
+                mUiRemoteEntry = null;
                 return;
             }
             String id = generateUniqueId();
             Entry entry = new Entry(REMOTE_ENTRY_KEY,
-                    id, remoteEntry.getSlice(), setUpFillInIntent(
-                            remoteEntry.getBeginGetCredentialOption().getId()));
-            mUiRemoteEntry = new Pair<>(generateUniqueId(), new Pair<>(remoteEntry, entry));
+                    id, remoteEntry.getSlice(), setUpFillInIntentForRemoteEntry());
+            mUiRemoteEntry = new Pair<>(id, new Pair<>(remoteEntry, entry));
         }
 
+
+
         public GetCredentialProviderData toGetCredentialProviderData() {
             return new GetCredentialProviderData.Builder(
                     mComponentName.flattenToString()).setActionChips(prepareActionEntries())
@@ -588,7 +593,6 @@
             return credEntries;
         }
 
-
         private Entry prepareRemoteEntry() {
             if (mUiRemoteEntry == null || mUiRemoteEntry.first == null
                     || mUiRemoteEntry.second == null) {
@@ -621,7 +625,7 @@
         }
 
         @Nullable
-        public CredentialEntry getRemoteEntry(String entryKey) {
+        public RemoteEntry getRemoteEntry(String entryKey) {
             return mUiRemoteEntry.first.equals(entryKey) && mUiRemoteEntry.second != null
                     ? mUiRemoteEntry.second.first : null;
         }
@@ -679,4 +683,10 @@
                     from.getFrameworkExtrasIntent());
         }
     }
+
+    private Intent setUpFillInIntentForRemoteEntry() {
+        return new Intent().putExtra(CredentialProviderService.EXTRA_GET_CREDENTIAL_REQUEST,
+                new GetCredentialRequest(
+                        mCallingAppInfo, mCompleteRequest.getCredentialOptions()));
+    }
 }
diff --git a/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java b/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java
index a57cb5f..a5196c5 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.credentials.CredentialOption;
@@ -33,6 +34,8 @@
 import android.service.credentials.CredentialProviderService;
 import android.telecom.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -52,7 +55,8 @@
         Set<CredentialDescriptionRegistry.FilterResult>> {
 
     private static final String TAG = "ProviderRegistryGetSession";
-    private static final String CREDENTIAL_ENTRY_KEY = "credential_key";
+    @VisibleForTesting
+    static final String CREDENTIAL_ENTRY_KEY = "credential_key";
 
     /** Creates a new provider session to be used by the request session. */
     @Nullable
@@ -60,13 +64,14 @@
             @NonNull Context context,
             @UserIdInt int userId,
             @NonNull GetRequestSession getRequestSession,
+            @NonNull CallingAppInfo callingAppInfo,
             @NonNull String credentialProviderPackageName,
             @NonNull CredentialOption requestOption) {
         return new ProviderRegistryGetSession(
                 context,
                 userId,
                 getRequestSession,
-                getRequestSession.mClientAppInfo,
+                callingAppInfo,
                 credentialProviderPackageName,
                 requestOption);
     }
@@ -81,7 +86,8 @@
     private final String mCredentialProviderPackageName;
     @NonNull
     private final String mFlattenedRequestOptionString;
-    private List<CredentialEntry> mCredentialEntries;
+    @VisibleForTesting
+    List<CredentialEntry> mCredentialEntries;
 
     protected ProviderRegistryGetSession(@NonNull Context context,
             @NonNull int userId,
@@ -89,7 +95,9 @@
             @NonNull CallingAppInfo callingAppInfo,
             @NonNull String servicePackageName,
             @NonNull CredentialOption requestOption) {
-        super(context, null, requestOption, session, userId, null);
+        super(context, requestOption, session,
+                new ComponentName(servicePackageName, servicePackageName) ,
+                userId, null);
         mCredentialDescriptionRegistry = CredentialDescriptionRegistry.forUser(userId);
         mCallingAppInfo = callingAppInfo;
         mCredentialProviderPackageName = servicePackageName;
@@ -121,7 +129,7 @@
                 CredentialProviderService
                         .EXTRA_GET_CREDENTIAL_REQUEST,
                 new android.service.credentials.GetCredentialRequest(
-                        mCallingAppInfo, mProviderRequest));
+                        mCallingAppInfo, List.of(mProviderRequest)));
         return intent;
     }
 
@@ -183,7 +191,7 @@
                             providerPendingIntentResponse.getResultData());
             if (getCredentialResponse != null) {
                 if (mCallbacks != null) {
-                    mCallbacks.onFinalResponseReceived(mComponentName,
+                    ((GetRequestSession) mCallbacks).onFinalResponseReceived(mComponentName,
                             getCredentialResponse);
                 }
                 return;
diff --git a/services/credentials/java/com/android/server/credentials/ProviderSession.java b/services/credentials/java/com/android/server/credentials/ProviderSession.java
index ecddcf3..77d4e77 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderSession.java
@@ -16,27 +16,29 @@
 
 package com.android.server.credentials;
 
-import static com.android.server.credentials.MetricUtilities.METRICS_PROVIDER_STATUS_QUERY_FAILURE;
-import static com.android.server.credentials.MetricUtilities.METRICS_PROVIDER_STATUS_QUERY_SUCCESS;
-
+import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 import android.credentials.Credential;
+import android.credentials.CredentialProviderInfo;
 import android.credentials.ui.ProviderData;
 import android.credentials.ui.ProviderPendingIntentResponse;
 import android.os.ICancellationSignal;
 import android.os.RemoteException;
-import android.service.credentials.CredentialProviderInfo;
 import android.util.Log;
 
-import com.android.server.credentials.metrics.CandidateProviderMetric;
+import com.android.server.credentials.metrics.CandidatePhaseMetric;
+import com.android.server.credentials.metrics.ProviderStatusForMetrics;
 
 import java.util.UUID;
 
 /**
  * Provider session storing the state of provider response and ui entries.
+ *
  * @param <T> The request to be sent to the provider
  * @param <R> The response to be expected from the provider
  */
@@ -45,21 +47,35 @@
 
     private static final String TAG = "ProviderSession";
 
-    @NonNull protected final Context mContext;
-    @NonNull protected final ComponentName mComponentName;
-    @Nullable protected final CredentialProviderInfo mProviderInfo;
-    @Nullable protected final RemoteCredentialService mRemoteCredentialService;
-    @NonNull protected final int mUserId;
-    @NonNull protected Status mStatus = Status.NOT_STARTED;
-    @Nullable protected final ProviderInternalCallback mCallbacks;
-    @Nullable protected Credential mFinalCredentialResponse;
-    @Nullable protected ICancellationSignal mProviderCancellationSignal;
-    @NonNull protected final T mProviderRequest;
-    @Nullable protected R mProviderResponse;
-    @NonNull protected Boolean mProviderResponseSet = false;
+    @NonNull
+    protected final Context mContext;
+    @NonNull
+    protected final ComponentName mComponentName;
+    @Nullable
+    protected final CredentialProviderInfo mProviderInfo;
+    @Nullable
+    protected final RemoteCredentialService mRemoteCredentialService;
+    @NonNull
+    protected final int mUserId;
+    @NonNull
+    protected Status mStatus = Status.NOT_STARTED;
+    @Nullable
+    protected final ProviderInternalCallback mCallbacks;
+    @Nullable
+    protected Credential mFinalCredentialResponse;
+    @Nullable
+    protected ICancellationSignal mProviderCancellationSignal;
+    @NonNull
+    protected final T mProviderRequest;
+    @Nullable
+    protected R mProviderResponse;
+    @NonNull
+    protected Boolean mProviderResponseSet = false;
     // Specific candidate provider metric for the provider this session handles
-    @Nullable protected CandidateProviderMetric mCandidateProviderMetric;
-    @NonNull private int mProviderSessionUid;
+    @Nullable
+    protected CandidatePhaseMetric mCandidatePhasePerProviderMetric;
+    @NonNull
+    private int mProviderSessionUid;
 
     /**
      * Returns true if the given status reflects that the provider state is ready to be shown
@@ -99,6 +115,7 @@
      * Interface to be implemented by any class that wishes to get a callback when a particular
      * provider session's status changes. Typically, implemented by the {@link RequestSession}
      * class.
+     *
      * @param <V> the type of the final response expected
      */
     public interface ProviderInternalCallback<V> {
@@ -113,19 +130,20 @@
                 @Nullable String message);
     }
 
-    protected ProviderSession(@NonNull Context context, @NonNull CredentialProviderInfo info,
+    protected ProviderSession(@NonNull Context context,
             @NonNull T providerRequest,
             @Nullable ProviderInternalCallback callbacks,
+            @NonNull ComponentName componentName,
             @NonNull int userId,
             @Nullable RemoteCredentialService remoteCredentialService) {
         mContext = context;
-        mProviderInfo = info;
+        mProviderInfo = null;
         mProviderRequest = providerRequest;
         mCallbacks = callbacks;
         mUserId = userId;
-        mComponentName = info.getServiceInfo().getComponentName();
+        mComponentName = componentName;
         mRemoteCredentialService = remoteCredentialService;
-        mCandidateProviderMetric = new CandidateProviderMetric();
+        mCandidatePhasePerProviderMetric = new CandidatePhaseMetric();
         mProviderSessionUid = MetricUtilities.getPackageUid(mContext, mComponentName);
     }
 
@@ -156,7 +174,7 @@
     }
 
     public Credential getFinalCredentialResponse() {
-        return  mFinalCredentialResponse;
+        return mFinalCredentialResponse;
     }
 
     /** Propagates cancellation signal to the remote provider service. */
@@ -190,7 +208,7 @@
         return mRemoteCredentialService;
     }
 
-    /** Updates the status .*/
+    /** Updates the status . */
     protected void updateStatusAndInvokeCallback(@NonNull Status status) {
         setStatus(status);
         updateCandidateMetric(status);
@@ -198,13 +216,18 @@
     }
 
     private void updateCandidateMetric(Status status) {
-        mCandidateProviderMetric.setCandidateUid(mProviderSessionUid);
-        mCandidateProviderMetric
+        mCandidatePhasePerProviderMetric.setCandidateUid(mProviderSessionUid);
+        // TODO immediately update the candidate phase here to have more new data
+        mCandidatePhasePerProviderMetric
                 .setQueryFinishTimeNanoseconds(System.nanoTime());
         if (isTerminatingStatus(status)) {
-            mCandidateProviderMetric.setProviderQueryStatus(METRICS_PROVIDER_STATUS_QUERY_FAILURE);
+            mCandidatePhasePerProviderMetric.setProviderQueryStatus(
+                    ProviderStatusForMetrics.QUERY_FAILURE
+                            .getMetricCode());
         } else if (isCompletionStatus(status)) {
-            mCandidateProviderMetric.setProviderQueryStatus(METRICS_PROVIDER_STATUS_QUERY_SUCCESS);
+            mCandidatePhasePerProviderMetric.setProviderQueryStatus(
+                    ProviderStatusForMetrics.QUERY_SUCCESS
+                            .getMetricCode());
         }
     }
 
@@ -224,19 +247,58 @@
     }
 
     /** Update the response state stored with the provider session. */
-    @Nullable protected R getProviderResponse() {
+    @Nullable
+    protected R getProviderResponse() {
         return mProviderResponse;
     }
 
-    /** Should be overridden to prepare, and stores state for {@link ProviderData} to be
-     * shown on the UI. */
-    @Nullable protected abstract ProviderData prepareUiData();
+    protected boolean enforceRemoteEntryRestrictions(
+            @Nullable ComponentName expectedRemoteEntryProviderService) {
+        // Check if the service is the one set by the OEM. If not silently reject this entry
+        if (!mComponentName.equals(expectedRemoteEntryProviderService)) {
+            Log.i(TAG, "Remote entry being dropped as it is not from the service "
+                    + "configured by the OEM.");
+            return false;
+        }
+        // Check if the service has the hybrid permission .If not, silently reject this entry.
+        // This check is in addition to the permission check happening in the provider's process.
+        try {
+            ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo(
+                    mComponentName.getPackageName(),
+                    PackageManager.ApplicationInfoFlags.of(PackageManager.MATCH_SYSTEM_ONLY));
+            if (appInfo != null
+                    && mContext.checkPermission(
+                    Manifest.permission.PROVIDE_REMOTE_CREDENTIALS,
+                    /*pId=*/-1, appInfo.uid) == PackageManager.PERMISSION_GRANTED) {
+                return true;
+            }
+        } catch (SecurityException e) {
+            Log.i(TAG, "Error getting info for "
+                    + mComponentName.flattenToString() + ": " + e.getMessage());
+            return false;
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.i(TAG, "Error getting info for "
+                    + mComponentName.flattenToString() + ": " + e.getMessage());
+            return false;
+        }
+        Log.i(TAG, "In enforceRemoteEntryRestrictions - remote entry checks fail");
+        return false;
+    }
+
+    /**
+     * Should be overridden to prepare, and stores state for {@link ProviderData} to be
+     * shown on the UI.
+     */
+    @Nullable
+    protected abstract ProviderData prepareUiData();
 
     /** Should be overridden to handle the selected entry from the UI. */
     protected abstract void onUiEntrySelected(String entryType, String entryId,
             ProviderPendingIntentResponse providerPendingIntentResponse);
 
-    /** Should be overridden to invoke the provider at a defined location. Helpful for
-     * situations such as metric generation. */
+    /**
+     * Should be overridden to invoke the provider at a defined location. Helpful for
+     * situations such as metric generation.
+     */
     protected abstract void invokeSession();
 }
diff --git a/services/credentials/java/com/android/server/credentials/RemoteCredentialService.java b/services/credentials/java/com/android/server/credentials/RemoteCredentialService.java
index 702261e..ff4e3b6 100644
--- a/services/credentials/java/com/android/server/credentials/RemoteCredentialService.java
+++ b/services/credentials/java/com/android/server/credentials/RemoteCredentialService.java
@@ -121,8 +121,6 @@
             ProviderCallbacks<BeginGetCredentialResponse> callback) {
         Log.i(TAG, "In onGetCredentials in RemoteCredentialService");
         AtomicReference<ICancellationSignal> cancellationSink = new AtomicReference<>();
-        AtomicReference<CompletableFuture<BeginGetCredentialResponse>> futureRef =
-                new AtomicReference<>();
 
         CompletableFuture<BeginGetCredentialResponse> connectThenExecute = postAsync(service -> {
             CompletableFuture<BeginGetCredentialResponse> getCredentials =
@@ -134,7 +132,6 @@
                                 new IBeginGetCredentialCallback.Stub() {
                                     @Override
                                     public void onSuccess(BeginGetCredentialResponse response) {
-                                        Log.i(TAG, "In onSuccess in RemoteCredentialService");
                                         getCredentials.complete(response);
                                     }
 
@@ -147,22 +144,15 @@
                                                 new GetCredentialException(errorType, errorMsg));
                                     }
                                 });
-                CompletableFuture<BeginGetCredentialResponse> future = futureRef.get();
-                if (future != null && future.isCancelled()) {
-                    dispatchCancellationSignal(cancellationSignal);
-                } else {
-                    cancellationSink.set(cancellationSignal);
-                }
+                cancellationSink.set(cancellationSignal);
                 return getCredentials;
             } finally {
                 Binder.restoreCallingIdentity(originalCallingUidToken);
             }
         }).orTimeout(TIMEOUT_REQUEST_MILLIS, TimeUnit.MILLISECONDS);
 
-        futureRef.set(connectThenExecute);
         connectThenExecute.whenComplete((result, error) -> Handler.getMain().post(() ->
                 handleExecutionResponse(result, error, cancellationSink, callback)));
-
         return cancellationSink.get();
     }
 
@@ -178,8 +168,6 @@
             ProviderCallbacks<BeginCreateCredentialResponse> callback) {
         Log.i(TAG, "In onCreateCredential in RemoteCredentialService");
         AtomicReference<ICancellationSignal> cancellationSink = new AtomicReference<>();
-        AtomicReference<CompletableFuture<BeginCreateCredentialResponse>> futureRef =
-                new AtomicReference<>();
 
         CompletableFuture<BeginCreateCredentialResponse> connectThenExecute =
                 postAsync(service -> {
@@ -205,19 +193,13 @@
                                                 new CreateCredentialException(errorType, errorMsg));
                                     }
                                 });
-                        CompletableFuture<BeginCreateCredentialResponse> future = futureRef.get();
-                        if (future != null && future.isCancelled()) {
-                            dispatchCancellationSignal(cancellationSignal);
-                        } else {
-                            cancellationSink.set(cancellationSignal);
-                        }
+                        cancellationSink.set(cancellationSignal);
                         return createCredentialFuture;
                     } finally {
                         Binder.restoreCallingIdentity(originalCallingUidToken);
                     }
                 }).orTimeout(TIMEOUT_REQUEST_MILLIS, TimeUnit.MILLISECONDS);
 
-        futureRef.set(connectThenExecute);
         connectThenExecute.whenComplete((result, error) -> Handler.getMain().post(() ->
                 handleExecutionResponse(result, error, cancellationSink, callback)));
 
@@ -236,7 +218,6 @@
             ProviderCallbacks<Void> callback) {
         Log.i(TAG, "In onClearCredentialState in RemoteCredentialService");
         AtomicReference<ICancellationSignal> cancellationSink = new AtomicReference<>();
-        AtomicReference<CompletableFuture<Void>> futureRef = new AtomicReference<>();
 
         CompletableFuture<Void> connectThenExecute =
                 postAsync(service -> {
@@ -263,19 +244,13 @@
                                                         errorMsg));
                                     }
                                 });
-                        CompletableFuture<Void> future = futureRef.get();
-                        if (future != null && future.isCancelled()) {
-                            dispatchCancellationSignal(cancellationSignal);
-                        } else {
-                            cancellationSink.set(cancellationSignal);
-                        }
+                        cancellationSink.set(cancellationSignal);
                         return clearCredentialFuture;
                     } finally {
                         Binder.restoreCallingIdentity(originalCallingUidToken);
                     }
                 }).orTimeout(TIMEOUT_REQUEST_MILLIS, TimeUnit.MILLISECONDS);
 
-        futureRef.set(connectThenExecute);
         connectThenExecute.whenComplete((result, error) -> Handler.getMain().post(() ->
                 handleExecutionResponse(result, error, cancellationSink, callback)));
 
diff --git a/services/credentials/java/com/android/server/credentials/RequestSession.java b/services/credentials/java/com/android/server/credentials/RequestSession.java
index f8bbfcf..ed42bb2 100644
--- a/services/credentials/java/com/android/server/credentials/RequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/RequestSession.java
@@ -16,17 +16,14 @@
 
 package com.android.server.credentials;
 
-import static com.android.server.credentials.MetricUtilities.METRICS_API_NAME_CLEAR_CREDENTIAL;
-import static com.android.server.credentials.MetricUtilities.METRICS_API_NAME_CREATE_CREDENTIAL;
-import static com.android.server.credentials.MetricUtilities.METRICS_API_NAME_GET_CREDENTIAL;
-import static com.android.server.credentials.MetricUtilities.METRICS_API_NAME_UNKNOWN;
-import static com.android.server.credentials.MetricUtilities.METRICS_API_STATUS_FAILURE;
-import static com.android.server.credentials.MetricUtilities.METRICS_API_STATUS_SUCCESS;
+import static com.android.server.credentials.MetricUtilities.logApiCalled;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.content.ComponentName;
 import android.content.Context;
+import android.credentials.CredentialProviderInfo;
 import android.credentials.ui.ProviderData;
 import android.credentials.ui.UserSelectionDialogResult;
 import android.os.Binder;
@@ -35,16 +32,20 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.service.credentials.CallingAppInfo;
-import android.service.credentials.CredentialProviderInfo;
 import android.util.Log;
 
 import com.android.internal.R;
-import com.android.internal.util.FrameworkStatsLog;
-import com.android.server.credentials.metrics.CandidateProviderMetric;
-import com.android.server.credentials.metrics.ChosenProviderMetric;
+import com.android.server.credentials.metrics.ApiName;
+import com.android.server.credentials.metrics.ApiStatus;
+import com.android.server.credentials.metrics.CandidateBrowsingPhaseMetric;
+import com.android.server.credentials.metrics.CandidatePhaseMetric;
+import com.android.server.credentials.metrics.ChosenProviderFinalPhaseMetric;
+import com.android.server.credentials.metrics.EntryEnum;
+import com.android.server.credentials.metrics.InitialPhaseMetric;
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -78,11 +79,20 @@
     protected final CancellationSignal mCancellationSignal;
 
     protected final Map<String, ProviderSession> mProviders = new HashMap<>();
-    protected ChosenProviderMetric mChosenProviderMetric = new ChosenProviderMetric();
-    //TODO improve design to allow grouped metrics per request
+    protected InitialPhaseMetric mInitialPhaseMetric = new InitialPhaseMetric();
+    protected ChosenProviderFinalPhaseMetric
+            mChosenProviderFinalPhaseMetric = new ChosenProviderFinalPhaseMetric();
+
+    // TODO(b/271135048) - Group metrics used in a scope together, such as here in RequestSession
+    // TODO(b/271135048) - Replace this with a new atom per each browsing emit (V4)
+    @Nullable
+    protected List<CandidateBrowsingPhaseMetric> mCandidateBrowsingPhaseMetric;
+    // As emits occur in sequential order, increment this counter and utilize
+    protected int mSequenceCounter = 0;
     protected final String mHybridService;
 
-    @NonNull protected RequestSessionStatus mRequestSessionStatus =
+    @NonNull
+    protected RequestSessionStatus mRequestSessionStatus =
             RequestSessionStatus.IN_PROGRESS;
 
     /** The status in which a given request session is. */
@@ -99,7 +109,7 @@
             @UserIdInt int userId, int callingUid, @NonNull T clientRequest, U clientCallback,
             @NonNull String requestType,
             CallingAppInfo callingAppInfo,
-            CancellationSignal cancellationSignal) {
+            CancellationSignal cancellationSignal, long timestampStarted) {
         mContext = context;
         mUserId = userId;
         mCallingUid = callingUid;
@@ -114,6 +124,9 @@
                 mUserId, this);
         mHybridService = context.getResources().getString(
                 R.string.config_defaultCredentialManagerHybridService);
+        mInitialPhaseMetric.setCredentialServiceStartedTimeNanoseconds(timestampStarted);
+        mInitialPhaseMetric.setSessionId(mRequestId.hashCode());
+        mInitialPhaseMetric.setCallerUid(mCallingUid);
     }
 
     public abstract ProviderSession initiateProviderSession(CredentialProviderInfo providerInfo,
@@ -121,6 +134,16 @@
 
     protected abstract void launchUiWithProviderData(ArrayList<ProviderData> providerDataList);
 
+    // Sets up the initial metric collector for use across all request session impls
+    protected void setupInitialPhaseMetric(int metricCode, int requestClassType) {
+        this.mInitialPhaseMetric.setApiName(metricCode);
+        this.mInitialPhaseMetric.setCountRequestClassType(requestClassType);
+    }
+
+    public void addProviderSession(ComponentName componentName, ProviderSession providerSession) {
+        mProviders.put(componentName.flattenToString(), providerSession);
+    }
+
     // UI callbacks
 
     @Override // from CredentialManagerUiCallbacks
@@ -141,10 +164,22 @@
             return;
         }
         Log.i(TAG, "Provider session found");
+        logBrowsingPhasePerSelect(selection, providerSession);
         providerSession.onUiEntrySelected(selection.getEntryKey(),
                 selection.getEntrySubkey(), selection.getPendingIntentProviderResponse());
     }
 
+    private void logBrowsingPhasePerSelect(UserSelectionDialogResult selection,
+            ProviderSession providerSession) {
+        CandidateBrowsingPhaseMetric browsingPhaseMetric = new CandidateBrowsingPhaseMetric();
+        browsingPhaseMetric.setSessionId(this.mInitialPhaseMetric.getSessionId());
+        browsingPhaseMetric.setEntryEnum(
+                EntryEnum.getMetricCodeFromString(selection.getEntryKey()));
+        browsingPhaseMetric.setProviderUid(providerSession.mCandidatePhasePerProviderMetric
+                .getCandidateUid());
+        this.mCandidateBrowsingPhaseMetric.add(new CandidateBrowsingPhaseMetric());
+    }
+
     protected void finishSession(boolean propagateCancellation) {
         Log.i(TAG, "finishing session");
         if (propagateCancellation) {
@@ -162,50 +197,17 @@
         }
         return false;
     }
-    // TODO: move these definitions to a separate logging focused class.
-    enum RequestType {
-        GET_CREDENTIALS,
-        CREATE_CREDENTIALS,
-        CLEAR_CREDENTIALS,
+
+    protected void logApiCall(ApiName apiName, ApiStatus apiStatus) {
+        logApiCalled(apiName, apiStatus, mProviders, mCallingUid,
+                mChosenProviderFinalPhaseMetric);
     }
 
-    private static int getApiNameFromRequestType(RequestType requestType) {
-        switch (requestType) {
-            case GET_CREDENTIALS:
-                return METRICS_API_NAME_GET_CREDENTIAL;
-            case CREATE_CREDENTIALS:
-                return METRICS_API_NAME_CREATE_CREDENTIAL;
-            case CLEAR_CREDENTIALS:
-                return METRICS_API_NAME_CLEAR_CREDENTIAL;
-            default:
-                return METRICS_API_NAME_UNKNOWN;
-        }
-    }
-
-    protected void logApiCalled(RequestType requestType, boolean isSuccessfulOverall) {
-        var providerSessions = mProviders.values();
-        int providerSize = providerSessions.size();
-        int[] candidateUidList = new int[providerSize];
-        int[] candidateQueryRoundTripTimeList = new int[providerSize];
-        int[] candidateStatusList = new int[providerSize];
-        int index = 0;
-        for (var session : providerSessions) {
-            CandidateProviderMetric metric = session.mCandidateProviderMetric;
-            candidateUidList[index] = metric.getCandidateUid();
-            candidateQueryRoundTripTimeList[index] = metric.getQueryLatencyMs();
-            candidateStatusList[index] = metric.getProviderQueryStatus();
-            index++;
-        }
-        FrameworkStatsLog.write(FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED,
-                /* api_name */getApiNameFromRequestType(requestType), /* caller_uid */
-                mCallingUid, /* api_status */
-                isSuccessfulOverall ? METRICS_API_STATUS_SUCCESS : METRICS_API_STATUS_FAILURE,
-                candidateUidList,
-                candidateQueryRoundTripTimeList,
-                candidateStatusList, mChosenProviderMetric.getChosenUid(),
-                mChosenProviderMetric.getEntireProviderLatencyMs(),
-                mChosenProviderMetric.getFinalPhaseLatencyMs(),
-                mChosenProviderMetric.getChosenProviderStatus());
+    protected void logApiCall(ChosenProviderFinalPhaseMetric finalPhaseMetric,
+            List<CandidateBrowsingPhaseMetric> browsingPhaseMetrics) {
+        // TODO (b/270403549) - this browsing phase object is fine but also have a new emit
+        // For the returned types by authentication entries - i.e. a CandidatePhase During Browse
+        // TODO call MetricUtilities with new setup
     }
 
     protected boolean isSessionCancelled() {
@@ -247,8 +249,10 @@
         }
         if (!providerDataList.isEmpty()) {
             Log.i(TAG, "provider list not empty about to initiate ui");
+            // TODO immediately Add paths to end it (say it fails)
             if (isSessionCancelled()) {
                 Log.i(TAG, "In getProviderDataAndInitiateUi but session has been cancelled");
+                // TODO immedaitely Add paths
             } else {
                 launchUiWithProviderData(providerDataList);
             }
@@ -257,15 +261,26 @@
 
     /**
      * Called by RequestSession's upon chosen metric determination.
+     *
      * @param componentName the componentName to associate with a provider
      */
     protected void setChosenMetric(ComponentName componentName) {
-        CandidateProviderMetric metric = this.mProviders.get(componentName.flattenToString())
-                .mCandidateProviderMetric;
-        mChosenProviderMetric.setChosenUid(metric.getCandidateUid());
-        mChosenProviderMetric.setFinalFinishTimeNanoseconds(System.nanoTime());
-        mChosenProviderMetric.setQueryFinishTimeNanoseconds(
-                metric.getQueryFinishTimeNanoseconds());
-        mChosenProviderMetric.setStartTimeNanoseconds(metric.getStartTimeNanoseconds());
+        CandidatePhaseMetric metric = this.mProviders.get(componentName.flattenToString())
+                .mCandidatePhasePerProviderMetric;
+
+        mChosenProviderFinalPhaseMetric.setSessionId(metric.getSessionId());
+        mChosenProviderFinalPhaseMetric.setChosenUid(metric.getCandidateUid());
+
+        mChosenProviderFinalPhaseMetric.setQueryPhaseLatencyMicroseconds(
+                metric.getQueryLatencyMicroseconds());
+
+        mChosenProviderFinalPhaseMetric.setServiceBeganTimeNanoseconds(
+                metric.getServiceBeganTimeNanoseconds());
+        mChosenProviderFinalPhaseMetric.setQueryStartTimeNanoseconds(
+                metric.getStartQueryTimeNanoseconds());
+
+        // TODO immediately update with the entry count numbers from the candidate metrics
+
+        mChosenProviderFinalPhaseMetric.setFinalFinishTimeNanoseconds(System.nanoTime());
     }
 }
diff --git a/services/credentials/java/com/android/server/credentials/metrics/ApiName.java b/services/credentials/java/com/android/server/credentials/metrics/ApiName.java
new file mode 100644
index 0000000..d4b51df
--- /dev/null
+++ b/services/credentials/java/com/android/server/credentials/metrics/ApiName.java
@@ -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.server.credentials.metrics;
+
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CLEAR_CREDENTIAL;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CREATE_CREDENTIAL;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_GET_CREDENTIAL;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_UNKNOWN;
+
+public enum ApiName {
+    UNKNOWN(CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_UNKNOWN),
+    GET_CREDENTIAL(CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_GET_CREDENTIAL),
+    CREATE_CREDENTIAL(CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CREATE_CREDENTIAL),
+    CLEAR_CREDENTIAL(CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CLEAR_CREDENTIAL),
+    IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE(
+            CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE
+    );
+
+    private final int mInnerMetricCode;
+
+    ApiName(int innerMetricCode) {
+        this.mInnerMetricCode = innerMetricCode;
+    }
+
+    /**
+     * Gives the West-world version of the metric name.
+     *
+     * @return a code corresponding to the west world metric name
+     */
+    public int getMetricCode() {
+        return this.mInnerMetricCode;
+    }
+}
diff --git a/services/credentials/java/com/android/server/credentials/metrics/ApiStatus.java b/services/credentials/java/com/android/server/credentials/metrics/ApiStatus.java
new file mode 100644
index 0000000..22cab70
--- /dev/null
+++ b/services/credentials/java/com/android/server/credentials/metrics/ApiStatus.java
@@ -0,0 +1,46 @@
+/*
+ * 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.credentials.metrics;
+
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_CLIENT_CANCELED;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_FAILURE;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_SUCCESS;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_USER_CANCELED;
+
+public enum ApiStatus {
+    SUCCESS(CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_SUCCESS),
+    FAILURE(CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_FAILURE),
+    CLIENT_CANCELED(
+            CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_CLIENT_CANCELED),
+    USER_CANCELED(
+            CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_USER_CANCELED);
+
+    private final int mInnerMetricCode;
+
+    ApiStatus(int innerMetricCode) {
+        this.mInnerMetricCode = innerMetricCode;
+    }
+
+    /**
+     * Gives the West-world version of the metric name.
+     *
+     * @return a code corresponding to the west world metric name
+     */
+    public int getMetricCode() {
+        return this.mInnerMetricCode;
+    }
+}
diff --git a/services/credentials/java/com/android/server/credentials/metrics/CandidateBrowsingPhaseMetric.java b/services/credentials/java/com/android/server/credentials/metrics/CandidateBrowsingPhaseMetric.java
new file mode 100644
index 0000000..0e1e0389
--- /dev/null
+++ b/services/credentials/java/com/android/server/credentials/metrics/CandidateBrowsingPhaseMetric.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.credentials.metrics;
+
+/**
+ * A part of the Candidate Phase, but emitted alongside {@link ChosenProviderFinalPhaseMetric}.
+ * The user is shown various entries from the provider responses, and may selectively browse through
+ * many entries. It is possible that the initial set of browsing is for a provider that is
+ * ultimately not chosen. This metric will be gathered PER browsing click, and aggregated, so that
+ * we can understand where user interaction is more cumbersome, informing us for future
+ * improvements. This can only be complete when the browsing is finished, ending in a final user
+ * choice, or possibly a cancellation. Thus, this will be collected and emitted in the final phase,
+ * though collection will begin in the candidate phase when the user begins browsing options.
+ */
+public class CandidateBrowsingPhaseMetric {
+
+    private static final String TAG = "CandidateBrowsingPhaseMetric";
+    // The session id associated with the API Call this candidate provider is a part of, default -1
+    private int mSessionId = -1;
+    // The EntryEnum that was pressed, defaults to -1
+    private int mEntryEnum = EntryEnum.UNKNOWN.getMetricCode();
+    // The provider associated with the press, defaults to -1
+    private int mProviderUid = -1;
+
+    /* -- The session ID -- */
+
+    public void setSessionId(int sessionId) {
+        mSessionId = sessionId;
+    }
+
+    public int getSessionId() {
+        return mSessionId;
+    }
+
+    /* -- The Entry of this tap -- */
+
+    public void setEntryEnum(int entryEnum) {
+        mEntryEnum = entryEnum;
+    }
+
+    public int getEntryEnum() {
+        return mEntryEnum;
+    }
+
+    /* -- The Provider UID of this Tap -- */
+
+    public void setProviderUid(int providerUid) {
+        mProviderUid = providerUid;
+    }
+
+    public int getProviderUid() {
+        return mProviderUid;
+    }
+}
diff --git a/services/credentials/java/com/android/server/credentials/metrics/CandidatePhaseMetric.java b/services/credentials/java/com/android/server/credentials/metrics/CandidatePhaseMetric.java
new file mode 100644
index 0000000..c392d78
--- /dev/null
+++ b/services/credentials/java/com/android/server/credentials/metrics/CandidatePhaseMetric.java
@@ -0,0 +1,239 @@
+/*
+ * 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.credentials.metrics;
+
+import android.util.Log;
+
+import com.android.server.credentials.MetricUtilities;
+
+/**
+ * The central candidate provider metric object that mimics our defined metric setup.
+ * Some types are redundant across these metric collectors, but that has debug use-cases as
+ * these data-types are available at different moments of the flow (and typically, one can feed
+ * into the next).
+ * TODO(b/270403549) - iterate on this in V3+
+ */
+public class CandidatePhaseMetric {
+
+    private static final String TAG = "CandidateProviderMetric";
+    // The session id of this provider, default set to -1
+    private int mSessionId = -1;
+    // Indicates if this provider returned from the query phase, default false
+    private boolean mQueryReturned = false;
+
+    // The candidate provider uid
+    private int mCandidateUid = -1;
+
+    // Raw timestamp in nanoseconds, will be converted to microseconds for logging
+
+    //For reference, the initial log timestamp when the service started running the API call
+    private long mServiceBeganTimeNanoseconds = -1;
+    // The moment when the query phase began
+    private long mStartQueryTimeNanoseconds = -1;
+    // The moment when the query phase ended
+    private long mQueryFinishTimeNanoseconds = -1;
+
+    // The status of this particular provider
+    private int mProviderQueryStatus = -1;
+    // Indicates if an exception was thrown by this provider, false by default
+    private boolean mHasException = false;
+    // Indicates the number of total entries available. We can also locally store the entries, but
+    // cannot emit them in the current split form. TODO(b/271135048) - possibly readjust candidate
+    // entries. Also, it may be okay to remove this and instead aggregate from inner counts.
+    // Defaults to -1
+    private int mNumEntriesTotal = -1;
+    // The count of action entries from this provider, defaults to -1
+    private int mActionEntryCount = -1;
+    // The count of credential entries from this provider, defaults to -1
+    private int mCredentialEntryCount = -1;
+    // The *type-count* of the credential entries, defaults to -1
+    private int mCredentialEntryTypeCount = -1;
+    // The count of remote entries from this provider, defaults to -1
+    private int mRemoteEntryCount = -1;
+    // The count of authentication entries from this provider, defaults to -1
+    private int mAuthenticationEntryCount = -1;
+
+    public CandidatePhaseMetric() {
+    }
+
+    /* ---------- Latencies ---------- */
+
+    /* -- Timestamps -- */
+
+    public void setServiceBeganTimeNanoseconds(long serviceBeganTimeNanoseconds) {
+        this.mServiceBeganTimeNanoseconds = serviceBeganTimeNanoseconds;
+    }
+
+    public void setStartQueryTimeNanoseconds(long startQueryTimeNanoseconds) {
+        this.mStartQueryTimeNanoseconds = startQueryTimeNanoseconds;
+    }
+
+    public void setQueryFinishTimeNanoseconds(long queryFinishTimeNanoseconds) {
+        this.mQueryFinishTimeNanoseconds = queryFinishTimeNanoseconds;
+    }
+
+    public long getServiceBeganTimeNanoseconds() {
+        return this.mServiceBeganTimeNanoseconds;
+    }
+
+    public long getStartQueryTimeNanoseconds() {
+        return this.mStartQueryTimeNanoseconds;
+    }
+
+    public long getQueryFinishTimeNanoseconds() {
+        return this.mQueryFinishTimeNanoseconds;
+    }
+
+    /* -- Actual time delta latencies (for local utility) -- */
+
+    /**
+     * Returns the latency in microseconds for the query phase.
+     */
+    public int getQueryLatencyMicroseconds() {
+        return (int) ((this.getQueryFinishTimeNanoseconds()
+                - this.getStartQueryTimeNanoseconds()) / 1000);
+    }
+
+    /* --- Time Stamp Conversion to Microseconds from Reference --- */
+
+    /**
+     * We collect raw timestamps in nanoseconds for ease of collection. However, given the scope
+     * of our logging timeframe, and size considerations of the metric, we require these to give us
+     * the microsecond timestamps from the start reference point.
+     *
+     * @param specificTimestamp the timestamp to consider, must be greater than the reference
+     * @return the microsecond integer timestamp from service start to query began
+     */
+    public int getTimestampFromReferenceStartMicroseconds(long specificTimestamp) {
+        if (specificTimestamp < this.mServiceBeganTimeNanoseconds) {
+            Log.i(TAG, "The timestamp is before service started, falling back to default int");
+            return MetricUtilities.DEFAULT_INT_32;
+        }
+        return (int) ((specificTimestamp
+                - this.mServiceBeganTimeNanoseconds) / 1000);
+    }
+
+    /* ------------- Provider Query Status ------------ */
+
+    public void setProviderQueryStatus(int providerQueryStatus) {
+        this.mProviderQueryStatus = providerQueryStatus;
+    }
+
+    public int getProviderQueryStatus() {
+        return this.mProviderQueryStatus;
+    }
+
+    /* -------------- Candidate Uid ---------------- */
+
+    public void setCandidateUid(int candidateUid) {
+        this.mCandidateUid = candidateUid;
+    }
+
+    public int getCandidateUid() {
+        return this.mCandidateUid;
+    }
+
+    /* -------------- Session Id ---------------- */
+
+    public void setSessionId(int sessionId) {
+        mSessionId = sessionId;
+    }
+
+    public int getSessionId() {
+        return mSessionId;
+    }
+
+    /* -------------- Query Returned Status ---------------- */
+
+    public void setQueryReturned(boolean queryReturned) {
+        mQueryReturned = queryReturned;
+    }
+
+    public boolean isQueryReturned() {
+        return mQueryReturned;
+    }
+
+    /* -------------- Has Exception Status ---------------- */
+
+    public void setHasException(boolean hasException) {
+        mHasException = hasException;
+    }
+
+    public boolean isHasException() {
+        return mHasException;
+    }
+
+    /* -------------- Number of Entries ---------------- */
+
+    public void setNumEntriesTotal(int numEntriesTotal) {
+        mNumEntriesTotal = numEntriesTotal;
+    }
+
+    public int getNumEntriesTotal() {
+        return mNumEntriesTotal;
+    }
+
+    /* -------------- Count of Action Entries ---------------- */
+
+    public void setActionEntryCount(int actionEntryCount) {
+        mActionEntryCount = actionEntryCount;
+    }
+
+    public int getActionEntryCount() {
+        return mActionEntryCount;
+    }
+
+    /* -------------- Count of Credential Entries ---------------- */
+
+    public void setCredentialEntryCount(int credentialEntryCount) {
+        mCredentialEntryCount = credentialEntryCount;
+    }
+
+    public int getCredentialEntryCount() {
+        return mCredentialEntryCount;
+    }
+
+    /* -------------- Count of Credential Entry Types ---------------- */
+
+    public void setCredentialEntryTypeCount(int credentialEntryTypeCount) {
+        mCredentialEntryTypeCount = credentialEntryTypeCount;
+    }
+
+    public int getCredentialEntryTypeCount() {
+        return mCredentialEntryTypeCount;
+    }
+
+    /* -------------- Count of Remote Entries ---------------- */
+
+    public void setRemoteEntryCount(int remoteEntryCount) {
+        mRemoteEntryCount = remoteEntryCount;
+    }
+
+    public int getRemoteEntryCount() {
+        return mRemoteEntryCount;
+    }
+
+    /* -------------- Count of Authentication Entries ---------------- */
+
+    public void setAuthenticationEntryCount(int authenticationEntryCount) {
+        mAuthenticationEntryCount = authenticationEntryCount;
+    }
+
+    public int getAuthenticationEntryCount() {
+        return mAuthenticationEntryCount;
+    }
+}
diff --git a/services/credentials/java/com/android/server/credentials/metrics/CandidateProviderMetric.java b/services/credentials/java/com/android/server/credentials/metrics/CandidateProviderMetric.java
deleted file mode 100644
index acfb4a4..0000000
--- a/services/credentials/java/com/android/server/credentials/metrics/CandidateProviderMetric.java
+++ /dev/null
@@ -1,80 +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.credentials.metrics;
-
-/**
- * The central candidate provider metric object that mimics our defined metric setup.
- */
-public class CandidateProviderMetric {
-
-    private int mCandidateUid = -1;
-    private long mStartTimeNanoseconds = -1;
-    private long mQueryFinishTimeNanoseconds = -1;
-
-    private int mProviderQueryStatus = -1;
-
-    public CandidateProviderMetric(long startTime, long queryFinishTime, int providerQueryStatus,
-            int candidateUid) {
-        this.mStartTimeNanoseconds = startTime;
-        this.mQueryFinishTimeNanoseconds = queryFinishTime;
-        this.mProviderQueryStatus = providerQueryStatus;
-        this.mCandidateUid = candidateUid;
-    }
-
-    public CandidateProviderMetric(){}
-
-    public void setStartTimeNanoseconds(long startTimeNanoseconds) {
-        this.mStartTimeNanoseconds = startTimeNanoseconds;
-    }
-
-    public void setQueryFinishTimeNanoseconds(long queryFinishTimeNanoseconds) {
-        this.mQueryFinishTimeNanoseconds = queryFinishTimeNanoseconds;
-    }
-
-    public void setProviderQueryStatus(int providerQueryStatus) {
-        this.mProviderQueryStatus = providerQueryStatus;
-    }
-
-    public void setCandidateUid(int candidateUid) {
-        this.mCandidateUid = candidateUid;
-    }
-
-    public long getStartTimeNanoseconds() {
-        return this.mStartTimeNanoseconds;
-    }
-
-    public long getQueryFinishTimeNanoseconds() {
-        return this.mQueryFinishTimeNanoseconds;
-    }
-
-    public int getProviderQueryStatus() {
-        return this.mProviderQueryStatus;
-    }
-
-    public int getCandidateUid() {
-        return this.mCandidateUid;
-    }
-
-    /**
-     * Returns the latency in microseconds for the query phase.
-     */
-    public int getQueryLatencyMs() {
-        return (int) ((this.getQueryFinishTimeNanoseconds()
-                - this.getStartTimeNanoseconds()) / 1000);
-    }
-
-}
diff --git a/services/credentials/java/com/android/server/credentials/metrics/ChosenProviderFinalPhaseMetric.java b/services/credentials/java/com/android/server/credentials/metrics/ChosenProviderFinalPhaseMetric.java
new file mode 100644
index 0000000..32fe204
--- /dev/null
+++ b/services/credentials/java/com/android/server/credentials/metrics/ChosenProviderFinalPhaseMetric.java
@@ -0,0 +1,242 @@
+/*
+ * 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.credentials.metrics;
+
+import android.util.Log;
+
+import com.android.server.credentials.MetricUtilities;
+
+/**
+ * The central chosen provider metric object that mimics our defined metric setup. This is used
+ * in the final phase of the flow and emits final status metrics.
+ * Some types are redundant across these metric collectors, but that has debug use-cases as
+ * these data-types are available at different moments of the flow (and typically, one can feed
+ * into the next).
+ * TODO(b/270403549) - iterate on this in V3+
+ * TODO(Immediately) - finalize V3 only types
+ */
+public class ChosenProviderFinalPhaseMetric {
+
+    // TODO(b/270403549) - applies elsewhere, likely removed or replaced w/ some hashed/count index
+    private static final String TAG = "ChosenFinalPhaseMetric";
+    // The session id associated with this API call, used to unite split emits
+    private long mSessionId = -1;
+    // Reveals if the UI was returned, false by default
+    private boolean mUiReturned = false;
+    private int mChosenUid = -1;
+
+    // Latency figures typically fed in from prior CandidateProviderMetric
+
+    private int mPreQueryPhaseLatencyMicroseconds = -1;
+    private int mQueryPhaseLatencyMicroseconds = -1;
+
+    // Timestamps kept in raw nanoseconds. Expected to be converted to microseconds from using
+    // reference 'mServiceBeganTimeNanoseconds' during metric log point
+
+    // Kept for local reference purposes, the initial timestamp of the service called passed in
+    private long mServiceBeganTimeNanoseconds = -1;
+    // The first query timestamp, which upon emit is normalized to microseconds using the reference
+    // start timestamp
+    private long mQueryStartTimeNanoseconds = -1;
+    // The UI call timestamp, which upon emit will be normalized to microseconds using reference
+    private long mUiCallStartTimeNanoseconds = -1;
+    // The UI return timestamp, which upon emit will be normalized to microseconds using reference
+    private long mUiCallEndTimeNanoseconds = -1;
+    // The final finish timestamp, which upon emit will be normalized to microseconds with reference
+    private long mFinalFinishTimeNanoseconds = -1;
+    // The status of this provider after selection
+
+    // Other General Information, such as final api status, provider status, entry info, etc...
+
+    private int mChosenProviderStatus = -1;
+    // TODO add remaining properties based on the Atom ; specifically, migrate the candidate
+    // Entry information, and store final status here
+
+
+    public ChosenProviderFinalPhaseMetric() {
+    }
+
+    /* ------------------- UID ------------------- */
+
+    public int getChosenUid() {
+        return mChosenUid;
+    }
+
+    public void setChosenUid(int chosenUid) {
+        mChosenUid = chosenUid;
+    }
+
+    /* ---------------- Latencies ------------------ */
+
+
+    /* ----- Direct Delta Latencies for Local Utility ------- */
+
+    /**
+     * In order for a chosen provider to be selected, the call must have successfully begun.
+     * Thus, the {@link InitialPhaseMetric} can directly pass this initial latency figure into
+     * this chosen provider metric.
+     *
+     * @param preQueryPhaseLatencyMicroseconds the millisecond latency for the service start,
+     *                                         typically passed in through the
+     *                                         {@link InitialPhaseMetric}
+     */
+    public void setPreQueryPhaseLatencyMicroseconds(int preQueryPhaseLatencyMicroseconds) {
+        mPreQueryPhaseLatencyMicroseconds = preQueryPhaseLatencyMicroseconds;
+    }
+
+    /**
+     * In order for a chosen provider to be selected, a candidate provider must exist. The
+     * candidate provider can directly pass the final latency figure into this chosen provider
+     * metric.
+     *
+     * @param queryPhaseLatencyMicroseconds the millisecond latency for the query phase, typically
+     *                                      passed in through the {@link CandidatePhaseMetric}
+     */
+    public void setQueryPhaseLatencyMicroseconds(int queryPhaseLatencyMicroseconds) {
+        mQueryPhaseLatencyMicroseconds = queryPhaseLatencyMicroseconds;
+    }
+
+    public int getPreQueryPhaseLatencyMicroseconds() {
+        return mPreQueryPhaseLatencyMicroseconds;
+    }
+
+    public int getQueryPhaseLatencyMicroseconds() {
+        return mQueryPhaseLatencyMicroseconds;
+    }
+
+    public int getUiPhaseLatencyMicroseconds() {
+        return (int) ((this.mUiCallEndTimeNanoseconds
+                - this.mUiCallStartTimeNanoseconds) / 1000);
+    }
+
+    /**
+     * Returns the full provider (invocation to response) latency in microseconds. Expects the
+     * start time to be provided, such as from {@link CandidatePhaseMetric}.
+     */
+    public int getEntireProviderLatencyMicroseconds() {
+        return (int) ((this.mFinalFinishTimeNanoseconds
+                - this.mQueryStartTimeNanoseconds) / 1000);
+    }
+
+    /**
+     * Returns the full (platform invoked to response) latency in microseconds. Expects the
+     * start time to be provided, such as from {@link InitialPhaseMetric}.
+     */
+    public int getEntireLatencyMicroseconds() {
+        return (int) ((this.mFinalFinishTimeNanoseconds
+                - this.mServiceBeganTimeNanoseconds) / 1000);
+    }
+
+    /* ----- Timestamps for Latency ----- */
+
+    /**
+     * In order for a chosen provider to be selected, the call must have successfully begun.
+     * Thus, the {@link InitialPhaseMetric} can directly pass this initial timestamp into this
+     * chosen provider metric.
+     *
+     * @param serviceBeganTimeNanoseconds the timestamp moment when the platform was called,
+     *                                    typically passed in through the {@link InitialPhaseMetric}
+     */
+    public void setServiceBeganTimeNanoseconds(long serviceBeganTimeNanoseconds) {
+        mServiceBeganTimeNanoseconds = serviceBeganTimeNanoseconds;
+    }
+
+    public void setQueryStartTimeNanoseconds(long queryStartTimeNanoseconds) {
+        mQueryStartTimeNanoseconds = queryStartTimeNanoseconds;
+    }
+
+    public void setUiCallStartTimeNanoseconds(long uiCallStartTimeNanoseconds) {
+        this.mUiCallStartTimeNanoseconds = uiCallStartTimeNanoseconds;
+    }
+
+    public void setUiCallEndTimeNanoseconds(long uiCallEndTimeNanoseconds) {
+        this.mUiCallEndTimeNanoseconds = uiCallEndTimeNanoseconds;
+    }
+
+    public void setFinalFinishTimeNanoseconds(long finalFinishTimeNanoseconds) {
+        mFinalFinishTimeNanoseconds = finalFinishTimeNanoseconds;
+    }
+
+    public long getServiceBeganTimeNanoseconds() {
+        return mServiceBeganTimeNanoseconds;
+    }
+
+    public long getQueryStartTimeNanoseconds() {
+        return mQueryStartTimeNanoseconds;
+    }
+
+    public long getUiCallStartTimeNanoseconds() {
+        return mUiCallStartTimeNanoseconds;
+    }
+
+    public long getUiCallEndTimeNanoseconds() {
+        return mUiCallEndTimeNanoseconds;
+    }
+
+    public long getFinalFinishTimeNanoseconds() {
+        return mFinalFinishTimeNanoseconds;
+    }
+
+    /* --- Time Stamp Conversion to Microseconds from Reference Point --- */
+
+    /**
+     * We collect raw timestamps in nanoseconds for ease of collection. However, given the scope
+     * of our logging timeframe, and size considerations of the metric, we require these to give us
+     * the microsecond timestamps from the start reference point.
+     *
+     * @param specificTimestamp the timestamp to consider, must be greater than the reference
+     * @return the microsecond integer timestamp from service start to query began
+     */
+    public int getTimestampFromReferenceStartMicroseconds(long specificTimestamp) {
+        if (specificTimestamp < this.mServiceBeganTimeNanoseconds) {
+            Log.i(TAG, "The timestamp is before service started, falling back to default int");
+            return MetricUtilities.DEFAULT_INT_32;
+        }
+        return (int) ((specificTimestamp
+                - this.mServiceBeganTimeNanoseconds) / 1000);
+    }
+
+    /* ----------- Provider Status -------------- */
+
+    public int getChosenProviderStatus() {
+        return mChosenProviderStatus;
+    }
+
+    public void setChosenProviderStatus(int chosenProviderStatus) {
+        mChosenProviderStatus = chosenProviderStatus;
+    }
+
+    /* ----------- Session ID -------------- */
+
+    public void setSessionId(long sessionId) {
+        mSessionId = sessionId;
+    }
+
+    public long getSessionId() {
+        return mSessionId;
+    }
+
+    /* ----------- UI Returned Successfully -------------- */
+
+    public void setUiReturned(boolean uiReturned) {
+        mUiReturned = uiReturned;
+    }
+
+    public boolean isUiReturned() {
+        return mUiReturned;
+    }
+}
diff --git a/services/credentials/java/com/android/server/credentials/metrics/ChosenProviderMetric.java b/services/credentials/java/com/android/server/credentials/metrics/ChosenProviderMetric.java
deleted file mode 100644
index c4d0b3c..0000000
--- a/services/credentials/java/com/android/server/credentials/metrics/ChosenProviderMetric.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.credentials.metrics;
-
-/**
- * The central chosen provider metric object that mimics our defined metric setup.
- */
-public class ChosenProviderMetric {
-
-    private int mChosenUid = -1;
-    private long mStartTimeNanoseconds = -1;
-    private long mQueryFinishTimeNanoseconds = -1;
-    private long mFinalFinishTimeNanoseconds = -1;
-    private int mChosenProviderStatus = -1;
-
-    public ChosenProviderMetric() {}
-
-    public int getChosenUid() {
-        return mChosenUid;
-    }
-
-    public void setChosenUid(int chosenUid) {
-        mChosenUid = chosenUid;
-    }
-
-    public long getStartTimeNanoseconds() {
-        return mStartTimeNanoseconds;
-    }
-
-    public void setStartTimeNanoseconds(long startTimeNanoseconds) {
-        mStartTimeNanoseconds = startTimeNanoseconds;
-    }
-
-    public long getQueryFinishTimeNanoseconds() {
-        return mQueryFinishTimeNanoseconds;
-    }
-
-    public void setQueryFinishTimeNanoseconds(long queryFinishTimeNanoseconds) {
-        mQueryFinishTimeNanoseconds = queryFinishTimeNanoseconds;
-    }
-
-    public long getFinalFinishTimeNanoseconds() {
-        return mFinalFinishTimeNanoseconds;
-    }
-
-    public void setFinalFinishTimeNanoseconds(long finalFinishTimeNanoseconds) {
-        mFinalFinishTimeNanoseconds = finalFinishTimeNanoseconds;
-    }
-
-    public int getChosenProviderStatus() {
-        return mChosenProviderStatus;
-    }
-
-    public void setChosenProviderStatus(int chosenProviderStatus) {
-        mChosenProviderStatus = chosenProviderStatus;
-    }
-
-    /**
-     * Returns the full provider (invocation to response) latency in microseconds.
-     */
-    public int getEntireProviderLatencyMs() {
-        return (int) ((this.getFinalFinishTimeNanoseconds()
-                - this.getStartTimeNanoseconds()) / 1000);
-    }
-
-    // TODO get post click final phase and re-add the query phase time to metric
-
-    /**
-     * Returns the end of query to response phase latency in microseconds.
-     */
-    public int getFinalPhaseLatencyMs() {
-        return (int) ((this.getFinalFinishTimeNanoseconds()
-                - this.getQueryFinishTimeNanoseconds()) / 1000);
-    }
-
-}
diff --git a/services/credentials/java/com/android/server/credentials/metrics/EntryEnum.java b/services/credentials/java/com/android/server/credentials/metrics/EntryEnum.java
new file mode 100644
index 0000000..73403a6
--- /dev/null
+++ b/services/credentials/java/com/android/server/credentials/metrics/EntryEnum.java
@@ -0,0 +1,86 @@
+/*
+ * 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.credentials.metrics;
+
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CLEAR_CREDENTIAL;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CREATE_CREDENTIAL;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_GET_CREDENTIAL;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_UNKNOWN;
+import static com.android.server.credentials.ProviderGetSession.ACTION_ENTRY_KEY;
+import static com.android.server.credentials.ProviderGetSession.AUTHENTICATION_ACTION_ENTRY_KEY;
+import static com.android.server.credentials.ProviderGetSession.CREDENTIAL_ENTRY_KEY;
+import static com.android.server.credentials.ProviderGetSession.REMOTE_ENTRY_KEY;
+
+import android.util.Log;
+
+import java.util.AbstractMap;
+import java.util.Map;
+
+public enum EntryEnum {
+    // TODO immediately, update with built entries
+    UNKNOWN(CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_UNKNOWN),
+    ACTION_ENTRY(CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_GET_CREDENTIAL),
+    CREDENTIAL_ENTRY(CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CREATE_CREDENTIAL),
+    REMOTE_ENTRY(CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CLEAR_CREDENTIAL),
+    AUTHENTICATION_ENTRY(
+            CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE
+    );
+
+    private static final String TAG = "EntryEnum";
+
+    private final int mInnerMetricCode;
+
+    private static final Map<String, Integer> sKeyToEntryCode = Map.ofEntries(
+            new AbstractMap.SimpleEntry<>(ACTION_ENTRY_KEY,
+                    ACTION_ENTRY.mInnerMetricCode),
+            new AbstractMap.SimpleEntry<>(AUTHENTICATION_ACTION_ENTRY_KEY,
+                    AUTHENTICATION_ENTRY.mInnerMetricCode),
+            new AbstractMap.SimpleEntry<>(REMOTE_ENTRY_KEY,
+                    REMOTE_ENTRY.mInnerMetricCode),
+            new AbstractMap.SimpleEntry<>(CREDENTIAL_ENTRY_KEY,
+                    CREDENTIAL_ENTRY.mInnerMetricCode)
+    );
+
+    EntryEnum(int innerMetricCode) {
+        this.mInnerMetricCode = innerMetricCode;
+    }
+
+    /**
+     * Gives the West-world version of the metric name.
+     *
+     * @return a code corresponding to the west world metric name
+     */
+    public int getMetricCode() {
+        return this.mInnerMetricCode;
+    }
+
+    /**
+     * Given a string key type known to the framework, this returns the known metric code associated
+     * with that string.
+     *
+     * @param stringKey a string key type for a particular entry
+     * @return the metric code associated with this enum
+     */
+    public static int getMetricCodeFromString(String stringKey) {
+        if (!sKeyToEntryCode.containsKey(stringKey)) {
+            Log.w(TAG, "Attempted to use an unsupported string key entry type");
+            return UNKNOWN.mInnerMetricCode;
+        }
+        return sKeyToEntryCode.get(stringKey);
+    }
+}
diff --git a/services/credentials/java/com/android/server/credentials/metrics/InitialPhaseMetric.java b/services/credentials/java/com/android/server/credentials/metrics/InitialPhaseMetric.java
new file mode 100644
index 0000000..a73495f
--- /dev/null
+++ b/services/credentials/java/com/android/server/credentials/metrics/InitialPhaseMetric.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.credentials.metrics;
+
+/**
+ * This handles metrics collected prior to any remote calls to providers.
+ * Some types are redundant across these metric collectors, but that has debug use-cases as
+ * these data-types are available at different moments of the flow (and typically, one can feed
+ * into the next).
+ * TODO(b/270403549) - iterate on this in V3+
+ */
+public class InitialPhaseMetric {
+    private static final String TAG = "InitialPhaseMetric";
+
+    // The api being called, default set to unknown
+    private int mApiName = ApiName.UNKNOWN.getMetricCode();
+    // The caller uid of the calling application, default to -1
+    private int mCallerUid = -1;
+    // The session id to unite multiple atom emits, default to -1
+    private int mSessionId = -1;
+    private int mCountRequestClassType = -1;
+
+    // Raw timestamps in nanoseconds, *the only* one logged as such (i.e. 64 bits) since it is a
+    // reference point.
+    private long mCredentialServiceStartedTimeNanoseconds = -1;
+
+    // A reference point to give this object utility to capture latency. Can be directly handed
+    // over to the next latency object.
+    private long mCredentialServiceBeginQueryTimeNanoseconds = -1;
+
+
+    public InitialPhaseMetric() {
+    }
+
+    /* ---------- Latencies ---------- */
+
+    /* -- Direct Latency Utility -- */
+
+    public int getServiceStartToQueryLatencyMicroseconds() {
+        return (int) ((this.mCredentialServiceStartedTimeNanoseconds
+                - this.mCredentialServiceBeginQueryTimeNanoseconds) / 1000);
+    }
+
+    /* -- Timestamps -- */
+
+    public void setCredentialServiceStartedTimeNanoseconds(
+            long credentialServiceStartedTimeNanoseconds
+    ) {
+        this.mCredentialServiceStartedTimeNanoseconds = credentialServiceStartedTimeNanoseconds;
+    }
+
+    public void setCredentialServiceBeginQueryTimeNanoseconds(
+            long credentialServiceBeginQueryTimeNanoseconds) {
+        mCredentialServiceBeginQueryTimeNanoseconds = credentialServiceBeginQueryTimeNanoseconds;
+    }
+
+    public long getCredentialServiceStartedTimeNanoseconds() {
+        return mCredentialServiceStartedTimeNanoseconds;
+    }
+
+    public long getCredentialServiceBeginQueryTimeNanoseconds() {
+        return mCredentialServiceBeginQueryTimeNanoseconds;
+    }
+
+    /* ------ ApiName ------ */
+
+    public void setApiName(int apiName) {
+        mApiName = apiName;
+    }
+
+    public int getApiName() {
+        return mApiName;
+    }
+
+    /* ------ CallerUid ------ */
+
+    public void setCallerUid(int callerUid) {
+        mCallerUid = callerUid;
+    }
+
+    public int getCallerUid() {
+        return mCallerUid;
+    }
+
+    /* ------ SessionId ------ */
+
+    public void setSessionId(int sessionId) {
+        mSessionId = sessionId;
+    }
+
+    public int getSessionId() {
+        return mSessionId;
+    }
+
+    /* ------ Count Request Class Types ------ */
+
+    public void setCountRequestClassType(int countRequestClassType) {
+        mCountRequestClassType = countRequestClassType;
+    }
+
+    public int getCountRequestClassType() {
+        return mCountRequestClassType;
+    }
+}
diff --git a/services/credentials/java/com/android/server/credentials/metrics/ProviderStatusForMetrics.java b/services/credentials/java/com/android/server/credentials/metrics/ProviderStatusForMetrics.java
new file mode 100644
index 0000000..08f1afa
--- /dev/null
+++ b/services/credentials/java/com/android/server/credentials/metrics/ProviderStatusForMetrics.java
@@ -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.server.credentials.metrics;
+
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_FINAL_FAILURE;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_FINAL_SUCCESS;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_QUERY_FAILURE;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_QUERY_SUCCESS;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_UNKNOWN;
+
+public enum ProviderStatusForMetrics {
+
+    UNKNOWN(
+            CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_UNKNOWN),
+    FINAL_FAILURE(
+            CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_FINAL_FAILURE),
+    QUERY_FAILURE(
+            CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_QUERY_FAILURE),
+    FINAL_SUCCESS(
+            CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_FINAL_SUCCESS),
+    QUERY_SUCCESS(
+            CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_QUERY_SUCCESS);
+
+    private final int mInnerMetricCode;
+
+    ProviderStatusForMetrics(int innerMetricCode) {
+        this.mInnerMetricCode = innerMetricCode;
+    }
+
+    /**
+     * Gives the West-world version of the metric name.
+     *
+     * @return a code corresponding to the west world metric name
+     */
+    public int getMetricCode() {
+        return this.mInnerMetricCode;
+    }
+}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java
index 4351bc1..80100a9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java
@@ -24,6 +24,8 @@
 
 import com.android.internal.annotations.GuardedBy;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
@@ -52,6 +54,11 @@
     @GuardedBy("mLock")
     private final SparseIntArray mPermissionPolicy = new SparseIntArray();
 
+    @GuardedBy("mLock")
+    private List<String> mLauncherShortcutOverrides =
+            new ArrayList<>();
+
+
     /** Maps to {@code ActiveAdmin.mAdminCanGrantSensorsPermissions}. */
     private final AtomicBoolean mCanGrantSensorsPermissions = new AtomicBoolean(false);
 
@@ -122,6 +129,22 @@
         mCanGrantSensorsPermissions.set(canGrant);
     }
 
+    @Override
+    public List<String> getLauncherShortcutOverrides() {
+        synchronized (mLock) {
+            return new ArrayList<>(mLauncherShortcutOverrides);
+        }
+    }
+
+    /**
+     * Sets a list of packages for which shortcuts should be replaced by their badged version.
+     */
+    public void setLauncherShortcutOverrides(List<String> launcherShortcutOverrides) {
+        synchronized (mLock) {
+            mLauncherShortcutOverrides = new ArrayList<>(launcherShortcutOverrides);
+        }
+    }
+
     /** Dump content */
     public void dump(IndentingPrintWriter pw) {
         synchronized (mLock) {
@@ -131,6 +154,8 @@
             pw.println("Password quality: " + mPasswordQuality);
             pw.println("Permission policy: " + mPermissionPolicy);
             pw.println("Admin can grant sensors permission: " + mCanGrantSensorsPermissions.get());
+            pw.print("Shortcuts overrides: ");
+            pw.println(mLauncherShortcutOverrides);
             pw.decreaseIndent();
         }
     }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
index c7f9952..7eeb51c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
@@ -16,17 +16,19 @@
 
 package com.android.server.devicepolicy;
 
-import static android.app.admin.PolicyUpdateResult.RESULT_FAILURE_CONFLICTING_ADMIN_POLICY;
-import static android.app.admin.PolicyUpdateResult.RESULT_POLICY_CLEARED;
-import static android.app.admin.PolicyUpdateResult.RESULT_SUCCESS;
 import static android.app.admin.PolicyUpdateReceiver.EXTRA_POLICY_TARGET_USER_ID;
 import static android.app.admin.PolicyUpdateReceiver.EXTRA_POLICY_UPDATE_RESULT_KEY;
+import static android.app.admin.PolicyUpdateResult.RESULT_FAILURE_CONFLICTING_ADMIN_POLICY;
+import static android.app.admin.PolicyUpdateResult.RESULT_FAILURE_HARDWARE_LIMITATION;
+import static android.app.admin.PolicyUpdateResult.RESULT_POLICY_CLEARED;
+import static android.app.admin.PolicyUpdateResult.RESULT_POLICY_SET;
 import static android.content.pm.UserProperties.INHERIT_DEVICE_POLICY_FROM_PARENT;
 import static android.provider.DeviceConfig.NAMESPACE_DEVICE_POLICY_MANAGER;
 
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.admin.DevicePolicyIdentifiers;
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyState;
 import android.app.admin.PolicyKey;
@@ -46,6 +48,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.DeviceConfig;
+import android.telephony.TelephonyManager;
 import android.util.AtomicFile;
 import android.util.Log;
 import android.util.SparseArray;
@@ -79,6 +82,10 @@
 final class DevicePolicyEngine {
     static final String TAG = "DevicePolicyEngine";
 
+    private static final String CELLULAR_2G_USER_RESTRICTION_ID =
+            DevicePolicyIdentifiers.getIdentifierForUserRestriction(
+                    UserManager.DISALLOW_CELLULAR_2G);
+
     private static final String ENABLE_COEXISTENCE_FLAG = "enable_coexistence";
     private static final boolean DEFAULT_ENABLE_COEXISTENCE_FLAG = true;
 
@@ -167,7 +174,8 @@
                         enforcingAdmin,
                         policyDefinition,
                         // TODO: we're always sending this for now, should properly handle errors.
-                        policyEnforced ? RESULT_SUCCESS : RESULT_FAILURE_CONFLICTING_ADMIN_POLICY,
+                        policyEnforced
+                                ? RESULT_POLICY_SET : RESULT_FAILURE_CONFLICTING_ADMIN_POLICY,
                         userId);
             }
 
@@ -379,6 +387,15 @@
         Objects.requireNonNull(value);
 
         synchronized (mLock) {
+            // TODO(b/270999567): Move error handling for DISALLOW_CELLULAR_2G into the code
+            //  that honors the restriction once there's an API available
+            if (checkFor2gFailure(policyDefinition, enforcingAdmin)) {
+                Log.i(TAG,
+                        "Device does not support capabilities required to disable 2g. Not setting"
+                                + " global policy state.");
+                return;
+            }
+
             PolicyState<V> globalPolicyState = getGlobalPolicyStateLocked(policyDefinition);
 
             boolean policyChanged = globalPolicyState.addPolicy(enforcingAdmin, value);
@@ -400,7 +417,7 @@
                         enforcingAdmin,
                         policyDefinition,
                         // TODO: we're always sending this for now, should properly handle errors.
-                        policyApplied ? RESULT_SUCCESS : RESULT_FAILURE_CONFLICTING_ADMIN_POLICY,
+                        policyApplied ? RESULT_POLICY_SET : RESULT_FAILURE_CONFLICTING_ADMIN_POLICY,
                         UserHandle.USER_ALL);
             }
 
@@ -792,7 +809,7 @@
             int result = Objects.equals(
                     policyState.getPoliciesSetByAdmins().get(admin),
                     policyState.getCurrentResolvedPolicy())
-                    ? RESULT_SUCCESS : RESULT_FAILURE_CONFLICTING_ADMIN_POLICY;
+                    ? RESULT_POLICY_SET : RESULT_FAILURE_CONFLICTING_ADMIN_POLICY;
             maybeSendOnPolicyChanged(
                     admin, policyDefinition, result, userId);
         }
@@ -1161,6 +1178,36 @@
                 DEFAULT_ENABLE_COEXISTENCE_FLAG);
     }
 
+    private <V> boolean checkFor2gFailure(@NonNull PolicyDefinition<V> policyDefinition,
+            @NonNull EnforcingAdmin enforcingAdmin) {
+        if (!policyDefinition.getPolicyKey().getIdentifier().equals(
+                CELLULAR_2G_USER_RESTRICTION_ID)) {
+            return false;
+        }
+
+        boolean isCapabilitySupported;
+        try {
+            isCapabilitySupported = mContext.getSystemService(
+                    TelephonyManager.class).isRadioInterfaceCapabilitySupported(
+                    TelephonyManager.CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK);
+        } catch (IllegalStateException e) {
+            // isRadioInterfaceCapabilitySupported can throw if there is no Telephony
+            // service initialized.
+            isCapabilitySupported = false;
+        }
+
+        if (!isCapabilitySupported) {
+            sendPolicyResultToAdmin(
+                    enforcingAdmin,
+                    policyDefinition,
+                    RESULT_FAILURE_HARDWARE_LIMITATION,
+                    UserHandle.USER_ALL);
+            return true;
+        }
+
+        return false;
+    }
+
     private class DevicePoliciesReaderWriter {
         private static final String DEVICE_POLICIES_XML = "device_policy_state.xml";
         private static final String TAG_LOCAL_POLICY_ENTRY = "local-policy-entry";
@@ -1315,8 +1362,8 @@
             if (adminsPolicy != null) {
                 mLocalPolicies.get(userId).put(policyKey, adminsPolicy);
             } else {
-                Log.e(TAG, "Error parsing file, " + policyKey + "doesn't have an "
-                        + "AdminsPolicy.");
+                Log.e(TAG,
+                        "Error parsing file, " + policyKey + "doesn't have an " + "AdminsPolicy.");
             }
         }
 
@@ -1327,8 +1374,8 @@
             if (adminsPolicy != null) {
                 mGlobalPolicies.put(policyKey, adminsPolicy);
             } else {
-                Log.e(TAG, "Error parsing file, " + policyKey + "doesn't have an "
-                        + "AdminsPolicy.");
+                Log.e(TAG,
+                        "Error parsing file, " + policyKey + "doesn't have an " + "AdminsPolicy.");
             }
         }
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index bfcb4c7..6cd9f1c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2237,6 +2237,16 @@
             }
             isOrgOwned = mOwners.isProfileOwnerOfOrganizationOwnedDevice(userHandle);
 
+            // Clear any restrictions set by the a profile owner and the parent admin.
+            final ActiveAdmin admin = getProfileOwnerLocked(userHandle);
+            if (admin != null) {
+                admin.userRestrictions = null;
+                final ActiveAdmin parentAdmin = admin.getParentActiveAdmin();
+                if (parentAdmin != null) {
+                    parentAdmin.userRestrictions = null;
+                }
+                pushUserRestrictions(userHandle);
+            }
             mOwners.removeProfileOwner(userHandle);
             mOwners.writeProfileOwner(userHandle);
             pushScreenCapturePolicy(userHandle);
@@ -3212,8 +3222,12 @@
     private void sendChangedNotification(int userHandle) {
         Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
         intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+        Bundle options = new BroadcastOptions()
+                .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
+                .setDeferUntilActive(true)
+                .toBundle();
         mInjector.binderWithCleanCallingIdentity(() ->
-                mContext.sendBroadcastAsUser(intent, new UserHandle(userHandle)));
+                mContext.sendBroadcastAsUser(intent, new UserHandle(userHandle), null, options));
     }
 
     private void loadSettingsLocked(DevicePolicyData policy, int userHandle) {
@@ -3518,16 +3532,30 @@
                 userId == UserHandle.USER_SYSTEM ? UserHandle.USER_ALL : userId);
         updatePermissionPolicyCache(userId);
         updateAdminCanGrantSensorsPermissionCache(userId);
-
         final List<PreferentialNetworkServiceConfig> preferentialNetworkServiceConfigs;
+        boolean isManagedSubscription;
+
         synchronized (getLockObject()) {
             ActiveAdmin owner = getDeviceOrProfileOwnerAdminLocked(userId);
             preferentialNetworkServiceConfigs = owner != null
                     ? owner.mPreferentialNetworkServiceConfigs
                     : List.of(PreferentialNetworkServiceConfig.DEFAULT);
+
+            isManagedSubscription = owner != null && owner.mManagedSubscriptionsPolicy != null
+                    && owner.mManagedSubscriptionsPolicy.getPolicyType()
+                    == ManagedSubscriptionsPolicy.TYPE_ALL_MANAGED_SUBSCRIPTIONS;
         }
         updateNetworkPreferenceForUser(userId, preferentialNetworkServiceConfigs);
 
+        if (isManagedSubscription) {
+            String defaultDialerPackageName = getDefaultRoleHolderPackageName(
+                    com.android.internal.R.string.config_defaultDialer);
+            String defaultSmsPackageName = getDefaultRoleHolderPackageName(
+                    com.android.internal.R.string.config_defaultSms);
+            updateDialerAndSmsManagedShortcutsOverrideCache(defaultDialerPackageName,
+                    defaultSmsPackageName);
+        }
+
         startOwnerService(userId, "start-user");
         if (isDevicePolicyEngineEnabled()) {
             mDevicePolicyEngine.handleStartUser(userId);
@@ -7610,6 +7638,7 @@
 
         if (isWorkProfileTelephonyFlagEnabled()) {
             clearManagedSubscriptionsPolicy();
+            clearLauncherShortcutOverrides();
             updateTelephonyCrossProfileIntentFilters(parentId, UserHandle.USER_NULL, false);
         }
         Slogf.i(LOG_TAG, "Cleaning up device-wide policies done.");
@@ -7627,6 +7656,10 @@
         }
     }
 
+    private void clearLauncherShortcutOverrides() {
+        mPolicyCache.setLauncherShortcutOverrides(new ArrayList<>());
+    }
+
     private void updateTelephonyCrossProfileIntentFilters(int parentUserId, int profileUserId,
             boolean enableWorkTelephony) {
         try {
@@ -11196,7 +11229,7 @@
         } else {
             Objects.requireNonNull(admin, "ComponentName is null");
             Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
-                    || (parent && isProfileOwnerOfOrganizationOwnedDevice(caller)));
+                    || isProfileOwnerOfOrganizationOwnedDevice(caller));
         }
         if (parent) {
             userId = getProfileParentId(mInjector.userHandleGetCallingUserId());
@@ -11337,7 +11370,7 @@
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_APPLICATION_RESTRICTIONS)
                 .setAdmin(caller.getPackageName())
-                .setBoolean(/* isDelegate */ who == null)
+                .setBoolean(/* isDelegate */ isCallerDelegate(caller))
                 .setStrings(packageName)
                 .write();
     }
@@ -13378,7 +13411,7 @@
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_APPLICATION_HIDDEN)
                 .setAdmin(caller.getPackageName())
-                .setBoolean(/* isDelegate */ who == null)
+                .setBoolean(/* isDelegate */ isCallerDelegate(caller))
                 .setStrings(packageName, hidden ? "hidden" : "not_hidden",
                         parent ? CALLED_FROM_PARENT : NOT_CALLED_FROM_PARENT)
                 .write();
@@ -13730,7 +13763,7 @@
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_UNINSTALL_BLOCKED)
                 .setAdmin(caller.getPackageName())
-                .setBoolean(/* isDelegate */ who == null)
+                .setBoolean(/* isDelegate */ isCallerDelegate(caller))
                 .setStrings(packageName)
                 .write();
     }
@@ -16280,7 +16313,8 @@
                                                 .setAdmin(caller.getPackageName())
                                                 .setStrings(permission)
                                                 .setInt(grantState)
-                                                .setBoolean(/* isDelegate */ admin == null)
+                                                .setBoolean(
+                                                        /* isDelegate */ isCallerDelegate(caller))
                                                 .write();
 
                                         callback.sendResult(Bundle.EMPTY);
@@ -16405,12 +16439,12 @@
                     mInjector.getPackageManager().getPackagesForUid(caller.getUid()));
             Preconditions.checkArgument(callerUidPackageNames.contains(packageName),
                     "Caller uid doesn't match the one for the provided package.");
+
+            return checkProvisioningPreconditionSkipPermission(action, packageName, caller.getUserId())
+                    == STATUS_OK;
         } finally {
             mInjector.binderRestoreCallingIdentity(ident);
         }
-
-        return checkProvisioningPreconditionSkipPermission(action, packageName, caller.getUserId())
-                == STATUS_OK;
     }
 
     @Override
@@ -22183,6 +22217,10 @@
     private static final HashMap<String, String> DELEGATE_SCOPES = new HashMap<>();
     {
         DELEGATE_SCOPES.put(MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS, DELEGATION_PERMISSION_GRANT);
+        DELEGATE_SCOPES.put(MANAGE_DEVICE_POLICY_APP_RESTRICTIONS, DELEGATION_APP_RESTRICTIONS);
+        DELEGATE_SCOPES.put(MANAGE_DEVICE_POLICY_APPS_CONTROL, DELEGATION_BLOCK_UNINSTALL);
+        DELEGATE_SCOPES.put(MANAGE_DEVICE_POLICY_SECURITY_LOGGING, DELEGATION_SECURITY_LOGGING);
+        DELEGATE_SCOPES.put(MANAGE_DEVICE_POLICY_PACKAGE_STATE, DELEGATION_PACKAGE_ACCESS);
     }
 
     private static final HashMap<String, String> CROSS_USER_PERMISSIONS =
@@ -22371,6 +22409,7 @@
                     + permission
                     + ", "
                     + CROSS_USER_PERMISSIONS.get(permission)
+                    + "(if calling cross-user)"
                     + "}");
         }
     }
@@ -22745,12 +22784,30 @@
             } else {
                 Slogf.w(LOG_TAG, "Couldn't install sms app, sms app package is null");
             }
+
+            updateDialerAndSmsManagedShortcutsOverrideCache(defaultDialerPackageName,
+                    defaultSmsPackageName);
         } catch (RemoteException re) {
             // shouldn't happen
             Slogf.wtf(LOG_TAG, "Failed to install dialer/sms app", re);
         }
     }
 
+    private void updateDialerAndSmsManagedShortcutsOverrideCache(
+            String defaultDialerPackageName, String defaultSmsPackageName) {
+
+        List<String> shortcutOverrides = new ArrayList<>();
+
+        if (defaultDialerPackageName != null) {
+            shortcutOverrides.add(defaultDialerPackageName);
+        }
+
+        if (defaultSmsPackageName != null) {
+            shortcutOverrides.add(defaultSmsPackageName);
+        }
+        mPolicyCache.setLauncherShortcutOverrides(shortcutOverrides);
+    }
+
     private void registerListenerToAssignSubscriptionsToUser(int userId) {
         synchronized (mSubscriptionsChangedListenerLock) {
             if (mSubscriptionsChangedListener != null) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
index 3ca158d..194647fd 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
@@ -120,7 +120,9 @@
                 } else {
                     mDeviceStateCache.setDeviceOwnerType(NO_DEVICE_OWNER);
                 }
-
+                for (int userId : usersIds) {
+                    mDeviceStateCache.setHasProfileOwner(userId, hasProfileOwner(userId));
+                }
             } else {
                 mUserManagerInternal.setDeviceManaged(hasDeviceOwner());
                 for (int userId : usersIds) {
diff --git a/services/incremental/TEST_MAPPING b/services/incremental/TEST_MAPPING
index 3976a70..be7feb5 100644
--- a/services/incremental/TEST_MAPPING
+++ b/services/incremental/TEST_MAPPING
@@ -16,13 +16,13 @@
     },
     {
       "name": "service.incremental_test"
+    },
+    {
+      "name": "CtsInstalledLoadingProgressHostTests"
     }
   ],
   "presubmit-large": [
     {
-      "name": "CtsInstalledLoadingProgressHostTests"
-    },
-    {
       "name": "CtsContentTestCases",
       "options": [
         {
diff --git a/services/java/com/android/server/HsumBootUserInitializer.java b/services/java/com/android/server/HsumBootUserInitializer.java
index 50113fe..b895812 100644
--- a/services/java/com/android/server/HsumBootUserInitializer.java
+++ b/services/java/com/android/server/HsumBootUserInitializer.java
@@ -18,6 +18,7 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.content.ContentResolver;
+import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.database.ContentObserver;
 import android.os.Handler;
@@ -27,6 +28,7 @@
 import android.provider.Settings;
 
 import com.android.server.am.ActivityManagerService;
+import com.android.server.pm.PackageManagerService;
 import com.android.server.pm.UserManagerInternal;
 import com.android.server.utils.Slogf;
 import com.android.server.utils.TimingsTraceAndSlog;
@@ -41,6 +43,7 @@
 
     private final UserManagerInternal mUmi;
     private final ActivityManagerService mAms;
+    private final PackageManagerService mPms;
     private final ContentResolver mContentResolver;
 
     private final ContentObserver mDeviceProvisionedObserver =
@@ -63,20 +66,23 @@
 
     /** Static factory method for creating a {@link HsumBootUserInitializer} instance. */
     public static @Nullable HsumBootUserInitializer createInstance(ActivityManagerService am,
-            ContentResolver contentResolver, boolean shouldAlwaysHaveMainUser) {
+            PackageManagerService pms, ContentResolver contentResolver,
+            boolean shouldAlwaysHaveMainUser) {
 
         if (!UserManager.isHeadlessSystemUserMode()) {
             return null;
         }
         return new HsumBootUserInitializer(
                 LocalServices.getService(UserManagerInternal.class),
-                am, contentResolver, shouldAlwaysHaveMainUser);
+                am, pms, contentResolver, shouldAlwaysHaveMainUser);
     }
 
     private HsumBootUserInitializer(UserManagerInternal umi, ActivityManagerService am,
-            ContentResolver contentResolver, boolean shouldAlwaysHaveMainUser) {
+            PackageManagerService pms, ContentResolver contentResolver,
+            boolean shouldAlwaysHaveMainUser) {
         mUmi = umi;
         mAms = am;
+        mPms = pms;
         mContentResolver = contentResolver;
         mShouldAlwaysHaveMainUser = shouldAlwaysHaveMainUser;
     }
@@ -131,7 +137,8 @@
 
         try {
             t.traceBegin("getBootUser");
-            final int bootUser = mUmi.getBootUser();
+            final int bootUser = mUmi.getBootUser(/* waitUntilSet= */ mPms
+                    .hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, /* version= */0));
             t.traceEnd();
             t.traceBegin("switchToBootUser-" + bootUser);
             switchToBootUser(bootUser);
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 850b5b6..b933508 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1793,6 +1793,10 @@
         }
         t.traceEnd();
 
+        t.traceBegin("StartAppHibernationService");
+        mSystemServiceManager.startService(APP_HIBERNATION_SERVICE_CLASS);
+        t.traceEnd();
+
         t.traceBegin("ArtManagerLocal");
         DexOptHelper.initializeArtManagerLocal(context, mPackageManagerService);
         t.traceEnd();
@@ -2200,9 +2204,11 @@
                 t.traceEnd();
             }
 
-            t.traceBegin("StartDockObserver");
-            mSystemServiceManager.startService(DockObserver.class);
-            t.traceEnd();
+            if (!isTv) {
+                t.traceBegin("StartDockObserver");
+                mSystemServiceManager.startService(DockObserver.class);
+                t.traceEnd();
+            }
 
             if (isWatch) {
                 t.traceBegin("StartThermalObserver");
@@ -2314,10 +2320,6 @@
             mSystemServiceManager.startService(VOICE_RECOGNITION_MANAGER_SERVICE_CLASS);
             t.traceEnd();
 
-            t.traceBegin("StartAppHibernationService");
-            mSystemServiceManager.startService(APP_HIBERNATION_SERVICE_CLASS);
-            t.traceEnd();
-
             if (GestureLauncherService.isGestureLauncherEnabled(context.getResources())) {
                 t.traceBegin("StartGestureLauncher");
                 mSystemServiceManager.startService(GestureLauncherService.class);
@@ -2719,7 +2721,7 @@
         // on it in their setup, but likely needs to be done after LockSettingsService is ready.
         final HsumBootUserInitializer hsumBootUserInitializer =
                 HsumBootUserInitializer.createInstance(
-                        mActivityManagerService, mContentResolver,
+                        mActivityManagerService, mPackageManagerService, mContentResolver,
                         context.getResources().getBoolean(R.bool.config_isMainUserPermanentAdmin));
         if (hsumBootUserInitializer != null) {
             t.traceBegin("HsumBootUserInitializer.init");
@@ -2739,6 +2741,14 @@
         }
         t.traceEnd();
 
+        t.traceBegin("RegisterLogMteState");
+        try {
+            LogMteState.register(context);
+        } catch (Throwable e) {
+            reportWtf("RegisterLogMteState", e);
+        }
+        t.traceEnd();
+
         // Emit any pending system_server WTFs
         synchronized (SystemService.class) {
             if (sPendingWtfs != null) {
@@ -3011,8 +3021,7 @@
             mSystemServiceManager.startBootPhase(t, SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
             t.traceEnd();
 
-            if (hsumBootUserInitializer != null && !isAutomotive) {
-                // TODO(b/261924826): remove isAutomotive check once the workflow is finalized
+            if (hsumBootUserInitializer != null) {
                 t.traceBegin("HsumBootUserInitializer.systemRunning");
                 hsumBootUserInitializer.systemRunning(t);
                 t.traceEnd();
diff --git a/services/people/java/com/android/server/people/data/ContactsQueryHelper.java b/services/people/java/com/android/server/people/data/ContactsQueryHelper.java
index 0993295..2505abf2 100644
--- a/services/people/java/com/android/server/people/data/ContactsQueryHelper.java
+++ b/services/people/java/com/android/server/people/data/ContactsQueryHelper.java
@@ -152,6 +152,8 @@
             }
         } catch (SQLiteException exception) {
             Slog.w("SQLite exception when querying contacts.", exception);
+        } catch (IllegalArgumentException exception) {
+            Slog.w("Illegal Argument exception when querying contacts.", exception);
         }
         if (found && lookupKey != null && hasPhoneNumber) {
             return queryPhoneNumber(lookupKey);
diff --git a/services/people/java/com/android/server/people/data/DataManager.java b/services/people/java/com/android/server/people/data/DataManager.java
index 17e1744..54d2c19 100644
--- a/services/people/java/com/android/server/people/data/DataManager.java
+++ b/services/people/java/com/android/server/people/data/DataManager.java
@@ -113,7 +113,6 @@
     private static final long USAGE_STATS_QUERY_INTERVAL_SEC = 120L;
     @VisibleForTesting
     static final int MAX_CACHED_RECENT_SHORTCUTS = 30;
-    private static final int DEBOUNCE_LENGTH_MS = 500;
 
     private final Context mContext;
     private final Injector mInjector;
@@ -130,8 +129,6 @@
     private final List<PeopleService.ConversationsListener> mConversationsListeners =
             new ArrayList<>(1);
     private final Handler mHandler;
-    private final PerPackageThrottler mShortcutsThrottler;
-
     private ContentObserver mCallLogContentObserver;
     private ContentObserver mMmsSmsContentObserver;
 
@@ -142,17 +139,14 @@
     private ConversationStatusExpirationBroadcastReceiver mStatusExpReceiver;
 
     public DataManager(Context context) {
-        this(context, new Injector(), BackgroundThread.get().getLooper(),
-                new PerPackageThrottlerImpl(BackgroundThread.getHandler(), DEBOUNCE_LENGTH_MS));
+        this(context, new Injector(), BackgroundThread.get().getLooper());
     }
 
-    DataManager(Context context, Injector injector, Looper looper,
-            PerPackageThrottler shortcutsThrottler) {
+    DataManager(Context context, Injector injector, Looper looper) {
         mContext = context;
         mInjector = injector;
         mScheduledExecutor = mInjector.createScheduledExecutor();
         mHandler = new Handler(looper);
-        mShortcutsThrottler = shortcutsThrottler;
     }
 
     /** Initialization. Called when the system services are up running. */
@@ -856,12 +850,12 @@
         // pair of <package name, conversation info>
         List<Pair<String, ConversationInfo>> cachedConvos = new ArrayList<>();
         userData.forAllPackages(packageData -> {
-            packageData.forAllConversations(conversationInfo -> {
-                if (isEligibleForCleanUp(conversationInfo)) {
-                    cachedConvos.add(
-                            Pair.create(packageData.getPackageName(), conversationInfo));
-                }
-            });
+                packageData.forAllConversations(conversationInfo -> {
+                    if (isEligibleForCleanUp(conversationInfo)) {
+                        cachedConvos.add(
+                                Pair.create(packageData.getPackageName(), conversationInfo));
+                    }
+                });
         });
         if (cachedConvos.size() <= targetCachedCount) {
             return;
@@ -872,8 +866,8 @@
                 numToUncache + 1,
                 Comparator.comparingLong((Pair<String, ConversationInfo> pair) ->
                         Math.max(
-                                pair.second.getLastEventTimestamp(),
-                                pair.second.getCreationTimestamp())).reversed());
+                            pair.second.getLastEventTimestamp(),
+                            pair.second.getCreationTimestamp())).reversed());
         for (Pair<String, ConversationInfo> cached : cachedConvos) {
             if (hasActiveNotifications(cached.first, userId, cached.second.getShortcutId())) {
                 continue;
@@ -1109,35 +1103,30 @@
         @Override
         public void onShortcutsAddedOrUpdated(@NonNull String packageName,
                 @NonNull List<ShortcutInfo> shortcuts, @NonNull UserHandle user) {
-            mShortcutsThrottler.scheduleDebounced(
-                    new Pair<>(packageName, user.getIdentifier()),
-                    () -> {
-                        PackageData packageData = getPackage(packageName, user.getIdentifier());
-                        List<ShortcutInfo> queriedShortcuts = getShortcuts(packageName,
-                                user.getIdentifier(), null);
-                        boolean hasCachedShortcut = false;
-                        for (ShortcutInfo shortcut : queriedShortcuts) {
-                            if (ShortcutHelper.isConversationShortcut(
-                                    shortcut, mShortcutServiceInternal, user.getIdentifier())) {
-                                if (shortcut.isCached()) {
-                                    ConversationInfo info = packageData != null
-                                            ? packageData.getConversationInfo(shortcut.getId())
-                                            : null;
-                                    if (info == null
-                                            || !info.isShortcutCachedForNotification()) {
-                                        hasCachedShortcut = true;
-                                    }
-                                }
-                                addOrUpdateConversationInfo(shortcut);
+            mInjector.getBackgroundExecutor().execute(() -> {
+                PackageData packageData = getPackage(packageName, user.getIdentifier());
+                boolean hasCachedShortcut = false;
+                for (ShortcutInfo shortcut : shortcuts) {
+                    if (ShortcutHelper.isConversationShortcut(
+                            shortcut, mShortcutServiceInternal, user.getIdentifier())) {
+                        if (shortcut.isCached()) {
+                            ConversationInfo conversationInfo = packageData != null
+                                    ? packageData.getConversationInfo(shortcut.getId()) : null;
+                            if (conversationInfo == null
+                                    || !conversationInfo.isShortcutCachedForNotification()) {
+                                hasCachedShortcut = true;
                             }
                         }
-                        // Added at least one new conversation. Uncache older existing cached
-                        // shortcuts to ensure the cache size is under the limit.
-                        if (hasCachedShortcut) {
-                            cleanupCachedShortcuts(user.getIdentifier(),
-                                    MAX_CACHED_RECENT_SHORTCUTS);
-                        }
-                    });
+                        addOrUpdateConversationInfo(shortcut);
+                    }
+                }
+                // Added at least one new conversation. Uncache older existing cached
+                // shortcuts to ensure the cache size is under the limit.
+                if (hasCachedShortcut) {
+                    cleanupCachedShortcuts(user.getIdentifier(),
+                            MAX_CACHED_RECENT_SHORTCUTS);
+                }
+            });
         }
 
         @Override
diff --git a/services/people/java/com/android/server/people/data/PerPackageThrottler.java b/services/people/java/com/android/server/people/data/PerPackageThrottler.java
deleted file mode 100644
index 3d6cd84..0000000
--- a/services/people/java/com/android/server/people/data/PerPackageThrottler.java
+++ /dev/null
@@ -1,28 +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.people.data;
-
-import android.util.Pair;
-
-/** The interface for throttling expensive runnables per package. */
-interface PerPackageThrottler {
-    /**
-     * Schedule a runnable to run in the future, and debounce runnables for same {@code pkgUserId}
-     * that occur until that future has run.
-     */
-    void scheduleDebounced(Pair<String, Integer> pkgUserId, Runnable runnable);
-}
diff --git a/services/people/java/com/android/server/people/data/PerPackageThrottlerImpl.java b/services/people/java/com/android/server/people/data/PerPackageThrottlerImpl.java
deleted file mode 100644
index fa5a67b..0000000
--- a/services/people/java/com/android/server/people/data/PerPackageThrottlerImpl.java
+++ /dev/null
@@ -1,52 +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.people.data;
-
-import android.os.Handler;
-import android.util.Pair;
-
-import java.util.HashSet;
-
-/**
- * A class that implements a per-package throttler that prevents a runnable from executing more than
- * once every {@code debounceTime}.
- */
-public class PerPackageThrottlerImpl implements PerPackageThrottler {
-    private final Handler mBackgroundHandler;
-    private final int mDebounceTime;
-    private final HashSet<Pair<String, Integer>> mPkgScheduledTasks = new HashSet<>();
-
-    PerPackageThrottlerImpl(Handler backgroundHandler, int debounceTime) {
-        mBackgroundHandler = backgroundHandler;
-        mDebounceTime = debounceTime;
-    }
-
-    @Override
-    public synchronized void scheduleDebounced(
-            Pair<String, Integer> pkgUserId, Runnable runnable) {
-        if (mPkgScheduledTasks.contains(pkgUserId)) {
-            return;
-        }
-        mPkgScheduledTasks.add(pkgUserId);
-        mBackgroundHandler.postDelayed(() -> {
-            synchronized (this) {
-                mPkgScheduledTasks.remove(pkgUserId);
-                runnable.run();
-            }
-        }, mDebounceTime);
-    }
-}
diff --git a/services/robotests/src/com/android/server/media/AudioPoliciesBluetoothRouteControllerTest.java b/services/robotests/src/com/android/server/media/AudioPoliciesBluetoothRouteControllerTest.java
new file mode 100644
index 0000000..0ad4184
--- /dev/null
+++ b/services/robotests/src/com/android/server/media/AudioPoliciesBluetoothRouteControllerTest.java
@@ -0,0 +1,293 @@
+/*
+ * 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.media;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.when;
+
+import android.app.Application;
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.content.Intent;
+import android.media.AudioManager;
+import android.media.MediaRoute2Info;
+import android.os.UserHandle;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.Shadows;
+import org.robolectric.shadows.ShadowBluetoothAdapter;
+import org.robolectric.shadows.ShadowBluetoothDevice;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+@RunWith(RobolectricTestRunner.class)
+public class AudioPoliciesBluetoothRouteControllerTest {
+
+    private static final String DEVICE_ADDRESS_UNKNOWN = ":unknown:ip:address:";
+    private static final String DEVICE_ADDRESS_SAMPLE_1 = "30:59:8B:E4:C6:35";
+    private static final String DEVICE_ADDRESS_SAMPLE_2 = "0D:0D:A6:FF:8D:B6";
+    private static final String DEVICE_ADDRESS_SAMPLE_3 = "2D:9B:0C:C2:6F:78";
+    private static final String DEVICE_ADDRESS_SAMPLE_4 = "66:88:F9:2D:A8:1E";
+
+    private Context mContext;
+
+    private ShadowBluetoothAdapter mShadowBluetoothAdapter;
+
+    @Mock
+    private BluetoothRouteController.BluetoothRoutesUpdatedListener mListener;
+
+    @Mock
+    private BluetoothProfileMonitor mBluetoothProfileMonitor;
+
+    private AudioPoliciesBluetoothRouteController mAudioPoliciesBluetoothRouteController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        Application application = ApplicationProvider.getApplicationContext();
+        mContext = application;
+
+        BluetoothManager bluetoothManager = (BluetoothManager)
+                mContext.getSystemService(Context.BLUETOOTH_SERVICE);
+
+        BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
+        mShadowBluetoothAdapter = Shadows.shadowOf(bluetoothAdapter);
+
+        mAudioPoliciesBluetoothRouteController =
+                new AudioPoliciesBluetoothRouteController(mContext, bluetoothAdapter,
+                        mBluetoothProfileMonitor, mListener) {
+                    @Override
+                    boolean isDeviceConnected(BluetoothDevice device) {
+                        return true;
+                    }
+                };
+
+        // Enable A2DP profile.
+        when(mBluetoothProfileMonitor.isProfileSupported(eq(BluetoothProfile.A2DP), any()))
+                .thenReturn(true);
+        mShadowBluetoothAdapter.setProfileConnectionState(BluetoothProfile.A2DP,
+                BluetoothProfile.STATE_CONNECTED);
+
+        mAudioPoliciesBluetoothRouteController.start(UserHandle.of(0));
+    }
+
+    @Test
+    public void getSelectedRoute_noBluetoothRoutesAvailable_returnsNull() {
+        assertThat(mAudioPoliciesBluetoothRouteController.getSelectedRoute()).isNull();
+    }
+
+    @Test
+    public void selectRoute_noBluetoothRoutesAvailable_returnsFalse() {
+        assertThat(mAudioPoliciesBluetoothRouteController
+                .selectRoute(DEVICE_ADDRESS_UNKNOWN)).isFalse();
+    }
+
+    @Test
+    public void selectRoute_noDeviceWithGivenAddress_returnsFalse() {
+        Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+                DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_3);
+
+        mShadowBluetoothAdapter.setBondedDevices(devices);
+
+        assertThat(mAudioPoliciesBluetoothRouteController
+                .selectRoute(DEVICE_ADDRESS_SAMPLE_2)).isFalse();
+    }
+
+    @Test
+    public void selectRoute_deviceIsInDevicesSet_returnsTrue() {
+        Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+                DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_2);
+
+        mShadowBluetoothAdapter.setBondedDevices(devices);
+
+        assertThat(mAudioPoliciesBluetoothRouteController
+                .selectRoute(DEVICE_ADDRESS_SAMPLE_1)).isTrue();
+    }
+
+    @Test
+    public void selectRoute_resetSelectedDevice_returnsTrue() {
+        Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+                DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_2);
+
+        mShadowBluetoothAdapter.setBondedDevices(devices);
+
+        mAudioPoliciesBluetoothRouteController.selectRoute(DEVICE_ADDRESS_SAMPLE_1);
+        assertThat(mAudioPoliciesBluetoothRouteController.selectRoute(null)).isTrue();
+    }
+
+    @Test
+    public void selectRoute_noSelectedDevice_returnsTrue() {
+        Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+                DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_2);
+
+        mShadowBluetoothAdapter.setBondedDevices(devices);
+
+        assertThat(mAudioPoliciesBluetoothRouteController.selectRoute(null)).isTrue();
+    }
+
+    @Test
+    public void getSelectedRoute_updateRouteFailed_returnsNull() {
+        Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+                DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_2);
+
+        mShadowBluetoothAdapter.setBondedDevices(devices);
+        mAudioPoliciesBluetoothRouteController
+                .selectRoute(DEVICE_ADDRESS_SAMPLE_3);
+
+        assertThat(mAudioPoliciesBluetoothRouteController.getSelectedRoute()).isNull();
+    }
+
+    @Test
+    public void getSelectedRoute_updateRouteSuccessful_returnsUpdateDevice() {
+        Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+                DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_2, DEVICE_ADDRESS_SAMPLE_4);
+
+        assertThat(mAudioPoliciesBluetoothRouteController.getSelectedRoute()).isNull();
+
+        mShadowBluetoothAdapter.setBondedDevices(devices);
+
+        assertThat(mAudioPoliciesBluetoothRouteController
+                .selectRoute(DEVICE_ADDRESS_SAMPLE_4)).isTrue();
+
+        MediaRoute2Info selectedRoute = mAudioPoliciesBluetoothRouteController.getSelectedRoute();
+        assertThat(selectedRoute.getAddress()).isEqualTo(DEVICE_ADDRESS_SAMPLE_4);
+    }
+
+    @Test
+    public void getSelectedRoute_resetSelectedRoute_returnsNull() {
+        Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+                DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_2, DEVICE_ADDRESS_SAMPLE_4);
+
+        mShadowBluetoothAdapter.setBondedDevices(devices);
+
+        // Device is not null now.
+        mAudioPoliciesBluetoothRouteController.selectRoute(DEVICE_ADDRESS_SAMPLE_4);
+        // Rest the device.
+        mAudioPoliciesBluetoothRouteController.selectRoute(null);
+
+        assertThat(mAudioPoliciesBluetoothRouteController.getSelectedRoute())
+                .isNull();
+    }
+
+    @Test
+    public void getTransferableRoutes_noSelectedRoute_returnsAllBluetoothDevices() {
+        String[] addresses = new String[] { DEVICE_ADDRESS_SAMPLE_1,
+                DEVICE_ADDRESS_SAMPLE_2, DEVICE_ADDRESS_SAMPLE_4 };
+        Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(addresses);
+        mShadowBluetoothAdapter.setBondedDevices(devices);
+
+        // Force route controller to update bluetooth devices list.
+        sendBluetoothDevicesChangedBroadcast();
+
+        Set<String> transferableDevices = extractAddressesListFrom(
+                mAudioPoliciesBluetoothRouteController.getTransferableRoutes());
+        assertThat(transferableDevices).containsExactlyElementsIn(addresses);
+    }
+
+    @Test
+    public void getTransferableRoutes_hasSelectedRoute_returnsRoutesWithoutSelectedDevice() {
+        String[] addresses = new String[] { DEVICE_ADDRESS_SAMPLE_1,
+                DEVICE_ADDRESS_SAMPLE_2, DEVICE_ADDRESS_SAMPLE_4 };
+        Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(addresses);
+        mShadowBluetoothAdapter.setBondedDevices(devices);
+
+        // Force route controller to update bluetooth devices list.
+        sendBluetoothDevicesChangedBroadcast();
+        mAudioPoliciesBluetoothRouteController.selectRoute(DEVICE_ADDRESS_SAMPLE_4);
+
+        Set<String> transferableDevices = extractAddressesListFrom(
+                mAudioPoliciesBluetoothRouteController.getTransferableRoutes());
+        assertThat(transferableDevices).containsExactly(DEVICE_ADDRESS_SAMPLE_1,
+                DEVICE_ADDRESS_SAMPLE_2);
+    }
+
+    @Test
+    public void getAllBluetoothRoutes_hasSelectedRoute_returnsAllRoutes() {
+        String[] addresses = new String[] { DEVICE_ADDRESS_SAMPLE_1,
+                DEVICE_ADDRESS_SAMPLE_2, DEVICE_ADDRESS_SAMPLE_4 };
+        Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(addresses);
+        mShadowBluetoothAdapter.setBondedDevices(devices);
+
+        // Force route controller to update bluetooth devices list.
+        sendBluetoothDevicesChangedBroadcast();
+        mAudioPoliciesBluetoothRouteController.selectRoute(DEVICE_ADDRESS_SAMPLE_4);
+
+        Set<String> bluetoothDevices = extractAddressesListFrom(
+                mAudioPoliciesBluetoothRouteController.getAllBluetoothRoutes());
+        assertThat(bluetoothDevices).containsExactlyElementsIn(addresses);
+    }
+
+    @Test
+    public void updateVolumeForDevice_setVolumeForA2DPTo25_selectedRouteVolumeIsUpdated() {
+        String[] addresses = new String[] { DEVICE_ADDRESS_SAMPLE_1,
+                DEVICE_ADDRESS_SAMPLE_2, DEVICE_ADDRESS_SAMPLE_4 };
+        Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(addresses);
+        mShadowBluetoothAdapter.setBondedDevices(devices);
+
+        // Force route controller to update bluetooth devices list.
+        sendBluetoothDevicesChangedBroadcast();
+        mAudioPoliciesBluetoothRouteController.selectRoute(DEVICE_ADDRESS_SAMPLE_4);
+
+        mAudioPoliciesBluetoothRouteController.updateVolumeForDevices(
+                AudioManager.DEVICE_OUT_BLUETOOTH_A2DP, 25);
+
+        MediaRoute2Info selectedRoute = mAudioPoliciesBluetoothRouteController.getSelectedRoute();
+        assertThat(selectedRoute.getVolume()).isEqualTo(25);
+    }
+
+    private void sendBluetoothDevicesChangedBroadcast() {
+        Intent intent = new Intent(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED);
+        mContext.sendBroadcast(intent);
+    }
+
+    private static Set<String> extractAddressesListFrom(Collection<MediaRoute2Info> routes) {
+        Set<String> addresses = new HashSet<>();
+
+        for (MediaRoute2Info route: routes) {
+            addresses.add(route.getAddress());
+        }
+
+        return addresses;
+    }
+
+    private static Set<BluetoothDevice> generateFakeBluetoothDevicesSet(String... addresses) {
+        Set<BluetoothDevice> devices = new HashSet<>();
+
+        for (String address: addresses) {
+            devices.add(ShadowBluetoothDevice.newInstance(address));
+        }
+
+        return devices;
+    }
+}
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
index 9501b96..9829e57 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
@@ -65,6 +65,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.mockito.Mock;
 import org.mockito.MockitoSession;
 import org.mockito.quality.Strictness;
@@ -121,6 +122,14 @@
     protected InputMethodManagerService mInputMethodManagerService;
     protected ServiceThread mServiceThread;
 
+    @BeforeClass
+    public static void setupClass() {
+        // Make sure DeviceConfig's lazy-initialized ContentProvider gets
+        // a real instance before we stub out all system services below.
+        // TODO(b/272229177): remove dependency on real ContentProvider
+        new InputMethodDeviceConfigs().destroy();
+    }
+
     @Before
     public void setUp() throws RemoteException {
         mMockingSession =
@@ -231,6 +240,10 @@
 
     @After
     public void tearDown() {
+        if (mInputMethodManagerService != null) {
+            mInputMethodManagerService.mInputMethodDeviceConfigs.destroy();
+        }
+
         if (mServiceThread != null) {
             mServiceThread.quitSafely();
         }
diff --git a/services/tests/PackageManagerServiceTests/TEST_MAPPING b/services/tests/PackageManagerServiceTests/TEST_MAPPING
index fe27a37..e98acb2 100644
--- a/services/tests/PackageManagerServiceTests/TEST_MAPPING
+++ b/services/tests/PackageManagerServiceTests/TEST_MAPPING
@@ -43,6 +43,38 @@
       ]
     }
   ],
+  "kernel-presubmit": [
+    {
+      "name": "PackageManagerServiceHostTests",
+      "options": [
+        {
+          // TODO(b/197552347) (crashes postsubmit)
+          "exclude-filter": "com.android.server.pm.test.OverlayActorVisibilityTest#testVisibilityByOverlayable"
+        },
+        {
+          // TODO(b/204133664)
+          "exclude-filter": "com.android.server.pm.test.SdCardEjectionTests"
+        },
+	{
+          // TODO(b/272575212)
+          "exclude-filter": "com.android.server.pm.test.SettingsTest#testWriteCorruptDataBinaryXml"
+	},
+	{
+          "exclude-filter": "com.android.server.pm.test.SettingsTest#testWriteCorruptDataTextXml"
+	},
+	{
+          "exclude-filter": "com.android.server.pm.test.SettingsTest#testWriteCorruptHeaderBinaryXml"
+	},
+	{
+          "exclude-filter": "com.android.server.pm.test.SettingsTest#testWriteCorruptHeaderTextXml"
+	},
+	{
+          // TODO(b/272714903)
+          "exclude-filter": "com.android.server.pm.test.OverlayPathsUninstallSystemUpdatesTest#verify"
+	}
+      ]
+    }
+  ],
   "imports": [
     {
       "path": "frameworks/base/services/tests/PackageManagerServiceTests/unit"
diff --git a/services/tests/PackageManagerServiceTests/apks/install_uses_sdk/Android.bp b/services/tests/PackageManagerServiceTests/apks/install_uses_sdk/Android.bp
index 2894395..24e380c 100644
--- a/services/tests/PackageManagerServiceTests/apks/install_uses_sdk/Android.bp
+++ b/services/tests/PackageManagerServiceTests/apks/install_uses_sdk/Android.bp
@@ -32,9 +32,9 @@
 }
 
 android_test_helper_app {
-    name: "FrameworksServicesTests_install_uses_sdk_r1000",
+    name: "FrameworksServicesTests_install_uses_sdk_r10000",
     defaults: ["FrameworksServicesTests_apks_defaults"],
-    manifest: "AndroidManifest-r1000.xml",
+    manifest: "AndroidManifest-r10000.xml",
 }
 
 android_test_helper_app {
@@ -44,9 +44,9 @@
 }
 
 android_test_helper_app {
-    name: "FrameworksServicesTests_install_uses_sdk_r0_s1000",
+    name: "FrameworksServicesTests_install_uses_sdk_r0_s10000",
     defaults: ["FrameworksServicesTests_apks_defaults"],
-    manifest: "AndroidManifest-r0-s1000.xml",
+    manifest: "AndroidManifest-r0-s10000.xml",
 }
 
 android_test_helper_app {
diff --git a/services/tests/PackageManagerServiceTests/apks/install_uses_sdk/AndroidManifest-r0-s1000.xml b/services/tests/PackageManagerServiceTests/apks/install_uses_sdk/AndroidManifest-r0-s10000.xml
similarity index 97%
rename from services/tests/PackageManagerServiceTests/apks/install_uses_sdk/AndroidManifest-r0-s1000.xml
rename to services/tests/PackageManagerServiceTests/apks/install_uses_sdk/AndroidManifest-r0-s10000.xml
index 25743b8..383e60a 100644
--- a/services/tests/PackageManagerServiceTests/apks/install_uses_sdk/AndroidManifest-r0-s1000.xml
+++ b/services/tests/PackageManagerServiceTests/apks/install_uses_sdk/AndroidManifest-r0-s10000.xml
@@ -19,7 +19,7 @@
     <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="29">
         <!-- This fails because 31 is not version 5 -->
         <extension-sdk android:sdkVersion="30" android:minExtensionVersion="0" />
-        <extension-sdk android:sdkVersion="31" android:minExtensionVersion="1000" />
+        <extension-sdk android:sdkVersion="31" android:minExtensionVersion="10000" />
     </uses-sdk>
 
     <application>
diff --git a/services/tests/PackageManagerServiceTests/apks/install_uses_sdk/AndroidManifest-r1000.xml b/services/tests/PackageManagerServiceTests/apks/install_uses_sdk/AndroidManifest-r10000.xml
similarity index 97%
rename from services/tests/PackageManagerServiceTests/apks/install_uses_sdk/AndroidManifest-r1000.xml
rename to services/tests/PackageManagerServiceTests/apks/install_uses_sdk/AndroidManifest-r10000.xml
index 9bf9254..fe7a212 100644
--- a/services/tests/PackageManagerServiceTests/apks/install_uses_sdk/AndroidManifest-r1000.xml
+++ b/services/tests/PackageManagerServiceTests/apks/install_uses_sdk/AndroidManifest-r10000.xml
@@ -18,7 +18,7 @@
 
     <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="29">
         <!-- This will fail to install, because minExtensionVersion is not met -->
-        <extension-sdk android:sdkVersion="30" android:minExtensionVersion="1000" />
+        <extension-sdk android:sdkVersion="30" android:minExtensionVersion="10000" />
     </uses-sdk>
 
     <application>
diff --git a/services/tests/PackageManagerServiceTests/server/Android.bp b/services/tests/PackageManagerServiceTests/server/Android.bp
index e711cab..1146271 100644
--- a/services/tests/PackageManagerServiceTests/server/Android.bp
+++ b/services/tests/PackageManagerServiceTests/server/Android.bp
@@ -127,10 +127,10 @@
         ":FrameworksServicesTests_install_uses_sdk_q0",
         ":FrameworksServicesTests_install_uses_sdk_q0_r0",
         ":FrameworksServicesTests_install_uses_sdk_r0",
-        ":FrameworksServicesTests_install_uses_sdk_r1000",
+        ":FrameworksServicesTests_install_uses_sdk_r10000",
         ":FrameworksServicesTests_install_uses_sdk_r_none",
         ":FrameworksServicesTests_install_uses_sdk_r0_s0",
-        ":FrameworksServicesTests_install_uses_sdk_r0_s1000",
+        ":FrameworksServicesTests_install_uses_sdk_r0_s10000",
         ":FrameworksServicesTests_keyset_permdef_sa_unone",
         ":FrameworksServicesTests_keyset_permuse_sa_ua_ub",
         ":FrameworksServicesTests_keyset_permuse_sb_ua_ub",
diff --git a/services/tests/PackageManagerServiceTests/server/AndroidManifest.xml b/services/tests/PackageManagerServiceTests/server/AndroidManifest.xml
index c383197..ddc8dfd 100644
--- a/services/tests/PackageManagerServiceTests/server/AndroidManifest.xml
+++ b/services/tests/PackageManagerServiceTests/server/AndroidManifest.xml
@@ -37,6 +37,7 @@
     <uses-permission android:name="android.permission.OBSERVE_NETWORK_POLICY"/>
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
     <uses-permission android:name="android.permission.MANAGE_USERS"/>
+    <uses-permission android:name="android.permission.CREATE_USERS"/>
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
     <uses-permission android:name="android.permission.MANAGE_DEVICE_ADMINS"/>
     <uses-permission android:name="android.permission.MODIFY_PHONE_STATE"/>
diff --git a/services/tests/PackageManagerServiceTests/server/AndroidTest.xml b/services/tests/PackageManagerServiceTests/server/AndroidTest.xml
index 869d60e..1b93527 100644
--- a/services/tests/PackageManagerServiceTests/server/AndroidTest.xml
+++ b/services/tests/PackageManagerServiceTests/server/AndroidTest.xml
@@ -20,6 +20,7 @@
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="install-arg" value="-t" />
+        <option name="install-arg" value="-g" />
         <option name="test-file-name" value="PackageManagerServiceServerTests.apk" />
     </target_preparer>
 
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 a39e021..836f858 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
@@ -566,6 +566,22 @@
     }
 
     @Test
+    public void testWriteCorruptReadPackageRestrictions() {
+        final Settings settingsUnderTest = makeSettings();
+
+        populateDistractionFlags(settingsUnderTest);
+        settingsUnderTest.writePackageRestrictionsLPr(0, /*sync=*/true);
+
+        // Corrupt primary file.
+        writeCorruptedPackageRestrictions(0);
+
+        // now read and verify
+        populateDefaultSettings(settingsUnderTest);
+        settingsUnderTest.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
+        verifyDistractionFlags(settingsUnderTest);
+    }
+
+    @Test
     public void testReadWritePackageRestrictionsAsync() {
         final Settings settingsWrite = makeSettings();
         final Settings settingsRead = makeSettings();
@@ -1811,6 +1827,14 @@
                         .getBytes());
     }
 
+    private void writeCorruptedPackageRestrictions(final int userId) {
+        writeFile(new File(InstrumentationRegistry.getContext().getFilesDir(), "system/users/"
+                        + userId + "/package-restrictions.xml"),
+                ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+                        + "<package-restrictions>\n"
+                        + "    <pkg name=\"" + PACKAGE_NAME_1 + "\" ").getBytes());
+    }
+
     private static void writeStoppedPackagesXml() {
         writeFile(new File(InstrumentationRegistry.getContext().getFilesDir(), "system/packages-stopped.xml"),
                 ( "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
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 ebf309f..906cc83 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
@@ -575,10 +575,10 @@
         assertEquals(0, minExtVers.get(31, -1));
 
         Map<Pair<String, Integer>, Integer> appToError = new HashMap<>();
-        appToError.put(Pair.create("install_uses_sdk.apk_r1000", R.raw.install_uses_sdk_r1000),
+        appToError.put(Pair.create("install_uses_sdk.apk_r10000", R.raw.install_uses_sdk_r10000),
                        PackageManager.INSTALL_FAILED_OLDER_SDK);
         appToError.put(
-                Pair.create("install_uses_sdk.apk_r0_s1000", R.raw.install_uses_sdk_r0_s1000),
+                Pair.create("install_uses_sdk.apk_r0_s10000", R.raw.install_uses_sdk_r0_s10000),
                 PackageManager.INSTALL_FAILED_OLDER_SDK);
 
         appToError.put(Pair.create("install_uses_sdk.apk_q0", R.raw.install_uses_sdk_q0),
diff --git a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
index bcd69fda..5377ee7 100644
--- a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
@@ -86,6 +86,9 @@
 import android.os.PowerSaveState;
 import android.os.SystemClock;
 import android.provider.DeviceConfig;
+import android.telephony.TelephonyCallback;
+import android.telephony.TelephonyManager;
+import android.telephony.emergency.EmergencyNumber;
 
 import androidx.test.runner.AndroidJUnit4;
 
@@ -119,6 +122,8 @@
     private AnyMotionDetectorForTest mAnyMotionDetector;
     private AppStateTrackerForTest mAppStateTracker;
     private DeviceIdleController.Constants mConstants;
+    private TelephonyCallback.OutgoingEmergencyCallListener mEmergencyCallListener;
+    private TelephonyCallback.CallStateListener mCallStateListener;
     private InjectorForTest mInjector;
 
     private MockitoSession mMockingSession;
@@ -140,6 +145,8 @@
     private Sensor mMotionSensor;
     @Mock
     private SensorManager mSensorManager;
+    @Mock
+    private TelephonyManager mTelephonyManager;
 
     class InjectorForTest extends DeviceIdleController.Injector {
         ConnectivityManager connectivityManager;
@@ -147,6 +154,7 @@
         ConstraintController constraintController;
         // Freeze time for testing.
         long nowElapsed;
+        boolean useMotionSensor = true;
 
         InjectorForTest(Context ctx) {
             super(ctx);
@@ -232,8 +240,13 @@
         }
 
         @Override
+        TelephonyManager getTelephonyManager() {
+            return mTelephonyManager;
+        }
+
+        @Override
         boolean useMotionSensor() {
-            return true;
+            return useMotionSensor;
         }
     }
 
@@ -333,6 +346,12 @@
         mAnyMotionDetector = new AnyMotionDetectorForTest();
         mInjector = new InjectorForTest(getContext());
 
+        setupDeviceIdleController();
+    }
+
+    private void setupDeviceIdleController() {
+        reset(mTelephonyManager);
+
         mDeviceIdleController = new DeviceIdleController(getContext(), mInjector);
         spyOn(mDeviceIdleController);
         doNothing().when(mDeviceIdleController).publishBinderService(any(), any());
@@ -343,6 +362,15 @@
 
         // Get the same Constants object that mDeviceIdleController got.
         mConstants = mInjector.getConstants(mDeviceIdleController);
+
+        final ArgumentCaptor<TelephonyCallback> telephonyCallbackCaptor =
+                ArgumentCaptor.forClass(TelephonyCallback.class);
+        verify(mTelephonyManager)
+                .registerTelephonyCallback(any(), telephonyCallbackCaptor.capture());
+        mEmergencyCallListener = (TelephonyCallback.OutgoingEmergencyCallListener)
+                telephonyCallbackCaptor.getValue();
+        mCallStateListener =
+                (TelephonyCallback.CallStateListener) telephonyCallbackCaptor.getValue();
     }
 
     @After
@@ -350,6 +378,10 @@
         if (mMockingSession != null) {
             mMockingSession.finishMocking();
         }
+    }
+
+    @After
+    public void cleanupDeviceIdleController() {
         // DeviceIdleController adds these to LocalServices in the constructor, so we have to remove
         // them after each test, otherwise, subsequent tests will fail.
         LocalServices.removeServiceForTest(AppStateTracker.class);
@@ -531,6 +563,16 @@
 
         mDeviceIdleController.becomeInactiveIfAppropriateLocked();
         verifyStateConditions(STATE_ACTIVE);
+
+        // All other conditions allow for going INACTIVE...
+        setAlarmSoon(false);
+        setChargingOn(false);
+        setScreenOn(false);
+        // ...except the emergency call.
+        setEmergencyCallActive(true);
+
+        mDeviceIdleController.becomeInactiveIfAppropriateLocked();
+        verifyStateConditions(STATE_ACTIVE);
     }
 
     @Test
@@ -559,6 +601,15 @@
 
         mDeviceIdleController.becomeInactiveIfAppropriateLocked();
         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
+
+        // All other conditions allow for going INACTIVE...
+        setChargingOn(false);
+        setScreenOn(false);
+        // ...except the emergency call.
+        setEmergencyCallActive(true);
+
+        mDeviceIdleController.becomeInactiveIfAppropriateLocked();
+        verifyLightStateConditions(LIGHT_STATE_ACTIVE);
     }
 
     @Test
@@ -569,6 +620,7 @@
         setAlarmSoon(false);
         setChargingOn(false);
         setScreenOn(false);
+        setEmergencyCallActive(false);
 
         mDeviceIdleController.becomeInactiveIfAppropriateLocked();
         verifyStateConditions(STATE_INACTIVE);
@@ -577,6 +629,60 @@
     }
 
     @Test
+    public void testStateActiveToStateInactive_DoNotUseMotionSensor() {
+        mInjector.useMotionSensor = false;
+        cleanupDeviceIdleController();
+        setupDeviceIdleController();
+        mDeviceIdleController.becomeActiveLocked("testing", 0);
+        verifyStateConditions(STATE_ACTIVE);
+
+        setAlarmSoon(false);
+        setChargingOn(false);
+        setScreenOn(false);
+        setEmergencyCallActive(false);
+
+        mDeviceIdleController.becomeInactiveIfAppropriateLocked();
+        verifyStateConditions(STATE_INACTIVE);
+        verify(mDeviceIdleController)
+                .scheduleAlarmLocked(eq(mConstants.INACTIVE_TIMEOUT), eq(false));
+        // The device configuration doesn't require a motion sensor to proceed with idling.
+        // This should be the case on TVs or other such devices. We should set an alarm to move
+        // forward if the motion sensor is missing in this case.
+        verify(mAlarmManager).setWindow(
+                anyInt(), anyLong(), anyLong(),
+                eq("DeviceIdleController.deep"), any(), any(Handler.class));
+    }
+
+    @Test
+    public void testStateActiveToStateInactive_MissingMotionSensor() {
+        mInjector.useMotionSensor = true;
+        mMotionSensor = null;
+        cleanupDeviceIdleController();
+        setupDeviceIdleController();
+        mDeviceIdleController.becomeActiveLocked("testing", 0);
+        verifyStateConditions(STATE_ACTIVE);
+
+        setAlarmSoon(false);
+        setChargingOn(false);
+        setScreenOn(false);
+        setEmergencyCallActive(false);
+
+        mDeviceIdleController.becomeInactiveIfAppropriateLocked();
+        verifyStateConditions(STATE_INACTIVE);
+        verify(mDeviceIdleController)
+                .scheduleAlarmLocked(eq(mConstants.INACTIVE_TIMEOUT), eq(false));
+        // The device configuration requires a motion sensor to proceed with idling,
+        // so we should never set an alarm to move forward if the motion sensor is
+        // missing in this case.
+        verify(mAlarmManager, never()).setWindow(
+                anyInt(), anyLong(), anyLong(),
+                eq("DeviceIdleController.deep"), any(), any(Handler.class));
+        verify(mAlarmManager, never()).set(
+                anyInt(), anyLong(),
+                eq("DeviceIdleController.deep"), any(), any(Handler.class));
+    }
+
+    @Test
     public void testStateActiveToStateInactive_UpcomingAlarm() {
         final long timeUntilAlarm = mConstants.MIN_TIME_TO_ALARM / 2;
         // Set an upcoming alarm that will prevent full idle.
@@ -613,6 +719,7 @@
 
         setChargingOn(false);
         setScreenOn(false);
+        setEmergencyCallActive(false);
 
         mDeviceIdleController.becomeInactiveIfAppropriateLocked();
         verifyLightStateConditions(LIGHT_STATE_INACTIVE);
@@ -715,6 +822,94 @@
     }
 
     @Test
+    public void testStepIdleStateLocked_ValidStates_MissingMotionSensor() {
+        mInjector.useMotionSensor = true;
+        mMotionSensor = null;
+        cleanupDeviceIdleController();
+        setupDeviceIdleController();
+        mInjector.locationManager = mLocationManager;
+        doReturn(mock(LocationProvider.class)).when(mLocationManager).getProvider(anyString());
+        // Make sure the controller doesn't think there's a wake-from-idle alarm coming soon.
+        setAlarmSoon(false);
+
+        InOrder alarmManagerInOrder = inOrder(mAlarmManager);
+
+        // Set state to INACTIVE.
+        mDeviceIdleController.becomeActiveLocked("testing", 0);
+        setChargingOn(false);
+        setScreenOn(false);
+        verifyStateConditions(STATE_INACTIVE);
+
+        // The device configuration requires a motion sensor to proceed with idling,
+        // so we should never set an alarm to move forward if the motion sensor is
+        // missing in this case.
+        alarmManagerInOrder.verify(mAlarmManager, never())
+                .setWindow(anyInt(), anyLong(), anyLong(),
+                        eq("DeviceIdleController.deep"), any(), any(Handler.class));
+
+        // Pretend that someone is forcing state stepping via adb
+
+        mDeviceIdleController.stepIdleStateLocked("testing");
+        // verifyStateConditions knows this state typically shouldn't happen during normal
+        // operation, so we can't use it directly here. For this test, all we care about
+        // is that the state stepped forward.
+        assertEquals(STATE_IDLE_PENDING, mDeviceIdleController.getState());
+        // Still no alarm
+        alarmManagerInOrder.verify(mAlarmManager, never())
+                .setWindow(anyInt(), anyLong(), anyLong(),
+                        eq("DeviceIdleController.deep"), any(), any(Handler.class));
+
+        mDeviceIdleController.stepIdleStateLocked("testing");
+        // verifyStateConditions knows this state typically shouldn't happen during normal
+        // operation, so we can't use it directly here. For this test, all we care about
+        // is that the state stepped forward.
+        assertEquals(STATE_SENSING, mDeviceIdleController.getState());
+        // Still no alarm
+        alarmManagerInOrder.verify(mAlarmManager, never())
+                .setWindow(anyInt(), anyLong(), anyLong(),
+                        eq("DeviceIdleController.deep"), any(), any(Handler.class));
+
+        mDeviceIdleController.stepIdleStateLocked("testing");
+        // Location manager exists with a provider, so SENSING should go to LOCATING.
+        // verifyStateConditions knows this state typically shouldn't happen during normal
+        // operation, so we can't use it directly here. For this test, all we care about
+        // is that the state stepped forward.
+        assertEquals(STATE_LOCATING, mDeviceIdleController.getState());
+        // Still no alarm
+        alarmManagerInOrder.verify(mAlarmManager, never())
+                .setWindow(anyInt(), anyLong(), anyLong(),
+                        eq("DeviceIdleController.deep"), any(), any(Handler.class));
+
+        mDeviceIdleController.stepIdleStateLocked("testing");
+        verifyStateConditions(STATE_IDLE);
+        // The device was forced into IDLE. AlarmManager should be notified.
+        alarmManagerInOrder.verify(mAlarmManager)
+                .setIdleUntil(anyInt(), anyLong(),
+                        eq("DeviceIdleController.deep"), any(), any(Handler.class));
+
+        // Should just alternate between IDLE and IDLE_MAINTENANCE now. Since we've gotten to this
+        // point, alarms should be set on each transition.
+
+        mDeviceIdleController.stepIdleStateLocked("testing");
+        verifyStateConditions(STATE_IDLE_MAINTENANCE);
+        alarmManagerInOrder.verify(mAlarmManager)
+                .setWindow(anyInt(), anyLong(), anyLong(),
+                        eq("DeviceIdleController.deep"), any(), any(Handler.class));
+
+        mDeviceIdleController.stepIdleStateLocked("testing");
+        verifyStateConditions(STATE_IDLE);
+        alarmManagerInOrder.verify(mAlarmManager)
+                .setIdleUntil(anyInt(), anyLong(),
+                        eq("DeviceIdleController.deep"), any(), any(Handler.class));
+
+        mDeviceIdleController.stepIdleStateLocked("testing");
+        verifyStateConditions(STATE_IDLE_MAINTENANCE);
+        alarmManagerInOrder.verify(mAlarmManager)
+                .setWindow(anyInt(), anyLong(), anyLong(),
+                        eq("DeviceIdleController.deep"), any(), any(Handler.class));
+    }
+
+    @Test
     public void testStepIdleStateLocked_ValidStates_WithWakeFromIdleAlarmSoon() {
         enterDeepState(STATE_ACTIVE);
         // Return that there's an alarm coming soon.
@@ -1147,6 +1342,22 @@
                 eq(true));
     }
 
+    @Test
+    public void testEmergencyCallEndTriggersInactive() {
+        setAlarmSoon(false);
+        setChargingOn(false);
+        setScreenOn(false);
+        setEmergencyCallActive(true);
+
+        verifyStateConditions(STATE_ACTIVE);
+        verifyLightStateConditions(LIGHT_STATE_ACTIVE);
+
+        setEmergencyCallActive(false);
+
+        verifyStateConditions(STATE_INACTIVE);
+        verifyLightStateConditions(LIGHT_STATE_INACTIVE);
+    }
+
     ///////////////// EXIT conditions ///////////////////
 
     @Test
@@ -2096,6 +2307,75 @@
                 .onDeviceStationaryChanged(eq(true));
     }
 
+    @Test
+    public void testEmergencyEndsIdle() {
+        enterDeepState(STATE_ACTIVE);
+        setEmergencyCallActive(true);
+        verifyStateConditions(STATE_ACTIVE);
+
+        enterDeepState(STATE_INACTIVE);
+        setEmergencyCallActive(true);
+        verifyStateConditions(STATE_ACTIVE);
+
+        enterDeepState(STATE_IDLE_PENDING);
+        setEmergencyCallActive(true);
+        verifyStateConditions(STATE_ACTIVE);
+
+        enterDeepState(STATE_SENSING);
+        setEmergencyCallActive(true);
+        verifyStateConditions(STATE_ACTIVE);
+
+        enterDeepState(STATE_LOCATING);
+        setEmergencyCallActive(true);
+        verifyStateConditions(STATE_ACTIVE);
+
+        // Quick doze enabled or not shouldn't affect the end state.
+        enterDeepState(STATE_QUICK_DOZE_DELAY);
+        setQuickDozeEnabled(true);
+        setEmergencyCallActive(true);
+        verifyStateConditions(STATE_ACTIVE);
+
+        enterDeepState(STATE_QUICK_DOZE_DELAY);
+        setQuickDozeEnabled(false);
+        setEmergencyCallActive(true);
+        verifyStateConditions(STATE_ACTIVE);
+
+        enterDeepState(STATE_IDLE);
+        setEmergencyCallActive(true);
+        verifyStateConditions(STATE_ACTIVE);
+
+        enterDeepState(STATE_IDLE_MAINTENANCE);
+        setEmergencyCallActive(true);
+        verifyStateConditions(STATE_ACTIVE);
+    }
+
+    @Test
+    public void testEmergencyEndsLightIdle() {
+        enterLightState(LIGHT_STATE_ACTIVE);
+        setEmergencyCallActive(true);
+        verifyLightStateConditions(LIGHT_STATE_ACTIVE);
+
+        enterLightState(LIGHT_STATE_INACTIVE);
+        setEmergencyCallActive(true);
+        verifyLightStateConditions(LIGHT_STATE_ACTIVE);
+
+        enterLightState(LIGHT_STATE_WAITING_FOR_NETWORK);
+        setEmergencyCallActive(true);
+        verifyLightStateConditions(LIGHT_STATE_ACTIVE);
+
+        enterLightState(LIGHT_STATE_IDLE);
+        setEmergencyCallActive(true);
+        verifyLightStateConditions(LIGHT_STATE_ACTIVE);
+
+        enterLightState(LIGHT_STATE_IDLE_MAINTENANCE);
+        setEmergencyCallActive(true);
+        verifyLightStateConditions(LIGHT_STATE_ACTIVE);
+
+        enterLightState(LIGHT_STATE_OVERRIDE);
+        setEmergencyCallActive(true);
+        verifyLightStateConditions(LIGHT_STATE_ACTIVE);
+    }
+
     private void enterDeepState(int state) {
         switch (state) {
             case STATE_ACTIVE:
@@ -2108,6 +2388,7 @@
                 setQuickDozeEnabled(true);
                 setScreenOn(false);
                 setChargingOn(false);
+                setEmergencyCallActive(false);
                 mDeviceIdleController.becomeInactiveIfAppropriateLocked();
                 break;
             case STATE_LOCATING:
@@ -2128,6 +2409,7 @@
                 setQuickDozeEnabled(false);
                 setScreenOn(false);
                 setChargingOn(false);
+                setEmergencyCallActive(false);
                 mDeviceIdleController.becomeInactiveIfAppropriateLocked();
                 int count = 0;
                 while (mDeviceIdleController.getState() != state) {
@@ -2159,6 +2441,7 @@
                 enterLightState(LIGHT_STATE_ACTIVE);
                 setScreenOn(false);
                 setChargingOn(false);
+                setEmergencyCallActive(false);
                 int count = 0;
                 mDeviceIdleController.becomeInactiveIfAppropriateLocked();
                 while (mDeviceIdleController.getLightState() != lightState) {
@@ -2177,6 +2460,7 @@
             case LIGHT_STATE_OVERRIDE:
                 setScreenOn(false);
                 setChargingOn(false);
+                setEmergencyCallActive(false);
                 mDeviceIdleController.setLightStateForTest(lightState);
                 break;
             default:
@@ -2188,6 +2472,14 @@
         mDeviceIdleController.updateChargingLocked(on);
     }
 
+    private void setEmergencyCallActive(boolean active) {
+        if (active) {
+            mEmergencyCallListener.onOutgoingEmergencyCall(mock(EmergencyNumber.class), 0);
+        } else {
+            mCallStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_IDLE);
+        }
+    }
+
     private void setScreenLocked(boolean locked) {
         mDeviceIdleController.keyguardShowingLocked(locked);
     }
@@ -2235,6 +2527,7 @@
                 assertFalse(mDeviceIdleController.isCharging());
                 assertFalse(mDeviceIdleController.isScreenOn()
                         && !mDeviceIdleController.isKeyguardShowing());
+                assertFalse(mDeviceIdleController.isEmergencyCallActive());
                 break;
             case STATE_IDLE_PENDING:
                 assertEquals(
@@ -2244,6 +2537,7 @@
                 assertFalse(mDeviceIdleController.isCharging());
                 assertFalse(mDeviceIdleController.isScreenOn()
                         && !mDeviceIdleController.isKeyguardShowing());
+                assertFalse(mDeviceIdleController.isEmergencyCallActive());
                 break;
             case STATE_SENSING:
                 assertEquals(
@@ -2255,6 +2549,7 @@
                 assertFalse(mDeviceIdleController.isCharging());
                 assertFalse(mDeviceIdleController.isScreenOn()
                         && !mDeviceIdleController.isKeyguardShowing());
+                assertFalse(mDeviceIdleController.isEmergencyCallActive());
                 break;
             case STATE_LOCATING:
                 assertEquals(
@@ -2263,6 +2558,7 @@
                 assertFalse(mDeviceIdleController.isCharging());
                 assertFalse(mDeviceIdleController.isScreenOn()
                         && !mDeviceIdleController.isKeyguardShowing());
+                assertFalse(mDeviceIdleController.isEmergencyCallActive());
                 break;
             case STATE_IDLE:
                 if (mDeviceIdleController.hasMotionSensor()) {
@@ -2276,6 +2572,7 @@
                         && !mDeviceIdleController.isKeyguardShowing());
                 // Light state should be OVERRIDE at this point.
                 verifyLightStateConditions(LIGHT_STATE_OVERRIDE);
+                assertFalse(mDeviceIdleController.isEmergencyCallActive());
                 break;
             case STATE_IDLE_MAINTENANCE:
                 if (mDeviceIdleController.hasMotionSensor()) {
@@ -2287,6 +2584,7 @@
                 assertFalse(mDeviceIdleController.isCharging());
                 assertFalse(mDeviceIdleController.isScreenOn()
                         && !mDeviceIdleController.isKeyguardShowing());
+                assertFalse(mDeviceIdleController.isEmergencyCallActive());
                 break;
             case STATE_QUICK_DOZE_DELAY:
                 // If quick doze is enabled, the motion listener should NOT be active.
@@ -2295,6 +2593,7 @@
                 assertFalse(mDeviceIdleController.isCharging());
                 assertFalse(mDeviceIdleController.isScreenOn()
                         && !mDeviceIdleController.isKeyguardShowing());
+                assertFalse(mDeviceIdleController.isEmergencyCallActive());
                 break;
             default:
                 fail("Conditions for " + stateToString(expectedState) + " unknown.");
@@ -2312,6 +2611,7 @@
             case LIGHT_STATE_ACTIVE:
                 assertTrue(
                         mDeviceIdleController.isCharging() || mDeviceIdleController.isScreenOn()
+                                || mDeviceIdleController.isEmergencyCallActive()
                                 // Or there's an alarm coming up soon.
                                 || SystemClock.elapsedRealtime() + mConstants.MIN_TIME_TO_ALARM
                                 > mAlarmManager.getNextWakeFromIdleTime());
@@ -2324,6 +2624,7 @@
                 assertFalse(mDeviceIdleController.isCharging());
                 assertFalse(mDeviceIdleController.isScreenOn()
                         && !mDeviceIdleController.isKeyguardShowing());
+                assertFalse(mDeviceIdleController.isEmergencyCallActive());
                 break;
             default:
                 fail("Conditions for " + lightStateToString(expectedLightState) + " unknown.");
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
index 95c2ed2..8a5d3a6 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
@@ -558,7 +558,7 @@
 
         // To maximize test coverage, dump current state; we're not worried
         // about the actual output, just that we don't crash
-        queue.getActive().setDeliveryState(0, BroadcastRecord.DELIVERY_SCHEDULED);
+        queue.getActive().setDeliveryState(0, BroadcastRecord.DELIVERY_SCHEDULED, "Test-driven");
         queue.dumpLocked(SystemClock.uptimeMillis(),
                 new IndentingPrintWriter(new PrintWriter(new ByteArrayOutputStream())));
 
@@ -759,40 +759,6 @@
     }
 
     /**
-     * Verify that sending a broadcast that removes any matching pending
-     * broadcasts is applied as expected.
-     */
-    @Test
-    public void testRemoveMatchingFilter() {
-        final Intent screenOn = new Intent(Intent.ACTION_SCREEN_ON);
-        final BroadcastOptions optionsOn = BroadcastOptions.makeBasic();
-        optionsOn.setRemoveMatchingFilter(new IntentFilter(Intent.ACTION_SCREEN_OFF));
-
-        final Intent screenOff = new Intent(Intent.ACTION_SCREEN_OFF);
-        final BroadcastOptions optionsOff = BroadcastOptions.makeBasic();
-        optionsOff.setRemoveMatchingFilter(new IntentFilter(Intent.ACTION_SCREEN_ON));
-
-        // Halt all processing so that we get a consistent view
-        mHandlerThread.getLooper().getQueue().postSyncBarrier();
-
-        mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOn, optionsOn));
-        mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOff, optionsOff));
-        mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOn, optionsOn));
-        mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOff, optionsOff));
-
-        // While we're here, give our health check some test coverage
-        mImpl.checkHealthLocked();
-
-        // Marching through the queue we should only have one SCREEN_OFF
-        // broadcast, since that's the last state we dispatched
-        final BroadcastProcessQueue queue = mImpl.getProcessQueue(PACKAGE_GREEN,
-                getUidForPackage(PACKAGE_GREEN));
-        queue.makeActiveNextPending();
-        assertEquals(Intent.ACTION_SCREEN_OFF, queue.getActive().intent.getAction());
-        assertTrue(queue.isEmpty());
-    }
-
-    /**
      * Verify that sending a broadcast with DELIVERY_GROUP_POLICY_MOST_RECENT works as expected.
      */
     @Test
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUidStateTrackerTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUidStateTrackerTest.java
index cd5ac7bc..1731590 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUidStateTrackerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUidStateTrackerTest.java
@@ -782,6 +782,34 @@
         assertTrue(mIntf.isUidInForeground(UID));
     }
 
+    @Test
+    public void testAppWidgetVisibleDoesntChangeUidState() {
+        procStateBuilder(UID)
+                .topState()
+                .update();
+
+        SparseArray<String> updatedAppWidgetVisibilities = new SparseArray<>();
+        updatedAppWidgetVisibilities.put(UID, "");
+
+        mIntf.updateAppWidgetVisibility(updatedAppWidgetVisibilities, true);
+
+        assertEquals(UID_STATE_TOP, mIntf.getUidState(UID));
+    }
+
+    @Test
+    public void testAppWidgetNotVisibleDoesntChangeUidState() {
+        SparseArray<String> updatedAppWidgetVisibilities = new SparseArray<>();
+        updatedAppWidgetVisibilities.put(UID, "");
+        mIntf.updateAppWidgetVisibility(updatedAppWidgetVisibilities, true);
+        procStateBuilder(UID)
+                .topState()
+                .update();
+
+        mIntf.updateAppWidgetVisibility(updatedAppWidgetVisibilities, false);
+
+        assertEquals(UID_STATE_TOP, mIntf.getUidState(UID));
+    }
+
     public void testUidStateChangedCallback(int initialState, int finalState) {
         int initialUidState = processStateToUidState(initialState);
         int finalUidState = processStateToUidState(finalState);
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
index 96b6345..1ced95b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
@@ -30,6 +30,7 @@
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.when;
@@ -64,6 +65,7 @@
 import com.android.server.display.RampAnimator.DualRampAnimator;
 import com.android.server.display.brightness.BrightnessEvent;
 import com.android.server.display.color.ColorDisplayService;
+import com.android.server.display.layout.Layout;
 import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
 import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.testutils.OffsettableClock;
@@ -91,6 +93,7 @@
     private static final String FOLLOWER_UNIQUE_ID = "unique_id_456";
     private static final int SECOND_FOLLOWER_DISPLAY_ID = FOLLOWER_DISPLAY_ID + 1;
     private static final String SECOND_FOLLOWER_UNIQUE_DISPLAY_ID = "unique_id_789";
+    private static final float PROX_SENSOR_MAX_RANGE = 5;
 
     private MockitoSession mSession;
     private OffsettableClock mClock;
@@ -159,7 +162,7 @@
     @Test
     public void testReleaseProxSuspendBlockersOnExit() throws Exception {
         when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
-        // send a display power request
+        // Send a display power request
         DisplayPowerRequest dpr = new DisplayPowerRequest();
         dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
         dpr.useProximitySensor = true;
@@ -171,7 +174,7 @@
         SensorEventListener listener = getSensorEventListener(mProxSensor);
         assertNotNull(listener);
 
-        listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor, 5 /* lux */));
+        listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor, /* value= */ 5));
         advanceTime(1);
 
         // two times, one for unfinished business and one for proximity
@@ -190,6 +193,83 @@
     }
 
     @Test
+    public void testScreenOffBecauseOfProximity() throws Exception {
+        when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
+        // Send a display power request
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
+        dpr.useProximitySensor = true;
+        mHolder.dpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
+
+        // Run updatePowerState to start listener for the prox sensor
+        advanceTime(1);
+
+        SensorEventListener listener = getSensorEventListener(mProxSensor);
+        assertNotNull(listener);
+
+        // Send a positive proximity event
+        listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor, /* value= */ 1));
+        advanceTime(1);
+
+        // The display should have been turned off
+        verify(mHolder.displayPowerState).setScreenState(Display.STATE_OFF);
+
+        clearInvocations(mHolder.displayPowerState);
+        when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_OFF);
+        // Send a negative proximity event
+        listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor,
+                (int) PROX_SENSOR_MAX_RANGE + 1));
+        // Advance time by less than PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY
+        advanceTime(1);
+
+        // The prox sensor is debounced so the display should not have been turned back on yet
+        verify(mHolder.displayPowerState, never()).setScreenState(Display.STATE_ON);
+
+        // Advance time by more than PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY
+        advanceTime(1000);
+
+        // The display should have been turned back on
+        verify(mHolder.displayPowerState).setScreenState(Display.STATE_ON);
+    }
+
+    @Test
+    public void testScreenOffBecauseOfProximity_ProxSensorGone() throws Exception {
+        when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
+        // Send a display power request
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
+        dpr.useProximitySensor = true;
+        mHolder.dpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
+
+        // Run updatePowerState to start listener for the prox sensor
+        advanceTime(1);
+
+        SensorEventListener listener = getSensorEventListener(mProxSensor);
+        assertNotNull(listener);
+
+        // Send a positive proximity event
+        listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor, /* value= */ 1));
+        advanceTime(1);
+
+        // The display should have been turned off
+        verify(mHolder.displayPowerState).setScreenState(Display.STATE_OFF);
+
+        when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_OFF);
+        // The display device changes and we no longer have a prox sensor
+        reset(mSensorManagerMock);
+        setUpDisplay(DISPLAY_ID, "new_unique_id", mHolder.display, mock(DisplayDevice.class),
+                mock(DisplayDeviceConfig.class), /* isEnabled= */ true);
+        mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, Layout.NO_LEAD_DISPLAY);
+
+        advanceTime(1); // Run updatePowerState
+
+        // The display should have been turned back on and the listener should have been
+        // unregistered
+        verify(mHolder.displayPowerState).setScreenState(Display.STATE_ON);
+        verify(mSensorManagerMock).unregisterListener(listener);
+    }
+
+    @Test
     public void testProximitySensorListenerNotRegisteredForNonDefaultDisplay() {
         when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
         // send a display power request
@@ -221,8 +301,8 @@
     }
 
     private void setUpSensors() throws Exception {
-        mProxSensor = TestUtils.createSensor(
-                Sensor.TYPE_PROXIMITY, Sensor.STRING_TYPE_PROXIMITY);
+        mProxSensor = TestUtils.createSensor(Sensor.TYPE_PROXIMITY, Sensor.STRING_TYPE_PROXIMITY,
+                PROX_SENSOR_MAX_RANGE);
         Sensor screenOffBrightnessSensor = TestUtils.createSensor(
                 Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT);
         when(mSensorManagerMock.getSensorList(eq(Sensor.TYPE_ALL)))
@@ -240,12 +320,15 @@
             boolean isEnabled) {
         DisplayInfo info = new DisplayInfo();
         DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
+        deviceInfo.uniqueId = uniqueId;
 
         when(logicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId);
         when(logicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(displayDeviceMock);
         when(logicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
         when(logicalDisplayMock.isEnabledLocked()).thenReturn(isEnabled);
         when(logicalDisplayMock.isInTransitionLocked()).thenReturn(false);
+        when(logicalDisplayMock.getBrightnessThrottlingDataIdLocked()).thenReturn(
+                DisplayDeviceConfig.DEFAULT_ID);
         when(displayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
         when(displayDeviceMock.getUniqueId()).thenReturn(uniqueId);
         when(displayDeviceMock.getDisplayDeviceConfig()).thenReturn(displayDeviceConfigMock);
@@ -626,6 +709,47 @@
                 .setLightSensorEnabled(false);
     }
 
+    @Test
+    public void testStopScreenOffBrightnessSensorControllerWhenDisplayDeviceChanges() {
+        setUpDisplay(DISPLAY_ID, "new_unique_id", mHolder.display, mock(DisplayDevice.class),
+                mock(DisplayDeviceConfig.class), /* isEnabled= */ true);
+
+        mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, Layout.NO_LEAD_DISPLAY);
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        advanceTime(1); // Run updatePowerState
+
+        verify(mHolder.screenOffBrightnessSensorController).stop();
+    }
+
+    @Test
+    public void testBrightnessNitsPersistWhenDisplayDeviceChanges() {
+        float brightness = 0.3f;
+        float nits = 500;
+        when(mResourcesMock.getBoolean(
+                com.android.internal.R.bool.config_persistBrightnessNitsForDefaultDisplay))
+                .thenReturn(true);
+        mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID);
+        when(mHolder.automaticBrightnessController.convertToNits(brightness)).thenReturn(nits);
+
+        mHolder.dpc.setBrightness(brightness);
+        verify(mHolder.brightnessSetting).setBrightnessNitsForDefaultDisplay(nits);
+
+        float newBrightness = 0.4f;
+        when(mHolder.brightnessSetting.getBrightnessNitsForDefaultDisplay()).thenReturn(nits);
+        when(mHolder.automaticBrightnessController.convertToFloatScale(nits))
+                .thenReturn(newBrightness);
+        // New display device
+        setUpDisplay(DISPLAY_ID, "new_unique_id", mHolder.display, mock(DisplayDevice.class),
+                mock(DisplayDeviceConfig.class), /* isEnabled= */ true);
+        mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, Layout.NO_LEAD_DISPLAY);
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        advanceTime(1); // Run updatePowerState
+        // One triggered by handleBrightnessModeChange, another triggered by onDisplayChanged
+        verify(mHolder.animator, times(2)).animateTo(eq(newBrightness), anyFloat(), anyFloat());
+    }
+
     private DisplayPowerControllerHolder createDisplayPowerController(int displayId,
             String uniqueId) {
         return createDisplayPowerController(displayId, uniqueId, /* isEnabled= */ true);
@@ -662,8 +786,8 @@
                 mBrightnessTrackerMock, brightnessSetting, () -> {},
                 hbmMetadata, /* bootCompleted= */ false);
 
-        return new DisplayPowerControllerHolder(dpc, displayPowerState, brightnessSetting, animator,
-                automaticBrightnessController, wakelockController,
+        return new DisplayPowerControllerHolder(dpc, display, displayPowerState, brightnessSetting,
+                animator, automaticBrightnessController, wakelockController,
                 screenOffBrightnessSensorController, hbmMetadata);
     }
 
@@ -673,6 +797,7 @@
      */
     private static class DisplayPowerControllerHolder {
         public final DisplayPowerController2 dpc;
+        public final LogicalDisplay display;
         public final DisplayPowerState displayPowerState;
         public final BrightnessSetting brightnessSetting;
         public final DualRampAnimator<DisplayPowerState> animator;
@@ -681,7 +806,7 @@
         public final ScreenOffBrightnessSensorController screenOffBrightnessSensorController;
         public final HighBrightnessModeMetadata hbmMetadata;
 
-        DisplayPowerControllerHolder(DisplayPowerController2 dpc,
+        DisplayPowerControllerHolder(DisplayPowerController2 dpc, LogicalDisplay display,
                 DisplayPowerState displayPowerState, BrightnessSetting brightnessSetting,
                 DualRampAnimator<DisplayPowerState> animator,
                 AutomaticBrightnessController automaticBrightnessController,
@@ -689,6 +814,7 @@
                 ScreenOffBrightnessSensorController screenOffBrightnessSensorController,
                 HighBrightnessModeMetadata hbmMetadata) {
             this.dpc = dpc;
+            this.display = display;
             this.displayPowerState = displayPowerState;
             this.brightnessSetting = brightnessSetting;
             this.animator = animator;
@@ -754,7 +880,13 @@
                 SensorManager sensorManager) {
             return new DisplayPowerProximityStateController(wakelockController,
                     displayDeviceConfig, looper, nudgeUpdatePowerState, displayId,
-                    sensorManager, /* injector= */ null);
+                    sensorManager,
+                    new DisplayPowerProximityStateController.Injector() {
+                        @Override
+                        DisplayPowerProximityStateController.Clock createClock() {
+                            return mClock::now;
+                        }
+                    });
         }
 
         @Override
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
index 28319ac..53fcdad 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -30,6 +30,7 @@
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.when;
@@ -64,6 +65,7 @@
 import com.android.server.display.RampAnimator.DualRampAnimator;
 import com.android.server.display.brightness.BrightnessEvent;
 import com.android.server.display.color.ColorDisplayService;
+import com.android.server.display.layout.Layout;
 import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
 import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.testutils.OffsettableClock;
@@ -91,6 +93,7 @@
     private static final String FOLLOWER_UNIQUE_DISPLAY_ID = "unique_id_456";
     private static final int SECOND_FOLLOWER_DISPLAY_ID = FOLLOWER_DISPLAY_ID + 1;
     private static final String SECOND_FOLLOWER_UNIQUE_DISPLAY_ID = "unique_id_789";
+    private static final float PROX_SENSOR_MAX_RANGE = 5;
 
     private MockitoSession mSession;
     private OffsettableClock mClock;
@@ -160,7 +163,7 @@
     @Test
     public void testReleaseProxSuspendBlockersOnExit() throws Exception {
         when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
-        // send a display power request
+        // Send a display power request
         DisplayPowerRequest dpr = new DisplayPowerRequest();
         dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
         dpr.useProximitySensor = true;
@@ -172,7 +175,7 @@
         SensorEventListener listener = getSensorEventListener(mProxSensor);
         assertNotNull(listener);
 
-        listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor, 5 /* lux */));
+        listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor, /* value= */ 5));
         advanceTime(1);
 
         // two times, one for unfinished business and one for proximity
@@ -192,6 +195,83 @@
     }
 
     @Test
+    public void testScreenOffBecauseOfProximity() throws Exception {
+        when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
+        // Send a display power request
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
+        dpr.useProximitySensor = true;
+        mHolder.dpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
+
+        // Run updatePowerState to start listener for the prox sensor
+        advanceTime(1);
+
+        SensorEventListener listener = getSensorEventListener(mProxSensor);
+        assertNotNull(listener);
+
+        // Send a positive proximity event
+        listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor, /* value= */ 1));
+        advanceTime(1);
+
+        // The display should have been turned off
+        verify(mHolder.displayPowerState).setScreenState(Display.STATE_OFF);
+
+        clearInvocations(mHolder.displayPowerState);
+        when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_OFF);
+        // Send a negative proximity event
+        listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor,
+                (int) PROX_SENSOR_MAX_RANGE + 1));
+        // Advance time by less than PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY
+        advanceTime(1);
+
+        // The prox sensor is debounced so the display should not have been turned back on yet
+        verify(mHolder.displayPowerState, never()).setScreenState(Display.STATE_ON);
+
+        // Advance time by more than PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY
+        advanceTime(1000);
+
+        // The display should have been turned back on
+        verify(mHolder.displayPowerState).setScreenState(Display.STATE_ON);
+    }
+
+    @Test
+    public void testScreenOffBecauseOfProximity_ProxSensorGone() throws Exception {
+        when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
+        // Send a display power request
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
+        dpr.useProximitySensor = true;
+        mHolder.dpc.requestPowerState(dpr, false /* waitForNegativeProximity */);
+
+        // Run updatePowerState to start listener for the prox sensor
+        advanceTime(1);
+
+        SensorEventListener listener = getSensorEventListener(mProxSensor);
+        assertNotNull(listener);
+
+        // Send a positive proximity event
+        listener.onSensorChanged(TestUtils.createSensorEvent(mProxSensor, /* value= */ 1));
+        advanceTime(1);
+
+        // The display should have been turned off
+        verify(mHolder.displayPowerState).setScreenState(Display.STATE_OFF);
+
+        when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_OFF);
+        // The display device changes and we no longer have a prox sensor
+        reset(mSensorManagerMock);
+        setUpDisplay(DISPLAY_ID, "new_unique_id", mHolder.display, mock(DisplayDevice.class),
+                mock(DisplayDeviceConfig.class), /* isEnabled= */ true);
+        mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, Layout.NO_LEAD_DISPLAY);
+
+        advanceTime(1); // Run updatePowerState
+
+        // The display should have been turned back on and the listener should have been
+        // unregistered
+        verify(mHolder.displayPowerState).setScreenState(Display.STATE_ON);
+        verify(mSensorManagerMock).unregisterListener(listener);
+    }
+
+    @Test
     public void testProximitySensorListenerNotRegisteredForNonDefaultDisplay() {
         DisplayPowerControllerHolder followerDpc =
                 createDisplayPowerController(FOLLOWER_DISPLAY_ID, FOLLOWER_UNIQUE_DISPLAY_ID);
@@ -224,8 +304,8 @@
     }
 
     private void setUpSensors() throws Exception {
-        mProxSensor = TestUtils.createSensor(
-                Sensor.TYPE_PROXIMITY, Sensor.STRING_TYPE_PROXIMITY);
+        mProxSensor = TestUtils.createSensor(Sensor.TYPE_PROXIMITY, Sensor.STRING_TYPE_PROXIMITY,
+                PROX_SENSOR_MAX_RANGE);
         Sensor screenOffBrightnessSensor = TestUtils.createSensor(
                 Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT);
         when(mSensorManagerMock.getSensorList(eq(Sensor.TYPE_ALL)))
@@ -243,12 +323,15 @@
             boolean isEnabled) {
         DisplayInfo info = new DisplayInfo();
         DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
+        deviceInfo.uniqueId = uniqueId;
 
         when(logicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId);
         when(logicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(displayDeviceMock);
         when(logicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
         when(logicalDisplayMock.isEnabledLocked()).thenReturn(isEnabled);
         when(logicalDisplayMock.isInTransitionLocked()).thenReturn(false);
+        when(logicalDisplayMock.getBrightnessThrottlingDataIdLocked()).thenReturn(
+                DisplayDeviceConfig.DEFAULT_ID);
         when(displayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
         when(displayDeviceMock.getUniqueId()).thenReturn(uniqueId);
         when(displayDeviceMock.getDisplayDeviceConfig()).thenReturn(displayDeviceConfigMock);
@@ -484,17 +567,17 @@
         // We should still set screen state for the default display
         DisplayPowerRequest dpr = new DisplayPowerRequest();
         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
-        advanceTime(1);
+        advanceTime(1); // Run updatePowerState
         verify(mHolder.displayPowerState, times(2)).setScreenState(anyInt());
 
         mHolder = createDisplayPowerController(42, UNIQUE_ID);
 
         mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
-        advanceTime(1);
+        advanceTime(1); // Run updatePowerState
         verify(mHolder.displayPowerState, never()).setScreenState(anyInt());
 
         mHolder.dpc.onBootCompleted();
-        advanceTime(1);
+        advanceTime(1); // Run updatePowerState
         verify(mHolder.displayPowerState).setScreenState(anyInt());
     }
 
@@ -630,6 +713,47 @@
                 .setLightSensorEnabled(false);
     }
 
+    @Test
+    public void testStopScreenOffBrightnessSensorControllerWhenDisplayDeviceChanges() {
+        setUpDisplay(DISPLAY_ID, "new_unique_id", mHolder.display, mock(DisplayDevice.class),
+                mock(DisplayDeviceConfig.class), /* isEnabled= */ true);
+
+        mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, Layout.NO_LEAD_DISPLAY);
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        advanceTime(1); // Run updatePowerState
+
+        verify(mHolder.screenOffBrightnessSensorController).stop();
+    }
+
+    @Test
+    public void testBrightnessNitsPersistWhenDisplayDeviceChanges() {
+        float brightness = 0.3f;
+        float nits = 500;
+        when(mResourcesMock.getBoolean(
+                com.android.internal.R.bool.config_persistBrightnessNitsForDefaultDisplay))
+                .thenReturn(true);
+        mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID);
+        when(mHolder.automaticBrightnessController.convertToNits(brightness)).thenReturn(nits);
+
+        mHolder.dpc.setBrightness(brightness);
+        verify(mHolder.brightnessSetting).setBrightnessNitsForDefaultDisplay(nits);
+
+        float newBrightness = 0.4f;
+        when(mHolder.brightnessSetting.getBrightnessNitsForDefaultDisplay()).thenReturn(nits);
+        when(mHolder.automaticBrightnessController.convertToFloatScale(nits))
+                .thenReturn(newBrightness);
+        // New display device
+        setUpDisplay(DISPLAY_ID, "new_unique_id", mHolder.display, mock(DisplayDevice.class),
+                mock(DisplayDeviceConfig.class), /* isEnabled= */ true);
+        mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, Layout.NO_LEAD_DISPLAY);
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        advanceTime(1); // Run updatePowerState
+        // One triggered by handleBrightnessModeChange, another triggered by onDisplayChanged
+        verify(mHolder.animator, times(2)).animateTo(eq(newBrightness), anyFloat(), anyFloat());
+    }
+
     private DisplayPowerControllerHolder createDisplayPowerController(int displayId,
             String uniqueId) {
         return createDisplayPowerController(displayId, uniqueId, /* isEnabled= */ true);
@@ -665,8 +789,9 @@
                 mBrightnessTrackerMock, brightnessSetting, () -> {},
                 hbmMetadata, /* bootCompleted= */ false);
 
-        return new DisplayPowerControllerHolder(dpc, displayPowerState, brightnessSetting, animator,
-                automaticBrightnessController, screenOffBrightnessSensorController, hbmMetadata);
+        return new DisplayPowerControllerHolder(dpc, display, displayPowerState, brightnessSetting,
+                animator, automaticBrightnessController, screenOffBrightnessSensorController,
+                hbmMetadata);
     }
 
     /**
@@ -675,6 +800,7 @@
      */
     private static class DisplayPowerControllerHolder {
         public final DisplayPowerController dpc;
+        public final LogicalDisplay display;
         public final DisplayPowerState displayPowerState;
         public final BrightnessSetting brightnessSetting;
         public final DualRampAnimator<DisplayPowerState> animator;
@@ -682,13 +808,14 @@
         public final ScreenOffBrightnessSensorController screenOffBrightnessSensorController;
         public final HighBrightnessModeMetadata hbmMetadata;
 
-        DisplayPowerControllerHolder(DisplayPowerController dpc,
+        DisplayPowerControllerHolder(DisplayPowerController dpc, LogicalDisplay display,
                 DisplayPowerState displayPowerState, BrightnessSetting brightnessSetting,
                 DualRampAnimator<DisplayPowerState> animator,
                 AutomaticBrightnessController automaticBrightnessController,
                 ScreenOffBrightnessSensorController screenOffBrightnessSensorController,
                 HighBrightnessModeMetadata hbmMetadata) {
             this.dpc = dpc;
+            this.display = display;
             this.displayPowerState = displayPowerState;
             this.brightnessSetting = brightnessSetting;
             this.animator = animator;
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerProximityStateControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerProximityStateControllerTest.java
index 6e91b24..5b0b989 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerProximityStateControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerProximityStateControllerTest.java
@@ -87,12 +87,7 @@
                 new DisplayPowerProximityStateController.Injector() {
                     @Override
                     DisplayPowerProximityStateController.Clock createClock() {
-                        return new DisplayPowerProximityStateController.Clock() {
-                            @Override
-                            public long uptimeMillis() {
-                                return mClock.now();
-                            }
-                        };
+                        return mClock::now;
                     }
                 };
         mDisplayPowerProximityStateController = new DisplayPowerProximityStateController(
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
index 95a5884..5f82ec1 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -53,6 +53,7 @@
 import com.android.internal.R;
 import com.android.server.LocalServices;
 import com.android.server.display.LocalDisplayAdapter.BacklightAdapter;
+import com.android.server.display.mode.DisplayModeDirector;
 import com.android.server.lights.LightsManager;
 import com.android.server.lights.LogicalLight;
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/BatteryControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/BatteryControllerTest.java
index f334a6a..3ba5d1e 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/BatteryControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/BatteryControllerTest.java
@@ -41,7 +41,7 @@
 
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.server.JobSchedulerBackgroundThread;
+import com.android.server.AppSchedulingModuleThread;
 import com.android.server.LocalServices;
 import com.android.server.job.JobSchedulerService;
 
@@ -180,7 +180,7 @@
     }
 
     private void waitForNonDelayedMessagesProcessed() {
-        JobSchedulerBackgroundThread.getHandler().runWithScissors(() -> {}, 15_000);
+        AppSchedulingModuleThread.getHandler().runWithScissors(() -> {}, 15_000);
     }
 
     private JobInfo.Builder createBaseJobInfoBuilder(int jobId) {
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 3f5d113..06ba5dd 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
@@ -664,7 +664,7 @@
     private fun mockQueryActivities(action: String, vararg activities: ActivityInfo) {
         whenever(mocks.componentResolver.queryActivities(any(),
                 argThat { intent: Intent? -> intent != null && (action == intent.action) },
-                nullable(), anyLong(), anyInt(), anyInt())) {
+                nullable(), anyLong(), anyInt())) {
             ArrayList(activities.asList().map { info: ActivityInfo? ->
                 ResolveInfo().apply { activityInfo = info }
             })
@@ -674,7 +674,7 @@
     private fun mockQueryServices(action: String, vararg services: ServiceInfo) {
         whenever(mocks.componentResolver.queryServices(any(),
                 argThat { intent: Intent? -> intent != null && (action == intent.action) },
-                nullable(), anyLong(), anyInt(), anyInt())) {
+                nullable(), anyLong(), anyInt())) {
             ArrayList(services.asList().map { info ->
                 ResolveInfo().apply { serviceInfo = info }
             })
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
index 564893c..e7b3e6f 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
@@ -260,7 +260,7 @@
         mUms.setBootUser(OTHER_USER_ID);
 
         assertWithMessage("getBootUser")
-                .that(mUmi.getBootUser()).isEqualTo(OTHER_USER_ID);
+                .that(mUmi.getBootUser(/* waitUntilSet= */ false)).isEqualTo(OTHER_USER_ID);
     }
 
     @Test
@@ -273,7 +273,8 @@
         mUms.setBootUser(PROFILE_USER_ID);
 
         assertWithMessage("getBootUser")
-                .that(mUmi.getBootUser()).isEqualTo(UserHandle.USER_SYSTEM);
+                .that(mUmi.getBootUser(/* waitUntilSet= */ false))
+                .isEqualTo(UserHandle.USER_SYSTEM);
     }
 
     @Test
@@ -289,7 +290,7 @@
 
         // Boot user not switchable so return most recently in foreground.
         assertWithMessage("getBootUser")
-                .that(mUmi.getBootUser()).isEqualTo(OTHER_USER_ID);
+                .that(mUmi.getBootUser(/* waitUntilSet= */ false)).isEqualTo(OTHER_USER_ID);
     }
 
     @Test
@@ -299,7 +300,8 @@
         addUser(OTHER_USER_ID);
 
         assertWithMessage("getBootUser")
-                .that(mUmi.getBootUser()).isEqualTo(UserHandle.USER_SYSTEM);
+                .that(mUmi.getBootUser(/* waitUntilSet= */ false))
+                .isEqualTo(UserHandle.USER_SYSTEM);
     }
 
     @Test
@@ -312,14 +314,15 @@
         setLastForegroundTime(OTHER_USER_ID, 2_000_000L);
 
         assertWithMessage("getBootUser")
-                .that(mUmi.getBootUser()).isEqualTo(OTHER_USER_ID);
+                .that(mUmi.getBootUser(/* waitUntilSet= */ false)).isEqualTo(OTHER_USER_ID);
     }
 
     @Test
     public void testGetBootUser_Headless_ThrowsIfOnlySystemUserExists() throws Exception {
         setSystemUserHeadless(true);
 
-        assertThrows(UserManager.CheckedUserOperationException.class, () -> mUmi.getBootUser());
+        assertThrows(UserManager.CheckedUserOperationException.class,
+                () -> mUmi.getBootUser(/* waitUntilSet= */ false));
     }
 
     private void mockCurrentUser(@UserIdInt int userId) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java
index 9aa53db..8979585 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java
@@ -20,6 +20,8 @@
 import static android.view.Display.INVALID_DISPLAY;
 
 import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_FAILURE;
+import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_ALREADY_VISIBLE;
+import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
 import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE;
 import static com.android.server.pm.UserVisibilityChangedEvent.onInvisible;
 import static com.android.server.pm.UserVisibilityChangedEvent.onVisible;
@@ -73,8 +75,8 @@
         assertUserCanBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);
 
         // Make sure another user cannot be started on default display
-        int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, visibleBgUserId,
-                BG_VISIBLE, DEFAULT_DISPLAY);
+        int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, otherUserId, BG_VISIBLE,
+                DEFAULT_DISPLAY);
         assertStartUserResult(result2, USER_ASSIGNMENT_RESULT_FAILURE,
                 "when user (%d) is starting on default display after it was started by user %d",
                 otherUserId, visibleBgUserId);
@@ -117,8 +119,8 @@
         assertUserCanBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);
 
         // Make sure another user cannot be started on default display
-        int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, visibleBgUserId,
-                BG_VISIBLE, DEFAULT_DISPLAY);
+        int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, otherUserId, BG_VISIBLE,
+                DEFAULT_DISPLAY);
         assertStartUserResult(result2, USER_ASSIGNMENT_RESULT_FAILURE,
                 "when user (%d) is starting on default display after it was started by user %d",
                 otherUserId, visibleBgUserId);
@@ -127,8 +129,6 @@
         listener.verify();
     }
 
-  /* TODO(b/261538337): re-add after the reverted CL is merged again
-
     @Test
     public void
        testStartVisibleBgProfile_onDefaultDisplay_whenParentIsStartedVisibleOnBgOnSecondaryDisplay()
@@ -226,5 +226,4 @@
 
         listener.verify();
     }
-  */
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java
index 1bf921c..70b5ac0 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java
@@ -44,7 +44,6 @@
 import android.util.IntArray;
 import android.util.Log;
 
-import com.android.internal.util.Preconditions;
 import com.android.server.DumpableDumperRule;
 import com.android.server.ExpectableTestCase;
 
@@ -140,6 +139,13 @@
     }
 
     @Test
+    public void testInvalidMode() {
+        assertThrows(IllegalArgumentException.class, () -> new UserVisibilityMediator(
+                /* visibleBackgroundUsersOnDisplaysEnabled= */ false,
+                /* visibleBackgroundUserOnDefaultDisplayAllowed= */ true, mHandler));
+    }
+
+    @Test
     public final void testAssignUserToDisplayOnStart_invalidUserIds() {
         assertThrows(IllegalArgumentException.class, () -> mMediator
                 .assignUserToDisplayOnStart(USER_NULL, USER_ID, FG, DEFAULT_DISPLAY));
@@ -152,6 +158,12 @@
     }
 
     @Test
+    public final void testAssignUserToDisplayOnStart_invalidUserStartMode() {
+        assertThrows(IllegalArgumentException.class, () -> mMediator
+                .assignUserToDisplayOnStart(USER_ID, USER_ID, 666, DEFAULT_DISPLAY));
+    }
+
+    @Test
     public final void testStartFgUser_onSecondaryDisplay() throws Exception {
         AsyncUserVisibilityListener listener = addListenerForNoEvents();
 
@@ -286,7 +298,7 @@
 
         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
                 BG_VISIBLE, DEFAULT_DISPLAY);
-        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
+        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
 
         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
         expectNoDisplayAssignedToUser(PROFILE_USER_ID);
@@ -302,14 +314,14 @@
 
         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
                 BG_VISIBLE, DEFAULT_DISPLAY);
-        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
+        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
 
         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
 
         expectNoDisplayAssignedToUser(PROFILE_USER_ID);
         expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);
 
-        assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+        assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
 
         listener.verify();
     }
@@ -335,6 +347,41 @@
     }
 
     @Test
+    public final void testStartBgProfile_onDefaultDisplay_whenParentIsNotStarted()
+            throws Exception {
+        AsyncUserVisibilityListener listener = addListenerForNoEvents();
+
+        int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, BG,
+                DEFAULT_DISPLAY);
+        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
+
+        expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
+        expectNoDisplayAssignedToUser(PROFILE_USER_ID);
+
+        listener.verify();
+    }
+
+    @Test
+    public final void testStartBgProfile_onDefaultDisplay_whenParentIsStartedOnBg()
+            throws Exception {
+        AsyncUserVisibilityListener listener = addListenerForNoEvents();
+        startBackgroundUser(PARENT_USER_ID);
+
+        int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, BG,
+                DEFAULT_DISPLAY);
+        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
+
+        expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
+
+        expectNoDisplayAssignedToUser(PROFILE_USER_ID);
+        expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);
+
+        assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+
+        listener.verify();
+    }
+
+    @Test
     public final void testStartBgProfile_onSecondaryDisplay() throws Exception {
         AsyncUserVisibilityListener listener = addListenerForNoEvents();
 
@@ -488,8 +535,6 @@
      * se.
      */
     protected final void startUserInSecondaryDisplay(@UserIdInt int userId, int displayId) {
-        Preconditions.checkArgument(displayId != INVALID_DISPLAY && displayId != DEFAULT_DISPLAY,
-                "must pass a secondary display, not %d", displayId);
         Log.d(TAG, "startUserInSecondaryDisplay(" + userId + ", " + displayId + ")");
         int result = mMediator.assignUserToDisplayOnStart(userId, userId, BG_VISIBLE, displayId);
         if (result != USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE) {
@@ -551,6 +596,7 @@
                 .that(mMediator.assignUserToExtraDisplay(userId, displayId))
                 .isTrue();
         expectUserIsVisibleOnDisplay(userId, displayId);
+        expectDisplaysAssignedToUserContainsDisplayId(userId, displayId);
 
         if (unassign) {
             Log.d(TAG, "Calling unassignUserFromExtraDisplay(" + userId + ", " + displayId + ")");
@@ -558,6 +604,7 @@
                     .that(mMediator.unassignUserFromExtraDisplay(userId, displayId))
                     .isTrue();
             expectUserIsNotVisibleOnDisplay(userId, displayId);
+            expectDisplaysAssignedToUserDoesNotContainDisplayId(userId, displayId);
         }
     }
 
@@ -623,6 +670,7 @@
         expectUserIsNotVisibleOnDisplay(userId, INVALID_DISPLAY);
         expectUserIsNotVisibleOnDisplay(userId, SECONDARY_DISPLAY_ID);
         expectUserIsNotVisibleOnDisplay(userId, OTHER_SECONDARY_DISPLAY_ID);
+        expectDisplaysAssignedToUserIsEmpty(userId);
     }
 
     protected void expectDisplayAssignedToUser(@UserIdInt int userId, int displayId) {
@@ -635,6 +683,24 @@
                 .that(mMediator.getDisplayAssignedToUser(userId)).isEqualTo(INVALID_DISPLAY);
     }
 
+    protected void expectDisplaysAssignedToUserContainsDisplayId(
+            @UserIdInt int userId, int displayId) {
+        expectWithMessage("getDisplaysAssignedToUser(%s)", userId)
+                .that(mMediator.getDisplaysAssignedToUser(userId)).asList().contains(displayId);
+    }
+
+    protected void expectDisplaysAssignedToUserDoesNotContainDisplayId(
+            @UserIdInt int userId, int displayId) {
+        expectWithMessage("getDisplaysAssignedToUser(%s)", userId)
+                .that(mMediator.getDisplaysAssignedToUser(userId)).asList()
+                .doesNotContain(displayId);
+    }
+
+    protected void expectDisplaysAssignedToUserIsEmpty(@UserIdInt int userId) {
+        expectWithMessage("getDisplaysAssignedToUser(%s)", userId)
+                .that(mMediator.getDisplaysAssignedToUser(userId)).isNull();
+    }
+
     protected void expectUserCannotBeUnassignedFromDisplay(@UserIdInt int userId, int displayId) {
         expectWithMessage("unassignUserFromExtraDisplay(%s, %s)", userId, displayId)
                 .that(mMediator.unassignUserFromExtraDisplay(userId, displayId)).isFalse();
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java
index af85ef4..08b094b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java
@@ -109,34 +109,6 @@
     }
 
     @Test
-    public final void testStartVisibleBgProfile_onDefaultDisplay_whenParentIsCurrentUser()
-            throws Exception {
-        AsyncUserVisibilityListener listener = addListenerForEvents(
-                onInvisible(INITIAL_CURRENT_USER_ID),
-                onVisible(PARENT_USER_ID),
-                onVisible(PROFILE_USER_ID));
-        startForegroundUser(PARENT_USER_ID);
-
-        int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
-                BG_VISIBLE, DEFAULT_DISPLAY);
-        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
-        expectUserCannotBeUnassignedFromDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
-
-        expectUserIsVisible(PROFILE_USER_ID);
-        expectUserIsNotVisibleOnDisplay(PROFILE_USER_ID, INVALID_DISPLAY);
-        expectUserIsNotVisibleOnDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
-        expectUserIsVisibleOnDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
-        expectVisibleUsers(PARENT_USER_ID, PROFILE_USER_ID);
-
-        expectDisplayAssignedToUser(PROFILE_USER_ID, DEFAULT_DISPLAY);
-        expectUserAssignedToDisplay(DEFAULT_DISPLAY, PARENT_USER_ID);
-
-        assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
-
-        listener.verify();
-    }
-
-    @Test
     public final void testStartFgUser_onInvalidDisplay() throws Exception {
         AsyncUserVisibilityListener listener = addListenerForNoEvents();
 
@@ -188,6 +160,8 @@
 
         assertUserCanBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);
 
+        listener.verify();
+
         // Assign again, without unassigning (to make sure it becomes invisible on stop)
         AsyncUserVisibilityListener listener2 = addListenerForEvents(onInvisible(USER_ID));
         assertUserCanBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID,
@@ -301,14 +275,83 @@
     }
 
     @Test
+    public final void testStartVisibleBgProfile_onDefaultDisplay_whenParentIsCurrentUser()
+            throws Exception {
+        AsyncUserVisibilityListener listener = addListenerForEvents(
+                onInvisible(INITIAL_CURRENT_USER_ID),
+                onVisible(PARENT_USER_ID),
+                onVisible(PROFILE_USER_ID));
+        startForegroundUser(PARENT_USER_ID);
+
+        int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
+                BG_VISIBLE, DEFAULT_DISPLAY);
+        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
+        expectUserCannotBeUnassignedFromDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
+
+        expectUserIsVisible(PROFILE_USER_ID);
+        expectUserIsNotVisibleOnDisplay(PROFILE_USER_ID, INVALID_DISPLAY);
+        expectUserIsNotVisibleOnDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+        expectUserIsVisibleOnDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
+        expectVisibleUsers(PARENT_USER_ID, PROFILE_USER_ID);
+
+        expectDisplayAssignedToUser(PROFILE_USER_ID, DEFAULT_DISPLAY);
+        expectUserAssignedToDisplay(DEFAULT_DISPLAY, PARENT_USER_ID);
+
+        assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+
+        listener.verify();
+    }
+
+    @Test
     public final void
-            testStartVisibleBgProfile_onDefaultDisplay_whenParentVisibleOnSecondaryDisplay()
-                    throws Exception {
+            testStartVisibleBgProfile_onDefaultDisplay_whenParentIsStartedVisibleOnAnotherDisplay()
+            throws Exception {
         AsyncUserVisibilityListener listener = addListenerForEvents(onVisible(PARENT_USER_ID));
         startUserInSecondaryDisplay(PARENT_USER_ID, OTHER_SECONDARY_DISPLAY_ID);
 
         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
                 BG_VISIBLE, DEFAULT_DISPLAY);
+        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
+
+        expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
+        expectNoDisplayAssignedToUser(PROFILE_USER_ID);
+        expectUserAssignedToDisplay(OTHER_SECONDARY_DISPLAY_ID, PARENT_USER_ID);
+
+        assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+
+        listener.verify();
+    }
+
+    // Not supported - profiles can only be started on default display
+    @Test
+    public final void
+            testStartVisibleBgProfile_onSecondaryDisplay_whenParentIsStartedVisibleOnThatDisplay()
+            throws Exception {
+        AsyncUserVisibilityListener listener = addListenerForEvents(onVisible(PARENT_USER_ID));
+        startUserInSecondaryDisplay(PARENT_USER_ID, OTHER_SECONDARY_DISPLAY_ID);
+
+        int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
+                BG_VISIBLE, DEFAULT_DISPLAY);
+        assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
+
+        expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
+        expectNoDisplayAssignedToUser(PROFILE_USER_ID);
+        expectUserAssignedToDisplay(OTHER_SECONDARY_DISPLAY_ID, PARENT_USER_ID);
+
+        assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+
+        listener.verify();
+    }
+
+    @Test
+    public final void
+            testStartProfile_onDefaultDisplay_whenParentIsStartedVisibleOnSecondaryDisplay()
+            throws Exception {
+        AsyncUserVisibilityListener listener = addListenerForEvents(onVisible(PARENT_USER_ID));
+        startUserInSecondaryDisplay(PARENT_USER_ID, OTHER_SECONDARY_DISPLAY_ID);
+
+        int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, BG,
+                DEFAULT_DISPLAY);
         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
 
         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 3a7b9a4..6f26a5f 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -31,6 +31,7 @@
         "services.backup",
         "services.companion",
         "services.core",
+        "services.credentials",
         "services.devicepolicy",
         "services.net",
         "services.people",
@@ -115,6 +116,7 @@
         ":StubTestApp",
         ":SuspendTestApp",
         ":MediaButtonReceiverHolderTestHelperApp",
+        "data/broken_shortcut.xml",
     ],
 
     java_resources: [
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 7149265..6861c2f 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -108,6 +108,7 @@
     <uses-permission android:name="android.permission.UPDATE_LOCK_TASK_PACKAGES" />
     <uses-permission android:name="android.permission.ACCESS_CONTEXT_HUB" />
     <uses-permission android:name="android.permission.USE_BIOMETRIC_INTERNAL" />
+    <uses-permission android:name="android.permission.MANAGE_MEDIA_PROJECTION" />
 
     <queries>
         <package android:name="com.android.servicestests.apps.suspendtestapp" />
diff --git a/services/tests/servicestests/AndroidTest.xml b/services/tests/servicestests/AndroidTest.xml
index d967647..b304968 100644
--- a/services/tests/servicestests/AndroidTest.xml
+++ b/services/tests/servicestests/AndroidTest.xml
@@ -21,6 +21,8 @@
         <option name="cleanup" value="true" />
         <option name="push-file" key="SimpleServiceTestApp3.apk"
                 value="/data/local/tmp/cts/content/SimpleServiceTestApp3.apk" />
+        <option name="push-file" key="broken_shortcut.xml"
+                value="/data/local/tmp/cts/content/broken_shortcut.xml" />
     </target_preparer>
 
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/services/tests/servicestests/data/broken_shortcut.xml b/services/tests/servicestests/data/broken_shortcut.xml
new file mode 100644
index 0000000..f2b083d
--- /dev/null
+++ b/services/tests/servicestests/data/broken_shortcut.xml
Binary files differ
diff --git a/services/tests/servicestests/res/xml/irq_device_map_3.xml b/services/tests/servicestests/res/xml/irq_device_map_3.xml
index 498b676..1d2a7d3 100644
--- a/services/tests/servicestests/res/xml/irq_device_map_3.xml
+++ b/services/tests/servicestests/res/xml/irq_device_map_3.xml
@@ -21,6 +21,6 @@
         <subsystem>Alarm</subsystem>
     </device>
     <device name="test.wifi.device">
-        <subsystem>undefined</subsystem>
+        <subsystem>Wifi</subsystem>
     </device>
 </irq-device-map>
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
index 503e579..96eca71 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
@@ -289,7 +289,7 @@
 
     @SmallTest
     @Test
-    public void testRegisterProxyWithoutPermission() throws Exception {
+    public void testRegisterProxyWithoutA11yPermission() throws Exception {
         doThrow(SecurityException.class).when(mMockSecurityPolicy)
                 .enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
 
@@ -301,6 +301,18 @@
 
     @SmallTest
     @Test
+    public void testRegisterProxyWithoutDevicePermission() throws Exception {
+        doThrow(SecurityException.class).when(mMockSecurityPolicy)
+                .enforceCallingOrSelfPermission(Manifest.permission.CREATE_VIRTUAL_DEVICE);
+
+        assertThrows(SecurityException.class,
+                () -> mA11yms.registerProxyForDisplay(mMockServiceClient, TEST_DISPLAY));
+        verify(mProxyManager, never()).registerProxy(any(), anyInt(), any(), anyInt(), any(), any(),
+                any(), any(), any());
+    }
+
+    @SmallTest
+    @Test
     public void testRegisterProxyForDefaultDisplay() throws Exception {
         assertThrows(IllegalArgumentException.class,
                 () -> mA11yms.registerProxyForDisplay(mMockServiceClient, Display.DEFAULT_DISPLAY));
@@ -328,7 +340,7 @@
 
     @SmallTest
     @Test
-    public void testUnRegisterProxyWithoutPermission() throws Exception {
+    public void testUnRegisterProxyWithoutA11yPermission() {
         doThrow(SecurityException.class).when(mMockSecurityPolicy)
                 .enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
 
@@ -339,6 +351,17 @@
 
     @SmallTest
     @Test
+    public void testUnRegisterProxyWithoutDevicePermission() {
+        doThrow(SecurityException.class).when(mMockSecurityPolicy)
+                .enforceCallingOrSelfPermission(Manifest.permission.CREATE_VIRTUAL_DEVICE);
+
+        assertThrows(SecurityException.class,
+                () -> mA11yms.unregisterProxyForDisplay(TEST_DISPLAY));
+        verify(mProxyManager, never()).unregisterProxy(TEST_DISPLAY);
+    }
+
+    @SmallTest
+    @Test
     public void testOnMagnificationTransitionFailed_capabilitiesIsAll_fallBackToPreviousMode() {
         final AccessibilityUserState userState = mA11yms.mUserStates.get(
                 mA11yms.getCurrentUserIdLocked());
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
index 88f0c93..f1ad577 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
@@ -238,7 +238,7 @@
     }
 
     private void notRegistered_publicMethodsShouldBeBenign(int displayId) {
-        checkActivatedAndMagnifyingState(/* activated= */false, /* magnifying= */false, displayId);
+        checkActivatedAndMagnifying(/* activated= */ false, /* magnifying= */ false, displayId);
 
         assertFalse(
                 mFullScreenMagnificationController.magnificationRegionContains(displayId, 100,
@@ -673,9 +673,9 @@
                 .setScale(displayId, 1.5f, startCenter.x, startCenter.y, false,
                         SERVICE_ID_2);
         assertFalse(mFullScreenMagnificationController.resetIfNeeded(displayId, SERVICE_ID_1));
-        checkActivatedAndMagnifyingState(/* activated= */true, /* magnifying= */true, displayId);
+        checkActivatedAndMagnifying(/* activated= */ true, /* magnifying= */ true, displayId);
         assertTrue(mFullScreenMagnificationController.resetIfNeeded(displayId, SERVICE_ID_2));
-        checkActivatedAndMagnifyingState(/* activated= */false, /* magnifying= */false, displayId);
+        checkActivatedAndMagnifying(/* activated= */ false, /* magnifying= */ false, displayId);
     }
 
     @Test
@@ -694,7 +694,7 @@
         assertTrue(mFullScreenMagnificationController.resetIfNeeded(displayId, false));
         verify(mRequestObserver).onFullScreenMagnificationChanged(eq(displayId),
                 eq(INITIAL_MAGNIFICATION_REGION), any(MagnificationConfig.class));
-        checkActivatedAndMagnifyingState(/* activated= */false, /* magnifying= */false, displayId);
+        checkActivatedAndMagnifying(/* activated= */ false, /* magnifying= */ false, displayId);
         assertFalse(mFullScreenMagnificationController.resetIfNeeded(displayId, false));
     }
 
@@ -758,7 +758,7 @@
         mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
         mStateListener.onAnimationEnd(mMockValueAnimator);
 
-        checkActivatedAndMagnifyingState(/* activated= */false, /* magnifying= */false, displayId);
+        checkActivatedAndMagnifying(/* activated= */ false, /* magnifying= */ false, displayId);
         verify(lastAnimationCallback).onResult(true);
     }
 
@@ -776,26 +776,72 @@
         mMessageCapturingHandler.sendAllMessages();
         br.onReceive(mMockContext, null);
         mMessageCapturingHandler.sendAllMessages();
-        checkActivatedAndMagnifyingState(/* activated= */false, /* magnifying= */false, DISPLAY_0);
-        checkActivatedAndMagnifyingState(/* activated= */false, /* magnifying= */false, DISPLAY_1);
+        checkActivatedAndMagnifying(/* activated= */ false, /* magnifying= */ false, DISPLAY_0);
+        checkActivatedAndMagnifying(/* activated= */ false, /* magnifying= */ false, DISPLAY_1);
     }
 
     @Test
-    public void testUserContextChange_resetsMagnification() {
+    public void testUserContextChange_magnifierActivated_resetMagnification() {
         for (int i = 0; i < DISPLAY_COUNT; i++) {
-            contextChange_resetsMagnification(i);
+            contextChange_expectedValues(
+                    /* displayId= */ i,
+                    /* isMagnifierActivated= */ true,
+                    /* isAlwaysOnEnabled= */ false,
+                    /* expectedActivated= */ false);
             resetMockWindowManager();
         }
     }
 
-    private void contextChange_resetsMagnification(int displayId) {
+    @Test
+    public void testUserContextChange_magnifierActivatedAndAlwaysOnEnabled_stayActivated() {
+        for (int i = 0; i < DISPLAY_COUNT; i++) {
+            contextChange_expectedValues(
+                    /* displayId= */ i,
+                    /* isMagnifierActivated= */ true,
+                    /* isAlwaysOnEnabled= */ true,
+                    /* expectedActivated= */ true);
+            resetMockWindowManager();
+        }
+    }
+
+    @Test
+    public void testUserContextChange_magnifierDeactivated_stayDeactivated() {
+        for (int i = 0; i < DISPLAY_COUNT; i++) {
+            contextChange_expectedValues(
+                    /* displayId= */ i,
+                    /* isMagnifierActivated= */ false,
+                    /* isAlwaysOnEnabled= */ false,
+                    /* expectedActivated= */ false);
+            resetMockWindowManager();
+        }
+    }
+
+    @Test
+    public void testUserContextChange_magnifierDeactivatedAndAlwaysOnEnabled_stayDeactivated() {
+        for (int i = 0; i < DISPLAY_COUNT; i++) {
+            contextChange_expectedValues(
+                    /* displayId= */ i,
+                    /* isMagnifierActivated= */ false,
+                    /* isAlwaysOnEnabled= */ true,
+                    /* expectedActivated= */ false);
+            resetMockWindowManager();
+        }
+    }
+
+    private void contextChange_expectedValues(
+            int displayId, boolean isMagnifierActivated, boolean isAlwaysOnEnabled,
+            boolean expectedActivated) {
+        mFullScreenMagnificationController.setAlwaysOnMagnificationEnabled(isAlwaysOnEnabled);
         register(displayId);
         MagnificationCallbacks callbacks = getMagnificationCallbacks(displayId);
-        zoomIn2xToMiddle(displayId);
-        mMessageCapturingHandler.sendAllMessages();
+        if (isMagnifierActivated) {
+            zoomIn2xToMiddle(displayId);
+            mMessageCapturingHandler.sendAllMessages();
+        }
         callbacks.onUserContextChanged();
         mMessageCapturingHandler.sendAllMessages();
-        checkActivatedAndMagnifyingState(/* activated= */false, /* magnifying= */false, displayId);
+        checkActivatedAndMagnifying(
+                /* activated= */ expectedActivated, /* magnifying= */ false, displayId);
     }
 
     @Test
@@ -811,10 +857,10 @@
         MagnificationCallbacks callbacks = getMagnificationCallbacks(displayId);
         zoomIn2xToMiddle(displayId);
         mMessageCapturingHandler.sendAllMessages();
-        checkActivatedAndMagnifyingState(/* activated= */true, /* magnifying= */true, displayId);
+        checkActivatedAndMagnifying(/* activated= */ true, /* magnifying= */ true, displayId);
         callbacks.onDisplaySizeChanged();
         mMessageCapturingHandler.sendAllMessages();
-        checkActivatedAndMagnifyingState(/* activated= */false, /* magnifying= */false, DISPLAY_0);
+        checkActivatedAndMagnifying(/* activated= */ false, /* magnifying= */ false, DISPLAY_0);
     }
 
     @Test
@@ -1169,7 +1215,7 @@
         mFullScreenMagnificationController.setScaleAndCenter(
                 DISPLAY_0, scale, Float.NaN, Float.NaN, true, SERVICE_ID_1);
 
-        checkActivatedAndMagnifyingState(/* activated= */true, /* magnifying= */false, DISPLAY_0);
+        checkActivatedAndMagnifying(/* activated= */ true, /* magnifying= */ false, DISPLAY_0);
         verify(mMockWindowManager).setForceShowMagnifiableBounds(DISPLAY_0, true);
     }
 
@@ -1280,11 +1326,10 @@
         float scale = 2.0f;
         mFullScreenMagnificationController.setScale(displayId, scale, startCenter.x, startCenter.y,
                 false, SERVICE_ID_1);
-        checkActivatedAndMagnifyingState(/* activated= */true, /* magnifying= */true, displayId);
+        checkActivatedAndMagnifying(/* activated= */ true, /* magnifying= */ true, displayId);
     }
 
-    private void checkActivatedAndMagnifyingState(
-            boolean activated, boolean magnifying, int displayId) {
+    private void checkActivatedAndMagnifying(boolean activated, boolean magnifying, int displayId) {
         final boolean isActivated = mFullScreenMagnificationController.isActivated(displayId);
         final boolean isMagnifying = mFullScreenMagnificationController.getScale(displayId) > 1.0f;
         assertTrue(isActivated == activated);
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 306ce4d..cf5ba27 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
@@ -416,6 +416,15 @@
     }
 
     @Test
+    public void testMagnifierDeactivates_shortcutTriggeredState_returnToIdleState() {
+        goFromStateIdleTo(STATE_SHORTCUT_TRIGGERED);
+
+        mFullScreenMagnificationController.reset(DISPLAY_0, /* animate= */ false);
+
+        assertIn(STATE_IDLE);
+    }
+
+    @Test
     public void testThreeFingersOneTap_activatedState_dispatchMotionEvents() {
         goFromStateIdleTo(STATE_ACTIVATED);
         final EventCaptor eventCaptor = new EventCaptor();
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index 1298e7b..24b003c 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -24,6 +24,7 @@
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.nullable;
 import static org.mockito.Mockito.times;
@@ -37,6 +38,7 @@
 import android.accounts.CantAddAccountActivity;
 import android.accounts.IAccountManagerResponse;
 import android.app.AppOpsManager;
+import android.app.BroadcastOptions;
 import android.app.INotificationManager;
 import android.app.PropertyInvalidatedCache;
 import android.app.admin.DevicePolicyManager;
@@ -171,6 +173,16 @@
         setContext(mockContext);
         mTestInjector = new TestInjector(realTestContext, mockContext, mMockNotificationManager);
         mAms = new AccountManagerService(mTestInjector);
+        doAnswer(invocation -> {
+            final Intent intent = invocation.getArgument(0);
+            final Bundle options = invocation.getArgument(3);
+            if (AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION.endsWith(intent.getAction())) {
+                final BroadcastOptions bOptions = new BroadcastOptions(options);
+                assertEquals(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT,
+                        bOptions.getDeliveryGroupPolicy());
+            }
+            return null;
+        }).when(mMockContext).sendBroadcastAsUser(any(), any(), any(), any());
     }
 
     @Override
@@ -3142,7 +3154,7 @@
         mAccountRemovedBroadcasts = 0;
         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
         verify(mMockContext, atLeast(expectedBroadcasts)).sendBroadcastAsUser(captor.capture(),
-            any(UserHandle.class));
+                any(UserHandle.class), any(), any());
         for (Intent intent : captor.getAllValues()) {
             if (AccountManager.ACTION_VISIBLE_ACCOUNTS_CHANGED.equals(intent.getAction())) {
                 mVisibleAccountsChangedBroadcasts++;
@@ -3499,7 +3511,19 @@
 
         @Override
         public void sendBroadcastAsUser(Intent intent, UserHandle user) {
-            mMockContext.sendBroadcastAsUser(intent, user);
+            sendBroadcastAsUser(intent, user, null, null);
+        }
+
+        @Override
+        public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission,
+                Bundle options) {
+            mMockContext.sendBroadcastAsUser(intent, user, receiverPermission, options);
+        }
+
+        @Override
+        public Intent registerReceiver(BroadcastReceiver receiver,
+                IntentFilter filter, String broadcastPermission, Handler scheduler) {
+            return mMockContext.registerReceiver(receiver, filter, broadcastPermission, scheduler);
         }
 
         @Override
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index 93dfee6..8c7b0c5 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -528,7 +528,7 @@
             ActivityManager.PROCESS_CAPABILITY_NONE,
             ActivityManager.PROCESS_CAPABILITY_NONE,
             ActivityManager.PROCESS_CAPABILITY_NONE,
-            ActivityManager.PROCESS_CAPABILITY_NETWORK,
+            ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK,
         };
         final Map<Integer, ChangeRecord> changeItems = new HashMap<>();
         for (int i = 0; i < changesForPendingUidRecords.length; ++i) {
diff --git a/services/tests/servicestests/src/com/android/server/am/DropboxRateLimiterTest.java b/services/tests/servicestests/src/com/android/server/am/DropboxRateLimiterTest.java
index e68a8a0..01563e2 100644
--- a/services/tests/servicestests/src/com/android/server/am/DropboxRateLimiterTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/DropboxRateLimiterTest.java
@@ -106,6 +106,64 @@
                 mRateLimiter.shouldRateLimit("tag", "p").droppedCountSinceRateLimitActivated());
     }
 
+    @Test
+    public void testStrictRepeatedLimiting() throws Exception {
+        // The first 6 entries should not be rate limited.
+        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+        // The 7th entry of the same process should be rate limited.
+        assertTrue(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+
+        // After 11 minutes there should be nothing left in the buffer and the same type of entry
+        // should not get rate limited anymore.
+        mClock.setOffsetMillis(11 * 60 * 1000);
+        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+        // The first 6 entries should not be rate limited again.
+        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+
+        // The 7th entry of the same process should be rate limited.
+        assertTrue(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+
+        // After 11 more minutes there should be nothing left in the buffer and the same type of
+        // entry should not get rate limited anymore.
+        mClock.setOffsetMillis(22 * 60 * 1000);
+        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+
+        // Repeated crashes after the last reset being rate limited should be restricted faster.
+        assertTrue(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+
+        // We now need to wait 61 minutes for the buffer should be empty again.
+        mClock.setOffsetMillis(83 * 60 * 1000);
+        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+
+        // After yet another 61 minutes, this time without triggering rate limiting, the strict
+        // limiting should be turnd off.
+        mClock.setOffsetMillis(144 * 60 * 1000);
+        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+
+        // As rate limiting was not triggered in the last reset, after another 11 minutes the
+        // buffer should still act as normal.
+        mClock.setOffsetMillis(155 * 60 * 1000);
+        // The first 6 entries should not be rate limited.
+        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+        assertFalse(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+        // The 7th entry of the same process should be rate limited.
+        assertTrue(mRateLimiter.shouldRateLimit("tag", "process").shouldRateLimit());
+    }
+
     private static class TestClock implements DropboxRateLimiter.Clock {
         long mOffsetMillis = 0L;
 
diff --git a/services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java b/services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java
index 4412cfe..8cbed2c 100644
--- a/services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java
@@ -305,60 +305,4 @@
         assertEquals("Interaction event time was not updated correctly.",
                 interactionEventTime, mProcessRecord.mState.getInteractionEventTime());
     }
-
-    private void updateShortFgsOwner(int uid, int pid, boolean add) {
-        sService.mOomAdjuster.updateShortFgsOwner(uid, pid, add);
-    }
-
-    private void assertHasUidShortForegroundService(int uid, boolean expected) {
-        assertEquals(expected, sService.mOomAdjuster.hasUidShortForegroundService(uid));
-    }
-
-    @Test
-    public void testHasUidShortForegroundService() {
-        assertHasUidShortForegroundService(1, false);
-        assertHasUidShortForegroundService(2, false);
-        assertHasUidShortForegroundService(3, false);
-        assertHasUidShortForegroundService(100, false);
-        assertHasUidShortForegroundService(101, false);
-
-        updateShortFgsOwner(1, 100, true);
-        assertHasUidShortForegroundService(1, true);
-        assertHasUidShortForegroundService(100, false);
-        assertHasUidShortForegroundService(2, false);
-
-        updateShortFgsOwner(1, 101, true);
-        assertHasUidShortForegroundService(1, true);
-        assertHasUidShortForegroundService(101, false);
-        assertHasUidShortForegroundService(2, false);
-
-        updateShortFgsOwner(2, 200, true);
-        assertHasUidShortForegroundService(1, true);
-        assertHasUidShortForegroundService(2, true);
-        assertHasUidShortForegroundService(200, false);
-
-        updateShortFgsOwner(1, 101, false);
-        assertHasUidShortForegroundService(1, true);
-        assertHasUidShortForegroundService(2, true);
-
-        updateShortFgsOwner(1, 99, false); // unused PID
-        assertHasUidShortForegroundService(1, true);
-        assertHasUidShortForegroundService(2, true);
-
-        updateShortFgsOwner(1, 100, false);
-        assertHasUidShortForegroundService(1, false);
-        assertHasUidShortForegroundService(2, true);
-
-        updateShortFgsOwner(1, 100, true);
-        assertHasUidShortForegroundService(1, true);
-        assertHasUidShortForegroundService(2, true);
-
-        updateShortFgsOwner(2, 200, false);
-        assertHasUidShortForegroundService(1, true);
-        assertHasUidShortForegroundService(2, false);
-
-        updateShortFgsOwner(2, 201, true);
-        assertHasUidShortForegroundService(1, true);
-        assertHasUidShortForegroundService(2, true);
-    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java
index 8a3f246..f788c92 100644
--- a/services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java
@@ -18,8 +18,8 @@
 
 import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
-import static android.app.ActivityManager.PROCESS_CAPABILITY_NETWORK;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
 import static android.app.ActivityManager.PROCESS_STATE_CACHED_RECENT;
 import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
 import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
@@ -185,10 +185,10 @@
         verifyNoMoreInteractions(observer2);
 
         addPendingChange(TEST_UID1, UidRecord.CHANGE_PROCSTATE | UidRecord.CHANGE_CAPABILITY,
-                PROCESS_STATE_RECEIVER, 111, PROCESS_CAPABILITY_NETWORK, false);
+                PROCESS_STATE_RECEIVER, 111, PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK, false);
         mUidObserverController.dispatchUidsChanged();
         verify(observer2).onUidStateChanged(TEST_UID1, PROCESS_STATE_RECEIVER,
-                111, PROCESS_CAPABILITY_NETWORK);
+                111, PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK);
         verifyNoMoreInteractions(observer1);
         verifyNoMoreInteractions(observer2);
 
diff --git a/services/tests/servicestests/src/com/android/server/audio/SpatializerHelperTest.java b/services/tests/servicestests/src/com/android/server/audio/SpatializerHelperTest.java
index 428eaff..8f07238 100644
--- a/services/tests/servicestests/src/com/android/server/audio/SpatializerHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/audio/SpatializerHelperTest.java
@@ -17,12 +17,17 @@
 
 import com.android.server.audio.SpatializerHelper.SADeviceState;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
 
+import android.media.AudioAttributes;
 import android.media.AudioDeviceAttributes;
 import android.media.AudioDeviceInfo;
+import android.media.AudioFormat;
 import android.media.AudioSystem;
 import android.util.Log;
 
@@ -36,6 +41,7 @@
 import org.mockito.Mock;
 import org.mockito.Spy;
 
+import java.util.ArrayList;
 import java.util.List;
 
 @MediumTest
@@ -49,14 +55,33 @@
 
     @Mock private AudioService mMockAudioService;
     @Spy private AudioSystemAdapter mSpyAudioSystem;
+    @Mock private AudioSystemAdapter mMockAudioSystem;
 
     @Before
     public void setUp() throws Exception {
         mMockAudioService = mock(AudioService.class);
-        mSpyAudioSystem = spy(new NoOpAudioSystemAdapter());
+    }
 
-        mSpatHelper = new SpatializerHelper(mMockAudioService, mSpyAudioSystem,
+    /**
+     * Initializes mSpatHelper, the SpatizerHelper instance under test, to use the mock or spy
+     * AudioSystemAdapter
+     * @param useSpyAudioSystem true to use the spy adapter, mSpyAudioSystem, or false to use
+     *                          the mock adapter, mMockAudioSystem.
+     */
+    private void setUpSpatHelper(boolean useSpyAudioSystem) {
+        final AudioSystemAdapter asAdapter;
+        if (useSpyAudioSystem) {
+            mSpyAudioSystem = spy(new NoOpAudioSystemAdapter());
+            asAdapter = mSpyAudioSystem;
+            mMockAudioSystem = null;
+        } else {
+            mSpyAudioSystem = null;
+            mMockAudioSystem = mock(NoOpAudioSystemAdapter.class);
+            asAdapter = mMockAudioSystem;
+        }
+        mSpatHelper = new SpatializerHelper(mMockAudioService, asAdapter,
                 false /*headTrackingEnabledByDefault*/);
+
     }
 
     /**
@@ -66,6 +91,7 @@
      */
     @Test
     public void testSADeviceStateNullAddressCtor() throws Exception {
+        setUpSpatHelper(true /*useSpyAudioSystem*/);
         try {
             SADeviceState devState = new SADeviceState(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, null);
             devState = new SADeviceState(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, null);
@@ -76,6 +102,7 @@
     @Test
     public void testSADeviceStateStringSerialization() throws Exception {
         Log.i(TAG, "starting testSADeviceStateStringSerialization");
+        setUpSpatHelper(true /*useSpyAudioSystem*/);
         final SADeviceState devState = new SADeviceState(
                 AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, "bla");
         devState.mHasHeadTracker = false;
@@ -91,6 +118,7 @@
     @Test
     public void testSADeviceSettings() throws Exception {
         Log.i(TAG, "starting testSADeviceSettings");
+        setUpSpatHelper(true /*useSpyAudioSystem*/);
         final AudioDeviceAttributes dev1 =
                 new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_SPEAKER, "");
         final AudioDeviceAttributes dev2 =
@@ -141,4 +169,34 @@
         Log.i(TAG, "device settingsRestored: " + settingsRestored);
         Assert.assertEquals(settings, settingsRestored);
     }
+
+    /**
+     * Test that null devices for routing do not break canBeSpatialized
+     * @throws Exception
+     */
+    @Test
+    public void testNoRoutingCanBeSpatialized() throws Exception {
+        Log.i(TAG, "Starting testNoRoutingCanBeSpatialized");
+        setUpSpatHelper(false /*useSpyAudioSystem*/);
+        mSpatHelper.forceStateForTest(SpatializerHelper.STATE_ENABLED_AVAILABLE);
+
+        final ArrayList<AudioDeviceAttributes> emptyList = new ArrayList<>(0);
+        final ArrayList<AudioDeviceAttributes> listWithNull = new ArrayList<>(1);
+        listWithNull.add(null);
+        final AudioAttributes media = new AudioAttributes.Builder()
+                .setUsage(AudioAttributes.USAGE_MEDIA).build();
+        final AudioFormat spatialFormat = new AudioFormat.Builder()
+                .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
+                .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1).build();
+
+        when(mMockAudioSystem.getDevicesForAttributes(any(AudioAttributes.class), anyBoolean()))
+                .thenReturn(emptyList);
+        Assert.assertFalse("can be spatialized on empty routing",
+                mSpatHelper.canBeSpatialized(media, spatialFormat));
+
+        when(mMockAudioSystem.getDevicesForAttributes(any(AudioAttributes.class), anyBoolean()))
+                .thenReturn(listWithNull);
+        Assert.assertFalse("can be spatialized on null routing",
+                mSpatHelper.canBeSpatialized(media, spatialFormat));
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
index 3ff802c..6b0e330 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
@@ -16,6 +16,8 @@
 
 package com.android.server.biometrics.sensors.face.aidl;
 
+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;
@@ -30,11 +32,15 @@
 import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.content.ComponentName;
+import android.hardware.biometrics.common.AuthenticateReason;
 import android.hardware.biometrics.common.ICancellationSignal;
+import android.hardware.biometrics.common.OperationContext;
+import android.hardware.biometrics.common.WakeReason;
 import android.hardware.biometrics.face.ISession;
 import android.hardware.face.Face;
 import android.hardware.face.FaceAuthenticateOptions;
 import android.os.IBinder;
+import android.os.PowerManager;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
 import android.testing.TestableContext;
@@ -69,6 +75,8 @@
 
     private static final int USER_ID = 12;
     private static final long OP_ID = 32;
+    private static final int WAKE_REASON = WakeReason.LIFT;
+    private static final int AUTH_REASON = AuthenticateReason.Face.ASSISTANT_VISIBLE;
 
     @Rule
     public final TestableContext mContext = new TestableContext(
@@ -126,8 +134,13 @@
         InOrder order = inOrder(mHal, mBiometricContext);
         order.verify(mBiometricContext).updateContext(
                 mOperationContextCaptor.capture(), anyBoolean());
-        order.verify(mHal).authenticateWithContext(
-                eq(OP_ID), same(mOperationContextCaptor.getValue().toAidlContext()));
+
+        final OperationContext aidlContext = mOperationContextCaptor.getValue().toAidlContext();
+        order.verify(mHal).authenticateWithContext(eq(OP_ID), same(aidlContext));
+        assertThat(aidlContext.wakeReason).isEqualTo(WAKE_REASON);
+        assertThat(aidlContext.authenticateReason.getFaceAuthenticateReason())
+                .isEqualTo(AUTH_REASON);
+
         verify(mHal, never()).authenticate(anyLong());
     }
 
@@ -156,8 +169,11 @@
         final AidlSession aidl = new AidlSession(version, mHal, USER_ID, mHalSessionCallback);
         final FaceAuthenticateOptions options = new FaceAuthenticateOptions.Builder()
                 .setOpPackageName("test-owner")
-                .setUserId(5)
+                .setUserId(USER_ID)
                 .setSensorId(9)
+                .setWakeReason(PowerManager.WAKE_REASON_LIFT)
+                .setAuthenticateReason(
+                        FaceAuthenticateOptions.AUTHENTICATE_REASON_ASSISTANT_VISIBLE)
                 .build();
         return new FaceAuthenticationClient(mContext, () -> aidl, mToken,
                 2 /* requestId */, mClientMonitorCallbackConverter, OP_ID,
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceDetectClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceDetectClientTest.java
index c4c5505..0abfa7e 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceDetectClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceDetectClientTest.java
@@ -16,6 +16,8 @@
 
 package com.android.server.biometrics.sensors.face.aidl;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Mockito.inOrder;
@@ -24,9 +26,13 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.hardware.biometrics.common.AuthenticateReason;
+import android.hardware.biometrics.common.OperationContext;
+import android.hardware.biometrics.common.WakeReason;
 import android.hardware.biometrics.face.ISession;
 import android.hardware.face.FaceAuthenticateOptions;
 import android.os.IBinder;
+import android.os.PowerManager;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
 import android.testing.TestableContext;
@@ -55,6 +61,8 @@
 public class FaceDetectClientTest {
 
     private static final int USER_ID = 12;
+    private static final int WAKE_REASON = WakeReason.POWER_BUTTON;
+    private static final int AUTH_REASON = AuthenticateReason.Face.OCCLUDING_APP_REQUESTED;
 
     @Rule
     public final TestableContext mContext = new TestableContext(
@@ -103,8 +111,13 @@
         InOrder order = inOrder(mHal, mBiometricContext);
         order.verify(mBiometricContext).updateContext(
                 mOperationContextCaptor.capture(), anyBoolean());
-        order.verify(mHal).detectInteractionWithContext(
-                same(mOperationContextCaptor.getValue().toAidlContext()));
+
+        final OperationContext aidlContext = mOperationContextCaptor.getValue().toAidlContext();
+        order.verify(mHal).detectInteractionWithContext(same(aidlContext));
+        assertThat(aidlContext.wakeReason).isEqualTo(WAKE_REASON);
+        assertThat(aidlContext.authenticateReason.getFaceAuthenticateReason())
+                .isEqualTo(AUTH_REASON);
+
         verify(mHal, never()).detectInteraction();
     }
 
@@ -118,6 +131,9 @@
                         .setUserId(USER_ID)
                         .setSensorId(5)
                         .setOpPackageName("own-it")
+                        .setWakeReason(PowerManager.WAKE_REASON_POWER_BUTTON)
+                        .setAuthenticateReason(
+                                FaceAuthenticateOptions.AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED)
                         .build(),
                 mBiometricLogger, mBiometricContext,
                 false /* isStrongBiometric */, null /* sensorPrivacyManager */);
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 f0f975c..c664500 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
@@ -36,6 +36,7 @@
 import android.app.ActivityTaskManager;
 import android.content.ComponentName;
 import android.hardware.biometrics.BiometricManager;
+import android.hardware.biometrics.common.AuthenticateReason;
 import android.hardware.biometrics.common.ICancellationSignal;
 import android.hardware.biometrics.common.OperationContext;
 import android.hardware.biometrics.fingerprint.ISession;
@@ -165,8 +166,12 @@
         InOrder order = inOrder(mHal, mBiometricContext);
         order.verify(mBiometricContext).updateContext(
                 mOperationContextCaptor.capture(), anyBoolean());
-        order.verify(mHal).authenticateWithContext(
-                eq(OP_ID), same(mOperationContextCaptor.getValue().toAidlContext()));
+
+        final OperationContext aidlContext = mOperationContextCaptor.getValue().toAidlContext();
+        order.verify(mHal).authenticateWithContext(eq(OP_ID), same(aidlContext));
+        assertThat(aidlContext.authenticateReason.getFingerprintAuthenticateReason())
+                .isEqualTo(AuthenticateReason.Fingerprint.UNKNOWN);
+
         verify(mHal, never()).authenticate(anyLong());
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java
index e741e44..c20cc39 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java
@@ -16,6 +16,8 @@
 
 package com.android.server.biometrics.sensors.fingerprint.aidl;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.inOrder;
@@ -24,6 +26,8 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.hardware.biometrics.common.AuthenticateReason;
+import android.hardware.biometrics.common.OperationContext;
 import android.hardware.biometrics.fingerprint.ISession;
 import android.hardware.fingerprint.FingerprintAuthenticateOptions;
 import android.hardware.fingerprint.IUdfpsOverlayController;
@@ -108,8 +112,12 @@
         InOrder order = inOrder(mHal, mBiometricContext);
         order.verify(mBiometricContext).updateContext(
                 mOperationContextCaptor.capture(), anyBoolean());
-        order.verify(mHal).detectInteractionWithContext(
-                same(mOperationContextCaptor.getValue().toAidlContext()));
+
+        final OperationContext aidlContext = mOperationContextCaptor.getValue().toAidlContext();
+        order.verify(mHal).detectInteractionWithContext(same(aidlContext));
+        assertThat(aidlContext.authenticateReason.getFingerprintAuthenticateReason())
+                .isEqualTo(AuthenticateReason.Fingerprint.UNKNOWN);
+
         verify(mHal, never()).detectInteraction();
     }
 
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 26524d7..7646c40 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
@@ -273,16 +273,6 @@
         showHideOverlay(c -> c.onEnrollResult(new Fingerprint("", 1, 1), 0));
     }
 
-    @Test
-    public void testPowerPressForwardsAcquireMessage() throws RemoteException {
-        final FingerprintEnrollClient client = createClient();
-        client.start(mCallback);
-        client.onPowerPressed();
-
-        verify(mClientMonitorCallbackConverter).onAcquired(anyInt(),
-                eq(FINGERPRINT_ACQUIRED_POWER_PRESSED), anyInt());
-    }
-
     private void showHideOverlay(Consumer<FingerprintEnrollClient> block)
             throws RemoteException {
         final FingerprintEnrollClient client = createClient();
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java
index 760ed9b..6c6b608 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java
@@ -28,7 +28,7 @@
 
 import android.hardware.display.DisplayManagerInternal;
 import android.hardware.input.IInputManager;
-import android.hardware.input.InputManager;
+import android.hardware.input.InputManagerGlobal;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
@@ -87,7 +87,7 @@
 
         // Allow virtual devices to be created on the looper thread for testing.
         final InputController.DeviceCreationThreadVerifier threadVerifier = () -> true;
-        mInputController = new InputController(new Object(), mNativeWrapperMock,
+        mInputController = new InputController(mNativeWrapperMock,
                 new Handler(TestableLooper.get(this).getLooper()),
                 InstrumentationRegistry.getTargetContext().getSystemService(WindowManager.class),
                 threadVerifier);
@@ -109,7 +109,7 @@
                 device1Id).isNotEqualTo(device2Id);
 
 
-        int[] deviceIds = InputManager.getInstance().getInputDeviceIds();
+        int[] deviceIds = InputManagerGlobal.getInstance().getInputDeviceIds();
         assertWithMessage("InputManager's deviceIds list should contain id of device 1").that(
                 deviceIds).asList().contains(device1Id);
         assertWithMessage("InputManager's deviceIds list should contain id of device 2").that(
@@ -153,7 +153,7 @@
                 deviceToken, /* displayId= */ 1, /* touchpadHeight= */ 50, /* touchpadWidth= */ 50);
 
         int deviceId = mInputController.getInputDeviceId(deviceToken);
-        int[] deviceIds = InputManager.getInstance().getInputDeviceIds();
+        int[] deviceIds = InputManagerGlobal.getInstance().getInputDeviceIds();
 
         assertWithMessage("InputManager's deviceIds list should contain id of the device").that(
             deviceIds).asList().contains(deviceId);
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/SensorControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/SensorControllerTest.java
index 6431e88..1259d71 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/SensorControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/SensorControllerTest.java
@@ -81,7 +81,7 @@
     @Test
     public void createSensor_invalidHandle_throwsException() {
         doReturn(/* handle= */0).when(mSensorManagerInternalMock).createRuntimeSensor(
-                anyInt(), anyInt(), anyString(), anyString(), any());
+                anyInt(), anyInt(), anyString(), anyString(), anyInt(), any());
 
         Throwable thrown = assertThrows(
                 RuntimeException.class,
@@ -138,7 +138,7 @@
 
     private void doCreateSensorSuccessfully() {
         doReturn(SENSOR_HANDLE).when(mSensorManagerInternalMock).createRuntimeSensor(
-                anyInt(), anyInt(), anyString(), anyString(), any());
+                anyInt(), anyInt(), anyString(), anyString(), anyInt(), any());
         assertThat(mSensorController.createSensor(mSensorToken, mVirtualSensorConfig))
                 .isEqualTo(SENSOR_HANDLE);
     }
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 9910a80..339ccd8 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
@@ -18,6 +18,7 @@
 
 import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
 import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
+import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_RECENTS;
 import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_SENSORS;
 import static android.content.Context.DEVICE_ID_DEFAULT;
 import static android.content.Context.DEVICE_ID_INVALID;
@@ -117,6 +118,7 @@
 
 import com.google.android.collect.Sets;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -128,7 +130,6 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.List;
 import java.util.Set;
 import java.util.function.Consumer;
 
@@ -281,7 +282,7 @@
         return blockedActivities;
     }
 
-    private Intent createRestrictedActivityBlockedIntent(List displayCategories,
+    private Intent createRestrictedActivityBlockedIntent(Set<String> displayCategories,
             String targetDisplayCategory) {
         when(mDisplayManagerInternalMock.createVirtualDisplay(any(), any(), any(), any(),
                 eq(NONBLOCKED_APP_PACKAGE_NAME))).thenReturn(DISPLAY_ID_1);
@@ -355,7 +356,7 @@
                 TestableLooper.get(this), mNativeWrapperMock, mIInputManagerMock);
         // Allow virtual devices to be created on the looper thread for testing.
         final InputController.DeviceCreationThreadVerifier threadVerifier = () -> true;
-        mInputController = new InputController(new Object(), mNativeWrapperMock,
+        mInputController = new InputController(mNativeWrapperMock,
                 new Handler(TestableLooper.get(this).getLooper()),
                 mContext.getSystemService(WindowManager.class), threadVerifier);
         mSensorController =
@@ -372,6 +373,11 @@
         mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1);
     }
 
+    @After
+    public void tearDown() {
+        mDeviceImpl.close();
+    }
+
     @Test
     public void getDeviceIdForDisplayId_invalidDisplayId_returnsDefault() {
         assertThat(mVdm.getDeviceIdForDisplayId(Display.INVALID_DISPLAY))
@@ -444,6 +450,7 @@
                 .setBlockedActivities(getBlockedActivities())
                 .setDevicePolicy(POLICY_TYPE_SENSORS, DEVICE_POLICY_CUSTOM)
                 .build();
+        mDeviceImpl.close();
         mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1, params);
 
         assertThat(mVdm.getDevicePolicy(mDeviceImpl.getDeviceId(), POLICY_TYPE_SENSORS))
@@ -451,6 +458,35 @@
     }
 
     @Test
+    public void getDevicePolicy_defaultRecentsPolicy_gwpcCanShowRecentsOnHostDevice() {
+        VirtualDeviceParams params = new VirtualDeviceParams
+                .Builder()
+                .build();
+        mDeviceImpl.close();
+        mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1, params);
+        addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+
+        GenericWindowPolicyController gwpc =
+                mDeviceImpl.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_1);
+        assertThat(gwpc.canShowTasksInHostDeviceRecents()).isTrue();
+    }
+
+    @Test
+    public void getDevicePolicy_customRecentsPolicy_gwpcCannotShowRecentsOnHostDevice() {
+        VirtualDeviceParams params = new VirtualDeviceParams
+                .Builder()
+                .setDevicePolicy(POLICY_TYPE_RECENTS, DEVICE_POLICY_CUSTOM)
+                .build();
+        mDeviceImpl.close();
+        mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1, params);
+        addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+
+        GenericWindowPolicyController gwpc =
+                mDeviceImpl.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_1);
+        assertThat(gwpc.canShowTasksInHostDeviceRecents()).isFalse();
+    }
+
+    @Test
     public void getDeviceOwnerUid_oneDevice_returnsCorrectId() {
         int ownerUid = mLocalService.getDeviceOwnerUid(mDeviceImpl.getDeviceId());
         assertThat(ownerUid).isEqualTo(mDeviceImpl.getOwnerUid());
@@ -500,7 +536,8 @@
                 .build();
 
         doReturn(SENSOR_HANDLE).when(mSensorManagerInternalMock).createRuntimeSensor(
-                anyInt(), anyInt(), anyString(), anyString(), any());
+                anyInt(), anyInt(), anyString(), anyString(), anyInt(), any());
+        mDeviceImpl.close();
         mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1, params);
 
         VirtualSensor sensor = mLocalService.getVirtualSensor(VIRTUAL_DEVICE_ID_1, SENSOR_HANDLE);
@@ -1596,7 +1633,7 @@
 
     @Test
     public void nonRestrictedActivityOnRestrictedVirtualDisplay_startBlockedAlertActivity() {
-        Intent blockedAppIntent = createRestrictedActivityBlockedIntent(List.of("abc"),
+        Intent blockedAppIntent = createRestrictedActivityBlockedIntent(Set.of("abc"),
                 /* targetDisplayCategory= */ null);
         verify(mContext).startActivityAsUser(argThat(intent ->
                 intent.filterEquals(blockedAppIntent)), any(), any());
@@ -1604,7 +1641,7 @@
 
     @Test
     public void restrictedActivityOnRestrictedVirtualDisplay_doesNotStartBlockedAlertActivity() {
-        Intent blockedAppIntent = createRestrictedActivityBlockedIntent(List.of("abc"), "abc");
+        Intent blockedAppIntent = createRestrictedActivityBlockedIntent(Set.of("abc"), "abc");
         verify(mContext, never()).startActivityAsUser(argThat(intent ->
                 intent.filterEquals(blockedAppIntent)), any(), any());
     }
@@ -1612,14 +1649,14 @@
     @Test
     public void restrictedActivityOnNonRestrictedVirtualDisplay_startBlockedAlertActivity() {
         Intent blockedAppIntent = createRestrictedActivityBlockedIntent(
-                /* displayCategories= */ List.of(), "abc");
+                /* displayCategories= */ Set.of(), "abc");
         verify(mContext).startActivityAsUser(argThat(intent ->
                 intent.filterEquals(blockedAppIntent)), any(), any());
     }
 
     @Test
     public void restrictedActivityNonMatchingRestrictedVirtualDisplay_startBlockedAlertActivity() {
-        Intent blockedAppIntent = createRestrictedActivityBlockedIntent(List.of("abc"), "def");
+        Intent blockedAppIntent = createRestrictedActivityBlockedIntent(Set.of("abc"), "def");
         verify(mContext).startActivityAsUser(argThat(intent ->
                 intent.filterEquals(blockedAppIntent)), any(), any());
     }
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
index 7b5af1e..2bfa44e 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
@@ -89,9 +89,8 @@
                         /* activityBlockedCallback= */ null,
                         /* secureWindowCallback= */ null,
                         /* intentListenerCallback= */ null,
-                        /* displayCategories= */ new ArrayList<>(),
-                        /* recentsPolicy= */
-                        VirtualDeviceParams.RECENTS_POLICY_ALLOW_IN_HOST_DEVICE_RECENTS);
+                        /* displayCategories= */ new ArraySet<>(),
+                        /* showTasksInHostDeviceRecents= */ true);
     }
 
 
diff --git a/services/tests/servicestests/src/com/android/server/credentials/CredentialDescriptionRegistryTest.java b/services/tests/servicestests/src/com/android/server/credentials/CredentialDescriptionRegistryTest.java
new file mode 100644
index 0000000..169210f
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/credentials/CredentialDescriptionRegistryTest.java
@@ -0,0 +1,199 @@
+/*
+ * 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.credentials;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.credentials.CredentialDescription;
+import android.credentials.RegisterCredentialDescriptionRequest;
+import android.service.credentials.CredentialEntry;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Tests for CredentialDescriptionRegistry.
+ *
+ * atest FrameworksServicesTests:com.android.server.credentials.CredentialDescriptionRegistryTest
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class CredentialDescriptionRegistryTest {
+
+    private static final int USER_ID_1 = 1;
+    private static final int USER_ID_2 = 2;
+    private static final String CALLING_PACKAGE_NAME = "com.credman.app";
+    private static final String CALLING_PACKAGE_NAME_2 = "com.credman.app2";
+    private static final String MDOC_CREDENTIAL_TYPE = "MDOC";
+    private static final String PASSKEY_CREDENTIAL_TYPE = "PASSKEY";
+    private static final String FLATTENED_REGISTRY =
+            "FLATTENED_REQ;FLATTENED_REQ123;FLATTENED_REQa";
+    private static final String FLATTENED_REGISTRY_2 = "FLATTENED_REQ_2";
+    private static final String FLATTENED_REQUEST = "FLATTENED_REQ;FLATTENED_REQ123";
+
+    private CredentialDescriptionRegistry mCredentialDescriptionRegistry;
+    private CredentialEntry mEntry;
+    private CredentialEntry mEntry2;
+    private CredentialEntry mEntry3;
+
+    @SuppressWarnings("GuardedBy")
+    @Before
+    public void setUp() {
+        CredentialDescriptionRegistry.clearAllSessions();
+        mEntry = mock(CredentialEntry.class);
+        mEntry2 = mock(CredentialEntry.class);
+        mEntry3 = mock(CredentialEntry.class);
+        when(mEntry.getType()).thenReturn(MDOC_CREDENTIAL_TYPE);
+        when(mEntry2.getType()).thenReturn(MDOC_CREDENTIAL_TYPE);
+        when(mEntry3.getType()).thenReturn(PASSKEY_CREDENTIAL_TYPE);
+        mCredentialDescriptionRegistry = CredentialDescriptionRegistry.forUser(USER_ID_1);
+    }
+
+    @SuppressWarnings("GuardedBy")
+    @Test
+    public void testForUser_createsUniqueInstanceForEachUserID() {
+        final CredentialDescriptionRegistry secondRegistry = CredentialDescriptionRegistry
+                .forUser(USER_ID_2);
+
+        assertThat(mCredentialDescriptionRegistry).isNotSameInstanceAs(secondRegistry);
+    }
+
+    @SuppressWarnings("GuardedBy")
+    @Test
+    public void testForUser_returnsSameInstanceForSameUserID() {
+        final CredentialDescriptionRegistry secondRegistry = CredentialDescriptionRegistry
+                .forUser(USER_ID_1);
+
+        assertThat(mCredentialDescriptionRegistry).isSameInstanceAs(secondRegistry);
+    }
+
+    @SuppressWarnings("GuardedBy")
+    @Test
+    public void testClearUserSession_removesExistingSessionForUserID() {
+        CredentialDescriptionRegistry.clearUserSession(USER_ID_1);
+        final CredentialDescriptionRegistry secondRegistry = CredentialDescriptionRegistry
+                .forUser(USER_ID_1);
+
+        assertThat(mCredentialDescriptionRegistry).isNotSameInstanceAs(secondRegistry);
+    }
+
+    @Test
+    public void testEvictProvider_existingProviders_succeeds() {
+        final CredentialDescription credentialDescription =
+                new CredentialDescription(MDOC_CREDENTIAL_TYPE, FLATTENED_REGISTRY,
+                        Collections.emptyList());
+        final RegisterCredentialDescriptionRequest registerCredentialDescriptionRequest =
+                new RegisterCredentialDescriptionRequest(credentialDescription);
+        final CredentialDescription credentialDescription2 =
+                new CredentialDescription(MDOC_CREDENTIAL_TYPE, FLATTENED_REGISTRY_2,
+                        Collections.emptyList());
+        final RegisterCredentialDescriptionRequest registerCredentialDescriptionRequest2 =
+                new RegisterCredentialDescriptionRequest(credentialDescription2);
+
+
+        mCredentialDescriptionRegistry
+                .executeRegisterRequest(registerCredentialDescriptionRequest, CALLING_PACKAGE_NAME);
+        mCredentialDescriptionRegistry
+                .executeRegisterRequest(registerCredentialDescriptionRequest2,
+                        CALLING_PACKAGE_NAME);
+        mCredentialDescriptionRegistry.evictProviderWithPackageName(CALLING_PACKAGE_NAME);
+        Set<CredentialDescriptionRegistry.FilterResult> providers = mCredentialDescriptionRegistry
+                .getMatchingProviders(Set.of(FLATTENED_REQUEST));
+
+        assertThat(providers).isEmpty();
+    }
+
+    @Test
+    public void testGetMatchingProviders_existingProviders_succeeds() {
+        final CredentialDescription credentialDescription =
+                new CredentialDescription(MDOC_CREDENTIAL_TYPE, FLATTENED_REGISTRY,
+                        Collections.emptyList());
+        final RegisterCredentialDescriptionRequest registerCredentialDescriptionRequest =
+                new RegisterCredentialDescriptionRequest(credentialDescription);
+        final CredentialDescription credentialDescription2 =
+                new CredentialDescription(MDOC_CREDENTIAL_TYPE, FLATTENED_REGISTRY,
+                        Collections.emptyList());
+        final RegisterCredentialDescriptionRequest registerCredentialDescriptionRequest2 =
+                new RegisterCredentialDescriptionRequest(credentialDescription2);
+
+
+        mCredentialDescriptionRegistry
+                .executeRegisterRequest(registerCredentialDescriptionRequest,
+                        CALLING_PACKAGE_NAME);
+        mCredentialDescriptionRegistry
+                .executeRegisterRequest(registerCredentialDescriptionRequest2,
+                        CALLING_PACKAGE_NAME_2);
+
+        Set<CredentialDescriptionRegistry.FilterResult> providers = mCredentialDescriptionRegistry
+                .getMatchingProviders(Set.of(FLATTENED_REQUEST));
+        Set<String> packageNames = providers.stream().map(
+                filterResult -> filterResult.mPackageName).collect(Collectors.toSet());
+
+        assertThat(providers).hasSize(2);
+        assertThat(packageNames).contains(CALLING_PACKAGE_NAME);
+        assertThat(packageNames).contains(CALLING_PACKAGE_NAME_2);
+    }
+
+    @Test
+    public void testExecuteRegisterRequest_noProviders_filterSucceedsWithNoResults() {
+        List<CredentialDescriptionRegistry.FilterResult> results = mCredentialDescriptionRegistry
+                .getFilteredResultForProvider(CALLING_PACKAGE_NAME,
+                        FLATTENED_REQUEST).stream().toList();
+
+        assertThat(results).isEmpty();
+    }
+
+    @Test
+    public void testExecuteRegisterRequest_existingProviders_filterSucceeds() {
+        final CredentialDescription credentialDescription =
+                new CredentialDescription(MDOC_CREDENTIAL_TYPE,
+                        FLATTENED_REGISTRY,
+                        List.of(mEntry, mEntry2));
+        final CredentialDescription credentialDescription2 =
+                new CredentialDescription(PASSKEY_CREDENTIAL_TYPE,
+                        FLATTENED_REGISTRY_2,
+                        List.of(mEntry3));
+        final RegisterCredentialDescriptionRequest registerCredentialDescriptionRequest =
+                new RegisterCredentialDescriptionRequest(Set.of(credentialDescription,
+                credentialDescription2));
+
+        mCredentialDescriptionRegistry
+                .executeRegisterRequest(registerCredentialDescriptionRequest, CALLING_PACKAGE_NAME);
+
+        List<CredentialDescriptionRegistry.FilterResult> results = mCredentialDescriptionRegistry
+                .getFilteredResultForProvider(CALLING_PACKAGE_NAME, FLATTENED_REQUEST)
+                .stream().toList();
+
+        assertThat(results).hasSize(1);
+        assertThat(results.get(0).mCredentialEntries).hasSize(2);
+        assertThat(results.get(0).mCredentialEntries.get(0)).isSameInstanceAs(mEntry);
+        assertThat(results.get(0).mCredentialEntries.get(1)).isSameInstanceAs(mEntry2);
+    }
+
+}
diff --git a/services/tests/servicestests/src/com/android/server/credentials/OWNERS b/services/tests/servicestests/src/com/android/server/credentials/OWNERS
new file mode 100644
index 0000000..cc73854
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/credentials/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/base:/core/java/android/credentials/OWNERS
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/credentials/ProviderRegistryGetSessionTest.java b/services/tests/servicestests/src/com/android/server/credentials/ProviderRegistryGetSessionTest.java
new file mode 100644
index 0000000..4c8e70a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/credentials/ProviderRegistryGetSessionTest.java
@@ -0,0 +1,331 @@
+/*
+ * 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.credentials;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertThrows;
+
+import android.app.Activity;
+import android.app.slice.Slice;
+import android.app.slice.SliceSpec;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ServiceInfo;
+import android.content.pm.Signature;
+import android.content.pm.SigningDetails;
+import android.content.pm.SigningInfo;
+import android.credentials.Credential;
+import android.credentials.CredentialOption;
+import android.credentials.GetCredentialException;
+import android.credentials.GetCredentialResponse;
+import android.credentials.ui.GetCredentialProviderData;
+import android.credentials.ui.ProviderPendingIntentResponse;
+import android.net.Uri;
+import android.os.Bundle;
+import android.service.credentials.CallingAppInfo;
+import android.service.credentials.CredentialEntry;
+import android.service.credentials.CredentialProviderService;
+import android.service.credentials.GetCredentialRequest;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.security.cert.CertificateException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Tests for CredentialDescriptionRegistry.
+ *
+ * atest FrameworksServicesTests:com.android.server.credentials.ProviderRegistryGetSessionTest
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class ProviderRegistryGetSessionTest {
+
+    private static final String CALLING_PACKAGE_NAME = "com.credman.app";
+    private static final int USER_ID_1 = 1;
+    private static final String FLATTENED_REQUEST = "FLATTENED_REQ";
+    private static final String CP_SERVICE_NAME = "CredentialProvider";
+    private static final ComponentName CREDENTIAL_PROVIDER_COMPONENT =
+            new ComponentName(CALLING_PACKAGE_NAME, CP_SERVICE_NAME);
+    private static final String GET_CREDENTIAL_EXCEPTION_TYPE = "TYPE";
+    private static final String CREDENTIAL_TYPE = "MDOC";
+    private static final String GET_CREDENTIAL_EXCEPTION_MESSAGE = "MESSAGE";
+
+    private ProviderRegistryGetSession mProviderRegistryGetSession;
+    @Mock private GetRequestSession mGetRequestSession;
+    private CredentialOption mGetCredentialOption;
+    @Mock private ServiceInfo mServiceInfo;
+    private CallingAppInfo mCallingAppInfo;
+    @Mock private CredentialDescriptionRegistry mCredentialDescriptionRegistry;
+    private Bundle mRetrievalData;
+    @Mock private CredentialEntry mEntry;
+    @Mock private CredentialEntry mEntry2;
+    private Slice mSlice;
+    private Slice mSlice2;
+    private CredentialDescriptionRegistry.FilterResult mResult;
+    private Set<CredentialDescriptionRegistry.FilterResult> mResponse;
+
+    @SuppressWarnings("GuardedBy")
+    @Before
+    public void setUp() throws CertificateException {
+        MockitoAnnotations.initMocks(this);
+        final Context context = ApplicationProvider.getApplicationContext();
+        mRetrievalData = new Bundle();
+        mRetrievalData.putString(CredentialOption.FLATTENED_REQUEST, FLATTENED_REQUEST);
+        mCallingAppInfo = createCallingAppInfo();
+        mGetCredentialOption = new CredentialOption(CREDENTIAL_TYPE, mRetrievalData,
+                new Bundle(), false);
+        when(mServiceInfo.getComponentName()).thenReturn(CREDENTIAL_PROVIDER_COMPONENT);
+        CredentialDescriptionRegistry.setSession(USER_ID_1, mCredentialDescriptionRegistry);
+        mResponse = new HashSet<>();
+        mSlice = createSlice();
+        mSlice2 = createSlice();
+        when(mEntry.getSlice()).thenReturn(mSlice);
+        when(mEntry2.getSlice()).thenReturn(mSlice2);
+        mResult = new CredentialDescriptionRegistry.FilterResult(CALLING_PACKAGE_NAME,
+                FLATTENED_REQUEST,
+                List.of(mEntry, mEntry2));
+        mResponse.add(mResult);
+        when(mCredentialDescriptionRegistry.getFilteredResultForProvider(anyString(), anyString()))
+                .thenReturn(mResponse);
+        mProviderRegistryGetSession = ProviderRegistryGetSession
+                .createNewSession(context, USER_ID_1, mGetRequestSession,
+                        mCallingAppInfo,
+                        CALLING_PACKAGE_NAME,
+                        mGetCredentialOption);
+    }
+
+    @Test
+    public void testInvokeSession_existingProvider_setsResults() {
+        final ArgumentCaptor<String> packageNameCaptor = ArgumentCaptor.forClass(String.class);
+        final ArgumentCaptor<String> flattenedRequestCaptor = ArgumentCaptor.forClass(String.class);
+        final ArgumentCaptor<ProviderSession.Status> statusCaptor =
+                ArgumentCaptor.forClass(ProviderSession.Status.class);
+        final ArgumentCaptor<ComponentName> cpComponentNameCaptor =
+                ArgumentCaptor.forClass(ComponentName.class);
+
+        mProviderRegistryGetSession.invokeSession();
+
+        verify(mCredentialDescriptionRegistry).getFilteredResultForProvider(
+                packageNameCaptor.capture(),
+                flattenedRequestCaptor.capture());
+        assertThat(packageNameCaptor.getValue()).isEqualTo(CALLING_PACKAGE_NAME);
+        assertThat(flattenedRequestCaptor.getValue()).isEqualTo(FLATTENED_REQUEST);
+        verify(mGetRequestSession).onProviderStatusChanged(statusCaptor.capture(),
+                cpComponentNameCaptor.capture());
+        assertThat(statusCaptor.getValue()).isEqualTo(ProviderSession.Status.CREDENTIALS_RECEIVED);
+        assertThat(cpComponentNameCaptor.getValue()).isEqualTo(CREDENTIAL_PROVIDER_COMPONENT);
+        assertThat(mProviderRegistryGetSession.mCredentialEntries).hasSize(2);
+        assertThat(mProviderRegistryGetSession.mCredentialEntries.get(0)).isSameInstanceAs(mEntry);
+        assertThat(mProviderRegistryGetSession.mCredentialEntries.get(1)).isSameInstanceAs(mEntry2);
+    }
+
+    @Test
+    public void testPrepareUiData_statusNonUIInvoking_throwsIllegalStateException() {
+        mProviderRegistryGetSession.setStatus(ProviderSession.Status.CREDENTIALS_RECEIVED);
+
+        assertThrows(IllegalStateException.class,
+                () -> mProviderRegistryGetSession.prepareUiData());
+    }
+
+    @Test
+    public void testPrepareUiData_statusUIInvokingNoResults_returnsNull() {
+        mProviderRegistryGetSession.setStatus(ProviderSession.Status.CANCELED);
+
+        assertThat(mProviderRegistryGetSession.prepareUiData()).isNull();
+    }
+
+    @Test
+    public void testPrepareUiData_invokeCalledSuccessfully_returnsCorrectData() {
+        mProviderRegistryGetSession.invokeSession();
+        GetCredentialProviderData providerData = (GetCredentialProviderData)
+                mProviderRegistryGetSession.prepareUiData();
+
+        assertThat(providerData).isNotNull();
+        assertThat(providerData.getCredentialEntries()).hasSize(2);
+        assertThat(providerData.getCredentialEntries().get(0).getSlice()).isSameInstanceAs(mSlice);
+        assertThat(providerData.getCredentialEntries().get(1).getSlice()).isSameInstanceAs(mSlice2);
+        Intent intent = providerData.getCredentialEntries().get(0).getFrameworkExtrasIntent();
+        GetCredentialRequest getRequest = intent.getParcelableExtra(CredentialProviderService
+                .EXTRA_GET_CREDENTIAL_REQUEST, GetCredentialRequest.class);
+        assertThat(getRequest.getCallingAppInfo()).isSameInstanceAs(mCallingAppInfo);
+        assertThat(getRequest.getCredentialOptions().get(0)).isSameInstanceAs(mGetCredentialOption);
+        Intent intent2 = providerData.getCredentialEntries().get(0).getFrameworkExtrasIntent();
+        GetCredentialRequest getRequest2 = intent2.getParcelableExtra(CredentialProviderService
+                .EXTRA_GET_CREDENTIAL_REQUEST, GetCredentialRequest.class);
+        assertThat(getRequest2.getCallingAppInfo()).isSameInstanceAs(mCallingAppInfo);
+        assertThat(getRequest2.getCredentialOptions().get(0))
+                .isSameInstanceAs(mGetCredentialOption);
+    }
+
+    @Test
+    public void testOnUiEntrySelected_wrongEntryKey_doesNothing() {
+        final Intent intent = new Intent();
+        final GetCredentialResponse response =
+                new GetCredentialResponse(new Credential(CREDENTIAL_TYPE, new Bundle()));
+        intent.putExtra(CredentialProviderService.EXTRA_GET_CREDENTIAL_RESPONSE, response);
+        final ProviderPendingIntentResponse providerPendingIntentResponse = new
+                ProviderPendingIntentResponse(Activity.RESULT_OK, intent);
+
+        mProviderRegistryGetSession.onUiEntrySelected(
+                ProviderRegistryGetSession.CREDENTIAL_ENTRY_KEY,
+                "unsupportedKey", providerPendingIntentResponse);
+
+        verifyZeroInteractions(mGetRequestSession);
+    }
+
+    @Test
+    public void testOnUiEntrySelected_nullPendingIntentResponse_doesNothing() {
+        mProviderRegistryGetSession.onUiEntrySelected(
+                ProviderRegistryGetSession.CREDENTIAL_ENTRY_KEY,
+                ProviderRegistryGetSession.CREDENTIAL_ENTRY_KEY, null);
+
+        verifyZeroInteractions(mGetRequestSession);
+    }
+
+    @Test
+    public void testOnUiEntrySelected_pendingIntentWithException_callbackWithGivenException() {
+        final ArgumentCaptor<String> exceptionTypeCaptor =
+                ArgumentCaptor.forClass(String.class);
+        final ArgumentCaptor<String> exceptionMessageCaptor =
+                ArgumentCaptor.forClass(String.class);
+        final ArgumentCaptor<ComponentName> cpComponentNameCaptor =
+                ArgumentCaptor.forClass(ComponentName.class);
+        final ArgumentCaptor<ProviderSession.Status> statusCaptor =
+                ArgumentCaptor.forClass(ProviderSession.Status.class);
+        final GetCredentialException exception =
+                new GetCredentialException(GET_CREDENTIAL_EXCEPTION_TYPE,
+                        GET_CREDENTIAL_EXCEPTION_MESSAGE);
+        mProviderRegistryGetSession.invokeSession();
+        GetCredentialProviderData providerData = (GetCredentialProviderData)
+                mProviderRegistryGetSession.prepareUiData();
+        String entryKey = providerData.getCredentialEntries().get(0).getSubkey();
+        final Intent intent = new Intent();
+        intent.putExtra(CredentialProviderService.EXTRA_GET_CREDENTIAL_EXCEPTION, exception);
+        final ProviderPendingIntentResponse providerPendingIntentResponse = new
+                ProviderPendingIntentResponse(Activity.RESULT_OK, intent);
+
+        mProviderRegistryGetSession.onUiEntrySelected(
+                ProviderRegistryGetSession.CREDENTIAL_ENTRY_KEY,
+                entryKey, providerPendingIntentResponse);
+
+        verify(mGetRequestSession).onProviderStatusChanged(statusCaptor.capture(),
+                cpComponentNameCaptor.capture());
+        assertThat(statusCaptor.getValue()).isEqualTo(ProviderSession.Status.CREDENTIALS_RECEIVED);
+        verify(mGetRequestSession).onFinalErrorReceived(cpComponentNameCaptor.capture(),
+                exceptionTypeCaptor.capture(), exceptionMessageCaptor.capture());
+        assertThat(cpComponentNameCaptor.getValue())
+                .isSameInstanceAs(CREDENTIAL_PROVIDER_COMPONENT);
+        assertThat(exceptionTypeCaptor.getValue()).isEqualTo(GET_CREDENTIAL_EXCEPTION_TYPE);
+        assertThat(exceptionMessageCaptor.getValue()).isEqualTo(GET_CREDENTIAL_EXCEPTION_MESSAGE);
+    }
+
+    @Test
+    public void testOnUiEntrySelected_pendingIntentWithException_callbackWithCancelledException() {
+        final ArgumentCaptor<String> exceptionTypeCaptor =
+                ArgumentCaptor.forClass(String.class);
+        final ArgumentCaptor<String> exceptionMessageCaptor =
+                ArgumentCaptor.forClass(String.class);
+        final ArgumentCaptor<ComponentName> cpComponentNameCaptor =
+                ArgumentCaptor.forClass(ComponentName.class);
+        final ArgumentCaptor<ProviderSession.Status> statusCaptor =
+                ArgumentCaptor.forClass(ProviderSession.Status.class);
+
+        mProviderRegistryGetSession.invokeSession();
+        GetCredentialProviderData providerData = (GetCredentialProviderData)
+                mProviderRegistryGetSession.prepareUiData();
+        String entryKey = providerData.getCredentialEntries().get(0).getSubkey();
+        final Intent intent = new Intent();
+        final ProviderPendingIntentResponse providerPendingIntentResponse = new
+                ProviderPendingIntentResponse(Activity.RESULT_CANCELED, intent);
+
+        mProviderRegistryGetSession.onUiEntrySelected(
+                ProviderRegistryGetSession.CREDENTIAL_ENTRY_KEY,
+                entryKey, providerPendingIntentResponse);
+
+        verify(mGetRequestSession).onProviderStatusChanged(statusCaptor.capture(),
+                cpComponentNameCaptor.capture());
+        assertThat(statusCaptor.getValue()).isEqualTo(ProviderSession.Status.CREDENTIALS_RECEIVED);
+        verify(mGetRequestSession).onFinalErrorReceived(cpComponentNameCaptor.capture(),
+                exceptionTypeCaptor.capture(), exceptionMessageCaptor.capture());
+        assertThat(cpComponentNameCaptor.getValue())
+                .isSameInstanceAs(CREDENTIAL_PROVIDER_COMPONENT);
+        assertThat(exceptionTypeCaptor.getValue())
+                .isEqualTo(GetCredentialException.TYPE_USER_CANCELED);
+    }
+
+    @Test
+    public void testOnUiEntrySelected_correctEntryKeyPendingIntentResponseExists_succeeds() {
+        final ArgumentCaptor<GetCredentialResponse> getCredentialResponseCaptor =
+                ArgumentCaptor.forClass(GetCredentialResponse.class);
+        final ArgumentCaptor<ComponentName> cpComponentNameCaptor =
+                ArgumentCaptor.forClass(ComponentName.class);
+        final ArgumentCaptor<ProviderSession.Status> statusCaptor =
+                ArgumentCaptor.forClass(ProviderSession.Status.class);
+        mProviderRegistryGetSession.invokeSession();
+        GetCredentialProviderData providerData = (GetCredentialProviderData)
+                mProviderRegistryGetSession.prepareUiData();
+        final Intent intent = new Intent();
+        final GetCredentialResponse response =
+                new GetCredentialResponse(new Credential(CREDENTIAL_TYPE, new Bundle()));
+        intent.putExtra(CredentialProviderService.EXTRA_GET_CREDENTIAL_RESPONSE, response);
+        String entryKey = providerData.getCredentialEntries().get(0).getSubkey();
+        final ProviderPendingIntentResponse providerPendingIntentResponse = new
+                ProviderPendingIntentResponse(Activity.RESULT_OK, intent);
+
+        mProviderRegistryGetSession.onUiEntrySelected(
+                ProviderRegistryGetSession.CREDENTIAL_ENTRY_KEY,
+                entryKey, providerPendingIntentResponse);
+
+        verify(mGetRequestSession).onProviderStatusChanged(statusCaptor.capture(),
+                cpComponentNameCaptor.capture());
+        assertThat(statusCaptor.getValue()).isEqualTo(ProviderSession.Status.CREDENTIALS_RECEIVED);
+        verify(mGetRequestSession).onFinalResponseReceived(cpComponentNameCaptor.capture(),
+                getCredentialResponseCaptor.capture());
+        assertThat(cpComponentNameCaptor.getValue())
+                .isSameInstanceAs(CREDENTIAL_PROVIDER_COMPONENT);
+        assertThat(getCredentialResponseCaptor.getValue()).isSameInstanceAs(response);
+    }
+
+    private static Slice createSlice() {
+        return new Slice.Builder(Uri.EMPTY, new SliceSpec("", 0)).build();
+    }
+
+    private static CallingAppInfo createCallingAppInfo() throws CertificateException {
+        return new CallingAppInfo(CALLING_PACKAGE_NAME,
+                new SigningInfo(
+                        new SigningDetails(new Signature[]{}, 0,
+                                null)));
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 1f25da7..aaabb28 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -162,9 +162,9 @@
 import org.hamcrest.BaseMatcher;
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
-import org.junit.Ignore;
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.mockito.Mockito;
 import org.mockito.internal.util.collections.Sets;
@@ -514,7 +514,9 @@
         verify(mContext.spiedContext).sendBroadcastAsUser(
                 MockUtils.checkIntentAction(
                         DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
-                MockUtils.checkUserHandle(CALLER_USER_HANDLE));
+                MockUtils.checkUserHandle(CALLER_USER_HANDLE),
+                eq(null),
+                any(Bundle.class));
         verify(mContext.spiedContext).sendBroadcastAsUser(
                 MockUtils.checkIntentAction(
                         DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED),
@@ -793,7 +795,9 @@
         verify(mContext.spiedContext, times(1)).sendBroadcastAsUser(
                 MockUtils.checkIntentAction(
                         DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
-                MockUtils.checkUserHandle(CALLER_USER_HANDLE));
+                MockUtils.checkUserHandle(CALLER_USER_HANDLE),
+                eq(null),
+                any(Bundle.class));
 
         // Remove.  No permissions, but same user, so it'll work.
         mContext.callerPermissions.clear();
@@ -820,7 +824,9 @@
         verify(mContext.spiedContext, times(2)).sendBroadcastAsUser(
                 MockUtils.checkIntentAction(
                         DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
-                MockUtils.checkUserHandle(CALLER_USER_HANDLE));
+                MockUtils.checkUserHandle(CALLER_USER_HANDLE),
+                eq(null),
+                any(Bundle.class));
 
         // TODO Check other internal calls.
     }
@@ -846,7 +852,9 @@
         verify(mContext.spiedContext, times(2)).sendBroadcastAsUser(
                 MockUtils.checkIntentAction(
                         DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
-                MockUtils.checkUserHandle(CALLER_USER_HANDLE));
+                MockUtils.checkUserHandle(CALLER_USER_HANDLE),
+                eq(null),
+                any(Bundle.class));
 
         // Remove.  No permissions, but same user, so it'll work.
         mContext.callerPermissions.clear();
@@ -874,7 +882,9 @@
         verify(mContext.spiedContext, times(3)).sendBroadcastAsUser(
                 MockUtils.checkIntentAction(
                         DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
-                MockUtils.checkUserHandle(CALLER_USER_HANDLE));
+                MockUtils.checkUserHandle(CALLER_USER_HANDLE),
+                eq(null),
+                any(Bundle.class));
     }
 
     /**
@@ -2425,7 +2435,9 @@
         verify(mContext.spiedContext, times(2)).sendBroadcastAsUser(
                 MockUtils.checkIntentAction(
                         DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
-                MockUtils.checkUserHandle(CALLER_USER_HANDLE));
+                MockUtils.checkUserHandle(CALLER_USER_HANDLE),
+                eq(null),
+                any(Bundle.class));
         verify(mContext.spiedContext).sendBroadcastAsUser(
                 MockUtils.checkIntentAction(
                         DevicePolicyManager.ACTION_PROFILE_OWNER_CHANGED),
@@ -5886,7 +5898,9 @@
         verify(mContext.spiedContext, times(1)).sendBroadcastAsUser(
                 MockUtils.checkIntentAction(
                         DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
-                MockUtils.checkUserHandle(userHandle));
+                MockUtils.checkUserHandle(userHandle),
+                eq(null),
+                any(Bundle.class));
 
         final Intent intent = new Intent(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED);
         intent.setComponent(admin1);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
index 85a2446..375b52d 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
@@ -21,6 +21,7 @@
 import static android.app.admin.SystemUpdatePolicy.TYPE_INSTALL_WINDOWED;
 
 import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
 
 import android.content.ComponentName;
 import android.os.IpcDataCache;
@@ -43,6 +44,7 @@
 @RunWith(AndroidJUnit4.class)
 public class OwnersTest extends DpmTestBase {
 
+    private static final int TEST_PO_USER = 10;
     private static final String TESTDPC_PACKAGE = "com.afwsamples.testdpc";
     private final DeviceStateCacheImpl mDeviceStateCache = new DeviceStateCacheImpl();
 
@@ -55,11 +57,11 @@
 
     @Test
     public void loadProfileOwner() throws Exception {
-        getServices().addUsers(10);
+        getServices().addUsers(TEST_PO_USER);
 
         final Owners owners = makeOwners();
 
-        DpmTestUtils.writeToFile(owners.getProfileOwnerFile(10),
+        DpmTestUtils.writeToFile(owners.getProfileOwnerFile(TEST_PO_USER),
                 DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/profile_owner_1.xml"));
 
         owners.load();
@@ -71,6 +73,9 @@
         assertThat(owners.getProfileOwnerComponent(10))
                 .isEqualTo(new ComponentName(TESTDPC_PACKAGE,
                         "com.afwsamples.testdpc.DeviceAdminReceiver"));
+
+        assertWithMessage("Profile owner data in DeviceStateCache wasn't populated")
+                .that(mDeviceStateCache.isUserOrganizationManaged(TEST_PO_USER)).isTrue();
     }
 
     @Test
@@ -90,6 +95,10 @@
                         "com.afwsamples.testdpc.DeviceAdminReceiver"));
 
         assertThat(owners.getSystemUpdatePolicy().getPolicyType()).isEqualTo(TYPE_INSTALL_WINDOWED);
+
+        assertWithMessage("Device owner data in DeviceStateCache wasn't populated")
+                .that(mDeviceStateCache.isUserOrganizationManaged(owners.getDeviceOwnerUserId()))
+                .isTrue();
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessThrottlerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessThrottlerTest.java
index 800f60b..ffe2fec 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessThrottlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessThrottlerTest.java
@@ -43,6 +43,7 @@
 import com.android.server.display.BrightnessThrottler.Injector;
 import com.android.server.display.DisplayDeviceConfig.BrightnessThrottlingData;
 import com.android.server.display.DisplayDeviceConfig.BrightnessThrottlingData.ThrottlingLevel;
+import com.android.server.display.mode.DisplayModeDirectorTest;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
index 6def7b1..8981160 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
@@ -176,21 +176,18 @@
         assertFalse(mInjector.mColorSamplingEnabled);
 
         // Update brightness config to enabled color sampling.
-        mTracker.setBrightnessConfiguration(buildBrightnessConfiguration(
-                /* collectColorSamples= */ true));
+        mTracker.setShouldCollectColorSample(/* collectColorSamples= */ true);
         mInjector.waitForHandler();
         assertTrue(mInjector.mColorSamplingEnabled);
 
         // Update brightness config to disable color sampling.
-        mTracker.setBrightnessConfiguration(buildBrightnessConfiguration(
-                /* collectColorSamples= */ false));
+        mTracker.setShouldCollectColorSample(/* collectColorSamples= */ false);
         mInjector.waitForHandler();
         assertFalse(mInjector.mColorSamplingEnabled);
 
         // Pretend screen is off, update config to turn on color sampling.
         mInjector.sendScreenChange(/* screenOn= */ false);
-        mTracker.setBrightnessConfiguration(buildBrightnessConfiguration(
-                /* collectColorSamples= */ true));
+        mTracker.setShouldCollectColorSample(/* collectColorSamples= */ true);
         mInjector.waitForHandler();
         assertFalse(mInjector.mColorSamplingEnabled);
 
@@ -883,7 +880,7 @@
     private void startTracker(BrightnessTracker tracker, float initialBrightness,
             boolean collectColorSamples) {
         tracker.start(initialBrightness);
-        tracker.setBrightnessConfiguration(buildBrightnessConfiguration(collectColorSamples));
+        tracker.setShouldCollectColorSample(collectColorSamples);
         mInjector.waitForHandler();
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/display/DeviceStateToLayoutMapTest.java b/services/tests/servicestests/src/com/android/server/display/DeviceStateToLayoutMapTest.java
index a380eff..a7d3df9 100644
--- a/services/tests/servicestests/src/com/android/server/display/DeviceStateToLayoutMapTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DeviceStateToLayoutMapTest.java
@@ -18,6 +18,7 @@
 
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 
 import android.view.Display;
 import android.view.DisplayAddress;
@@ -63,26 +64,10 @@
         Layout configLayout = mDeviceStateToLayoutMap.get(0);
 
         Layout testLayout = new Layout();
-        testLayout.createDisplayLocked(
-                DisplayAddress.fromPhysicalDisplayId(123456L), /* isDefault= */ true,
-                /* isEnabled= */ true, /* displayGroup= */ null, mDisplayIdProducerMock,
-                /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
-        testLayout.createDisplayLocked(
-                DisplayAddress.fromPhysicalDisplayId(78910L), /* isDefault= */ false,
-                /* isEnabled= */ false, /* displayGroup= */ null, mDisplayIdProducerMock,
-                /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
-        testLayout.createDisplayLocked(
-                DisplayAddress.fromPhysicalDisplayId(98765L), /* isDefault= */ false,
-                /* isEnabled= */ true, "group1", mDisplayIdProducerMock,
-                /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
-        testLayout.createDisplayLocked(
-                DisplayAddress.fromPhysicalDisplayId(786L), /* isDefault= */ false,
-                /* isEnabled= */ false, "group2", mDisplayIdProducerMock,
-                /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
+        createDefaultDisplay(testLayout, 123456L);
+        createNonDefaultDisplay(testLayout, 78910L, /* enabled= */ false, /* group= */ null);
+        createNonDefaultDisplay(testLayout, 98765L, /* enabled= */ true, /* group= */ "group1");
+        createNonDefaultDisplay(testLayout, 786L, /* enabled= */ false, /* group= */ "group2");
 
         assertEquals(testLayout, configLayout);
     }
@@ -92,41 +77,18 @@
         Layout configLayout = mDeviceStateToLayoutMap.get(1);
 
         Layout testLayout = new Layout();
-        testLayout.createDisplayLocked(
-                DisplayAddress.fromPhysicalDisplayId(78910L), /* isDefault= */ true,
-                /* isEnabled= */ true, /* displayGroup= */ null, mDisplayIdProducerMock,
-                /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
-        testLayout.createDisplayLocked(
-                DisplayAddress.fromPhysicalDisplayId(123456L), /* isDefault= */ false,
-                /* isEnabled= */ false, /* displayGroup= */ null, mDisplayIdProducerMock,
-                /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
+        createDefaultDisplay(testLayout, 78910L);
+        createNonDefaultDisplay(testLayout, 123456L, /* enabled= */ false, /* group= */ null);
 
         assertEquals(testLayout, configLayout);
     }
 
     @Test
-    public void testConcurrentState() {
+    public void testBrightnessThrottlingMapId() {
         Layout configLayout = mDeviceStateToLayoutMap.get(2);
 
-        Layout testLayout = new Layout();
-
-        Layout.Display display1 = testLayout.createDisplayLocked(
-                DisplayAddress.fromPhysicalDisplayId(345L), /* isDefault= */ true,
-                /* isEnabled= */ true, /* displayGroup= */ null, mDisplayIdProducerMock,
-                /* brightnessThrottlingMapId= */ "concurrent",
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
-        display1.setPosition(Layout.Display.POSITION_FRONT);
-
-        Layout.Display display2 = testLayout.createDisplayLocked(
-                DisplayAddress.fromPhysicalDisplayId(678L), /* isDefault= */ false,
-                /* isEnabled= */ true, /* displayGroup= */ null, mDisplayIdProducerMock,
-                /* brightnessThrottlingMapId= */ "concurrent",
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
-        display2.setPosition(Layout.Display.POSITION_REAR);
-
-        assertEquals(testLayout, configLayout);
+        assertEquals("concurrent1", configLayout.getAt(0).getBrightnessThrottlingMapId());
+        assertEquals("concurrent2", configLayout.getAt(1).getBrightnessThrottlingMapId());
     }
 
     @Test
@@ -141,18 +103,33 @@
     public void testRefreshRateZoneId() {
         Layout configLayout = mDeviceStateToLayoutMap.get(3);
 
+        assertEquals("test1", configLayout.getAt(0).getRefreshRateZoneId());
+        assertNull(configLayout.getAt(1).getRefreshRateZoneId());
+    }
+
+    @Test
+    public void testRefreshRateThermalThrottlingMapId() {
+        Layout configLayout = mDeviceStateToLayoutMap.get(4);
+
+        assertEquals("test2", configLayout.getAt(0).getRefreshRateThermalThrottlingMapId());
+        assertNull(configLayout.getAt(1).getRefreshRateThermalThrottlingMapId());
+    }
+
+    @Test
+    public void testWholeStateConfig() {
+        Layout configLayout = mDeviceStateToLayoutMap.get(99);
+
         Layout testLayout = new Layout();
-        Layout.Display display1 = testLayout.createDisplayLocked(
-                DisplayAddress.fromPhysicalDisplayId(345L), /* isDefault= */ true,
-                /* isEnabled= */ true, /* displayGroup= */ null, mDisplayIdProducerMock,
-                /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
-        display1.setRefreshRateZoneId("test1");
-        testLayout.createDisplayLocked(
-                DisplayAddress.fromPhysicalDisplayId(678L), /* isDefault= */ false,
-                /* isEnabled= */ true, /* displayGroup= */ null, mDisplayIdProducerMock,
-                /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
+        testLayout.createDisplayLocked(DisplayAddress.fromPhysicalDisplayId(345L),
+                /* isDefault= */ true, /* isEnabled= */ true, /* displayGroupName= */ null,
+                mDisplayIdProducerMock,  Layout.Display.POSITION_FRONT, Display.DEFAULT_DISPLAY,
+                /* brightnessThrottlingMapId= */ "brightness1",
+                /* refreshRateZoneId= */ "zone1", /* refreshRateThermalThrottlingMapId= */ "rr1");
+        testLayout.createDisplayLocked(DisplayAddress.fromPhysicalDisplayId(678L),
+                /* isDefault= */ false, /* isEnabled= */ false, /* displayGroupName= */ "group1",
+                mDisplayIdProducerMock, Layout.Display.POSITION_REAR, Display.DEFAULT_DISPLAY,
+                /* brightnessThrottlingMapId= */ "brightness2",
+                /* refreshRateZoneId= */ "zone2", /* refreshRateThermalThrottlingMapId= */ "rr2");
 
         assertEquals(testLayout, configLayout);
     }
@@ -161,6 +138,18 @@
     // Helper Methods //
     ////////////////////
 
+    private void createDefaultDisplay(Layout layout, long id) {
+        layout.createDefaultDisplayLocked(DisplayAddress.fromPhysicalDisplayId(id),
+                mDisplayIdProducerMock);
+    }
+
+    private void createNonDefaultDisplay(Layout layout, long id, boolean enabled, String group) {
+        layout.createDisplayLocked(DisplayAddress.fromPhysicalDisplayId(id), /* isDefault= */ false,
+                enabled, group, mDisplayIdProducerMock, Layout.Display.POSITION_UNKNOWN,
+                Display.DEFAULT_DISPLAY, /* brightnessThrottlingMapId= */ null,
+                /* refreshRateZoneId= */ null, /* refreshRateThermalThrottlingMapId= */ null);
+    }
+
     private void setupDeviceStateToLayoutMap() throws IOException {
         Path tempFile = Files.createTempFile("device_state_layout_map", ".tmp");
         Files.write(tempFile, getContent().getBytes(StandardCharsets.UTF_8));
@@ -202,12 +191,12 @@
                 +      "<display enabled=\"true\" defaultDisplay=\"true\">\n"
                 +        "<address>345</address>\n"
                 +        "<position>front</position>\n"
-                +        "<brightnessThrottlingMapId>concurrent</brightnessThrottlingMapId>\n"
+                +        "<brightnessThrottlingMapId>concurrent1</brightnessThrottlingMapId>\n"
                 +      "</display>\n"
                 +      "<display enabled=\"true\">\n"
                 +        "<address>678</address>\n"
                 +        "<position>rear</position>\n"
-                +        "<brightnessThrottlingMapId>concurrent</brightnessThrottlingMapId>\n"
+                +        "<brightnessThrottlingMapId>concurrent2</brightnessThrottlingMapId>\n"
                 +      "</display>\n"
                 +    "</layout>\n"
 
@@ -221,6 +210,40 @@
                 +        "<address>678</address>\n"
                 +      "</display>\n"
                 +    "</layout>\n"
-                +  "</layouts>\n";
+
+                +    "<layout>\n"
+                +      "<state>4</state> \n"
+                +      "<display enabled=\"true\" defaultDisplay=\"true\" >\n"
+                +        "<address>345</address>\n"
+                +        "<refreshRateThermalThrottlingMapId>"
+                +          "test2"
+                +        "</refreshRateThermalThrottlingMapId>"
+                +      "</display>\n"
+                +      "<display enabled=\"true\">\n"
+                +        "<address>678</address>\n"
+                +      "</display>\n"
+                +    "</layout>\n"
+                +    "<layout>\n"
+                +      "<state>99</state> \n"
+                +      "<display enabled=\"true\" defaultDisplay=\"true\" "
+                +                                          "refreshRateZoneId=\"zone1\">\n"
+                +         "<address>345</address>\n"
+                +         "<position>front</position>\n"
+                +         "<brightnessThrottlingMapId>brightness1</brightnessThrottlingMapId>\n"
+                +         "<refreshRateThermalThrottlingMapId>"
+                +           "rr1"
+                +         "</refreshRateThermalThrottlingMapId>"
+                +       "</display>\n"
+                +       "<display enabled=\"false\" displayGroup=\"group1\" "
+                +                                           "refreshRateZoneId=\"zone2\">\n"
+                +         "<address>678</address>\n"
+                +         "<position>rear</position>\n"
+                +         "<brightnessThrottlingMapId>brightness2</brightnessThrottlingMapId>\n"
+                +         "<refreshRateThermalThrottlingMapId>"
+                +           "rr2"
+                +         "</refreshRateThermalThrottlingMapId>"
+                +       "</display>\n"
+                +     "</layout>\n"
+                +   "</layouts>\n";
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java
index fdfcd81..9fd647b 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java
@@ -20,6 +20,7 @@
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.mockito.ArgumentMatchers.anyFloat;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.mock;
@@ -28,6 +29,9 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
+import android.os.Temperature;
+import android.util.SparseArray;
+import android.view.SurfaceControl;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -82,6 +86,7 @@
     public void testConfigValuesFromDisplayConfig() throws IOException {
         setupDisplayDeviceConfigFromDisplayConfigFile();
 
+        assertEquals(mDisplayDeviceConfig.getName(), "Example Display");
         assertEquals(mDisplayDeviceConfig.getAmbientHorizonLong(), 5000);
         assertEquals(mDisplayDeviceConfig.getAmbientHorizonShort(), 50);
         assertEquals(mDisplayDeviceConfig.getBrightnessRampDecreaseMaxMillis(), 3000);
@@ -230,6 +235,18 @@
         assertEquals(mDisplayDeviceConfig.getHostUsiVersion().getMajorVersion(), 2);
         assertEquals(mDisplayDeviceConfig.getHostUsiVersion().getMinorVersion(), 0);
 
+        // Max desired Hdr/SDR ratio upper-bounds the HDR brightness.
+        assertEquals(1.0f,
+                mDisplayDeviceConfig.getHdrBrightnessFromSdr(0.62f, Float.POSITIVE_INFINITY),
+                ZERO_DELTA);
+        assertEquals(0.62f,
+                mDisplayDeviceConfig.getHdrBrightnessFromSdr(0.62f, 1.0f),
+                ZERO_DELTA);
+        assertEquals(0.77787f,
+                mDisplayDeviceConfig.getHdrBrightnessFromSdr(0.62f, 1.25f),
+                SMALL_DELTA);
+
+
         // Todo: Add asserts for BrightnessThrottlingData, DensityMapping,
         // HighBrightnessModeData AmbientLightSensor, RefreshRateLimitations and ProximitySensor.
     }
@@ -237,6 +254,7 @@
     @Test
     public void testConfigValuesFromConfigResource() {
         setupDisplayDeviceConfigFromConfigResourceFile();
+        assertNull(mDisplayDeviceConfig.getName());
         assertArrayEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsNits(), new
                 float[]{2.0f, 200.0f, 600.0f}, ZERO_DELTA);
         assertArrayEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsLux(), new
@@ -315,9 +333,59 @@
         // HighBrightnessModeData AmbientLightSensor, RefreshRateLimitations and ProximitySensor.
     }
 
+    @Test
+    public void testRefreshRateThermalThrottlingFromDisplayConfig() throws IOException {
+        setupDisplayDeviceConfigFromDisplayConfigFile();
+
+        SparseArray<SurfaceControl.RefreshRateRange> defaultMap =
+                mDisplayDeviceConfig.getRefreshRateThrottlingData(null);
+        assertNotNull(defaultMap);
+        assertEquals(2, defaultMap.size());
+        assertEquals(30, defaultMap.get(Temperature.THROTTLING_CRITICAL).min, SMALL_DELTA);
+        assertEquals(60, defaultMap.get(Temperature.THROTTLING_CRITICAL).max, SMALL_DELTA);
+        assertEquals(0, defaultMap.get(Temperature.THROTTLING_SHUTDOWN).min, SMALL_DELTA);
+        assertEquals(30, defaultMap.get(Temperature.THROTTLING_SHUTDOWN).max, SMALL_DELTA);
+
+        SparseArray<SurfaceControl.RefreshRateRange> testMap =
+                mDisplayDeviceConfig.getRefreshRateThrottlingData("test");
+        assertNotNull(testMap);
+        assertEquals(1, testMap.size());
+        assertEquals(60, testMap.get(Temperature.THROTTLING_EMERGENCY).min, SMALL_DELTA);
+        assertEquals(90, testMap.get(Temperature.THROTTLING_EMERGENCY).max, SMALL_DELTA);
+    }
+
+    private String getRefreshThermalThrottlingMaps() {
+        return "<refreshRateThrottlingMap>\n"
+               + "    <refreshRateThrottlingPoint>\n"
+               + "        <thermalStatus>critical</thermalStatus>\n"
+               + "        <refreshRateRange>\n"
+               + "            <minimum>30</minimum>\n"
+               + "            <maximum>60</maximum>\n"
+               + "        </refreshRateRange>\n"
+               + "    </refreshRateThrottlingPoint>\n"
+               + "    <refreshRateThrottlingPoint>\n"
+               + "        <thermalStatus>shutdown</thermalStatus>\n"
+               + "        <refreshRateRange>\n"
+               + "            <minimum>0</minimum>\n"
+               + "            <maximum>30</maximum>\n"
+               + "        </refreshRateRange>\n"
+               + "    </refreshRateThrottlingPoint>\n"
+               + "</refreshRateThrottlingMap>\n"
+               + "<refreshRateThrottlingMap id=\"test\">\n"
+               + "    <refreshRateThrottlingPoint>\n"
+               + "        <thermalStatus>emergency</thermalStatus>\n"
+               + "        <refreshRateRange>\n"
+               + "            <minimum>60</minimum>\n"
+               + "            <maximum>90</maximum>\n"
+               + "        </refreshRateRange>\n"
+               + "    </refreshRateThrottlingPoint>\n"
+               + "</refreshRateThrottlingMap>\n";
+    }
+
     private String getContent() {
         return "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
                 + "<displayConfiguration>\n"
+                +   "<name>Example Display</name>"
                 +   "<screenBrightnessMap>\n"
                 +       "<point>\n"
                 +           "<value>0.0</value>\n"
@@ -361,6 +429,16 @@
                 +       "</refreshRate>\n"
                 +       "<thermalStatusLimit>light</thermalStatusLimit>\n"
                 +       "<allowInLowPowerMode>false</allowInLowPowerMode>\n"
+                +       "<sdrHdrRatioMap>\n"
+                +            "<point>\n"
+                +                "<sdrNits>2.000</sdrNits>\n"
+                +                "<hdrRatio>4.000</hdrRatio>\n"
+                +            "</point>\n"
+                +            "<point>\n"
+                +                "<sdrNits>500.0</sdrNits>\n"
+                +                "<hdrRatio>1.6</hdrRatio>\n"
+                +            "</point>\n"
+                +       "</sdrHdrRatioMap>\n"
                 +   "</highBrightnessMode>\n"
                 +   "<screenOffBrightnessSensor>\n"
                 +       "<type>sensor_12345</type>\n"
@@ -557,6 +635,7 @@
                 +               "<brightness>0.0125</brightness>\n"
                 +           "</brightnessThrottlingPoint>\n"
                 +       "</brightnessThrottlingMap>\n"
+                +  getRefreshThermalThrottlingMaps()
                 +   "</thermalThrottling>\n"
                 +   "<refreshRate>\n"
                 +       "<defaultRefreshRate>45</defaultRefreshRate>\n"
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index 1b6b143..94d30bb 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -24,15 +24,20 @@
 
 import static com.android.server.display.VirtualDisplayAdapter.UNIQUE_ID_PREFIX;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.doReturn;
 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 static org.mockito.Mockito.when;
@@ -60,10 +65,13 @@
 import android.hardware.display.IDisplayManagerCallback;
 import android.hardware.display.IVirtualDisplayCallback;
 import android.hardware.display.VirtualDisplayConfig;
+import android.media.projection.IMediaProjectionManager;
+import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.MessageQueue;
 import android.os.Process;
+import android.view.ContentRecordingSession;
 import android.view.Display;
 import android.view.DisplayCutout;
 import android.view.DisplayEventReceiver;
@@ -127,6 +135,10 @@
 
     private Context mContext;
 
+    private int mHdrConversionMode;
+
+    private int mPreferredHdrOutputType;
+
     private final DisplayManagerService.Injector mShortMockedInjector =
             new DisplayManagerService.Injector() {
                 @Override
@@ -153,29 +165,46 @@
                 }
             };
 
-   class BasicInjector extends DisplayManagerService.Injector {
-       @Override
-       VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot, Context context,
-               Handler handler, DisplayAdapter.Listener displayAdapterListener) {
-           return new VirtualDisplayAdapter(syncRoot, context, handler, displayAdapterListener,
-                   (String name, boolean secure, float refreshRate) -> mMockDisplayToken);
-       }
+    class BasicInjector extends DisplayManagerService.Injector {
+        @Override
+        IMediaProjectionManager getProjectionService() {
+            return mMockProjectionService;
+        }
 
-       @Override
-       LocalDisplayAdapter getLocalDisplayAdapter(SyncRoot syncRoot, Context context,
-               Handler handler, DisplayAdapter.Listener displayAdapterListener) {
-           return new LocalDisplayAdapter(syncRoot, context, handler,
-                   displayAdapterListener, new LocalDisplayAdapter.Injector() {
-               @Override
-               public LocalDisplayAdapter.SurfaceControlProxy getSurfaceControlProxy() {
-                   return mSurfaceControlProxy;
-               }
-           });
-       }
+        @Override
+        VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot, Context context,
+                Handler handler, DisplayAdapter.Listener displayAdapterListener) {
+            return new VirtualDisplayAdapter(syncRoot, context, handler, displayAdapterListener,
+                    new VirtualDisplayAdapter.SurfaceControlDisplayFactory() {
+                        @Override
+                        public IBinder createDisplay(String name, boolean secure,
+                                float requestedRefreshRate) {
+                            return mMockDisplayToken;
+                        }
+
+                        @Override
+                        public void destroyDisplay(IBinder displayToken) {
+                        }
+                    });
+        }
+
+        @Override
+        LocalDisplayAdapter getLocalDisplayAdapter(SyncRoot syncRoot, Context context,
+                Handler handler, DisplayAdapter.Listener displayAdapterListener) {
+            return new LocalDisplayAdapter(syncRoot, context, handler,
+                    displayAdapterListener, new LocalDisplayAdapter.Injector() {
+                        @Override
+                        public LocalDisplayAdapter.SurfaceControlProxy getSurfaceControlProxy() {
+                            return mSurfaceControlProxy;
+                        }
+                    });
+        }
 
         @Override
         int setHdrConversionMode(int conversionMode, int preferredHdrOutputType,
                 int[] autoHdrTypes) {
+            mHdrConversionMode = conversionMode;
+            mPreferredHdrOutputType = preferredHdrOutputType;
             return Display.HdrCapabilities.HDR_TYPE_INVALID;
         }
 
@@ -185,12 +214,13 @@
         }
 
         boolean getHdrOutputConversionSupport() {
-            return false;
+            return true;
         }
    }
 
     private final DisplayManagerService.Injector mBasicInjector = new BasicInjector();
 
+    @Mock IMediaProjectionManager mMockProjectionService;
     @Mock IVirtualDeviceManager mIVirtualDeviceManager;
     @Mock InputManagerInternal mMockInputManagerInternal;
     @Mock VirtualDeviceManagerInternal mMockVirtualDeviceManagerInternal;
@@ -278,6 +308,7 @@
         builder.setFlags(flags);
         int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
                 null /* projection */, PACKAGE_NAME);
+        verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
 
         displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
 
@@ -403,6 +434,7 @@
         builder.setUniqueId(uniqueId);
         int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
                 null /* projection */, PACKAGE_NAME);
+        verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
 
         displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
 
@@ -439,6 +471,7 @@
         builder.setUniqueId(uniqueId);
         int displayId = bs.createVirtualDisplay(builder.build(), /* callback= */ mMockAppToken,
                 /* projection= */ null, PACKAGE_NAME);
+        verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
 
         displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
 
@@ -472,6 +505,7 @@
         builder.setUniqueId(uniqueId);
         int displayId = bs.createVirtualDisplay(builder.build(), /* callback= */ mMockAppToken,
                 /* projection= */ null, PACKAGE_NAME);
+        verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
 
         displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
 
@@ -713,6 +747,7 @@
         builder.setUniqueId(uniqueId);
         final int firstDisplayId = binderService.createVirtualDisplay(builder.build(),
                 mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
+        verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
 
         // The second virtual display requests to mirror the first virtual display.
         final String uniqueId2 = "uniqueId --- displayIdToMirrorTest #2";
@@ -724,6 +759,7 @@
         final int secondDisplayId = binderService.createVirtualDisplay(builder2.build(),
                 mMockAppToken2 /* callback */, null /* projection */,
                 PACKAGE_NAME);
+        verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
         displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
 
         // flush the handler
@@ -761,6 +797,7 @@
                         virtualDevice /* virtualDeviceToken */,
                         mock(DisplayWindowPolicyController.class),
                         PACKAGE_NAME);
+        verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
         int displayGroupId1 = localService.getDisplayInfo(displayId1).displayGroupId;
 
         // Create a second virtual display. This should be added to the previously created display
@@ -776,6 +813,7 @@
                         virtualDevice /* virtualDeviceToken */,
                         mock(DisplayWindowPolicyController.class),
                         PACKAGE_NAME);
+        verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
         int displayGroupId2 = localService.getDisplayInfo(displayId2).displayGroupId;
 
         assertEquals(
@@ -813,6 +851,7 @@
                         virtualDevice /* virtualDeviceToken */,
                         mock(DisplayWindowPolicyController.class),
                         PACKAGE_NAME);
+        verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
         int displayGroupId1 = localService.getDisplayInfo(displayId1).displayGroupId;
 
         // Create a second virtual display. With the flag VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP,
@@ -831,6 +870,7 @@
                         virtualDevice /* virtualDeviceToken */,
                         mock(DisplayWindowPolicyController.class),
                         PACKAGE_NAME);
+        verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
         int displayGroupId2 = localService.getDisplayInfo(displayId2).displayGroupId;
 
         assertNotEquals(
@@ -874,6 +914,7 @@
                         virtualDevice /* virtualDeviceToken */,
                         mock(DisplayWindowPolicyController.class),
                         PACKAGE_NAME);
+        verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
 
         // Check that FLAG_ALWAYS_UNLOCKED is set.
         assertNotEquals(
@@ -899,6 +940,7 @@
                         virtualDevice /* virtualDeviceToken */,
                         mock(DisplayWindowPolicyController.class),
                         PACKAGE_NAME);
+        verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
 
         // Check that FLAG_ALWAYS_UNLOCKED is set.
         assertNotEquals(
@@ -922,6 +964,7 @@
                         null /* virtualDeviceToken */,
                         mock(DisplayWindowPolicyController.class),
                         PACKAGE_NAME);
+        verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
 
         // Check that FLAG_ALWAYS_UNLOCKED is not set.
         assertEquals(
@@ -953,6 +996,7 @@
                 .setFlags(VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY);
         final int firstDisplayId = binderService.createVirtualDisplay(builder.build(),
                 mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
+        verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
 
         // The second virtual display requests to mirror the first virtual display.
         final String uniqueId2 = "uniqueId --- displayIdToMirrorTest #2";
@@ -960,10 +1004,11 @@
         final VirtualDisplayConfig.Builder builder2 = new VirtualDisplayConfig.Builder(
                 VIRTUAL_DISPLAY_NAME, width, height, dpi)
                 .setUniqueId(uniqueId2)
-                .setWindowManagerMirroring(true);
+                .setWindowManagerMirroringEnabled(true);
         final int secondDisplayId = binderService.createVirtualDisplay(builder2.build(),
                 mMockAppToken2 /* callback */, null /* projection */,
                 PACKAGE_NAME);
+        verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
         displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
 
         // flush the handler
@@ -978,6 +1023,54 @@
                 Display.INVALID_DISPLAY);
     }
 
+    @Test
+    public void testCreateVirtualDisplay_setContentRecordingSessionSuccess() throws Exception {
+        when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
+        when(mMockWindowManagerInternal
+                .setContentRecordingSession(any(ContentRecordingSession.class)))
+                .thenReturn(true);
+
+        final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
+                VIRTUAL_DISPLAY_NAME, 600, 800, 320);
+        builder.setUniqueId("uniqueId --- setContentRecordingSession true");
+        builder.setContentRecordingSession(
+                ContentRecordingSession.createDisplaySession(new Binder("")));
+
+        DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
+        registerDefaultDisplays(displayManager);
+        displayManager.windowManagerAndInputReady();
+
+        DisplayManagerService.BinderService binderService = displayManager.new BinderService();
+        final int displayId = binderService.createVirtualDisplay(builder.build(),
+                mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
+
+        assertThat(displayId).isNotEqualTo(Display.INVALID_DISPLAY);
+    }
+
+    @Test
+    public void testCreateVirtualDisplay_setContentRecordingSessionFail() throws Exception {
+        when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
+        when(mMockWindowManagerInternal
+                .setContentRecordingSession(any(ContentRecordingSession.class)))
+                .thenReturn(false);
+
+        final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
+                VIRTUAL_DISPLAY_NAME, 600, 800, 320);
+        builder.setUniqueId("uniqueId --- setContentRecordingSession false");
+        builder.setContentRecordingSession(
+                ContentRecordingSession.createDisplaySession(new Binder("")));
+
+        DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
+        registerDefaultDisplays(displayManager);
+        displayManager.windowManagerAndInputReady();
+
+        DisplayManagerService.BinderService binderService = displayManager.new BinderService();
+        final int displayId = binderService.createVirtualDisplay(builder.build(),
+                mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
+
+        assertThat(displayId).isEqualTo(Display.INVALID_DISPLAY);
+    }
+
     /**
      * Tests that the virtual display is created with
      * {@link VirtualDisplayConfig.Builder#setSurface(Surface)}
@@ -1004,6 +1097,7 @@
         builder.setUniqueId(uniqueId);
         final int displayId = binderService.createVirtualDisplay(builder.build(),
                 mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
+        verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
 
         displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
 
@@ -1036,6 +1130,7 @@
 
         int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
                 null /* projection */, PACKAGE_NAME);
+        verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
         displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
         displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
         DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId);
@@ -1086,7 +1181,6 @@
 
         registerDefaultDisplays(displayManager);
 
-        DisplayManagerService.BinderService bs = displayManager.new BinderService();
         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
 
         when(mContext.checkCallingPermission(ADD_TRUSTED_DISPLAY)).thenReturn(
@@ -1104,6 +1198,7 @@
         int displayId = localService.createVirtualDisplay(builder.build(),
                 mMockAppToken /* callback */, virtualDevice /* virtualDeviceToken */,
                 mock(DisplayWindowPolicyController.class), PACKAGE_NAME);
+        verify(mMockWindowManagerInternal, never()).setContentRecordingSession(Mockito.any());
         displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
         displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
         DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId);
@@ -1541,6 +1636,40 @@
                 new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_SYSTEM));
     }
 
+    @Test
+    public void testCreateHdrConversionMode_withInvalidArguments_throwsException() {
+        assertThrows(
+                "preferredHdrOutputType must not be set if the conversion mode is "
+                        + "HDR_CONVERSION_PASSTHROUGH",
+                IllegalArgumentException.class,
+                () -> new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_PASSTHROUGH,
+                        Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION));
+    }
+
+    @Test
+    public void testSetHdrConversionModeInternal_withInvalidArguments_throwsException() {
+        DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
+        assertThrows("Expected DisplayManager to throw IllegalArgumentException when "
+                        + "preferredHdrOutputType is set and the conversion mode is "
+                        + "HDR_CONVERSION_SYSTEM",
+                IllegalArgumentException.class,
+                () -> displayManager.setHdrConversionModeInternal(new HdrConversionMode(
+                        HdrConversionMode.HDR_CONVERSION_SYSTEM,
+                        Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION)));
+    }
+
+    @Test
+    public void testSetAndGetHdrConversionModeInternal() {
+        DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
+        final HdrConversionMode mode = new HdrConversionMode(
+                HdrConversionMode.HDR_CONVERSION_FORCE,
+                Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION);
+        displayManager.setHdrConversionModeInternal(mode);
+        assertEquals(mode, displayManager.getHdrConversionModeSettingInternal());
+        assertEquals(mode.getConversionMode(), mHdrConversionMode);
+        assertEquals(mode.getPreferredHdrOutputType(), mPreferredHdrOutputType);
+    }
+
     private void testDisplayInfoFrameRateOverrideModeCompat(boolean compatChangeEnabled)
             throws Exception {
         DisplayManagerService displayManager =
diff --git a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
index 2655c3f..3b10db4 100644
--- a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
@@ -29,6 +29,7 @@
 import static com.android.server.display.HighBrightnessModeController.HBM_TRANSITION_POINT_INVALID;
 
 import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.anyFloat;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.never;
@@ -103,6 +104,7 @@
 
     @Mock IThermalService mThermalServiceMock;
     @Mock Injector mInjectorMock;
+    @Mock HighBrightnessModeController.HdrBrightnessDeviceConfig mHdrBrightnessDeviceConfigMock;
 
     @Captor ArgumentCaptor<IThermalEventListener> mThermalEventListenerCaptor;
 
@@ -376,18 +378,49 @@
 
         // ensure hdr doesn't turn on if layer is too small
         hbmc.getHdrListener().onHdrInfoChanged(null /*displayToken*/, 1 /*numberOfHdrLayers*/,
-                layerWidth, smallLayerHeight, 0 /*flags*/);
+                layerWidth, smallLayerHeight, 0 /*flags*/, 1.0f /*maxDesiredHdrSdrRatio*/);
         advanceTime(0);
         assertEquals(HIGH_BRIGHTNESS_MODE_OFF, hbmc.getHighBrightnessMode());
 
         // Now check with layer larger than 50%
         hbmc.getHdrListener().onHdrInfoChanged(null /*displayToken*/, 1 /*numberOfHdrLayers*/,
-                layerWidth, largeLayerHeight, 0 /*flags*/);
+                layerWidth, largeLayerHeight, 0 /*flags*/, 1.0f /*maxDesiredHdrSdrRatio*/);
         advanceTime(0);
         assertEquals(HIGH_BRIGHTNESS_MODE_HDR, hbmc.getHighBrightnessMode());
     }
 
     @Test
+    public void testHdrRespectsMaxDesiredHdrSdrRatio() {
+        final HighBrightnessModeController hbmc = new TestHbmBuilder()
+                .setClock(new OffsettableClock())
+                .setHdrBrightnessConfig(mHdrBrightnessDeviceConfigMock)
+                .build();
+
+        // Passthrough return the max desired hdr/sdr ratio
+        when(mHdrBrightnessDeviceConfigMock.getHdrBrightnessFromSdr(anyFloat(), anyFloat()))
+                .thenAnswer(i -> i.getArgument(1));
+
+        hbmc.getHdrListener().onHdrInfoChanged(null /*displayToken*/, 1 /*numberOfHdrLayers*/,
+                DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/, 2.0f /*maxDesiredHdrSdrRatio*/);
+        advanceTime(0);
+        assertEquals(2.0f, hbmc.getHdrBrightnessValue(), EPSILON);
+
+        // The hdr ratio cannot be less than 1.
+        hbmc.getHdrListener().onHdrInfoChanged(null /*displayToken*/, 1 /*numberOfHdrLayers*/,
+                DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/, 0.5f /*maxDesiredHdrSdrRatio*/);
+        advanceTime(0);
+        assertEquals(1.0f, hbmc.getHdrBrightnessValue(), EPSILON);
+
+        // The hdr ratio can be as much as positive infinity
+        hbmc.getHdrListener().onHdrInfoChanged(null /*displayToken*/, 1 /*numberOfHdrLayers*/,
+                DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/,
+                Float.POSITIVE_INFINITY /*maxDesiredHdrSdrRatio*/);
+        advanceTime(0);
+        assertEquals(Float.POSITIVE_INFINITY, hbmc.getHdrBrightnessValue(), 0.0);
+    }
+
+
+    @Test
     public void testHdrTrumpsSunlight() {
         final HighBrightnessModeController hbmc = createDefaultHbm(new OffsettableClock());
 
@@ -400,7 +433,7 @@
 
         // turn on hdr
         hbmc.getHdrListener().onHdrInfoChanged(null /*displayToken*/, 1 /*numberOfHdrLayers*/,
-                DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/);
+                DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/, 1.0f /*maxDesiredHdrSdrRatio*/);
         advanceTime(0);
         assertEquals(HIGH_BRIGHTNESS_MODE_HDR, hbmc.getHighBrightnessMode());
         assertEquals(TRANSITION_POINT, hbmc.getCurrentBrightnessMax(), EPSILON);
@@ -412,14 +445,14 @@
 
         // Check limit when HBM is off
         hbmc.getHdrListener().onHdrInfoChanged(null /*displayToken*/, 1 /*numberOfHdrLayers*/,
-                DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/);
+                DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/, 1.0f /*maxDesiredHdrSdrRatio*/);
         advanceTime(0);
         assertEquals(HIGH_BRIGHTNESS_MODE_HDR, hbmc.getHighBrightnessMode());
         assertEquals(TRANSITION_POINT, hbmc.getCurrentBrightnessMax(), EPSILON);
 
         // Check limit with HBM is set to HDR
         hbmc.getHdrListener().onHdrInfoChanged(null /*displayToken*/, 0 /*numberOfHdrLayers*/,
-                DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/);
+                DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/, 1.0f /*maxDesiredHdrSdrRatio*/);
         advanceTime(0);
         assertEquals(HIGH_BRIGHTNESS_MODE_OFF, hbmc.getHighBrightnessMode());
         assertEquals(TRANSITION_POINT, hbmc.getCurrentBrightnessMax(), EPSILON);
@@ -430,7 +463,7 @@
         final HighBrightnessModeController hbmc = createDefaultHbm(new OffsettableClock());
 
         hbmc.getHdrListener().onHdrInfoChanged(null /*displayToken*/, 1 /*numberOfHdrLayers*/,
-                DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/);
+                DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/, 1.0f /*maxDesiredHdrSdrRatio*/);
         advanceTime(0);
         assertEquals(HIGH_BRIGHTNESS_MODE_HDR, hbmc.getHighBrightnessMode());
 
@@ -473,7 +506,7 @@
         hbmc.setAutoBrightnessEnabled(AUTO_BRIGHTNESS_ENABLED);
         hbmcOnBrightnessChanged(hbmc, TRANSITION_POINT);
         hbmc.getHdrListener().onHdrInfoChanged(null /*displayToken*/, 1 /*numberOfHdrLayers*/,
-                DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/);
+                DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/, 1.0f /*maxDesiredHdrSdrRatio*/);
         advanceTime(0);
         assertEquals(HIGH_BRIGHTNESS_MODE_HDR, hbmc.getHighBrightnessMode());
 
@@ -483,7 +516,7 @@
             eq(FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__REASON__HBM_TRANSITION_REASON_UNKNOWN));
 
         hbmc.getHdrListener().onHdrInfoChanged(null /*displayToken*/, 0 /*numberOfHdrLayers*/,
-                0, 0, 0 /*flags*/);
+                0, 0, 0 /*flags*/, 1.0f /*maxDesiredHdrSdrRatio*/);
         advanceTime(0);
 
         // Verify Stats HBM_OFF
@@ -517,7 +550,7 @@
         hbmc.setAutoBrightnessEnabled(AUTO_BRIGHTNESS_ENABLED);
         hbmcOnBrightnessChanged(hbmc, DEFAULT_MIN);
         hbmc.getHdrListener().onHdrInfoChanged(null /*displayToken*/, 1 /*numberOfHdrLayers*/,
-                DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/);
+                DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/, 1.0f /*maxDesiredHdrSdrRatio*/);
         advanceTime(0);
         assertEquals(HIGH_BRIGHTNESS_MODE_HDR, hbmc.getHighBrightnessMode());
 
@@ -657,7 +690,7 @@
             eq(FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__REASON__HBM_TRANSITION_REASON_UNKNOWN));
 
         hbmc.getHdrListener().onHdrInfoChanged(null /*displayToken*/, 1 /*numberOfHdrLayers*/,
-                DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/);
+                DISPLAY_WIDTH, DISPLAY_HEIGHT, 0 /*flags*/, 1.0f /*maxDesiredHdrSdrRatio*/);
         advanceTime(0);
 
         verify(mInjectorMock).reportHbmStateChange(eq(displayStatsId),
@@ -696,19 +729,42 @@
         assertEquals(hbmMode, hbmc.getHighBrightnessMode());
     }
 
+    private class TestHbmBuilder {
+        OffsettableClock mClock;
+        HighBrightnessModeController.HdrBrightnessDeviceConfig mHdrBrightnessCfg;
+
+        TestHbmBuilder setClock(OffsettableClock clock) {
+            mClock = clock;
+            return this;
+        }
+
+        TestHbmBuilder setHdrBrightnessConfig(
+                HighBrightnessModeController.HdrBrightnessDeviceConfig hdrBrightnessCfg
+        ) {
+            mHdrBrightnessCfg = hdrBrightnessCfg;
+            return this;
+        }
+
+        HighBrightnessModeController build() {
+            initHandler(mClock);
+            if (mHighBrightnessModeMetadata == null) {
+                mHighBrightnessModeMetadata = new HighBrightnessModeMetadata();
+            }
+            return new HighBrightnessModeController(mInjectorMock, mHandler, DISPLAY_WIDTH,
+                    DISPLAY_HEIGHT, mDisplayToken, mDisplayUniqueId, DEFAULT_MIN, DEFAULT_MAX,
+                    DEFAULT_HBM_DATA, mHdrBrightnessCfg, () -> {}, mHighBrightnessModeMetadata,
+                    mContextSpy);
+        }
+
+    }
+
     private HighBrightnessModeController createDefaultHbm() {
-        return createDefaultHbm(null);
+        return new TestHbmBuilder().build();
     }
 
     // Creates instance with standard initialization values.
     private HighBrightnessModeController createDefaultHbm(OffsettableClock clock) {
-        initHandler(clock);
-        if (mHighBrightnessModeMetadata == null) {
-            mHighBrightnessModeMetadata = new HighBrightnessModeMetadata();
-        }
-        return new HighBrightnessModeController(mInjectorMock, mHandler, DISPLAY_WIDTH,
-                DISPLAY_HEIGHT, mDisplayToken, mDisplayUniqueId, DEFAULT_MIN, DEFAULT_MAX,
-                DEFAULT_HBM_DATA, null, () -> {}, mHighBrightnessModeMetadata, mContextSpy);
+        return new TestHbmBuilder().setClock(clock).build();
     }
 
     private void initHandler(OffsettableClock clock) {
diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
index b698cdf..567548e 100644
--- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -60,8 +60,8 @@
 import android.view.DisplayAddress;
 import android.view.DisplayInfo;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.display.layout.DisplayIdProducer;
 import com.android.server.display.layout.Layout;
@@ -300,14 +300,8 @@
         add(device2);
 
         Layout layout1 = new Layout();
-        layout1.createDisplayLocked(info(device1).address, /* isDefault= */ true,
-                /* isEnabled= */ true, /* displayGroup= */ null, mIdProducer,
-                /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
-        layout1.createDisplayLocked(info(device2).address, /* isDefault= */ false,
-                /* isEnabled= */ true, /* displayGroup= */ null, mIdProducer,
-                /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
+        createDefaultDisplay(layout1, device1);
+        createNonDefaultDisplay(layout1, device2, /* enabled= */ true, /* group= */ null);
         when(mDeviceStateToLayoutMapSpy.get(STATE_DEFAULT)).thenReturn(layout1);
         assertThat(layout1.size()).isEqualTo(2);
         final int logicalId2 = layout1.getByAddress(info(device2).address).getLogicalDisplayId();
@@ -340,23 +334,14 @@
         add(device3);
 
         Layout layout1 = new Layout();
-        layout1.createDisplayLocked(info(device1).address, /* isDefault= */ true,
-                /* isEnabled= */ true, /* displayGroup= */ null, mIdProducer,
-                /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
+        createDefaultDisplay(layout1, device1);
         when(mDeviceStateToLayoutMapSpy.get(STATE_DEFAULT)).thenReturn(layout1);
 
         final int layoutState2 = 2;
         Layout layout2 = new Layout();
-        layout2.createDisplayLocked(info(device2).address, /* isDefault= */ false,
-                /* isEnabled= */ true, /* displayGroup= */ null, mIdProducer,
-                /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
+        createNonDefaultDisplay(layout2, device2, /* enabled= */ true, /* group= */ null);
         // Device3 is the default display.
-        layout2.createDisplayLocked(info(device3).address, /* isDefault= */ true,
-                /* isEnabled= */ true, /* displayGroup= */ null, mIdProducer,
-                /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
+        createDefaultDisplay(layout2, device3);
         when(mDeviceStateToLayoutMapSpy.get(layoutState2)).thenReturn(layout2);
         assertThat(layout2.size()).isEqualTo(2);
         final int logicalId2 = layout2.getByAddress(info(device2).address).getLogicalDisplayId();
@@ -398,22 +383,11 @@
                 FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
 
         Layout layout = new Layout();
-        layout.createDisplayLocked(info(device1).address,
-                /* isDefault= */ true, /* isEnabled= */ true, /* displayGroup= */ null,
-                mIdProducer, /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
-        layout.createDisplayLocked(info(device2).address,
-                /* isDefault= */ false, /* isEnabled= */ true, "group1", mIdProducer,
-                /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
-        layout.createDisplayLocked(info(device3).address,
-                /* isDefault= */ false, /* isEnabled= */ true, "group1", mIdProducer,
-                /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
-        layout.createDisplayLocked(info(device4).address,
-                /* isDefault= */ false, /* isEnabled= */ true, "group2", mIdProducer,
-                /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
+        createDefaultDisplay(layout, device1);
+        createNonDefaultDisplay(layout, device2, /* enabled= */  true, /* group= */ "group1");
+        createNonDefaultDisplay(layout, device3, /* enabled= */  true, /* group= */ "group1");
+        createNonDefaultDisplay(layout, device4, /* enabled= */  true, /* group= */ "group2");
+
         when(mDeviceStateToLayoutMapSpy.get(STATE_DEFAULT)).thenReturn(layout);
 
         LogicalDisplay display1 = add(device1);
@@ -629,23 +603,21 @@
         Layout layout = new Layout();
         layout.createDisplayLocked(device1.getDisplayDeviceInfoLocked().address,
                 /* isDefault= */ true, /* isEnabled= */ true, /* displayGroup= */ null,
-                mIdProducer, /* brightnessThrottlingMapId= */ "concurrent",
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
+                mIdProducer, POSITION_UNKNOWN,
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY,
+                /* brightnessThrottlingMapId= */ "concurrent",
+                /* refreshRateZoneId= */ null, /* refreshRateThermalThrottlingMapId= */ null);
         layout.createDisplayLocked(device2.getDisplayDeviceInfoLocked().address,
                 /* isDefault= */ false, /* isEnabled= */ true, /* displayGroup= */ null,
-                mIdProducer, /* brightnessThrottlingMapId= */ "concurrent",
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
+                mIdProducer, POSITION_UNKNOWN,
+                /* leadDisplayId= */ Display.DEFAULT_DISPLAY,
+                /* brightnessThrottlingMapId= */ "concurrent",
+                /* refreshRateZoneId= */ null, /* refreshRateThermalThrottlingMapId= */ null);
         when(mDeviceStateToLayoutMapSpy.get(0)).thenReturn(layout);
 
         layout = new Layout();
-        layout.createDisplayLocked(device1.getDisplayDeviceInfoLocked().address,
-                /* isDefault= */ false, /* isEnabled= */ false, /* displayGroup= */ null,
-                mIdProducer, /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
-        layout.createDisplayLocked(device2.getDisplayDeviceInfoLocked().address,
-                /* isDefault= */ true, /* isEnabled= */ true, /* displayGroup= */ null,
-                mIdProducer, /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
+        createNonDefaultDisplay(layout, device1, /* enabled= */ false, /* group= */ null);
+        createDefaultDisplay(layout, device2);
         when(mDeviceStateToLayoutMapSpy.get(1)).thenReturn(layout);
         when(mDeviceStateToLayoutMapSpy.get(2)).thenReturn(layout);
 
@@ -687,10 +659,10 @@
         assertTrue(mLogicalDisplayMapper.getDisplayLocked(device2).isEnabledLocked());
         assertFalse(mLogicalDisplayMapper.getDisplayLocked(device1).isInTransitionLocked());
         assertFalse(mLogicalDisplayMapper.getDisplayLocked(device2).isInTransitionLocked());
-        assertEquals(DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID,
+        assertEquals(DisplayDeviceConfig.DEFAULT_ID,
                 mLogicalDisplayMapper.getDisplayLocked(device1)
                         .getBrightnessThrottlingDataIdLocked());
-        assertEquals(DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID,
+        assertEquals(DisplayDeviceConfig.DEFAULT_ID,
                 mLogicalDisplayMapper.getDisplayLocked(device2)
                         .getBrightnessThrottlingDataIdLocked());
 
@@ -700,10 +672,10 @@
         assertTrue(mLogicalDisplayMapper.getDisplayLocked(device2).isEnabledLocked());
         assertFalse(mLogicalDisplayMapper.getDisplayLocked(device1).isInTransitionLocked());
         assertFalse(mLogicalDisplayMapper.getDisplayLocked(device2).isInTransitionLocked());
-        assertEquals(DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID,
+        assertEquals(DisplayDeviceConfig.DEFAULT_ID,
                 mLogicalDisplayMapper.getDisplayLocked(device1)
                         .getBrightnessThrottlingDataIdLocked());
-        assertEquals(DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID,
+        assertEquals(DisplayDeviceConfig.DEFAULT_ID,
                 mLogicalDisplayMapper.getDisplayLocked(device2)
                         .getBrightnessThrottlingDataIdLocked());
     }
@@ -722,30 +694,11 @@
                 TYPE_INTERNAL, 600, 900, DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP);
 
         Layout threeDevicesEnabledLayout = new Layout();
-        threeDevicesEnabledLayout.createDisplayLocked(
-                displayAddressOne,
-                /* isDefault= */ true,
-                /* isEnabled= */ true,
-                /* displayGroup= */ null,
-                mIdProducer,
-                /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
-        threeDevicesEnabledLayout.createDisplayLocked(
-                displayAddressTwo,
-                /* isDefault= */ false,
-                /* isEnabled= */ true,
-                /* displayGroup= */ null,
-                mIdProducer,
-                /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
-        threeDevicesEnabledLayout.createDisplayLocked(
-                displayAddressThree,
-                /* isDefault= */ false,
-                /* isEnabled= */ true,
-                /* displayGroup= */ null,
-                mIdProducer,
-                /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
+        createDefaultDisplay(threeDevicesEnabledLayout, displayAddressOne);
+        createNonDefaultDisplay(threeDevicesEnabledLayout, displayAddressTwo,
+                /* enabled= */ true, /* group= */ null);
+        createNonDefaultDisplay(threeDevicesEnabledLayout, displayAddressThree,
+                /* enabled= */ true, /* group= */ null);
 
         when(mDeviceStateToLayoutMapSpy.get(STATE_DEFAULT))
                 .thenReturn(threeDevicesEnabledLayout);
@@ -776,30 +729,11 @@
                 /* includeDisabled= */ false));
 
         Layout oneDeviceEnabledLayout = new Layout();
-        oneDeviceEnabledLayout.createDisplayLocked(
-                displayAddressOne,
-                /* isDefault= */ true,
-                /* isEnabled= */ true,
-                /* displayGroup= */ null,
-                mIdProducer,
-                /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
-        oneDeviceEnabledLayout.createDisplayLocked(
-                displayAddressTwo,
-                /* isDefault= */ false,
-                /* isEnabled= */ false,
-                /* displayGroup= */ null,
-                mIdProducer,
-                /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
-        oneDeviceEnabledLayout.createDisplayLocked(
-                displayAddressThree,
-                /* isDefault= */ false,
-                /* isEnabled= */ false,
-                /* displayGroup= */ null,
-                mIdProducer,
-                /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
+        createDefaultDisplay(oneDeviceEnabledLayout, displayAddressOne);
+        createNonDefaultDisplay(oneDeviceEnabledLayout, displayAddressTwo,
+                /* enabled= */ false, /* group= */ null);
+        createNonDefaultDisplay(oneDeviceEnabledLayout, displayAddressThree,
+                /* enabled= */ false, /* group= */ null);
 
         when(mDeviceStateToLayoutMapSpy.get(0)).thenReturn(oneDeviceEnabledLayout);
         when(mDeviceStateToLayoutMapSpy.get(1)).thenReturn(threeDevicesEnabledLayout);
@@ -873,12 +807,13 @@
                 FLAG_REAR);
 
         Layout layout = new Layout();
-        layout.createDisplayLocked(device1.getDisplayDeviceInfoLocked().address,
-                true, true, null, mIdProducer, /* brightnessThrottlingMapId= */ null,
-                /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
+        layout.createDefaultDisplayLocked(device1.getDisplayDeviceInfoLocked().address,
+                mIdProducer);
         layout.createDisplayLocked(device2.getDisplayDeviceInfoLocked().address,
-                false, true, null, mIdProducer, /* brightnessThrottlingMapId= */ null,
-                POSITION_REAR, Display.DEFAULT_DISPLAY);
+                /* isDefault= */ false, /* isEnabled= */ true, /* displayGroupName= */ null,
+                mIdProducer, POSITION_REAR, Display.DEFAULT_DISPLAY,
+                /* brightnessThrottlingMapId= */ null, /* refreshRateZoneId= */ null,
+                /* refreshRateThermalThrottlingMapId= */null);
         when(mDeviceStateToLayoutMapSpy.get(0)).thenReturn(layout);
 
         when(mDeviceStateToLayoutMapSpy.size()).thenReturn(1);
@@ -910,6 +845,27 @@
     // Helper Methods
     /////////////////
 
+    private void createDefaultDisplay(Layout layout, DisplayDevice device) {
+        createDefaultDisplay(layout, info(device).address);
+    }
+
+    private void createDefaultDisplay(Layout layout, DisplayAddress address) {
+        layout.createDefaultDisplayLocked(address, mIdProducer);
+    }
+
+    private void createNonDefaultDisplay(Layout layout, DisplayDevice device, boolean enabled,
+            String group) {
+        createNonDefaultDisplay(layout, info(device).address, enabled, group);
+    }
+
+    private void createNonDefaultDisplay(Layout layout, DisplayAddress address, boolean enabled,
+            String group) {
+        layout.createDisplayLocked(address, /* isDefault= */ false, enabled, group, mIdProducer,
+                Layout.Display.POSITION_UNKNOWN, Display.DEFAULT_DISPLAY,
+                /* brightnessThrottlingMapId= */ null, /* refreshRateZoneId= */ null,
+                /* refreshRateThrottlingMapId= */ null);
+    }
+
     private void advanceTime(long timeMs) {
         mLooper.moveTimeForward(1000);
         mLooper.dispatchAll();
diff --git a/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java b/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java
index 35a677e..817b245 100644
--- a/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java
@@ -377,6 +377,33 @@
         assertTrue(Float.isNaN(mDataStore.getBrightness(testDisplayDevice)));
     }
 
+    @Test
+    public void testStoreAndRestoreBrightnessNitsForDefaultDisplay() {
+        float brightnessNitsForDefaultDisplay = 190;
+        mDataStore.loadIfNeeded();
+        mDataStore.setBrightnessNitsForDefaultDisplay(brightnessNitsForDefaultDisplay);
+
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        mInjector.setWriteStream(baos);
+        mDataStore.saveIfNeeded();
+        mTestLooper.dispatchAll();
+        assertTrue(mInjector.wasWriteSuccessful());
+        TestInjector newInjector = new TestInjector();
+        PersistentDataStore newDataStore = new PersistentDataStore(newInjector);
+        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+        newInjector.setReadStream(bais);
+        newDataStore.loadIfNeeded();
+        assertEquals(brightnessNitsForDefaultDisplay,
+                mDataStore.getBrightnessNitsForDefaultDisplay(), 0);
+        assertEquals(brightnessNitsForDefaultDisplay,
+                newDataStore.getBrightnessNitsForDefaultDisplay(), 0);
+    }
+
+    @Test
+    public void testInitialBrightnessNitsForDefaultDisplay() {
+        mDataStore.loadIfNeeded();
+        assertEquals(-1, mDataStore.getBrightnessNitsForDefaultDisplay(), 0);
+    }
 
     public class TestInjector extends PersistentDataStore.Injector {
         private InputStream mReadStream;
diff --git a/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java b/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
index ae05e32..cfb432a 100644
--- a/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
@@ -26,6 +26,7 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
 import android.os.HandlerExecutor;
 import android.os.PowerManager;
@@ -34,6 +35,7 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.server.display.AutomaticBrightnessController;
 import com.android.server.display.BrightnessSetting;
 import com.android.server.display.brightness.strategy.DisplayBrightnessStrategy;
 import com.android.server.display.brightness.strategy.TemporaryBrightnessStrategy;
@@ -47,7 +49,7 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public final class DisplayBrightnessControllerTest {
-    private static final int DISPLAY_ID = 1;
+    private static final int DISPLAY_ID = Display.DEFAULT_DISPLAY;
     private static final float DEFAULT_BRIGHTNESS = 0.15f;
 
     @Mock
@@ -55,6 +57,8 @@
     @Mock
     private Context mContext;
     @Mock
+    private Resources mResources;
+    @Mock
     private BrightnessSetting mBrightnessSetting;
     @Mock
     private Runnable mOnBrightnessChangeRunnable;
@@ -67,6 +71,7 @@
     @Before
     public void before() {
         MockitoAnnotations.initMocks(this);
+        when(mContext.getResources()).thenReturn(mResources);
         DisplayBrightnessController.Injector injector = new DisplayBrightnessController.Injector() {
             @Override
             DisplayBrightnessStrategySelector getDisplayBrightnessStrategySelector(
@@ -75,6 +80,10 @@
             }
         };
         when(mBrightnessSetting.getBrightness()).thenReturn(Float.NaN);
+        when(mBrightnessSetting.getBrightnessNitsForDefaultDisplay()).thenReturn(-1f);
+        when(mResources.getBoolean(
+                com.android.internal.R.bool.config_persistBrightnessNitsForDefaultDisplay))
+                .thenReturn(true);
         mDisplayBrightnessController = new DisplayBrightnessController(mContext, injector,
                 DISPLAY_ID, DEFAULT_BRIGHTNESS, mBrightnessSetting, mOnBrightnessChangeRunnable,
                 mBrightnessChangeExecutor);
@@ -82,8 +91,8 @@
 
     @Test
     public void testIfFirstScreenBrightnessIsDefault() {
-        assertEquals(mDisplayBrightnessController.getCurrentBrightness(), DEFAULT_BRIGHTNESS,
-                0.0f);
+        assertEquals(DEFAULT_BRIGHTNESS, mDisplayBrightnessController.getCurrentBrightness(),
+                /* delta= */ 0.0f);
     }
 
     @Test
@@ -123,7 +132,7 @@
         float currentScreenBrightness = 0.4f;
         mDisplayBrightnessController.setAndNotifyCurrentScreenBrightness(currentScreenBrightness);
         assertEquals(mDisplayBrightnessController.getCurrentBrightness(),
-                currentScreenBrightness, 0.0f);
+                currentScreenBrightness, /* delta= */ 0.0f);
         verify(mBrightnessChangeExecutor).execute(mOnBrightnessChangeRunnable);
 
         // No change to the current screen brightness is same as the existing one
@@ -136,7 +145,7 @@
         float pendingScreenBrightness = 0.4f;
         mDisplayBrightnessController.setPendingScreenBrightness(pendingScreenBrightness);
         assertEquals(mDisplayBrightnessController.getPendingScreenBrightness(),
-                pendingScreenBrightness, 0.0f);
+                pendingScreenBrightness, /* delta= */ 0.0f);
     }
 
     @Test
@@ -158,7 +167,7 @@
         verify(temporaryBrightnessStrategy).setTemporaryScreenBrightness(
                 PowerManager.BRIGHTNESS_INVALID_FLOAT);
         assertEquals(mDisplayBrightnessController.getPendingScreenBrightness(),
-                PowerManager.BRIGHTNESS_INVALID_FLOAT, 0.0f);
+                PowerManager.BRIGHTNESS_INVALID_FLOAT, /* delta= */ 0.0f);
 
         // user set brightness is set as expected
         currentBrightness = 0.4f;
@@ -169,15 +178,15 @@
         mDisplayBrightnessController.setTemporaryBrightness(temporaryScreenBrightness);
         assertTrue(mDisplayBrightnessController.updateUserSetScreenBrightness());
         assertEquals(mDisplayBrightnessController.getCurrentBrightness(),
-                pendingScreenBrightness, 0.0f);
+                pendingScreenBrightness, /* delta= */ 0.0f);
         assertEquals(mDisplayBrightnessController.getLastUserSetScreenBrightness(),
-                pendingScreenBrightness, 0.0f);
+                pendingScreenBrightness, /* delta= */ 0.0f);
         verify(mBrightnessChangeExecutor, times(2))
                 .execute(mOnBrightnessChangeRunnable);
         verify(temporaryBrightnessStrategy, times(2))
                 .setTemporaryScreenBrightness(PowerManager.BRIGHTNESS_INVALID_FLOAT);
         assertEquals(mDisplayBrightnessController.getPendingScreenBrightness(),
-                PowerManager.BRIGHTNESS_INVALID_FLOAT, 0.0f);
+                PowerManager.BRIGHTNESS_INVALID_FLOAT, /* delta= */ 0.0f);
     }
 
     @Test
@@ -198,20 +207,20 @@
         float brightnessSetting = 0.2f;
         when(mBrightnessSetting.getBrightness()).thenReturn(brightnessSetting);
         assertEquals(mDisplayBrightnessController.getScreenBrightnessSetting(), brightnessSetting,
-                0.0f);
+                /* delta= */ 0.0f);
 
         // getScreenBrightnessSetting value is clamped if BrightnessSetting returns value beyond max
         brightnessSetting = 1.1f;
         when(mBrightnessSetting.getBrightness()).thenReturn(brightnessSetting);
         assertEquals(mDisplayBrightnessController.getScreenBrightnessSetting(), 1.0f,
-                0.0f);
+                /* delta= */ 0.0f);
 
         // getScreenBrightnessSetting returns default value is BrightnessSetting returns invalid
         // value.
         brightnessSetting = Float.NaN;
         when(mBrightnessSetting.getBrightness()).thenReturn(brightnessSetting);
         assertEquals(mDisplayBrightnessController.getScreenBrightnessSetting(), DEFAULT_BRIGHTNESS,
-                0.0f);
+                /* delta= */ 0.0f);
     }
 
     @Test
@@ -248,6 +257,64 @@
     }
 
     @Test
+    public void testBrightnessNitsForDefaultDisplay() {
+        float brightness = 0.3f;
+        float nits = 500;
+        AutomaticBrightnessController automaticBrightnessController =
+                mock(AutomaticBrightnessController.class);
+        when(automaticBrightnessController.convertToFloatScale(nits)).thenReturn(brightness);
+        when(mBrightnessSetting.getBrightnessNitsForDefaultDisplay()).thenReturn(nits);
+
+        mDisplayBrightnessController.setAutomaticBrightnessController(
+                automaticBrightnessController);
+        assertEquals(brightness, mDisplayBrightnessController.getCurrentBrightness(),
+                /* delta= */ 0);
+
+        float newBrightness = 0.5f;
+        float newNits = 700;
+        when(automaticBrightnessController.convertToNits(newBrightness)).thenReturn(newNits);
+        mDisplayBrightnessController.setBrightness(newBrightness);
+        verify(mBrightnessSetting).setBrightnessNitsForDefaultDisplay(newNits);
+    }
+
+    @Test
+    public void testConvertToNits() {
+        float brightness = 0.5f;
+        float nits = 300;
+
+        // ABC is null
+        assertEquals(-1f, mDisplayBrightnessController.convertToNits(brightness),
+                /* delta= */ 0);
+
+        AutomaticBrightnessController automaticBrightnessController =
+                mock(AutomaticBrightnessController.class);
+        when(automaticBrightnessController.convertToNits(brightness)).thenReturn(nits);
+        mDisplayBrightnessController.setAutomaticBrightnessController(
+                automaticBrightnessController);
+
+        assertEquals(nits, mDisplayBrightnessController.convertToNits(brightness), /* delta= */ 0);
+    }
+
+    @Test
+    public void testConvertToFloatScale() {
+        float brightness = 0.5f;
+        float nits = 300;
+
+        // ABC is null
+        assertEquals(PowerManager.BRIGHTNESS_INVALID_FLOAT,
+                mDisplayBrightnessController.convertToFloatScale(nits), /* delta= */ 0);
+
+        AutomaticBrightnessController automaticBrightnessController =
+                mock(AutomaticBrightnessController.class);
+        when(automaticBrightnessController.convertToFloatScale(nits)).thenReturn(brightness);
+        mDisplayBrightnessController.setAutomaticBrightnessController(
+                automaticBrightnessController);
+
+        assertEquals(brightness, mDisplayBrightnessController.convertToFloatScale(nits),
+                /* delta= */ 0);
+    }
+
+    @Test
     public void stop() {
         BrightnessSetting.BrightnessSettingListener brightnessSettingListener = mock(
                 BrightnessSetting.BrightnessSettingListener.class);
diff --git a/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java b/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java
index bbed1b6..618ab1b 100644
--- a/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java
@@ -34,6 +34,7 @@
 import android.content.ContextWrapper;
 import android.content.res.Resources;
 import android.hardware.display.ColorDisplayManager;
+import android.hardware.display.DisplayManagerInternal;
 import android.hardware.display.Time;
 import android.os.Handler;
 import android.os.UserHandle;
@@ -77,6 +78,7 @@
 
     private MockTwilightManager mTwilightManager;
     private DisplayTransformManager mDisplayTransformManager;
+    private DisplayManagerInternal mDisplayManagerInternal;
 
     private ColorDisplayService mCds;
     private ColorDisplayService.BinderService mBinderService;
@@ -116,6 +118,10 @@
         doReturn(true).when(mDisplayTransformManager).needsLinearColorMatrix();
         LocalServices.addService(DisplayTransformManager.class, mDisplayTransformManager);
 
+        mDisplayManagerInternal = Mockito.mock(DisplayManagerInternal.class);
+        LocalServices.removeServiceForTest(DisplayManagerInternal.class);
+        LocalServices.addService(DisplayManagerInternal.class, mDisplayManagerInternal);
+
         mCds = new ColorDisplayService(mContext);
         mBinderService = mCds.new BinderService();
         LocalServices.addService(ColorDisplayService.ColorDisplayServiceInternal.class,
@@ -142,6 +148,7 @@
         FakeSettingsProvider.clearSettingsProvider();
 
         LocalServices.removeServiceForTest(ColorDisplayService.ColorDisplayServiceInternal.class);
+        LocalServices.removeServiceForTest(DisplayManagerInternal.class);
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
rename to services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
index 7e6eeee..1b02799 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.display;
+package com.android.server.display.mode;
 
 import static android.hardware.display.DisplayManager.DeviceConfig.KEY_BRIGHTNESS_THROTTLING_DATA;
 import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS;
@@ -27,8 +27,7 @@
 import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HIGH_ZONE;
 import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_LOW_ZONE;
 
-import static com.android.server.display.DisplayModeDirector.Vote.INVALID_SIZE;
-import static com.android.server.display.HighBrightnessModeController.HBM_TRANSITION_POINT_INVALID;
+import static com.android.server.display.mode.DisplayModeDirector.Vote.INVALID_SIZE;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -60,12 +59,12 @@
 import android.hardware.display.BrightnessInfo;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManager.DisplayListener;
+import android.hardware.display.DisplayManagerGlobal;
 import android.hardware.display.DisplayManagerInternal;
 import android.hardware.display.DisplayManagerInternal.RefreshRateLimitation;
 import android.hardware.fingerprint.IUdfpsRefreshRateRequestCallback;
 import android.os.Handler;
 import android.os.IThermalEventListener;
-import android.os.IThermalService;
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.Temperature;
@@ -76,6 +75,7 @@
 import android.util.SparseArray;
 import android.util.TypedValue;
 import android.view.Display;
+import android.view.DisplayInfo;
 import android.view.SurfaceControl.RefreshRateRange;
 import android.view.SurfaceControl.RefreshRateRanges;
 
@@ -84,13 +84,16 @@
 
 import com.android.internal.R;
 import com.android.internal.display.BrightnessSynchronizer;
+import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.test.FakeSettingsProvider;
 import com.android.internal.util.test.FakeSettingsProviderRule;
 import com.android.server.LocalServices;
-import com.android.server.display.DisplayModeDirector.BrightnessObserver;
-import com.android.server.display.DisplayModeDirector.DesiredDisplayModeSpecs;
-import com.android.server.display.DisplayModeDirector.Vote;
+import com.android.server.display.DisplayDeviceConfig;
+import com.android.server.display.TestUtils;
+import com.android.server.display.mode.DisplayModeDirector.BrightnessObserver;
+import com.android.server.display.mode.DisplayModeDirector.DesiredDisplayModeSpecs;
+import com.android.server.display.mode.DisplayModeDirector.Vote;
 import com.android.server.sensors.SensorManagerInternal;
 import com.android.server.sensors.SensorManagerInternal.ProximityActiveListener;
 import com.android.server.statusbar.StatusBarManagerInternal;
@@ -126,6 +129,8 @@
     private static final int DISPLAY_ID = 0;
     private static final float TRANSITION_POINT = 0.763f;
 
+    private static final float HBM_TRANSITION_POINT_INVALID = Float.POSITIVE_INFINITY;
+
     private Context mContext;
     private FakesInjector mInjector;
     private Handler mHandler;
@@ -137,8 +142,6 @@
     public SensorManagerInternal mSensorManagerInternalMock;
     @Mock
     public DisplayManagerInternal mDisplayManagerInternalMock;
-    @Mock
-    public IThermalService mThermalServiceMock;
 
     @Before
     public void setUp() throws Exception {
@@ -147,7 +150,6 @@
         final MockContentResolver resolver = mSettingsProviderRule.mockContentResolver(mContext);
         when(mContext.getContentResolver()).thenReturn(resolver);
         mInjector = spy(new FakesInjector());
-        when(mInjector.getThermalService()).thenReturn(mThermalServiceMock);
         mHandler = new Handler(Looper.getMainLooper());
 
         LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
@@ -1770,11 +1772,12 @@
 
         ArgumentCaptor<DisplayListener> DisplayCaptor =
                 ArgumentCaptor.forClass(DisplayListener.class);
-        verify(mInjector).registerDisplayListener(DisplayCaptor.capture(), any(Handler.class),
+        verify(mInjector, times(2)).registerDisplayListener(DisplayCaptor.capture(),
+                any(Handler.class),
                 eq(DisplayManager.EVENT_FLAG_DISPLAY_ADDED
                         | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
                         | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED));
-        DisplayListener displayListener = DisplayCaptor.getValue();
+        DisplayListener displayListener = DisplayCaptor.getAllValues().get(0);
 
         // Verify that there is no proximity vote initially
         Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
@@ -2233,8 +2236,7 @@
         ArgumentCaptor<IThermalEventListener> thermalEventListener =
                 ArgumentCaptor.forClass(IThermalEventListener.class);
 
-        verify(mThermalServiceMock).registerThermalEventListenerWithType(
-            thermalEventListener.capture(), eq(Temperature.TYPE_SKIN));
+        verify(mInjector).registerThermalServiceListener(thermalEventListener.capture());
         final IThermalEventListener listener = thermalEventListener.getValue();
 
         // Verify that there is no skin temperature vote initially.
@@ -2243,11 +2245,13 @@
 
         // Set the skin temperature to critical and verify that we added a vote.
         listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_CRITICAL));
+        BackgroundThread.getHandler().runWithScissors(() -> { }, 500 /*timeout*/);
         vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_SKIN_TEMPERATURE);
         assertVoteForRenderFrameRateRange(vote, 0f, 60.f);
 
         // Set the skin temperature to severe and verify that the vote is gone.
         listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_SEVERE));
+        BackgroundThread.getHandler().runWithScissors(() -> { }, 500 /*timeout*/);
         vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_SKIN_TEMPERATURE);
         assertNull(vote);
     }
@@ -2548,7 +2552,7 @@
                     KEY_REFRESH_RATE_IN_HBM_HDR, String.valueOf(fps));
         }
 
-        void setBrightnessThrottlingData(String brightnessThrottlingData) {
+        public void setBrightnessThrottlingData(String brightnessThrottlingData) {
             putPropertyAndNotify(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
                     KEY_BRIGHTNESS_THROTTLING_DATA, brightnessThrottlingData);
         }
@@ -2706,6 +2710,16 @@
         public void registerDisplayListener(DisplayListener listener, Handler handler, long flag) {}
 
         @Override
+        public Display[] getDisplays() {
+            return new Display[] { createDisplay(DISPLAY_ID) };
+        }
+
+        @Override
+        public boolean getDisplayInfo(int displayId, DisplayInfo displayInfo) {
+            return false;
+        }
+
+        @Override
         public BrightnessInfo getBrightnessInfo(int displayId) {
             return null;
         }
@@ -2716,8 +2730,8 @@
         }
 
         @Override
-        public IThermalService getThermalService() {
-            return null;
+        public boolean registerThermalServiceListener(IThermalEventListener listener) {
+            return true;
         }
 
         @Override
@@ -2725,6 +2739,11 @@
             return true;
         }
 
+        protected Display createDisplay(int id) {
+            return new Display(DisplayManagerGlobal.getInstance(), id, new DisplayInfo(),
+                    ApplicationProvider.getApplicationContext().getResources());
+        }
+
         void notifyPeakRefreshRateChanged() {
             if (mPeakRefreshRateObserver != null) {
                 mPeakRefreshRateObserver.dispatchChange(false /*selfChange*/,
diff --git a/services/tests/servicestests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java b/services/tests/servicestests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java
new file mode 100644
index 0000000..fd1889c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java
@@ -0,0 +1,285 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import android.hardware.display.DisplayManager;
+import android.os.Handler;
+import android.os.IThermalEventListener;
+import android.os.Temperature;
+import android.util.SparseArray;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.SurfaceControl;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.server.testutils.TestHandler;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * Tests for DisplayModeDirector.SkinThermalStatusObserver. Comply with changes described in
+ * b/266789924
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SkinThermalStatusObserverTest {
+    private static final float FLOAT_TOLERANCE = 0.01f;
+    private static final int DISPLAY_ID = 1;
+    private static final int DISPLAY_ID_OTHER = 2;
+    private static final int DISPLAY_ID_ADDED = 3;
+
+    SkinThermalStatusObserver mObserver;
+
+    private RegisteringFakesInjector mInjector = new RegisteringFakesInjector();
+
+    private final TestHandler mHandler = new TestHandler(null);
+    private final FakeVoteStorage mStorage = new FakeVoteStorage();
+
+    @Before
+    public void setUp() {
+        mObserver = new SkinThermalStatusObserver(mInjector, mStorage, mHandler);
+    }
+
+    @Test
+    public void testRegisterListenersOnObserve() {
+        // GIVEN thermal sensor is available
+        assertNull(mInjector.mThermalEventListener);
+        assertNull(mInjector.mDisplayListener);
+        // WHEN observe is called
+        mObserver.observe();
+        // THEN thermal and display listeners are registered
+        assertEquals(mObserver, mInjector.mThermalEventListener);
+        assertEquals(mObserver, mInjector.mDisplayListener);
+    }
+
+    @Test
+    public void testFailToRegisterThermalListenerOnObserve() {
+        // GIVEN thermal sensor is not available
+        mInjector = new RegisteringFakesInjector(false);
+        mObserver = new SkinThermalStatusObserver(mInjector, mStorage, mHandler);
+        // WHEN observe is called
+        mObserver.observe();
+        // THEN nothing is registered
+        assertNull(mInjector.mThermalEventListener);
+        assertNull(mInjector.mDisplayListener);
+    }
+
+    @Test
+    public void testNotifyWithDefaultVotesForCritical() {
+        // GIVEN 2 displays with no thermalThrottling config
+        mObserver.observe();
+        assertEquals(0, mStorage.mVoteRegistry.size());
+
+        // WHEN thermal sensor notifies CRITICAL
+        mObserver.notifyThrottling(createTemperature(Temperature.THROTTLING_CRITICAL));
+        mHandler.flush();
+
+        // THEN 2 votes are added to storage with (0,60) render refresh rate(default behaviour)
+        assertEquals(2, mStorage.mVoteRegistry.size());
+
+        SparseArray<DisplayModeDirector.Vote> displayVotes = mStorage.mVoteRegistry.get(DISPLAY_ID);
+        assertEquals(1, displayVotes.size());
+
+        DisplayModeDirector.Vote vote = displayVotes.get(
+                DisplayModeDirector.Vote.PRIORITY_SKIN_TEMPERATURE);
+        assertEquals(0, vote.refreshRateRanges.render.min, FLOAT_TOLERANCE);
+        assertEquals(60, vote.refreshRateRanges.render.max, FLOAT_TOLERANCE);
+
+        SparseArray<DisplayModeDirector.Vote> otherDisplayVotes = mStorage.mVoteRegistry.get(
+                DISPLAY_ID_OTHER);
+        assertEquals(1, otherDisplayVotes.size());
+
+        vote = otherDisplayVotes.get(DisplayModeDirector.Vote.PRIORITY_SKIN_TEMPERATURE);
+        assertEquals(0, vote.refreshRateRanges.render.min, FLOAT_TOLERANCE);
+        assertEquals(60, vote.refreshRateRanges.render.max, FLOAT_TOLERANCE);
+    }
+
+    @Test
+    public void testNotifyWithDefaultVotesChangeFromCriticalToSevere() {
+        // GIVEN 2 displays with no thermalThrottling config AND temperature level CRITICAL
+        mObserver.observe();
+        assertEquals(0, mStorage.mVoteRegistry.size());
+        mObserver.notifyThrottling(createTemperature(Temperature.THROTTLING_CRITICAL));
+        // WHEN thermal sensor notifies SEVERE
+        mObserver.notifyThrottling(createTemperature(Temperature.THROTTLING_SEVERE));
+        mHandler.flush();
+        // THEN all votes with PRIORITY_SKIN_TEMPERATURE are removed from the storage
+        assertEquals(0, mStorage.mVoteRegistry.size());
+    }
+
+    @Test
+    public void testNotifyWithDefaultVotesForSevere() {
+        // GIVEN 2 displays with no thermalThrottling config
+        mObserver.observe();
+        assertEquals(0, mStorage.mVoteRegistry.size());
+        // WHEN thermal sensor notifies CRITICAL
+        mObserver.notifyThrottling(createTemperature(Temperature.THROTTLING_SEVERE));
+        mHandler.flush();
+        // THEN nothing is added to the storage
+        assertEquals(0, mStorage.mVoteRegistry.size());
+    }
+
+    @Test
+    public void testNotifiesWithConfigVotes() {
+        // GIVEN 2 displays AND one has thermalThrottling config defined
+        SparseArray<SurfaceControl.RefreshRateRange> displayConfig = new SparseArray<>();
+        displayConfig.put(Temperature.THROTTLING_MODERATE,
+                new SurfaceControl.RefreshRateRange(90.0f, 120.0f));
+        SparseArray<SparseArray<SurfaceControl.RefreshRateRange>> config = new SparseArray<>();
+        config.put(DISPLAY_ID, displayConfig);
+        mInjector = new RegisteringFakesInjector(true, config);
+        mObserver = new SkinThermalStatusObserver(mInjector, mStorage, mHandler);
+        mObserver.observe();
+        mObserver.onDisplayChanged(DISPLAY_ID);
+        assertEquals(0, mStorage.mVoteRegistry.size());
+        // WHEN thermal sensor notifies temperature above configured
+        mObserver.notifyThrottling(createTemperature(Temperature.THROTTLING_SEVERE));
+        mHandler.flush();
+        // THEN vote with refreshRate from config is added to the storage
+        assertEquals(1, mStorage.mVoteRegistry.size());
+        SparseArray<DisplayModeDirector.Vote> displayVotes = mStorage.mVoteRegistry.get(DISPLAY_ID);
+        assertEquals(1, displayVotes.size());
+        DisplayModeDirector.Vote vote = displayVotes.get(
+                DisplayModeDirector.Vote.PRIORITY_SKIN_TEMPERATURE);
+        assertEquals(90, vote.refreshRateRanges.render.min, FLOAT_TOLERANCE);
+        assertEquals(120, vote.refreshRateRanges.render.max, FLOAT_TOLERANCE);
+    }
+
+    @Test
+    public void testDisplayAdded() {
+        // GIVEN 2 displays with no thermalThrottling config AND temperature level CRITICAL
+        mObserver.observe();
+        mObserver.notifyThrottling(createTemperature(Temperature.THROTTLING_CRITICAL));
+        // WHEN new display is added
+        mObserver.onDisplayAdded(DISPLAY_ID_ADDED);
+        mHandler.flush();
+        // THEN 3rd vote is added to storage with (0,60) render refresh rate(default behaviour)
+        assertEquals(3, mStorage.mVoteRegistry.size());
+
+        SparseArray<DisplayModeDirector.Vote> displayVotes = mStorage.mVoteRegistry.get(
+                DISPLAY_ID_ADDED);
+        assertEquals(1, displayVotes.size());
+
+        DisplayModeDirector.Vote vote = displayVotes.get(
+                DisplayModeDirector.Vote.PRIORITY_SKIN_TEMPERATURE);
+        assertEquals(0, vote.refreshRateRanges.render.min, FLOAT_TOLERANCE);
+        assertEquals(60, vote.refreshRateRanges.render.max, FLOAT_TOLERANCE);
+    }
+
+    @Test
+    public void testDisplayAddedAndThenImmediatelyRemoved() {
+        // GIVEN 2 displays with no thermalThrottling config AND temperature level CRITICAL
+        mObserver.observe();
+        mObserver.notifyThrottling(createTemperature(Temperature.THROTTLING_CRITICAL));
+        // WHEN new display is added and immediately removed
+        mObserver.onDisplayAdded(DISPLAY_ID_ADDED);
+        mObserver.onDisplayRemoved(DISPLAY_ID_ADDED);
+        mHandler.flush();
+        // THEN there are 2 votes in registry
+        assertEquals(2, mStorage.mVoteRegistry.size());
+        assertNotNull(mStorage.mVoteRegistry.get(DISPLAY_ID));
+        assertNotNull(mStorage.mVoteRegistry.get(DISPLAY_ID_OTHER));
+    }
+
+    private static Temperature createTemperature(@Temperature.ThrottlingStatus int status) {
+        return new Temperature(40.0f, Temperature.TYPE_SKIN, "test_temp", status);
+    }
+
+
+    private static class RegisteringFakesInjector extends DisplayModeDirectorTest.FakesInjector {
+        private IThermalEventListener mThermalEventListener;
+        private DisplayManager.DisplayListener mDisplayListener;
+
+        private final boolean mRegisterThermalListener;
+        private final SparseArray<SparseArray<SurfaceControl.RefreshRateRange>> mOverriddenConfig;
+
+
+        private RegisteringFakesInjector() {
+            this(true);
+        }
+
+        private RegisteringFakesInjector(boolean registerThermalListener) {
+            this(registerThermalListener, new SparseArray<>());
+        }
+
+        private RegisteringFakesInjector(boolean registerThermalListener,
+                SparseArray<SparseArray<SurfaceControl.RefreshRateRange>> overriddenConfig) {
+            mRegisterThermalListener = registerThermalListener;
+            mOverriddenConfig = overriddenConfig;
+        }
+
+        @Override
+        public boolean registerThermalServiceListener(IThermalEventListener listener) {
+            mThermalEventListener = (mRegisterThermalListener ? listener : null);
+            return mRegisterThermalListener;
+        }
+
+        @Override
+        public void registerDisplayListener(DisplayManager.DisplayListener listener,
+                Handler handler, long flag) {
+            mDisplayListener = listener;
+        }
+
+        @Override
+        public Display[] getDisplays() {
+            return new Display[] {createDisplay(DISPLAY_ID), createDisplay(DISPLAY_ID_OTHER)};
+        }
+
+        @Override
+        public boolean getDisplayInfo(int displayId, DisplayInfo displayInfo) {
+            SparseArray<SurfaceControl.RefreshRateRange> config = mOverriddenConfig.get(displayId);
+            if (config != null) {
+                displayInfo.refreshRateThermalThrottling = config;
+                return true;
+            }
+            return false;
+        }
+    }
+
+
+    private static class FakeVoteStorage implements DisplayModeDirector.BallotBox {
+        private final SparseArray<SparseArray<DisplayModeDirector.Vote>> mVoteRegistry =
+                new SparseArray<>();
+
+        @Override
+        public void vote(int displayId, int priority, DisplayModeDirector.Vote vote) {
+            SparseArray<DisplayModeDirector.Vote> votesPerDisplay = mVoteRegistry.get(displayId);
+            if (votesPerDisplay == null) {
+                votesPerDisplay = new SparseArray<>();
+                mVoteRegistry.put(displayId, votesPerDisplay);
+            }
+            if (vote == null) {
+                votesPerDisplay.remove(priority);
+            } else {
+                votesPerDisplay.put(priority, vote);
+            }
+            if (votesPerDisplay.size() == 0) {
+                mVoteRegistry.remove(displayId);
+            }
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/dreams/DreamOverlayServiceTest.java b/services/tests/servicestests/src/com/android/server/dreams/DreamOverlayServiceTest.java
index 6c73f71..851d8f9 100644
--- a/services/tests/servicestests/src/com/android/server/dreams/DreamOverlayServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/dreams/DreamOverlayServiceTest.java
@@ -18,6 +18,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
@@ -39,10 +41,13 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
+import java.util.concurrent.Executor;
+
 /**
  * A collection of tests to exercise {@link DreamOverlayService}.
  */
@@ -60,6 +65,9 @@
     @Mock
     IDreamOverlayCallback mOverlayCallback;
 
+    @Mock
+    Executor mExecutor;
+
     /**
      * {@link TestDreamOverlayService} is a simple {@link DreamOverlayService} implementation for
      * tracking interactions across {@link IDreamOverlay} binder interface. The service reports
@@ -78,8 +86,8 @@
 
         private final Monitor mMonitor;
 
-        TestDreamOverlayService(Monitor monitor) {
-            super();
+        TestDreamOverlayService(Monitor monitor, Executor executor) {
+            super(executor);
             mMonitor = monitor;
         }
 
@@ -118,13 +126,63 @@
     }
 
     /**
+     * Verifies that callbacks for subclasses are run on the provided executor.
+     */
+    @Test
+    public void testCallbacksRunOnExecutor() throws RemoteException {
+        final TestDreamOverlayService.Monitor monitor = Mockito.mock(
+                TestDreamOverlayService.Monitor.class);
+        final TestDreamOverlayService service = new TestDreamOverlayService(monitor, mExecutor);
+        final IBinder binder = service.onBind(new Intent());
+        final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(binder);
+
+        final IDreamOverlayClient client = getClient(overlay);
+
+        // Start the dream.
+        client.startDream(mLayoutParams, mOverlayCallback,
+                FIRST_DREAM_COMPONENT.flattenToString(), false);
+
+        // The callback should not have run yet.
+        verify(monitor, never()).onStartDream();
+
+        // Run the Runnable sent to the executor.
+        ArgumentCaptor<Runnable> mRunnableCaptor = ArgumentCaptor.forClass(Runnable.class);
+        verify(mExecutor).execute(mRunnableCaptor.capture());
+        mRunnableCaptor.getValue().run();
+
+        // Callback is run.
+        verify(monitor).onStartDream();
+
+        // Verify onWakeUp is run on the executor.
+        client.wakeUp();
+        verify(monitor, never()).onWakeUp();
+        mRunnableCaptor = ArgumentCaptor.forClass(Runnable.class);
+        verify(mExecutor).execute(mRunnableCaptor.capture());
+        mRunnableCaptor.getValue().run();
+        verify(monitor).onWakeUp();
+
+        // Verify onEndDream is run on the executor.
+        client.endDream();
+        verify(monitor, never()).onEndDream();
+        mRunnableCaptor = ArgumentCaptor.forClass(Runnable.class);
+        verify(mExecutor).execute(mRunnableCaptor.capture());
+        mRunnableCaptor.getValue().run();
+        verify(monitor).onEndDream();
+    }
+
+    /**
      * Verifies that only the currently started dream is able to affect the overlay.
      */
     @Test
     public void testOverlayClientInteraction() throws RemoteException {
+        doAnswer(invocation -> {
+            ((Runnable) invocation.getArgument(0)).run();
+            return null;
+        }).when(mExecutor).execute(any());
+
         final TestDreamOverlayService.Monitor monitor = Mockito.mock(
                 TestDreamOverlayService.Monitor.class);
-        final TestDreamOverlayService service = new TestDreamOverlayService(monitor);
+        final TestDreamOverlayService service = new TestDreamOverlayService(monitor, mExecutor);
         final IBinder binder = service.onBind(new Intent());
         final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(binder);
 
diff --git a/services/tests/servicestests/src/com/android/server/dreams/OWNERS b/services/tests/servicestests/src/com/android/server/dreams/OWNERS
new file mode 100644
index 0000000..2f19cf5
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/dreams/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/dreams/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/input/KeyboardLayoutManagerTests.kt b/services/tests/servicestests/src/com/android/server/input/KeyboardLayoutManagerTests.kt
index b2bfd2b..b660926 100644
--- a/services/tests/servicestests/src/com/android/server/input/KeyboardLayoutManagerTests.kt
+++ b/services/tests/servicestests/src/com/android/server/input/KeyboardLayoutManagerTests.kt
@@ -256,12 +256,16 @@
     @Test
     fun testNewUi_getKeyboardLayoutsForInputDevice() {
         NewSettingsApiFlag(true).use {
-            val keyboardLayouts =
-                keyboardLayoutManager.getKeyboardLayoutsForInputDevice(keyboardDevice.identifier)
-            assertEquals(
-                "New UI: getKeyboardLayoutsForInputDevice API should always return empty array",
-                0,
-                keyboardLayouts.size
+            val keyboardLayouts = keyboardLayoutManager.keyboardLayouts
+            assertNotEquals(
+                    "New UI: getKeyboardLayoutsForInputDevice API should not return empty array",
+                    0,
+                    keyboardLayouts.size
+            )
+            assertTrue(
+                    "New UI: getKeyboardLayoutsForInputDevice API should provide English(US) " +
+                            "layout",
+                    hasLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
             )
         }
     }
diff --git a/services/tests/servicestests/src/com/android/server/locales/AppUpdateTrackerTest.java b/services/tests/servicestests/src/com/android/server/locales/AppUpdateTrackerTest.java
deleted file mode 100644
index 2c5d97d..0000000
--- a/services/tests/servicestests/src/com/android/server/locales/AppUpdateTrackerTest.java
+++ /dev/null
@@ -1,190 +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.server.locales;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.Binder;
-import android.os.LocaleList;
-import android.util.ArraySet;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-
-import java.util.Arrays;
-import java.util.Set;
-
-/**
- * Unit tests for {@link AppUpdateTracker}.
- */
-@RunWith(AndroidJUnit4.class)
-public class AppUpdateTrackerTest {
-    private static final String DEFAULT_PACKAGE_NAME = "com.android.myapp";
-    private static final int DEFAULT_UID = Binder.getCallingUid() + 100;
-    private static final int DEFAULT_USER_ID = 0;
-    private static final String DEFAULT_LOCALE_TAGS = "en-XC,ar-XB";
-    private static final LocaleList DEFAULT_LOCALES = LocaleList.forLanguageTags(
-            DEFAULT_LOCALE_TAGS);
-    private AppUpdateTracker mAppUpdateTracker;
-
-    @Mock
-    private Context mMockContext;
-    @Mock
-    private LocaleManagerService mMockLocaleManagerService;
-    @Mock
-    private ShadowLocaleManagerBackupHelper mMockBackupHelper;
-
-    @Before
-    public void setUp() throws Exception {
-        mMockContext = mock(Context.class);
-        mMockLocaleManagerService = mock(LocaleManagerService.class);
-        mMockBackupHelper = mock(ShadowLocaleManagerBackupHelper.class);
-        mAppUpdateTracker = spy(
-                new AppUpdateTracker(mMockContext, mMockLocaleManagerService, mMockBackupHelper));
-    }
-
-    @Test
-    public void testPackageUpgraded_localeEmpty_doNothing() throws Exception {
-        setUpLocalesForPackage(DEFAULT_PACKAGE_NAME, LocaleList.getEmptyLocaleList());
-        setUpPackageNamesForSp(new ArraySet<>(Arrays.asList(DEFAULT_PACKAGE_NAME)));
-        setUpPackageLocaleConfig(null, DEFAULT_PACKAGE_NAME);
-        setUpAppLocalesOptIn(true);
-
-        mAppUpdateTracker.onPackageUpdateFinished(DEFAULT_PACKAGE_NAME, DEFAULT_UID);
-        verifyNoLocalesCleared();
-    }
-
-    @Test
-    public void testPackageUpgraded_pkgNotInSp_doNothing() throws Exception {
-        setUpLocalesForPackage(DEFAULT_PACKAGE_NAME, DEFAULT_LOCALES);
-        String pkgNameA = "com.android.myAppA";
-        String pkgNameB = "com.android.myAppB";
-        setUpPackageNamesForSp(new ArraySet<>(Arrays.asList(pkgNameA, pkgNameB)));
-        setUpPackageLocaleConfig(null, DEFAULT_PACKAGE_NAME);
-        setUpAppLocalesOptIn(true);
-
-        mAppUpdateTracker.onPackageUpdateFinished(DEFAULT_PACKAGE_NAME, DEFAULT_UID);
-        verifyNoLocalesCleared();
-    }
-
-    @Test
-    public void testPackageUpgraded_appLocalesSupported_doNothing() throws Exception {
-        setUpLocalesForPackage(DEFAULT_PACKAGE_NAME, DEFAULT_LOCALES);
-        setUpPackageNamesForSp(new ArraySet<>(Arrays.asList(DEFAULT_PACKAGE_NAME)));
-        setUpPackageLocaleConfig(DEFAULT_LOCALES, DEFAULT_PACKAGE_NAME);
-
-        setUpAppLocalesOptIn(true);
-        mAppUpdateTracker.onPackageUpdateFinished(DEFAULT_PACKAGE_NAME, DEFAULT_UID);
-        verifyNoLocalesCleared();
-
-        setUpAppLocalesOptIn(false);
-        mAppUpdateTracker.onPackageUpdateFinished(DEFAULT_PACKAGE_NAME, DEFAULT_UID);
-        verifyNoLocalesCleared();
-
-        setUpAppLocalesOptIn(false);
-        setUpPackageLocaleConfig(null, DEFAULT_PACKAGE_NAME);
-        mAppUpdateTracker.onPackageUpdateFinished(DEFAULT_PACKAGE_NAME, DEFAULT_UID);
-        verifyNoLocalesCleared();
-    }
-
-    @Test
-    public void testPackageUpgraded_appLocalesNotSupported_clearAppLocale() throws Exception {
-        setUpLocalesForPackage(DEFAULT_PACKAGE_NAME, DEFAULT_LOCALES);
-        setUpPackageNamesForSp(new ArraySet<>(Arrays.asList(DEFAULT_PACKAGE_NAME)));
-        setUpPackageLocaleConfig(null, DEFAULT_PACKAGE_NAME);
-        setUpAppLocalesOptIn(true);
-
-        mAppUpdateTracker.onPackageUpdateFinished(DEFAULT_PACKAGE_NAME, DEFAULT_UID);
-        verify(mMockLocaleManagerService, times(1)).setApplicationLocales(DEFAULT_PACKAGE_NAME,
-                DEFAULT_USER_ID, LocaleList.forLanguageTags(""), false);
-
-        setUpPackageLocaleConfig(LocaleList.getEmptyLocaleList(), DEFAULT_PACKAGE_NAME);
-
-        mAppUpdateTracker.onPackageUpdateFinished(DEFAULT_PACKAGE_NAME, DEFAULT_UID);
-        verify(mMockLocaleManagerService, times(2)).setApplicationLocales(DEFAULT_PACKAGE_NAME,
-                DEFAULT_USER_ID, LocaleList.forLanguageTags(""), false);
-
-        setUpAppLocalesOptIn(false);
-
-        mAppUpdateTracker.onPackageUpdateFinished(DEFAULT_PACKAGE_NAME, DEFAULT_UID);
-        verify(mMockLocaleManagerService, times(3)).setApplicationLocales(DEFAULT_PACKAGE_NAME,
-                DEFAULT_USER_ID, LocaleList.forLanguageTags(""), false);
-    }
-
-    @Test
-    public void testPackageUpgraded_appLocalesNotInLocaleConfig_clearAppLocale() throws Exception {
-        setUpLocalesForPackage(DEFAULT_PACKAGE_NAME, DEFAULT_LOCALES);
-        setUpPackageNamesForSp(new ArraySet<>(Arrays.asList(DEFAULT_PACKAGE_NAME)));
-        setUpPackageLocaleConfig(LocaleList.forLanguageTags("hi,fr"), DEFAULT_PACKAGE_NAME);
-        setUpAppLocalesOptIn(true);
-
-        mAppUpdateTracker.onPackageUpdateFinished(DEFAULT_PACKAGE_NAME, DEFAULT_UID);
-        verify(mMockLocaleManagerService, times(1)).setApplicationLocales(DEFAULT_PACKAGE_NAME,
-                DEFAULT_USER_ID, LocaleList.forLanguageTags(""), false);
-
-        setUpAppLocalesOptIn(false);
-
-        mAppUpdateTracker.onPackageUpdateFinished(DEFAULT_PACKAGE_NAME, DEFAULT_UID);
-        verify(mMockLocaleManagerService, times(2)).setApplicationLocales(DEFAULT_PACKAGE_NAME,
-                DEFAULT_USER_ID, LocaleList.forLanguageTags(""), false);
-    }
-
-    private void setUpLocalesForPackage(String packageName, LocaleList locales) throws Exception {
-        doReturn(locales).when(mMockLocaleManagerService).getApplicationLocales(eq(packageName),
-                anyInt());
-    }
-
-    private void setUpPackageNamesForSp(Set<String> packageNames) {
-        SharedPreferences mockSharedPreference = mock(SharedPreferences.class);
-        doReturn(mockSharedPreference).when(mMockBackupHelper).getPersistedInfo();
-        doReturn(packageNames).when(mockSharedPreference).getStringSet(anyString(), any());
-    }
-
-    private void setUpPackageLocaleConfig(LocaleList locales, String packageName) {
-        doReturn(locales).when(mAppUpdateTracker).getPackageLocales(eq(packageName), anyInt());
-    }
-
-    private void setUpAppLocalesOptIn(boolean optIn) {
-        doReturn(optIn).when(mAppUpdateTracker).isSettingsAppLocalesOptIn();
-    }
-
-    /**
-     * Verifies that no app locales needs to be cleared for any package.
-     *
-     * <p>If {@link LocaleManagerService#setApplicationLocales} is not invoked when receiving the
-     * callback of package upgraded, we can conclude that no app locales needs to be cleared.
-     */
-    private void verifyNoLocalesCleared() throws Exception {
-        verify(mMockLocaleManagerService, times(0)).setApplicationLocales(anyString(), anyInt(),
-                any(), anyBoolean());
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/locales/LocaleManagerBackupRestoreTest.java b/services/tests/servicestests/src/com/android/server/locales/LocaleManagerBackupRestoreTest.java
index 1b8958b..13371cc 100644
--- a/services/tests/servicestests/src/com/android/server/locales/LocaleManagerBackupRestoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/locales/LocaleManagerBackupRestoreTest.java
@@ -142,7 +142,6 @@
         mMockDelegateAppLocalePackages = mock(SharedPreferences.class);
         mMockSpEditor = mock(SharedPreferences.Editor.class);
         SystemAppUpdateTracker systemAppUpdateTracker = mock(SystemAppUpdateTracker.class);
-        AppUpdateTracker appUpdateTracker = mock(AppUpdateTracker.class);
 
         doReturn(mMockPackageManager).when(mMockContext).getPackageManager();
         doReturn(mMockSpEditor).when(mMockDelegateAppLocalePackages).edit();
@@ -158,7 +157,7 @@
 
         mUserMonitor = mBackupHelper.getUserMonitor();
         mPackageMonitor = new LocaleManagerServicePackageMonitor(mBackupHelper,
-            systemAppUpdateTracker, appUpdateTracker, mMockLocaleManagerService);
+            systemAppUpdateTracker, mMockLocaleManagerService);
         setCurrentTimeMillis(DEFAULT_CREATION_TIME_MILLIS);
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/locales/SystemAppUpdateTrackerTest.java b/services/tests/servicestests/src/com/android/server/locales/SystemAppUpdateTrackerTest.java
index 9429462..da9de25 100644
--- a/services/tests/servicestests/src/com/android/server/locales/SystemAppUpdateTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locales/SystemAppUpdateTrackerTest.java
@@ -138,9 +138,8 @@
         mSystemAppUpdateTracker = new SystemAppUpdateTracker(mMockContext,
             mLocaleManagerService, mStoragefile);
 
-        AppUpdateTracker appUpdateTracker = mock(AppUpdateTracker.class);
         mPackageMonitor = new LocaleManagerServicePackageMonitor(mockLocaleManagerBackupHelper,
-                mSystemAppUpdateTracker, appUpdateTracker, mLocaleManagerService);
+                mSystemAppUpdateTracker, mLocaleManagerService);
     }
 
     @After
diff --git a/services/tests/servicestests/src/com/android/server/location/contexthub/ContextHubServiceTest.java b/services/tests/servicestests/src/com/android/server/location/contexthub/ContextHubServiceTest.java
index c0a994b..685e8d6 100644
--- a/services/tests/servicestests/src/com/android/server/location/contexthub/ContextHubServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/location/contexthub/ContextHubServiceTest.java
@@ -18,7 +18,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -75,7 +76,7 @@
 
     @Test
     public void testDump_emptyPreloadedNanoappList() {
-        when(mMockContextHubWrapper.getPreloadedNanoappIds()).thenReturn(null);
+        when(mMockContextHubWrapper.getPreloadedNanoappIds(anyInt())).thenReturn(null);
         StringWriter stringWriter = new StringWriter();
 
         ContextHubService service = new ContextHubService(mContext, mMockContextHubWrapper);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
index c9612cd..ad63da5 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
@@ -39,6 +39,7 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
+import android.content.res.Resources;
 import android.hardware.authsecret.IAuthSecret;
 import android.hardware.face.FaceManager;
 import android.hardware.fingerprint.FingerprintManager;
@@ -97,6 +98,7 @@
     MockLockSettingsContext mContext;
     LockSettingsStorageTestable mStorage;
 
+    Resources mResources;
     FakeGateKeeperService mGateKeeperService;
     NotificationManager mNotificationManager;
     UserManager mUserManager;
@@ -122,6 +124,7 @@
 
     @Before
     public void setUp_baseServices() throws Exception {
+        mResources = createMockResources();
         mGateKeeperService = new FakeGateKeeperService();
         mNotificationManager = mock(NotificationManager.class);
         mUserManager = mock(UserManager.class);
@@ -146,7 +149,7 @@
         LocalServices.addService(WindowManagerInternal.class, mMockWindowManager);
 
         final Context origContext = InstrumentationRegistry.getContext();
-        mContext = new MockLockSettingsContext(origContext,
+        mContext = new MockLockSettingsContext(origContext, mResources,
                 mSettingsRule.mockContentResolver(origContext), mUserManager, mNotificationManager,
                 mDevicePolicyManager, mock(StorageManager.class), mock(TrustManager.class),
                 mock(KeyguardManager.class), mFingerprintManager, mFaceManager, mPackageManager);
@@ -245,6 +248,22 @@
         mLocalService = LocalServices.getService(LockSettingsInternal.class);
     }
 
+    private Resources createMockResources() {
+        Resources res = mock(Resources.class);
+
+        // Set up some default configs, copied from core/res/res/values/config.xml
+        when(res.getBoolean(eq(com.android.internal.R.bool.config_disableLockscreenByDefault)))
+                .thenReturn(false);
+        when(res.getBoolean(
+                eq(com.android.internal.R.bool.config_enableCredentialFactoryResetProtection)))
+                .thenReturn(true);
+        when(res.getBoolean(eq(com.android.internal.R.bool.config_isMainUserPermanentAdmin)))
+                .thenReturn(true);
+        when(res.getBoolean(eq(com.android.internal.R.bool.config_strongAuthRequiredOnBoot)))
+                .thenReturn(true);
+        return res;
+    }
+
     protected void setDeviceProvisioned(boolean provisioned) {
         Settings.Global.putInt(mContext.getContentResolver(),
                 Settings.Global.DEVICE_PROVISIONED, provisioned ? 1 : 0);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
index 05208441e..10ed882 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
@@ -34,6 +34,7 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
+import android.content.res.Resources;
 import android.database.sqlite.SQLiteDatabase;
 import android.hardware.face.FaceManager;
 import android.hardware.fingerprint.FingerprintManager;
@@ -106,8 +107,8 @@
         when(mockUserManager.getProfileParent(eq(3))).thenReturn(new UserInfo(0, "name", 0));
 
         MockLockSettingsContext context = new MockLockSettingsContext(origContext,
-                mSettingsRule.mockContentResolver(origContext), mockUserManager,
-                mock(NotificationManager.class), mock(DevicePolicyManager.class),
+                mock(Resources.class), mSettingsRule.mockContentResolver(origContext),
+                mockUserManager, mock(NotificationManager.class), mock(DevicePolicyManager.class),
                 mock(StorageManager.class), mock(TrustManager.class), mock(KeyguardManager.class),
                 mock(FingerprintManager.class), mock(FaceManager.class),
                 mock(PackageManager.class));
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/MockLockSettingsContext.java b/services/tests/servicestests/src/com/android/server/locksettings/MockLockSettingsContext.java
index 21c367b..96d7cbe 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/MockLockSettingsContext.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/MockLockSettingsContext.java
@@ -27,6 +27,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
+import android.content.res.Resources;
 import android.hardware.face.FaceManager;
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.Handler;
@@ -36,6 +37,7 @@
 
 public class MockLockSettingsContext extends ContextWrapper {
 
+    private final Resources mResources;
     private final ContentResolver mContentResolver;
     private final UserManager mUserManager;
     private final NotificationManager mNotificationManager;
@@ -47,13 +49,14 @@
     private final FaceManager mFaceManager;
     private final PackageManager mPackageManager;
 
-    public MockLockSettingsContext(Context base, ContentResolver contentResolver,
-            UserManager userManager, NotificationManager notificationManager,
-            DevicePolicyManager devicePolicyManager, StorageManager storageManager,
-            TrustManager trustManager, KeyguardManager keyguardManager,
-            FingerprintManager fingerprintManager, FaceManager faceManager,
-            PackageManager packageManager) {
+    public MockLockSettingsContext(Context base, Resources resources,
+            ContentResolver contentResolver, UserManager userManager,
+            NotificationManager notificationManager, DevicePolicyManager devicePolicyManager,
+            StorageManager storageManager, TrustManager trustManager,
+            KeyguardManager keyguardManager, FingerprintManager fingerprintManager,
+            FaceManager faceManager, PackageManager packageManager) {
         super(base);
+        mResources = resources;
         mContentResolver = contentResolver;
         mUserManager = userManager;
         mNotificationManager = notificationManager;
@@ -67,6 +70,11 @@
     }
 
     @Override
+    public Resources getResources() {
+        return mResources;
+    }
+
+    @Override
     public ContentResolver getContentResolver() {
         return mContentResolver;
     }
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java
index d9d0715..64e6236 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java
@@ -74,6 +74,8 @@
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
 
 import javax.crypto.SecretKey;
@@ -324,16 +326,30 @@
         mInjected = mock(MockableRebootEscrowInjected.class);
         mMockInjector = new MockInjector(mContext, mUserManager, mRebootEscrow,
                 mKeyStoreManager, mStorage, mInjected);
-        mService = new RebootEscrowManager(mMockInjector, mCallbacks, mStorage);
         HandlerThread thread = new HandlerThread("RebootEscrowManagerTest");
         thread.start();
         mHandler = new Handler(thread.getLooper());
+        mService = new RebootEscrowManager(mMockInjector, mCallbacks, mStorage, mHandler);
+
     }
 
     private void setServerBasedRebootEscrowProvider() throws Exception {
         mMockInjector = new MockInjector(mContext, mUserManager, mServiceConnection,
                 mKeyStoreManager, mStorage, mInjected);
-        mService = new RebootEscrowManager(mMockInjector, mCallbacks, mStorage);
+        mService = new RebootEscrowManager(mMockInjector, mCallbacks, mStorage, mHandler);
+    }
+
+    private void waitForHandler() throws InterruptedException {
+        // Wait for handler to complete processing.
+        CountDownLatch latch = new CountDownLatch(1);
+        mHandler.post(latch::countDown);
+        assertTrue(latch.await(5, TimeUnit.SECONDS));
+
+    }
+
+    private void callToRebootEscrowIfNeededAndWait(int userId) throws InterruptedException {
+        mService.callToRebootEscrowIfNeeded(userId, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        waitForHandler();
     }
 
     @Test
@@ -343,7 +359,7 @@
         mService.prepareRebootEscrow();
 
         clearInvocations(mRebootEscrow);
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
         verify(mRebootEscrow, never()).storeKey(any());
     }
@@ -355,8 +371,7 @@
         mService.setRebootEscrowListener(mockListener);
         mService.prepareRebootEscrow();
 
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
-        verify(mockListener).onPreparedForReboot(eq(true));
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
         assertFalse(mStorage.hasRebootEscrowServerBlob());
     }
@@ -366,7 +381,7 @@
         RebootEscrowListener mockListener = mock(RebootEscrowListener.class);
         mService.setRebootEscrowListener(mockListener);
         mService.prepareRebootEscrow();
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
 
         clearInvocations(mRebootEscrow);
@@ -390,7 +405,7 @@
         mService.prepareRebootEscrow();
 
         clearInvocations(mRebootEscrow);
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
         verify(mRebootEscrow, never()).storeKey(any());
 
@@ -414,7 +429,7 @@
         mService.prepareRebootEscrow();
 
         clearInvocations(mServiceConnection);
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
         verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
 
@@ -435,7 +450,7 @@
         mService.prepareRebootEscrow();
 
         clearInvocations(mRebootEscrow);
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
         verify(mRebootEscrow, never()).storeKey(any());
 
@@ -453,10 +468,9 @@
         mService.prepareRebootEscrow();
 
         clearInvocations(mRebootEscrow);
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
-        mService.callToRebootEscrowIfNeeded(SECURE_SECONDARY_USER_ID, FAKE_SP_VERSION,
-                FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(SECURE_SECONDARY_USER_ID);
         verify(mRebootEscrow, never()).storeKey(any());
 
         assertTrue(mStorage.hasRebootEscrow(PRIMARY_USER_ID));
@@ -488,7 +502,7 @@
         mService.prepareRebootEscrow();
 
         clearInvocations(mRebootEscrow);
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
         verify(mRebootEscrow, never()).storeKey(any());
 
@@ -511,7 +525,7 @@
         mService.prepareRebootEscrow();
 
         clearInvocations(mRebootEscrow);
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
 
         verify(mRebootEscrow, never()).storeKey(any());
@@ -554,7 +568,7 @@
         mService.prepareRebootEscrow();
 
         clearInvocations(mServiceConnection);
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
         verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
 
@@ -598,7 +612,7 @@
         mService.prepareRebootEscrow();
 
         clearInvocations(mServiceConnection);
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
         verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
 
@@ -643,7 +657,7 @@
         mService.prepareRebootEscrow();
 
         clearInvocations(mServiceConnection);
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
         verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
 
@@ -689,7 +703,7 @@
         mService.prepareRebootEscrow();
 
         clearInvocations(mServiceConnection);
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
         verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
 
@@ -738,7 +752,7 @@
         mService.prepareRebootEscrow();
 
         clearInvocations(mServiceConnection);
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
         verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
 
@@ -791,7 +805,7 @@
         mService.prepareRebootEscrow();
 
         clearInvocations(mServiceConnection);
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
         verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
 
@@ -846,7 +860,7 @@
         mService.prepareRebootEscrow();
 
         clearInvocations(mServiceConnection);
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
         verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
 
@@ -893,7 +907,7 @@
         mService.prepareRebootEscrow();
 
         clearInvocations(mServiceConnection);
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
         verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
 
@@ -949,7 +963,7 @@
         mService.prepareRebootEscrow();
 
         clearInvocations(mServiceConnection);
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
         verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
 
@@ -1008,7 +1022,7 @@
         mService.prepareRebootEscrow();
 
         clearInvocations(mServiceConnection);
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
         verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
 
@@ -1068,7 +1082,7 @@
         mService.prepareRebootEscrow();
 
         clearInvocations(mServiceConnection);
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
         verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
 
@@ -1124,7 +1138,7 @@
         mService.prepareRebootEscrow();
 
         clearInvocations(mServiceConnection);
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
         verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
 
@@ -1176,7 +1190,7 @@
         mService.prepareRebootEscrow();
 
         clearInvocations(mRebootEscrow);
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
 
         verify(mRebootEscrow, never()).storeKey(any());
@@ -1207,7 +1221,7 @@
         mService.prepareRebootEscrow();
 
         clearInvocations(mRebootEscrow);
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
 
         verify(mRebootEscrow, never()).storeKey(any());
@@ -1235,7 +1249,7 @@
         mService.prepareRebootEscrow();
 
         clearInvocations(mRebootEscrow);
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
 
         verify(mRebootEscrow, never()).storeKey(any());
@@ -1274,7 +1288,7 @@
         mService.prepareRebootEscrow();
 
         clearInvocations(mRebootEscrow);
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
 
         verify(mRebootEscrow, never()).storeKey(any());
@@ -1309,7 +1323,7 @@
         mService.prepareRebootEscrow();
 
         clearInvocations(mRebootEscrow);
-        mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+        callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
         verify(mockListener).onPreparedForReboot(eq(true));
         assertTrue(mStorage.hasRebootEscrow(PRIMARY_USER_ID));
         verify(mRebootEscrow, never()).storeKey(any());
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
index 2affe92..8b178dd 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
@@ -41,7 +41,7 @@
 import android.app.KeyguardManager;
 import android.app.PendingIntent;
 import android.app.RemoteLockscreenValidationResult;
-import android.app.StartLockscreenValidationRequest;
+import android.app.RemoteLockscreenValidationSession;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Binder;
@@ -1326,11 +1326,10 @@
         when(mLockSettingsService.getCredentialType(anyInt())).thenReturn(
                 LockPatternUtils.CREDENTIAL_TYPE_PIN);
 
-        StartLockscreenValidationRequest request =
+        RemoteLockscreenValidationSession request =
                 mRecoverableKeyStoreManager.startRemoteLockscreenValidation(mLockSettingsService);
 
-        int credetialsType = request.getLockscreenUiType();
-        assertThat(credetialsType).isEqualTo(KeyguardManager.PIN);
+        assertThat(request.getLockType()).isEqualTo(KeyguardManager.PIN);
         assertThat(request.getRemainingAttempts()).isEqualTo(5);
         verify(mLockSettingsService).getCredentialType(anyInt());
     }
@@ -1340,11 +1339,10 @@
                 LockPatternUtils.CREDENTIAL_TYPE_PATTERN);
         mRecoverableKeyStoreDb.setBadRemoteGuessCounter(mUserId, 3);
 
-        StartLockscreenValidationRequest request =
+        RemoteLockscreenValidationSession request =
                 mRecoverableKeyStoreManager.startRemoteLockscreenValidation(mLockSettingsService);
 
-        int credetialsType = request.getLockscreenUiType();
-        assertThat(credetialsType).isEqualTo(KeyguardManager.PATTERN);
+        assertThat(request.getLockType()).isEqualTo(KeyguardManager.PATTERN);
         assertThat(request.getRemainingAttempts()).isEqualTo(2);
     }
     @Test
@@ -1353,24 +1351,23 @@
                 LockPatternUtils.CREDENTIAL_TYPE_PASSWORD);
         mRecoverableKeyStoreDb.setBadRemoteGuessCounter(mUserId, 7);
 
-        StartLockscreenValidationRequest request =
+        RemoteLockscreenValidationSession request =
                 mRecoverableKeyStoreManager.startRemoteLockscreenValidation(mLockSettingsService);
 
-        int credetialsType = request.getLockscreenUiType();
         assertThat(request.getRemainingAttempts()).isEqualTo(0);
-        assertThat(credetialsType).isEqualTo(KeyguardManager.PASSWORD);
+        assertThat(request.getLockType()).isEqualTo(KeyguardManager.PASSWORD);
     }
     @Test
     public void validateRemoteLockscreen_noActiveSession() throws Exception {
         when(mLockSettingsService.getCredentialType(anyInt())).thenReturn(
-                LockPatternUtils.CREDENTIAL_TYPE_NONE);
-        try {
-            mRecoverableKeyStoreManager.validateRemoteLockscreen(INVALID_GUESS,
-                    mLockSettingsService);
-            fail("should have thrown");
-        } catch (IllegalStateException e) {
-            assertThat(e.getMessage()).contains("session");
-        }
+                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD);
+
+        RemoteLockscreenValidationResult result =
+                mRecoverableKeyStoreManager.validateRemoteLockscreen(INVALID_GUESS,
+                        mLockSettingsService);
+
+        assertThat(result.getResultCode()).isEqualTo(
+                RemoteLockscreenValidationResult.RESULT_SESSION_EXPIRED);
     }
     @Test
     public void validateRemoteLockscreen_decryptionError() throws Exception {
@@ -1456,7 +1453,7 @@
     }
 
     private byte[] encryptCredentialsForNewSession(byte[] credentials) throws Exception {
-        StartLockscreenValidationRequest request =
+        RemoteLockscreenValidationSession request =
                 mRecoverableKeyStoreManager.startRemoteLockscreenValidation(mLockSettingsService);
         PublicKey publicKey = SecureBox.decodePublicKey(request.getSourcePublicKey());
         return SecureBox.encrypt(
diff --git a/services/tests/servicestests/src/com/android/server/media/AudioPoliciesDeviceRouteControllerTest.java b/services/tests/servicestests/src/com/android/server/media/AudioPoliciesDeviceRouteControllerTest.java
new file mode 100644
index 0000000..1e73a45
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/media/AudioPoliciesDeviceRouteControllerTest.java
@@ -0,0 +1,247 @@
+/*
+ * 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.media;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.media.AudioManager;
+import android.media.AudioRoutesInfo;
+import android.media.IAudioRoutesObserver;
+import android.media.MediaRoute2Info;
+import android.os.RemoteException;
+
+import com.android.internal.R;
+import com.android.server.audio.AudioService;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(JUnit4.class)
+public class AudioPoliciesDeviceRouteControllerTest {
+
+    private static final String ROUTE_NAME_DEFAULT = "default";
+    private static final String ROUTE_NAME_DOCK = "dock";
+    private static final String ROUTE_NAME_HEADPHONES = "headphones";
+
+    private static final int VOLUME_SAMPLE_1 = 25;
+
+    @Mock
+    private Context mContext;
+    @Mock
+    private Resources mResources;
+    @Mock
+    private AudioManager mAudioManager;
+    @Mock
+    private AudioService mAudioService;
+    @Mock
+    private DeviceRouteController.OnDeviceRouteChangedListener mOnDeviceRouteChangedListener;
+
+    @Captor
+    private ArgumentCaptor<IAudioRoutesObserver.Stub> mAudioRoutesObserverCaptor;
+
+    private AudioPoliciesDeviceRouteController mController;
+
+    private IAudioRoutesObserver.Stub mAudioRoutesObserver;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        when(mContext.getResources()).thenReturn(mResources);
+        when(mResources.getText(anyInt())).thenReturn(ROUTE_NAME_DEFAULT);
+
+        // Setting built-in speaker as default speaker.
+        AudioRoutesInfo audioRoutesInfo = new AudioRoutesInfo();
+        audioRoutesInfo.mainType = AudioRoutesInfo.MAIN_SPEAKER;
+        when(mAudioService.startWatchingRoutes(mAudioRoutesObserverCaptor.capture()))
+                .thenReturn(audioRoutesInfo);
+
+        mController = new AudioPoliciesDeviceRouteController(
+                mContext, mAudioManager, mAudioService, mOnDeviceRouteChangedListener);
+
+        mAudioRoutesObserver = mAudioRoutesObserverCaptor.getValue();
+    }
+
+    @Test
+    public void getDeviceRoute_noSelectedRoutes_returnsDefaultDevice() {
+        MediaRoute2Info route2Info = mController.getDeviceRoute();
+
+        assertThat(route2Info.getName()).isEqualTo(ROUTE_NAME_DEFAULT);
+        assertThat(route2Info.getType()).isEqualTo(MediaRoute2Info.TYPE_BUILTIN_SPEAKER);
+    }
+
+    @Test
+    public void getDeviceRoute_audioRouteHasChanged_returnsRouteFromAudioService() {
+        when(mResources.getText(R.string.default_audio_route_name_headphones))
+                .thenReturn(ROUTE_NAME_HEADPHONES);
+
+        AudioRoutesInfo audioRoutesInfo = new AudioRoutesInfo();
+        audioRoutesInfo.mainType = AudioRoutesInfo.MAIN_HEADPHONES;
+        callAudioRoutesObserver(audioRoutesInfo);
+
+        MediaRoute2Info route2Info = mController.getDeviceRoute();
+        assertThat(route2Info.getName()).isEqualTo(ROUTE_NAME_HEADPHONES);
+        assertThat(route2Info.getType()).isEqualTo(MediaRoute2Info.TYPE_WIRED_HEADPHONES);
+    }
+
+    @Test
+    public void getDeviceRoute_selectDevice_returnsSelectedRoute() {
+        when(mResources.getText(R.string.default_audio_route_name_dock_speakers))
+                .thenReturn(ROUTE_NAME_DOCK);
+
+        mController.selectRoute(MediaRoute2Info.TYPE_DOCK);
+
+        MediaRoute2Info route2Info = mController.getDeviceRoute();
+        assertThat(route2Info.getName()).isEqualTo(ROUTE_NAME_DOCK);
+        assertThat(route2Info.getType()).isEqualTo(MediaRoute2Info.TYPE_DOCK);
+    }
+
+    @Test
+    public void getDeviceRoute_hasSelectedAndAudioServiceRoutes_returnsSelectedRoute() {
+        when(mResources.getText(R.string.default_audio_route_name_headphones))
+                .thenReturn(ROUTE_NAME_HEADPHONES);
+        when(mResources.getText(R.string.default_audio_route_name_dock_speakers))
+                .thenReturn(ROUTE_NAME_DOCK);
+
+        AudioRoutesInfo audioRoutesInfo = new AudioRoutesInfo();
+        audioRoutesInfo.mainType = AudioRoutesInfo.MAIN_HEADPHONES;
+        callAudioRoutesObserver(audioRoutesInfo);
+
+        mController.selectRoute(MediaRoute2Info.TYPE_DOCK);
+
+        MediaRoute2Info route2Info = mController.getDeviceRoute();
+        assertThat(route2Info.getName()).isEqualTo(ROUTE_NAME_DOCK);
+        assertThat(route2Info.getType()).isEqualTo(MediaRoute2Info.TYPE_DOCK);
+    }
+
+    @Test
+    public void getDeviceRoute_unselectRoute_returnsAudioServiceRoute() {
+        when(mResources.getText(R.string.default_audio_route_name_headphones))
+                .thenReturn(ROUTE_NAME_HEADPHONES);
+        when(mResources.getText(R.string.default_audio_route_name_dock_speakers))
+                .thenReturn(ROUTE_NAME_DOCK);
+
+        mController.selectRoute(MediaRoute2Info.TYPE_DOCK);
+
+        AudioRoutesInfo audioRoutesInfo = new AudioRoutesInfo();
+        audioRoutesInfo.mainType = AudioRoutesInfo.MAIN_HEADPHONES;
+        callAudioRoutesObserver(audioRoutesInfo);
+
+        mController.selectRoute(null);
+
+        MediaRoute2Info route2Info = mController.getDeviceRoute();
+        assertThat(route2Info.getName()).isEqualTo(ROUTE_NAME_HEADPHONES);
+        assertThat(route2Info.getType()).isEqualTo(MediaRoute2Info.TYPE_WIRED_HEADPHONES);
+    }
+
+    @Test
+    public void getDeviceRoute_selectRouteFails_returnsAudioServiceRoute() {
+        when(mResources.getText(R.string.default_audio_route_name_headphones))
+                .thenReturn(ROUTE_NAME_HEADPHONES);
+
+        AudioRoutesInfo audioRoutesInfo = new AudioRoutesInfo();
+        audioRoutesInfo.mainType = AudioRoutesInfo.MAIN_HEADPHONES;
+        callAudioRoutesObserver(audioRoutesInfo);
+
+        mController.selectRoute(MediaRoute2Info.TYPE_BLUETOOTH_A2DP);
+
+        MediaRoute2Info route2Info = mController.getDeviceRoute();
+        assertThat(route2Info.getName()).isEqualTo(ROUTE_NAME_HEADPHONES);
+        assertThat(route2Info.getType()).isEqualTo(MediaRoute2Info.TYPE_WIRED_HEADPHONES);
+    }
+
+    @Test
+    public void selectRoute_selectWiredRoute_returnsTrue() {
+        assertThat(mController.selectRoute(MediaRoute2Info.TYPE_HDMI)).isTrue();
+    }
+
+    @Test
+    public void selectRoute_selectBluetoothRoute_returnsFalse() {
+        assertThat(mController.selectRoute(MediaRoute2Info.TYPE_BLUETOOTH_A2DP)).isFalse();
+    }
+
+    @Test
+    public void selectRoute_unselectRoute_returnsTrue() {
+        assertThat(mController.selectRoute(null)).isTrue();
+    }
+
+    @Test
+    public void updateVolume_noSelectedRoute_deviceRouteVolumeChanged() {
+        when(mResources.getText(R.string.default_audio_route_name_headphones))
+                .thenReturn(ROUTE_NAME_HEADPHONES);
+
+        AudioRoutesInfo audioRoutesInfo = new AudioRoutesInfo();
+        audioRoutesInfo.mainType = AudioRoutesInfo.MAIN_HEADPHONES;
+        callAudioRoutesObserver(audioRoutesInfo);
+
+        mController.updateVolume(VOLUME_SAMPLE_1);
+
+        MediaRoute2Info route2Info = mController.getDeviceRoute();
+        assertThat(route2Info.getType()).isEqualTo(MediaRoute2Info.TYPE_WIRED_HEADPHONES);
+        assertThat(route2Info.getVolume()).isEqualTo(VOLUME_SAMPLE_1);
+    }
+
+    @Test
+    public void updateVolume_connectSelectedRouteLater_selectedRouteVolumeChanged() {
+        when(mResources.getText(R.string.default_audio_route_name_headphones))
+                .thenReturn(ROUTE_NAME_HEADPHONES);
+        when(mResources.getText(R.string.default_audio_route_name_dock_speakers))
+                .thenReturn(ROUTE_NAME_DOCK);
+
+        AudioRoutesInfo audioRoutesInfo = new AudioRoutesInfo();
+        audioRoutesInfo.mainType = AudioRoutesInfo.MAIN_HEADPHONES;
+        callAudioRoutesObserver(audioRoutesInfo);
+
+        mController.updateVolume(VOLUME_SAMPLE_1);
+
+        mController.selectRoute(MediaRoute2Info.TYPE_DOCK);
+
+        MediaRoute2Info route2Info = mController.getDeviceRoute();
+        assertThat(route2Info.getType()).isEqualTo(MediaRoute2Info.TYPE_DOCK);
+        assertThat(route2Info.getVolume()).isEqualTo(VOLUME_SAMPLE_1);
+    }
+
+    /**
+     * Simulates {@link IAudioRoutesObserver.Stub#dispatchAudioRoutesChanged(AudioRoutesInfo)}
+     * from {@link AudioService}. This happens when there is a wired route change,
+     * like a wired headset being connected.
+     *
+     * @param audioRoutesInfo updated state of connected wired device
+     */
+    private void callAudioRoutesObserver(AudioRoutesInfo audioRoutesInfo) {
+        try {
+            // this is a captured observer implementation
+            // from WiredRoutesController's AudioService#startWatchingRoutes call
+            mAudioRoutesObserver.dispatchAudioRoutesChanged(audioRoutesInfo);
+        } catch (RemoteException exception) {
+            // Should not happen since the object is mocked.
+            assertWithMessage("An unexpected RemoteException happened.").fail();
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/media/LegacyDeviceRouteControllerTest.java b/services/tests/servicestests/src/com/android/server/media/LegacyDeviceRouteControllerTest.java
new file mode 100644
index 0000000..24e4851
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/media/LegacyDeviceRouteControllerTest.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.server.media;
+
+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.Mockito.when;
+
+import android.annotation.IdRes;
+import android.content.Context;
+import android.content.res.Resources;
+import android.media.AudioManager;
+import android.media.AudioRoutesInfo;
+import android.media.IAudioRoutesObserver;
+import android.media.MediaRoute2Info;
+import android.os.RemoteException;
+import android.text.TextUtils;
+
+import com.android.internal.R;
+import com.android.server.audio.AudioService;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.junit.runners.Parameterized;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+@RunWith(Enclosed.class)
+public class LegacyDeviceRouteControllerTest {
+
+    private static final String DEFAULT_ROUTE_NAME = "default_route";
+    private static final String DEFAULT_HEADPHONES_NAME = "headphone";
+    private static final String DEFAULT_HEADSET_NAME = "headset";
+    private static final String DEFAULT_DOCK_NAME = "dock";
+    private static final String DEFAULT_HDMI_NAME = "hdmi";
+    private static final String DEFAULT_USB_NAME = "usb";
+    private static final int VOLUME_DEFAULT_VALUE = 0;
+    private static final int VOLUME_VALUE_SAMPLE_1 = 10;
+
+    private static AudioRoutesInfo createFakeBluetoothAudioRoute() {
+        AudioRoutesInfo btRouteInfo = new AudioRoutesInfo();
+        btRouteInfo.mainType = AudioRoutesInfo.MAIN_SPEAKER;
+        btRouteInfo.bluetoothName = "bt_device";
+        return btRouteInfo;
+    }
+
+    @RunWith(JUnit4.class)
+    public static class DefaultDeviceRouteValueTest {
+        @Mock
+        private Context mContext;
+        @Mock
+        private Resources mResources;
+        @Mock
+        private AudioManager mAudioManager;
+        @Mock
+        private AudioService mAudioService;
+        @Mock
+        private DeviceRouteController.OnDeviceRouteChangedListener mOnDeviceRouteChangedListener;
+
+        @Before
+        public void setUp() {
+            MockitoAnnotations.initMocks(this);
+
+            when(mContext.getResources()).thenReturn(mResources);
+        }
+
+        @Test
+        public void initialize_noRoutesInfo_defaultRouteIsNotNull() {
+            // Mocking default_audio_route_name.
+            when(mResources.getText(R.string.default_audio_route_name))
+                    .thenReturn(DEFAULT_ROUTE_NAME);
+
+            // Default route should be initialized even when AudioService returns null.
+            when(mAudioService.startWatchingRoutes(any())).thenReturn(null);
+
+            LegacyDeviceRouteController deviceRouteController = new LegacyDeviceRouteController(
+                    mContext,
+                    mAudioManager,
+                    mAudioService,
+                    mOnDeviceRouteChangedListener
+            );
+
+            MediaRoute2Info actualMediaRoute = deviceRouteController.getDeviceRoute();
+
+            assertThat(actualMediaRoute.getType()).isEqualTo(MediaRoute2Info.TYPE_BUILTIN_SPEAKER);
+            assertThat(TextUtils.equals(actualMediaRoute.getName(), DEFAULT_ROUTE_NAME))
+                    .isTrue();
+            assertThat(actualMediaRoute.getVolume()).isEqualTo(VOLUME_DEFAULT_VALUE);
+        }
+
+        @Test
+        public void initialize_bluetoothRouteAvailable_deviceRouteReturnsDefaultRoute() {
+            // Mocking default_audio_route_name.
+            when(mResources.getText(R.string.default_audio_route_name))
+                    .thenReturn(DEFAULT_ROUTE_NAME);
+
+            // This route should be ignored.
+            AudioRoutesInfo fakeBluetoothAudioRoute = createFakeBluetoothAudioRoute();
+            when(mAudioService.startWatchingRoutes(any())).thenReturn(fakeBluetoothAudioRoute);
+
+            LegacyDeviceRouteController deviceRouteController = new LegacyDeviceRouteController(
+                    mContext,
+                    mAudioManager,
+                    mAudioService,
+                    mOnDeviceRouteChangedListener
+            );
+
+            MediaRoute2Info actualMediaRoute = deviceRouteController.getDeviceRoute();
+
+            assertThat(actualMediaRoute.getType()).isEqualTo(MediaRoute2Info.TYPE_BUILTIN_SPEAKER);
+            assertThat(TextUtils.equals(actualMediaRoute.getName(), DEFAULT_ROUTE_NAME))
+                    .isTrue();
+            assertThat(actualMediaRoute.getVolume()).isEqualTo(VOLUME_DEFAULT_VALUE);
+        }
+    }
+
+    @RunWith(Parameterized.class)
+    public static class DeviceRouteInitializationTest {
+
+        @Parameterized.Parameters
+        public static Collection<Object[]> data() {
+            return Arrays.asList(new Object[][] {
+                    {     /* expected res */
+                          com.android.internal.R.string.default_audio_route_name_headphones,
+                          /* expected name */
+                          DEFAULT_HEADPHONES_NAME,
+                          /* expected type */
+                          MediaRoute2Info.TYPE_WIRED_HEADPHONES,
+                          /* actual audio route type */
+                          AudioRoutesInfo.MAIN_HEADPHONES },
+                    {   /* expected res */
+                        com.android.internal.R.string.default_audio_route_name_headphones,
+                        /* expected name */
+                        DEFAULT_HEADSET_NAME,
+                        /* expected type */
+                        MediaRoute2Info.TYPE_WIRED_HEADSET,
+                        /* actual audio route type */
+                        AudioRoutesInfo.MAIN_HEADSET },
+                    {    /* expected res */
+                        R.string.default_audio_route_name_dock_speakers,
+                        /* expected name */
+                        DEFAULT_DOCK_NAME,
+                        /* expected type */
+                        MediaRoute2Info.TYPE_DOCK,
+                        /* actual audio route type */
+                        AudioRoutesInfo.MAIN_DOCK_SPEAKERS },
+                    {   /* expected res */
+                        R.string.default_audio_route_name_external_device,
+                        /* expected name */
+                        DEFAULT_HDMI_NAME,
+                        /* expected type */
+                        MediaRoute2Info.TYPE_HDMI,
+                        /* actual audio route type */
+                        AudioRoutesInfo.MAIN_HDMI },
+                    {   /* expected res */
+                        R.string.default_audio_route_name_usb,
+                        /* expected name */
+                        DEFAULT_USB_NAME,
+                        /* expected type */
+                        MediaRoute2Info.TYPE_USB_DEVICE,
+                        /* actual audio route type */
+                        AudioRoutesInfo.MAIN_USB }
+            });
+        }
+
+        @Mock
+        private Context mContext;
+        @Mock
+        private Resources mResources;
+        @Mock
+        private AudioManager mAudioManager;
+        @Mock
+        private AudioService mAudioService;
+        @Mock
+        private DeviceRouteController.OnDeviceRouteChangedListener mOnDeviceRouteChangedListener;
+
+        @IdRes
+        private final int mExpectedRouteNameResource;
+        private final String mExpectedRouteNameValue;
+        private final int mExpectedRouteType;
+        private final int mActualAudioRouteType;
+
+        public DeviceRouteInitializationTest(int expectedRouteNameResource,
+                String expectedRouteNameValue,
+                int expectedMediaRouteType,
+                int actualAudioRouteType) {
+            this.mExpectedRouteNameResource = expectedRouteNameResource;
+            this.mExpectedRouteNameValue = expectedRouteNameValue;
+            this.mExpectedRouteType = expectedMediaRouteType;
+            this.mActualAudioRouteType = actualAudioRouteType;
+        }
+
+        @Before
+        public void setUp() {
+            MockitoAnnotations.initMocks(this);
+
+            when(mContext.getResources()).thenReturn(mResources);
+        }
+
+        @Test
+        public void initialize_wiredRouteAvailable_deviceRouteReturnsWiredRoute() {
+            // Mocking default_audio_route_name.
+            when(mResources.getText(R.string.default_audio_route_name))
+                    .thenReturn(DEFAULT_ROUTE_NAME);
+
+            // At first, WiredRouteController should initialize device
+            // route based on AudioService response.
+            AudioRoutesInfo audioRoutesInfo = new AudioRoutesInfo();
+            audioRoutesInfo.mainType = mActualAudioRouteType;
+            when(mAudioService.startWatchingRoutes(any())).thenReturn(audioRoutesInfo);
+
+            when(mResources.getText(mExpectedRouteNameResource))
+                    .thenReturn(mExpectedRouteNameValue);
+
+            LegacyDeviceRouteController deviceRouteController = new LegacyDeviceRouteController(
+                    mContext,
+                    mAudioManager,
+                    mAudioService,
+                    mOnDeviceRouteChangedListener
+            );
+
+            MediaRoute2Info actualMediaRoute = deviceRouteController.getDeviceRoute();
+
+            assertThat(actualMediaRoute.getType()).isEqualTo(mExpectedRouteType);
+            assertThat(TextUtils.equals(actualMediaRoute.getName(), mExpectedRouteNameValue))
+                    .isTrue();
+            // Volume did not change, so it should be set to default value (0).
+            assertThat(actualMediaRoute.getVolume()).isEqualTo(VOLUME_DEFAULT_VALUE);
+        }
+    }
+
+    @RunWith(JUnit4.class)
+    public static class VolumeAndDeviceRoutesChangesTest {
+        @Mock
+        private Context mContext;
+        @Mock
+        private Resources mResources;
+        @Mock
+        private AudioManager mAudioManager;
+        @Mock
+        private AudioService mAudioService;
+        @Mock
+        private DeviceRouteController.OnDeviceRouteChangedListener mOnDeviceRouteChangedListener;
+
+        @Captor
+        private ArgumentCaptor<IAudioRoutesObserver.Stub> mAudioRoutesObserverCaptor;
+
+        private LegacyDeviceRouteController mDeviceRouteController;
+        private IAudioRoutesObserver.Stub mAudioRoutesObserver;
+
+        @Before
+        public void setUp() {
+            MockitoAnnotations.initMocks(this);
+
+            when(mContext.getResources()).thenReturn(mResources);
+
+            when(mResources.getText(R.string.default_audio_route_name))
+                    .thenReturn(DEFAULT_ROUTE_NAME);
+
+            // Setting built-in speaker as default speaker.
+            AudioRoutesInfo audioRoutesInfo = new AudioRoutesInfo();
+            audioRoutesInfo.mainType = AudioRoutesInfo.MAIN_SPEAKER;
+            when(mAudioService.startWatchingRoutes(mAudioRoutesObserverCaptor.capture()))
+                    .thenReturn(audioRoutesInfo);
+
+            mDeviceRouteController = new LegacyDeviceRouteController(
+                    mContext,
+                    mAudioManager,
+                    mAudioService,
+                    mOnDeviceRouteChangedListener
+            );
+
+            mAudioRoutesObserver = mAudioRoutesObserverCaptor.getValue();
+        }
+
+        @Test
+        public void newDeviceConnects_wiredDevice_deviceRouteReturnsWiredDevice() {
+            // Connecting wired headset
+            AudioRoutesInfo audioRoutesInfo = new AudioRoutesInfo();
+            audioRoutesInfo.mainType = AudioRoutesInfo.MAIN_HEADPHONES;
+
+            when(mResources.getText(
+                    com.android.internal.R.string.default_audio_route_name_headphones))
+                    .thenReturn(DEFAULT_HEADPHONES_NAME);
+
+            // Simulating wired device being connected.
+            callAudioRoutesObserver(audioRoutesInfo);
+
+            MediaRoute2Info actualMediaRoute = mDeviceRouteController.getDeviceRoute();
+
+            assertThat(actualMediaRoute.getType()).isEqualTo(MediaRoute2Info.TYPE_WIRED_HEADPHONES);
+            assertThat(TextUtils.equals(actualMediaRoute.getName(), DEFAULT_HEADPHONES_NAME))
+                    .isTrue();
+            assertThat(actualMediaRoute.getVolume()).isEqualTo(VOLUME_DEFAULT_VALUE);
+        }
+
+        @Test
+        public void newDeviceConnects_bluetoothDevice_deviceRouteReturnsBluetoothDevice() {
+            // Simulating bluetooth speaker being connected.
+            AudioRoutesInfo fakeBluetoothAudioRoute = createFakeBluetoothAudioRoute();
+            callAudioRoutesObserver(fakeBluetoothAudioRoute);
+
+            MediaRoute2Info actualMediaRoute = mDeviceRouteController.getDeviceRoute();
+
+            assertThat(actualMediaRoute.getType()).isEqualTo(MediaRoute2Info.TYPE_BUILTIN_SPEAKER);
+            assertThat(TextUtils.equals(actualMediaRoute.getName(), DEFAULT_ROUTE_NAME))
+                    .isTrue();
+            assertThat(actualMediaRoute.getVolume()).isEqualTo(VOLUME_DEFAULT_VALUE);
+        }
+
+        @Test
+        public void updateVolume_differentValue_updatesDeviceRouteVolume() {
+            MediaRoute2Info actualMediaRoute = mDeviceRouteController.getDeviceRoute();
+            assertThat(actualMediaRoute.getVolume()).isEqualTo(VOLUME_DEFAULT_VALUE);
+
+            assertThat(mDeviceRouteController.updateVolume(VOLUME_VALUE_SAMPLE_1)).isTrue();
+
+            actualMediaRoute = mDeviceRouteController.getDeviceRoute();
+            assertThat(actualMediaRoute.getVolume()).isEqualTo(VOLUME_VALUE_SAMPLE_1);
+        }
+
+        @Test
+        public void updateVolume_sameValue_returnsFalse() {
+            assertThat(mDeviceRouteController.updateVolume(VOLUME_VALUE_SAMPLE_1)).isTrue();
+            assertThat(mDeviceRouteController.updateVolume(VOLUME_VALUE_SAMPLE_1)).isFalse();
+        }
+
+        /**
+         * Simulates {@link IAudioRoutesObserver.Stub#dispatchAudioRoutesChanged(AudioRoutesInfo)}
+         * from {@link AudioService}. This happens when there is a wired route change,
+         * like a wired headset being connected.
+         *
+         * @param audioRoutesInfo updated state of connected wired device
+         */
+        private void callAudioRoutesObserver(AudioRoutesInfo audioRoutesInfo) {
+            try {
+                // this is a captured observer implementation
+                // from WiredRoutesController's AudioService#startWatchingRoutes call
+                mAudioRoutesObserver.dispatchAudioRoutesChanged(audioRoutesInfo);
+            } catch (RemoteException exception) {
+                // Should not happen since the object is mocked.
+                assertWithMessage("An unexpected RemoteException happened.").fail();
+            }
+        }
+    }
+
+}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/ContactsQueryHelperTest.java b/services/tests/servicestests/src/com/android/server/people/data/ContactsQueryHelperTest.java
index 299f153..16a02b6 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/ContactsQueryHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/ContactsQueryHelperTest.java
@@ -91,8 +91,16 @@
     }
 
     @Test
-    public void testQueryException_returnsFalse() {
-        contentProvider.setThrowException(true);
+    public void testQuerySQLiteException_returnsFalse() {
+        contentProvider.setThrowSQLiteException(true);
+
+        Uri contactUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, CONTACT_LOOKUP_KEY);
+        assertFalse(mHelper.query(contactUri.toString()));
+    }
+
+    @Test
+    public void testQueryIllegalArgumentException_returnsFalse() {
+        contentProvider.setThrowIllegalArgumentException(true);
 
         Uri contactUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, CONTACT_LOOKUP_KEY);
         assertFalse(mHelper.query(contactUri.toString()));
@@ -178,14 +186,18 @@
     private class ContactsContentProvider extends MockContentProvider {
 
         private Map<Uri, Cursor> mUriPrefixToCursorMap = new ArrayMap<>();
-        private boolean throwException = false;
+        private boolean mThrowSQLiteException = false;
+        private boolean mThrowIllegalArgumentException = false;
 
         @Override
         public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
                 String sortOrder) {
-            if (throwException) {
+            if (mThrowSQLiteException) {
                 throw new SQLiteException();
             }
+            if (mThrowIllegalArgumentException) {
+                throw new IllegalArgumentException();
+            }
 
             for (Uri prefixUri : mUriPrefixToCursorMap.keySet()) {
                 if (uri.isPathPrefixMatch(prefixUri)) {
@@ -195,8 +207,12 @@
             return mUriPrefixToCursorMap.get(uri);
         }
 
-        public void setThrowException(boolean throwException) {
-            this.throwException = throwException;
+        public void setThrowSQLiteException(boolean throwException) {
+            this.mThrowSQLiteException = throwException;
+        }
+
+        public void setThrowIllegalArgumentException(boolean throwException) {
+            this.mThrowIllegalArgumentException = throwException;
         }
 
         private void registerCursor(Uri uriPrefix, Cursor cursor) {
diff --git a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
index 4a2e5d7..9fc46c5 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
@@ -86,7 +86,6 @@
 import android.telecom.TelecomManager;
 import android.telephony.TelephonyManager;
 import android.text.format.DateUtils;
-import android.util.Pair;
 import android.util.Range;
 
 import com.android.internal.app.ChooserActivity;
@@ -187,7 +186,6 @@
     private ShortcutInfo mShortcutInfo;
     private TestInjector mInjector;
     private TestLooper mLooper;
-    private TestPerPackageThrottler mShortcutThrottler;
 
     @Before
     public void setUp() throws PackageManager.NameNotFoundException {
@@ -277,9 +275,7 @@
 
         mInjector = new TestInjector();
         mLooper = new TestLooper();
-        mShortcutThrottler = new TestPerPackageThrottler();
-        mDataManager = new DataManager(mContext, mInjector, mLooper.getLooper(),
-                mShortcutThrottler);
+        mDataManager = new DataManager(mContext, mInjector, mLooper.getLooper());
         mDataManager.initialize();
 
         when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
@@ -287,7 +283,10 @@
 
         mShortcutInfo = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                 buildPerson());
-        mockGetShortcuts(Collections.singletonList(mShortcutInfo));
+        when(mShortcutServiceInternal.getShortcuts(
+                anyInt(), anyString(), anyLong(), anyString(), anyList(), any(), any(),
+                anyInt(), anyInt(), anyInt(), anyInt()))
+                .thenReturn(Collections.singletonList(mShortcutInfo));
         verify(mShortcutServiceInternal).addShortcutChangeCallback(
                 mShortcutChangeCallbackCaptor.capture());
         mShortcutChangeCallback = mShortcutChangeCallbackCaptor.getValue();
@@ -973,7 +972,6 @@
                 buildPerson());
         ShortcutInfo shortcut3 = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, "sc3",
                 buildPerson());
-        mockGetShortcuts(List.of(shortcut1, shortcut2, shortcut3));
         mShortcutChangeCallback.onShortcutsAddedOrUpdated(TEST_PKG_NAME,
                 Arrays.asList(shortcut1, shortcut2, shortcut3), UserHandle.of(USER_ID_PRIMARY));
         mShortcutChangeCallback.onShortcutsRemoved(TEST_PKG_NAME,
@@ -1225,6 +1223,7 @@
                     eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
         }
     }
+
     @Test
     public void testUncacheOldestCachedShortcut_missingNotificationEvents() {
         mDataManager.onUserUnlocked(USER_ID_PRIMARY);
@@ -1234,7 +1233,6 @@
             ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, shortcutId,
                     buildPerson());
             shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
-            mockGetShortcuts(Collections.singletonList(shortcut));
             mShortcutChangeCallback.onShortcutsAddedOrUpdated(
                     TEST_PKG_NAME,
                     Collections.singletonList(shortcut),
@@ -1254,6 +1252,7 @@
                     eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
         }
     }
+
     @Test
     public void testUncacheOldestCachedShortcut_legacyConversation() {
         mDataManager.onUserUnlocked(USER_ID_PRIMARY);
@@ -1275,7 +1274,6 @@
             ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, shortcutId,
                     buildPerson());
             shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
-            mockGetShortcuts(Collections.singletonList(shortcut));
             mShortcutChangeCallback.onShortcutsAddedOrUpdated(
                     TEST_PKG_NAME,
                     Collections.singletonList(shortcut),
@@ -1313,8 +1311,7 @@
         mDataManager.reportShareTargetEvent(appTargetEvent, intentFilter);
         byte[] payload = mDataManager.getBackupPayload(USER_ID_PRIMARY);
 
-        DataManager dataManager = new DataManager(
-                mContext, mInjector, mLooper.getLooper(), mShortcutThrottler);
+        DataManager dataManager = new DataManager(mContext, mInjector, mLooper.getLooper());
         dataManager.onUserUnlocked(USER_ID_PRIMARY);
         dataManager.restore(USER_ID_PRIMARY, payload);
         ConversationInfo conversationInfo = dataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY)
@@ -1726,13 +1723,6 @@
         return (queryFlags & flag) != 0;
     }
 
-    private void mockGetShortcuts(List<ShortcutInfo> shortcutInfoList) {
-        when(mShortcutServiceInternal.getShortcuts(
-                anyInt(), anyString(), anyLong(), anyString(), any(), any(), any(),
-                anyInt(), anyInt(), anyInt(), anyInt()))
-                .thenReturn(shortcutInfoList);
-    }
-
     // "Sends" a notification to a non-customized notification channel - the notification channel
     // is something generic like "messages" and the notification has a  shortcut id
     private void sendGenericNotification() {
@@ -1994,11 +1984,4 @@
             return mUsageStatsQueryHelper;
         }
     }
-
-    private static class TestPerPackageThrottler implements PerPackageThrottler {
-        @Override
-        public void scheduleDebounced(Pair<String, Integer> pkgUserId, Runnable runnable) {
-            runnable.run();
-        }
-    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/people/data/PerPackageThrottlerImplTest.java b/services/tests/servicestests/src/com/android/server/people/data/PerPackageThrottlerImplTest.java
deleted file mode 100644
index 672cbb9..0000000
--- a/services/tests/servicestests/src/com/android/server/people/data/PerPackageThrottlerImplTest.java
+++ /dev/null
@@ -1,67 +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.people.data;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import android.util.Pair;
-
-import com.android.server.testutils.OffsettableClock;
-import com.android.server.testutils.TestHandler;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-
-@RunWith(JUnit4.class)
-public class PerPackageThrottlerImplTest {
-    private static final int DEBOUNCE_INTERVAL = 500;
-    private static final String PKG_ONE = "pkg_one";
-    private static final String PKG_TWO = "pkg_two";
-    private static final int USER_ID = 10;
-
-    private final OffsettableClock mClock = new OffsettableClock.Stopped();
-    private final TestHandler mTestHandler = new TestHandler(null, mClock);
-    private PerPackageThrottlerImpl mThrottler;
-
-    @Before
-    public void setUp() {
-        mThrottler = new PerPackageThrottlerImpl(mTestHandler, DEBOUNCE_INTERVAL);
-    }
-
-    @Test
-    public void scheduleDebounced() {
-        AtomicBoolean pkgOneRan = new AtomicBoolean();
-        AtomicBoolean pkgTwoRan = new AtomicBoolean();
-
-        mThrottler.scheduleDebounced(new Pair<>(PKG_ONE, USER_ID), () -> pkgOneRan.set(true));
-        mThrottler.scheduleDebounced(new Pair<>(PKG_ONE, USER_ID), () -> pkgOneRan.set(true));
-        mThrottler.scheduleDebounced(new Pair<>(PKG_TWO, USER_ID), () -> pkgTwoRan.set(true));
-        mThrottler.scheduleDebounced(new Pair<>(PKG_TWO, USER_ID), () -> pkgTwoRan.set(true));
-
-        assertFalse(pkgOneRan.get());
-        assertFalse(pkgTwoRan.get());
-        mClock.fastForward(DEBOUNCE_INTERVAL);
-        mTestHandler.timeAdvance();
-        assertTrue(pkgOneRan.get());
-        assertTrue(pkgTwoRan.get());
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 0a718e3..e65f8cf 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -4007,6 +4007,18 @@
         // TODO Check all other fields
     }
 
+    public void testLoadCorruptedShortcuts() throws Exception {
+        initService();
+
+        addPackage("com.android.chrome", 0, 0);
+
+        ShortcutUser user = new ShortcutUser(mService, 0);
+
+        File corruptedShortcutPackage = new File("/data/local/tmp/cts/content/",
+                "broken_shortcut.xml");
+        assertNull(ShortcutPackage.loadFromFile(mService, user, corruptedShortcutPackage, false));
+    }
+
     public void testSaveCorruptAndLoadUser() throws Exception {
         // First, create some shortcuts and save.
         runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
@@ -4096,11 +4108,12 @@
 
         // Save and corrupt the primary files.
         mService.saveDirtyInfo();
-        try (Writer os = new FileWriter(mService.getUserFile(UserHandle.USER_SYSTEM))) {
+        try (Writer os = new FileWriter(
+                mService.getUserFile(UserHandle.USER_SYSTEM).getBaseFile())) {
             os.write("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
                     + "<user locales=\"en\" last-app-scan-time2=\"14400000");
         }
-        try (Writer os = new FileWriter(mService.getUserFile(USER_10))) {
+        try (Writer os = new FileWriter(mService.getUserFile(USER_10).getBaseFile())) {
             os.write("<?xml version='1.0' encoding='utf");
         }
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index 15fd73c..01e56a0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -2349,7 +2349,7 @@
      * can still be read.
      */
     public void testLoadLegacySavedFile() throws Exception {
-        final File path = mService.getUserFile(USER_0);
+        final File path = mService.getUserFile(USER_0).getBaseFile();
         path.getParentFile().mkdirs();
         try (Writer w = new FileWriter(path)) {
             w.write(readTestAsset("shortcut/shortcut_legacy_file.xml"));
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceShellCommandTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceShellCommandTest.java
index 4434a32..32c9e75 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceShellCommandTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceShellCommandTest.java
@@ -121,4 +121,31 @@
         assertEquals("Couldn't get main user.", mOutStream.toString().trim());
     }
 
+    @Test
+    public void testCanSwitchToHeadlessSystemUser() {
+        doReturn(true).when(mUserManagerService).canSwitchToHeadlessSystemUser();
+        doReturn(mWriter).when(mCommand).getOutPrintWriter();
+
+        assertEquals(0, mCommand.exec(mBinder, in, out, err,
+                new String[]{"can-switch-to-headless-system-user"},
+                mShellCallback, mResultReceiver));
+
+        mWriter.flush();
+        assertEquals("true", mOutStream.toString().trim());
+    }
+
+
+    @Test
+    public void testIsMainUserPermanentAdmin() {
+        doReturn(false).when(mUserManagerService).isMainUserPermanentAdmin();
+        doReturn(mWriter).when(mCommand).getOutPrintWriter();
+
+        assertEquals(0, mCommand.exec(mBinder, in, out, err,
+                new String[]{"is-main-user-permanent-admin"}, mShellCallback, mResultReceiver));
+
+        mWriter.flush();
+        assertEquals("false", mOutStream.toString().trim());
+    }
+
+
 }
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index d71deaf..a0fb3de 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -16,7 +16,6 @@
 
 package com.android.server.power;
 
-import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
 import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
 import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
 import static android.app.AppOpsManager.MODE_ALLOWED;
@@ -30,8 +29,6 @@
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.AdditionalMatchers.gt;
-import static org.mockito.AdditionalMatchers.leq;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -153,9 +150,6 @@
     @Mock
     private InattentiveSleepWarningController mInattentiveSleepWarningControllerMock;
 
-    @Mock
-    private ActivityManagerInternal mActivityManagerInternal;
-
     private PowerManagerService mService;
     private ContextWrapper mContextSpy;
     private BatteryReceiver mBatteryReceiver;
@@ -211,7 +205,6 @@
         addLocalServiceMock(ActivityManagerInternal.class, mActivityManagerInternalMock);
         addLocalServiceMock(AttentionManagerInternal.class, mAttentionManagerInternalMock);
         addLocalServiceMock(DreamManagerInternal.class, mDreamManagerInternalMock);
-        addLocalServiceMock(ActivityManagerInternal.class, mActivityManagerInternal);
 
         mContextSpy = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
         mResourcesSpy = spy(mContextSpy.getResources());
@@ -228,14 +221,6 @@
 
         mClock = new OffsettableClock.Stopped();
         mTestLooper = new TestLooper(mClock::now);
-
-        // Set up canHoldWakeLocksInDeepDoze.
-        // - procstate <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE -> true
-        // - procstate >  PROCESS_STATE_BOUND_FOREGROUND_SERVICE -> false
-        when(mActivityManagerInternal.canHoldWakeLocksInDeepDoze(
-                anyInt(), leq(PROCESS_STATE_BOUND_FOREGROUND_SERVICE))).thenReturn(true);
-        when(mActivityManagerInternal.canHoldWakeLocksInDeepDoze(
-                anyInt(), gt(PROCESS_STATE_BOUND_FOREGROUND_SERVICE))).thenReturn(false);
     }
 
     private PowerManagerService createService() {
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsImplTest.java b/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsImplTest.java
index c6a7fbc..ee4b839 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsImplTest.java
@@ -572,41 +572,14 @@
         mBatteryStatsImpl.noteBluetoothScanStoppedFromSourceLocked(ws, true, 9000, 9000);
         mBatteryStatsImpl.noteBluetoothScanResultsFromSourceLocked(ws, 42, 9000, 9000);
 
-
-
-        final Parcel uidTrafficParcel1 = Parcel.obtain();
-        final Parcel uidTrafficParcel2 = Parcel.obtain();
-
-        uidTrafficParcel1.writeInt(10042);
-        uidTrafficParcel1.writeLong(3000);
-        uidTrafficParcel1.writeLong(4000);
-        uidTrafficParcel1.setDataPosition(0);
-        uidTrafficParcel2.writeInt(10043);
-        uidTrafficParcel2.writeLong(5000);
-        uidTrafficParcel2.writeLong(8000);
-        uidTrafficParcel2.setDataPosition(0);
-
-        List<UidTraffic> uidTrafficList = ImmutableList.of(
-                UidTraffic.CREATOR.createFromParcel(uidTrafficParcel1),
-                UidTraffic.CREATOR.createFromParcel(uidTrafficParcel2));
-
-        final Parcel btActivityEnergyInfoParcel = Parcel.obtain();
-        btActivityEnergyInfoParcel.writeLong(1000);
-        btActivityEnergyInfoParcel.writeInt(
-                BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_ACTIVE);
-        btActivityEnergyInfoParcel.writeLong(9000);
-        btActivityEnergyInfoParcel.writeLong(8000);
-        btActivityEnergyInfoParcel.writeLong(12000);
-        btActivityEnergyInfoParcel.writeLong(0);
-        btActivityEnergyInfoParcel.writeTypedList(uidTrafficList);
-        btActivityEnergyInfoParcel.setDataPosition(0);
-
-        BluetoothActivityEnergyInfo info = BluetoothActivityEnergyInfo.CREATOR
-                .createFromParcel(btActivityEnergyInfoParcel);
-
-        uidTrafficParcel1.recycle();
-        uidTrafficParcel2.recycle();
-        btActivityEnergyInfoParcel.recycle();
+        BluetoothActivityEnergyInfo info = createBluetoothActivityEnergyInfo(
+                /* timestamp= */ 1000,
+                /* controllerTxTimeMs= */ 9000,
+                /* controllerRxTimeMs= */ 8000,
+                /* controllerIdleTimeMs= */ 12000,
+                /* controllerEnergyUsed= */ 0,
+                createUidTraffic(/* appUid= */ 10042, /* rxBytes= */ 3000, /* txBytes= */ 4000),
+                createUidTraffic(/* appUid= */ 10043, /* rxBytes= */ 5000, /* txBytes= */ 8000));
 
         mBatteryStatsImpl.updateBluetoothStateLocked(info, -1, 1000, 1000);
 
@@ -622,4 +595,105 @@
         assertThat(uidStats.rxTimeMs).isEqualTo(7375);  // Some scan time is treated as RX
         assertThat(uidStats.txTimeMs).isEqualTo(7666);  // Some scan time is treated as TX
     }
+
+    /** A regression test for b/266128651 */
+    @Test
+    public void testGetNetworkActivityBytes_multipleUpdates() {
+        when(mPowerProfile.getAveragePower(
+                PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE)).thenReturn(3.0);
+        mBatteryStatsImpl.setOnBatteryInternal(true);
+        mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
+
+        BluetoothActivityEnergyInfo info1 = createBluetoothActivityEnergyInfo(
+                /* timestamp= */ 10000,
+                /* controllerTxTimeMs= */ 9000,
+                /* controllerRxTimeMs= */ 8000,
+                /* controllerIdleTimeMs= */ 2000,
+                /* controllerEnergyUsed= */ 0,
+                createUidTraffic(/* appUid= */ 10042, /* rxBytes= */ 3000, /* txBytes= */ 4000),
+                createUidTraffic(/* appUid= */ 10043, /* rxBytes= */ 5000, /* txBytes= */ 8000));
+
+        mBatteryStatsImpl.updateBluetoothStateLocked(info1, -1, 1000, 1000);
+
+        long totalRx1 = mBatteryStatsImpl.getNetworkActivityBytes(
+                BatteryStats.NETWORK_BT_RX_DATA, BatteryStats.STATS_SINCE_CHARGED);
+        long totalTx1 = mBatteryStatsImpl.getNetworkActivityBytes(
+                BatteryStats.NETWORK_BT_TX_DATA, BatteryStats.STATS_SINCE_CHARGED);
+
+        assertThat(totalRx1).isEqualTo(8000);  // 3000 + 5000
+        assertThat(totalTx1).isEqualTo(12000);  // 4000 + 8000
+
+        BluetoothActivityEnergyInfo info2 = createBluetoothActivityEnergyInfo(
+                /* timestamp= */ 20000,
+                /* controllerTxTimeMs= */ 19000,
+                /* controllerRxTimeMs= */ 18000,
+                /* controllerIdleTimeMs= */ 3000,
+                /* controllerEnergyUsed= */ 0,
+                createUidTraffic(/* appUid= */ 10043, /* rxBytes= */ 6000, /* txBytes= */ 9500),
+                createUidTraffic(/* appUid= */ 10044, /* rxBytes= */ 7000, /* txBytes= */ 9000));
+
+        mBatteryStatsImpl.updateBluetoothStateLocked(info2, -1, 2000, 2000);
+
+        long totalRx2 = mBatteryStatsImpl.getNetworkActivityBytes(
+                BatteryStats.NETWORK_BT_RX_DATA, BatteryStats.STATS_SINCE_CHARGED);
+        long totalTx2 = mBatteryStatsImpl.getNetworkActivityBytes(
+                BatteryStats.NETWORK_BT_TX_DATA, BatteryStats.STATS_SINCE_CHARGED);
+
+        assertThat(totalRx2).isEqualTo(16000);  // 3000 + 6000 (updated) + 7000 (new)
+        assertThat(totalTx2).isEqualTo(22500);  // 4000 + 9500 (updated) + 9000 (new)
+
+        BluetoothActivityEnergyInfo info3 = createBluetoothActivityEnergyInfo(
+                /* timestamp= */ 30000,
+                /* controllerTxTimeMs= */ 20000,
+                /* controllerRxTimeMs= */ 20000,
+                /* controllerIdleTimeMs= */ 4000,
+                /* controllerEnergyUsed= */ 0,
+                createUidTraffic(/* appUid= */ 10043, /* rxBytes= */ 7000, /* txBytes= */ 9900),
+                createUidTraffic(/* appUid= */ 10044, /* rxBytes= */ 8000, /* txBytes= */ 10000));
+
+        mBatteryStatsImpl.updateBluetoothStateLocked(info3, -1, 2000, 2000);
+
+        long totalRx3 = mBatteryStatsImpl.getNetworkActivityBytes(
+                BatteryStats.NETWORK_BT_RX_DATA, BatteryStats.STATS_SINCE_CHARGED);
+        long totalTx3 = mBatteryStatsImpl.getNetworkActivityBytes(
+                BatteryStats.NETWORK_BT_TX_DATA, BatteryStats.STATS_SINCE_CHARGED);
+
+        assertThat(totalRx3).isEqualTo(18000);  // 3000 + 7000 (updated) + 8000 (updated)
+        assertThat(totalTx3).isEqualTo(23900);  // 4000 + 9900 (updated) + 10000 (updated)
+    }
+
+    private UidTraffic createUidTraffic(int appUid, long rxBytes, long txBytes) {
+        final Parcel parcel = Parcel.obtain();
+        parcel.writeInt(appUid); // mAppUid
+        parcel.writeLong(rxBytes); // mRxBytes
+        parcel.writeLong(txBytes); // mTxBytes
+        parcel.setDataPosition(0);
+        UidTraffic uidTraffic = UidTraffic.CREATOR.createFromParcel(parcel);
+        parcel.recycle();
+        return uidTraffic;
+    }
+
+    private BluetoothActivityEnergyInfo createBluetoothActivityEnergyInfo(
+            long timestamp,
+            long controllerTxTimeMs,
+            long controllerRxTimeMs,
+            long controllerIdleTimeMs,
+            long controllerEnergyUsed,
+            UidTraffic... uidTraffic) {
+        Parcel parcel = Parcel.obtain();
+        parcel.writeLong(timestamp); // mTimestamp
+        parcel.writeInt(
+                BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_ACTIVE); // mBluetoothStackState
+        parcel.writeLong(controllerTxTimeMs); // mControllerTxTimeMs;
+        parcel.writeLong(controllerRxTimeMs); // mControllerRxTimeMs;
+        parcel.writeLong(controllerIdleTimeMs); // mControllerIdleTimeMs;
+        parcel.writeLong(controllerEnergyUsed); // mControllerEnergyUsed;
+        parcel.writeTypedList(ImmutableList.copyOf(uidTraffic)); // mUidTraffic
+        parcel.setDataPosition(0);
+
+        BluetoothActivityEnergyInfo info =
+                BluetoothActivityEnergyInfo.CREATOR.createFromParcel(parcel);
+        parcel.recycle();
+        return info;
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/CpuWakeupStatsTest.java b/services/tests/servicestests/src/com/android/server/power/stats/CpuWakeupStatsTest.java
index 34e45c2..397d7b5 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/CpuWakeupStatsTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/CpuWakeupStatsTest.java
@@ -18,9 +18,9 @@
 
 import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_ALARM;
 import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_UNKNOWN;
+import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_WIFI;
 
 import static com.android.server.power.stats.CpuWakeupStats.WAKEUP_REASON_HALF_WINDOW_MS;
-import static com.android.server.power.stats.CpuWakeupStats.WAKEUP_RETENTION_MS;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -45,6 +45,7 @@
 @RunWith(AndroidJUnit4.class)
 public class CpuWakeupStatsTest {
     private static final String KERNEL_REASON_ALARM_IRQ = "120 test.alarm.device";
+    private static final String KERNEL_REASON_WIFI_IRQ = "120 test.wifi.device";
     private static final String KERNEL_REASON_UNKNOWN_IRQ = "140 test.unknown.device";
     private static final String KERNEL_REASON_UNKNOWN = "free-form-reason test.alarm.device";
     private static final String KERNEL_REASON_UNSUPPORTED = "-1 test.alarm.device";
@@ -64,28 +65,29 @@
     public void removesOldWakeups() {
         // The xml resource doesn't matter for this test.
         final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_1, mHandler);
+        final long retention = obj.mConfig.WAKEUP_STATS_RETENTION_MS;
 
         final Set<Long> timestamps = new HashSet<>();
         final long firstWakeup = 453192;
 
-        obj.noteWakeupTimeAndReason(firstWakeup, 32, "unused");
+        obj.noteWakeupTimeAndReason(firstWakeup, 32, KERNEL_REASON_UNKNOWN_IRQ);
         timestamps.add(firstWakeup);
         for (int i = 1; i < 1000; i++) {
-            final long delta = mRandom.nextLong(WAKEUP_RETENTION_MS);
+            final long delta = mRandom.nextLong(retention);
             if (timestamps.add(firstWakeup + delta)) {
-                obj.noteWakeupTimeAndReason(firstWakeup + delta, i, "unused");
+                obj.noteWakeupTimeAndReason(firstWakeup + delta, i, KERNEL_REASON_UNKNOWN_IRQ);
             }
         }
         assertThat(obj.mWakeupEvents.size()).isEqualTo(timestamps.size());
 
-        obj.noteWakeupTimeAndReason(firstWakeup + WAKEUP_RETENTION_MS + 1242, 231, "unused");
+        obj.noteWakeupTimeAndReason(firstWakeup + retention + 1242, 231,
+                KERNEL_REASON_UNKNOWN_IRQ);
         assertThat(obj.mWakeupEvents.size()).isEqualTo(timestamps.size());
 
         for (int i = 0; i < 100; i++) {
-            final long now = mRandom.nextLong(WAKEUP_RETENTION_MS + 1, 100 * WAKEUP_RETENTION_MS);
-            obj.noteWakeupTimeAndReason(now, i, "unused");
-            assertThat(obj.mWakeupEvents.closestIndexOnOrBefore(now - WAKEUP_RETENTION_MS))
-                    .isLessThan(0);
+            final long now = mRandom.nextLong(retention + 1, 100 * retention);
+            obj.noteWakeupTimeAndReason(now, i, KERNEL_REASON_UNKNOWN_IRQ);
+            assertThat(obj.mWakeupEvents.closestIndexOnOrBefore(now - retention)).isLessThan(0);
         }
     }
 
@@ -111,17 +113,45 @@
         assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_1)).isEqualTo(false);
         assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_2)).isEqualTo(false);
         assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_3)).isEqualTo(true);
+        assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_4)).isEqualTo(false);
         assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_5)).isEqualTo(true);
     }
 
     @Test
-    public void alarmIrqAttributionCombined() {
+    public void wifiIrqAttributionSolo() {
+        final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, mHandler);
+        final long wakeupTime = 12423121;
+
+        obj.noteWakeupTimeAndReason(wakeupTime, 1, KERNEL_REASON_WIFI_IRQ);
+
+        // Outside the window, so should be ignored.
+        obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI,
+                wakeupTime - WAKEUP_REASON_HALF_WINDOW_MS - 1, TEST_UID_1);
+        obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI,
+                wakeupTime + WAKEUP_REASON_HALF_WINDOW_MS + 1, TEST_UID_2);
+        // Should be attributed
+        obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime + 3, TEST_UID_4, TEST_UID_5);
+
+        final SparseArray<SparseBooleanArray> attribution = obj.mWakeupAttribution.get(wakeupTime);
+        assertThat(attribution).isNotNull();
+        assertThat(attribution.size()).isEqualTo(1);
+        assertThat(attribution.contains(CPU_WAKEUP_SUBSYSTEM_WIFI)).isTrue();
+        assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_1)).isEqualTo(false);
+        assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_2)).isEqualTo(false);
+        assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_3)).isEqualTo(false);
+        assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_4)).isEqualTo(true);
+        assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_5)).isEqualTo(true);
+    }
+
+    @Test
+    public void alarmAndWifiIrqAttribution() {
         final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, mHandler);
         final long wakeupTime = 92123210;
 
         obj.noteWakeupTimeAndReason(wakeupTime, 4,
-                KERNEL_REASON_UNKNOWN_IRQ + ":" + KERNEL_REASON_ALARM_IRQ);
+                KERNEL_REASON_WIFI_IRQ + ":" + KERNEL_REASON_ALARM_IRQ);
 
+        // Alarm activity
         // Outside the window, so should be ignored.
         obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM,
                 wakeupTime - WAKEUP_REASON_HALF_WINDOW_MS - 1, TEST_UID_1);
@@ -132,16 +162,34 @@
         obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime - 3, TEST_UID_4,
                 TEST_UID_5);
 
+        // Wifi activity
+        // Outside the window, so should be ignored.
+        obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI,
+                wakeupTime - WAKEUP_REASON_HALF_WINDOW_MS - 1, TEST_UID_4);
+        obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI,
+                wakeupTime + WAKEUP_REASON_HALF_WINDOW_MS + 1, TEST_UID_3);
+        // Should be attributed
+        obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime + 2, TEST_UID_1);
+        obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime - 1, TEST_UID_2,
+                TEST_UID_5);
+
         final SparseArray<SparseBooleanArray> attribution = obj.mWakeupAttribution.get(wakeupTime);
         assertThat(attribution).isNotNull();
         assertThat(attribution.size()).isEqualTo(2);
+
         assertThat(attribution.contains(CPU_WAKEUP_SUBSYSTEM_ALARM)).isTrue();
         assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_1)).isEqualTo(false);
         assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_2)).isEqualTo(false);
         assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_3)).isEqualTo(true);
         assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_4)).isEqualTo(true);
         assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_5)).isEqualTo(true);
-        assertThat(attribution.contains(CPU_WAKEUP_SUBSYSTEM_UNKNOWN)).isTrue();
+
+        assertThat(attribution.contains(CPU_WAKEUP_SUBSYSTEM_WIFI)).isTrue();
+        assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_1)).isEqualTo(true);
+        assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_2)).isEqualTo(true);
+        assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_3)).isEqualTo(false);
+        assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_4)).isEqualTo(false);
+        assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_5)).isEqualTo(true);
     }
 
     @Test
@@ -151,9 +199,11 @@
 
         obj.noteWakeupTimeAndReason(wakeupTime, 24, KERNEL_REASON_UNKNOWN_IRQ);
 
+        assertThat(obj.mWakeupEvents.size()).isEqualTo(1);
+
         // Unrelated subsystems, should not be attributed
         obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime + 5, TEST_UID_3);
-        obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime - 3, TEST_UID_4,
+        obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime - 3, TEST_UID_4,
                 TEST_UID_5);
 
         final SparseArray<SparseBooleanArray> attribution = obj.mWakeupAttribution.get(wakeupTime);
@@ -165,42 +215,48 @@
     }
 
     @Test
-    public void unknownAttribution() {
+    public void unknownWakeupIgnored() {
         final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, mHandler);
         final long wakeupTime = 72123210;
 
         obj.noteWakeupTimeAndReason(wakeupTime, 34, KERNEL_REASON_UNKNOWN);
 
-        // Should be ignored as this type of wakeup is unsupported.
+        // Should be ignored as this type of wakeup is not known.
+        assertThat(obj.mWakeupEvents.size()).isEqualTo(0);
+
         obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime + 5, TEST_UID_3);
         obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime - 3, TEST_UID_4);
 
-        // There should be nothing in the attribution map.
+        // Any nearby activity should not end up in the attribution map.
         assertThat(obj.mWakeupAttribution.size()).isEqualTo(0);
     }
 
     @Test
-    public void unsupportedAttribution() {
+    public void unsupportedWakeupIgnored() {
         final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, mHandler);
 
         long wakeupTime = 970934;
         obj.noteWakeupTimeAndReason(wakeupTime, 34, KERNEL_REASON_UNSUPPORTED);
 
         // Should be ignored as this type of wakeup is unsupported.
+        assertThat(obj.mWakeupEvents.size()).isEqualTo(0);
+
         obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime + 5, TEST_UID_3);
         obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime - 3, TEST_UID_4);
 
-        // There should be nothing in the attribution map.
+        // Any nearby activity should not end up in the attribution map.
         assertThat(obj.mWakeupAttribution.size()).isEqualTo(0);
 
         wakeupTime = 883124;
         obj.noteWakeupTimeAndReason(wakeupTime, 3, KERNEL_REASON_ABORT);
 
         // Should be ignored as this type of wakeup is unsupported.
-        obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime + 2, TEST_UID_1, TEST_UID_4);
-        obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime - 5, TEST_UID_3);
+        assertThat(obj.mWakeupEvents.size()).isEqualTo(0);
 
-        // There should be nothing in the attribution map.
+        obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime + 2, TEST_UID_1, TEST_UID_4);
+        obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime - 5, TEST_UID_3);
+
+        // Any nearby activity should not end up in the attribution map.
         assertThat(obj.mWakeupAttribution.size()).isEqualTo(0);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java b/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java
index 6edef75..07b4345 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java
@@ -34,6 +34,7 @@
 import android.hardware.input.IInputDevicesChangedListener;
 import android.hardware.input.IInputManager;
 import android.hardware.input.InputManager;
+import android.hardware.input.InputManagerGlobal;
 import android.os.CombinedVibration;
 import android.os.Handler;
 import android.os.Process;
@@ -82,8 +83,8 @@
     @Before
     public void setUp() throws Exception {
         mTestLooper = new TestLooper();
-        mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
         InputManager inputManager = InputManager.resetInstance(mIInputManagerMock);
+        mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
 
         when(mContextSpy.getSystemService(eq(Context.INPUT_SERVICE))).thenReturn(inputManager);
         doAnswer(invocation -> mIInputDevicesChangedListener = invocation.getArgument(0))
@@ -314,7 +315,7 @@
             deviceIdsAndGenerations[i + 1] = 2; // update by increasing it's generation to 2.
         }
         // Force initialization of mIInputDevicesChangedListener, if it still haven't
-        InputManager.getInstance().getInputDeviceIds();
+        InputManagerGlobal.getInstance().getInputDeviceIds();
         mIInputDevicesChangedListener.onInputDevicesChanged(deviceIdsAndGenerations);
         // Makes sure all callbacks from InputDeviceDelegate are executed.
         mTestLooper.dispatchAll();
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
index 6f37e60..ce07621 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
@@ -24,6 +24,8 @@
 import static com.android.server.notification.ManagedServices.APPROVAL_BY_COMPONENT;
 import static com.android.server.notification.ManagedServices.APPROVAL_BY_PACKAGE;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertNotNull;
@@ -1201,28 +1203,11 @@
                     mIpm, approvalLevel);
             loadXml(service);
 
-            List<String> allowedPackagesForUser0 = new ArrayList<>();
-            allowedPackagesForUser0.add("this.is.a.package.name");
-            allowedPackagesForUser0.add("another.package");
-            allowedPackagesForUser0.add("secondary");
-
-            List<String> actual = service.getAllowedPackages(0);
-            assertEquals(3, actual.size());
-            for (String pkg : allowedPackagesForUser0) {
-                assertTrue(actual.contains(pkg));
-            }
-
-            List<String> allowedPackagesForUser10 = new ArrayList<>();
-            allowedPackagesForUser10.add("this.is.another.package");
-            allowedPackagesForUser10.add("package");
-            allowedPackagesForUser10.add("this.is.another.package");
-            allowedPackagesForUser10.add("component");
-
-            actual = service.getAllowedPackages(10);
-            assertEquals(4, actual.size());
-            for (String pkg : allowedPackagesForUser10) {
-                assertTrue(actual.contains(pkg));
-            }
+            assertThat(service.getAllowedPackages(0)).containsExactly("this.is.a.package.name",
+                    "another.package", "secondary");
+            assertThat(service.getAllowedPackages(10)).containsExactly("this.is.another.package",
+                    "package", "this.is.another.package", "component");
+            assertThat(service.getAllowedPackages(999)).isEmpty();
         }
     }
 
@@ -1263,31 +1248,6 @@
     }
 
     @Test
-    public void testGetAllowedPackages() throws Exception {
-        ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
-                mIpm, APPROVAL_BY_COMPONENT);
-        loadXml(service);
-        service.mApprovalLevel = APPROVAL_BY_PACKAGE;
-        loadXml(service);
-
-        List<String> allowedPackages = new ArrayList<>();
-        allowedPackages.add("this.is.a.package.name");
-        allowedPackages.add("another.package");
-        allowedPackages.add("secondary");
-        allowedPackages.add("this.is.another.package");
-        allowedPackages.add("package");
-        allowedPackages.add("component");
-        allowedPackages.add("bananas!");
-        allowedPackages.add("non.user.set.package");
-
-        Set<String> actual = service.getAllowedPackages();
-        assertEquals(allowedPackages.size(), actual.size());
-        for (String pkg : allowedPackages) {
-            assertTrue(actual.contains(pkg));
-        }
-    }
-
-    @Test
     public void testOnUserRemoved() throws Exception {
         for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
             ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
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 f08d0f5..41a9504 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -29,6 +29,7 @@
 import static android.app.Notification.FLAG_NO_CLEAR;
 import static android.app.Notification.FLAG_ONGOING_EVENT;
 import static android.app.NotificationChannel.USER_LOCKED_ALLOW_BUBBLE;
+import static android.app.NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED;
 import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
 import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
 import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
@@ -50,7 +51,6 @@
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
-
 import static android.app.PendingIntent.FLAG_IMMUTABLE;
 import static android.app.PendingIntent.FLAG_MUTABLE;
 import static android.app.PendingIntent.FLAG_ONE_SHOT;
@@ -237,6 +237,7 @@
 import com.android.server.wm.ActivityTaskManagerInternal;
 import com.android.server.wm.WindowManagerInternal;
 
+import com.google.android.collect.Lists;
 import com.google.common.collect.ImmutableList;
 
 import org.junit.After;
@@ -245,10 +246,13 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatcher;
+import org.mockito.ArgumentMatchers;
 import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
 import java.io.BufferedInputStream;
@@ -412,7 +416,7 @@
         // Shell permisssions will override permissions of our app, so add all necessary permissions
         // for this test here:
         InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
-                "android.permission.WRITE_DEVICE_CONFIG",
+                "android.permission.ALLOWLISTED_WRITE_DEVICE_CONFIG",
                 "android.permission.READ_DEVICE_CONFIG",
                 "android.permission.READ_CONTACTS");
 
@@ -440,6 +444,7 @@
         mContext.addMockSystemService(Context.ALARM_SERVICE, mAlarmManager);
         mContext.addMockSystemService(NotificationManager.class, mMockNm);
 
+        doNothing().when(mContext).sendBroadcastAsUser(any(), any());
         doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
 
         setDpmAppOppsExemptFromDismissal(false);
@@ -7828,6 +7833,75 @@
     }
 
     @Test
+    public void onZenModeChanged_sendsBroadcasts() throws Exception {
+        when(mAmi.getCurrentUserId()).thenReturn(100);
+        when(mUmInternal.getProfileIds(eq(100), anyBoolean())).thenReturn(new int[]{100, 101, 102});
+        when(mConditionProviders.getAllowedPackages(anyInt())).then(new Answer<List<String>>() {
+            @Override
+            public List<String> answer(InvocationOnMock invocation) {
+                int userId = invocation.getArgument(0);
+                switch (userId) {
+                    case 100:
+                        return Lists.newArrayList("a", "b", "c");
+                    case 101:
+                        return Lists.newArrayList();
+                    case 102:
+                        return Lists.newArrayList("b");
+                    default:
+                        throw new IllegalArgumentException(
+                                "Why would you ask for packages of userId " + userId + "?");
+                }
+            }
+        });
+
+        mService.getBinderService().setZenMode(Settings.Global.ZEN_MODE_NO_INTERRUPTIONS, null,
+                "testing!");
+        waitForIdle();
+
+        InOrder inOrder = inOrder(mContext);
+        // Verify broadcasts for registered receivers
+        inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(
+                new Intent(ACTION_INTERRUPTION_FILTER_CHANGED).setFlags(
+                        Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(UserHandle.of(100)), eq(null));
+        inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(
+                new Intent(ACTION_INTERRUPTION_FILTER_CHANGED).setFlags(
+                        Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(UserHandle.of(101)), eq(null));
+        inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(
+                new Intent(ACTION_INTERRUPTION_FILTER_CHANGED).setFlags(
+                        Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(UserHandle.of(102)), eq(null));
+
+        // Verify broadcast for packages that manage DND.
+        inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent(
+                ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("a").setFlags(
+                Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(100)));
+        inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent(
+                ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("b").setFlags(
+                Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(100)));
+        inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent(
+                ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("c").setFlags(
+                Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(100)));
+        inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent(
+                ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("b").setFlags(
+                Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(102)));
+    }
+
+    private static Intent eqIntent(Intent wanted) {
+        return ArgumentMatchers.argThat(
+                new ArgumentMatcher<Intent>() {
+                    @Override
+                    public boolean matches(Intent argument) {
+                        return wanted.filterEquals(argument)
+                                && wanted.getFlags() == argument.getFlags();
+                    }
+
+                    @Override
+                    public String toString() {
+                        return wanted.toString();
+                    }
+                });
+    }
+
+    @Test
     public void testAreNotificationsEnabledForPackage() throws Exception {
         mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
                 mUid);
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 1ecd4a1..06bcb91 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -63,6 +63,7 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -70,6 +71,7 @@
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
 import android.app.AppOpsManager;
@@ -161,7 +163,6 @@
     private static final String SYSTEM_PKG = "android";
     private static final int SYSTEM_UID = 1000;
     private static final UserHandle USER2 = UserHandle.of(10);
-    private static final String TEST_CHANNEL_ID = "test_channel_id";
     private static final String TEST_AUTHORITY = "test";
     private static final Uri SOUND_URI =
             Uri.parse("content://" + TEST_AUTHORITY + "/internal/audio/media/10");
@@ -284,9 +285,9 @@
                 anyString(), eq(null), anyString())).thenReturn(MODE_DEFAULT);
 
         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
-        appPermissions.put(new Pair(UID_P, PKG_P), new Pair(true, false));
-        appPermissions.put(new Pair(UID_O, PKG_O), new Pair(true, false));
-        appPermissions.put(new Pair(UID_N_MR1, PKG_N_MR1), new Pair(true, false));
+        appPermissions.put(new Pair<>(UID_P, PKG_P), new Pair<>(true, false));
+        appPermissions.put(new Pair<>(UID_O, PKG_O), new Pair<>(true, false));
+        appPermissions.put(new Pair<>(UID_N_MR1, PKG_N_MR1), new Pair<>(true, false));
 
         when(mPermissionHelper.getNotificationPermissionValues(USER_SYSTEM))
                 .thenReturn(appPermissions);
@@ -422,8 +423,8 @@
         assertTrue(mHelper.createNotificationChannel(package10, uid10, channel10, true, false));
 
         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
-        appPermissions.put(new Pair(uid0, package0), new Pair(false, false));
-        appPermissions.put(new Pair(uid10, package10), new Pair(true, false));
+        appPermissions.put(new Pair<>(uid0, package0), new Pair<>(false, false));
+        appPermissions.put(new Pair<>(uid10, package10), new Pair<>(true, false));
 
         when(mPermissionHelper.getNotificationPermissionValues(10))
                 .thenReturn(appPermissions);
@@ -454,7 +455,7 @@
         assertTrue(mHelper.createNotificationChannel(package0, uid0, channel0, true, false));
 
         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
-        appPermissions.put(new Pair(uid0, package0), new Pair(true, false));
+        appPermissions.put(new Pair<>(uid0, package0), new Pair<>(true, false));
 
         when(mPermissionHelper.getNotificationPermissionValues(USER_SYSTEM))
                 .thenReturn(appPermissions);
@@ -1009,11 +1010,11 @@
                 mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
 
         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
-        appPermissions.put(new Pair(1, "first"), new Pair(true, false));
-        appPermissions.put(new Pair(3, "third"), new Pair(false, false));
-        appPermissions.put(new Pair(UID_P, PKG_P), new Pair(true, false));
-        appPermissions.put(new Pair(UID_O, PKG_O), new Pair(false, false));
-        appPermissions.put(new Pair(UID_N_MR1, PKG_N_MR1), new Pair(true, false));
+        appPermissions.put(new Pair<>(1, "first"), new Pair<>(true, false));
+        appPermissions.put(new Pair<>(3, "third"), new Pair<>(false, false));
+        appPermissions.put(new Pair<>(UID_P, PKG_P), new Pair<>(true, false));
+        appPermissions.put(new Pair<>(UID_O, PKG_O), new Pair<>(false, false));
+        appPermissions.put(new Pair<>(UID_N_MR1, PKG_N_MR1), new Pair<>(true, false));
 
         when(mPermissionHelper.getNotificationPermissionValues(USER_SYSTEM))
                 .thenReturn(appPermissions);
@@ -1089,11 +1090,11 @@
                 mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
 
         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
-        appPermissions.put(new Pair(1, "first"), new Pair(true, false));
-        appPermissions.put(new Pair(3, "third"), new Pair(false, false));
-        appPermissions.put(new Pair(UID_P, PKG_P), new Pair(true, false));
-        appPermissions.put(new Pair(UID_O, PKG_O), new Pair(false, false));
-        appPermissions.put(new Pair(UID_N_MR1, PKG_N_MR1), new Pair(true, false));
+        appPermissions.put(new Pair<>(1, "first"), new Pair<>(true, false));
+        appPermissions.put(new Pair<>(3, "third"), new Pair<>(false, false));
+        appPermissions.put(new Pair<>(UID_P, PKG_P), new Pair<>(true, false));
+        appPermissions.put(new Pair<>(UID_O, PKG_O), new Pair<>(false, false));
+        appPermissions.put(new Pair<>(UID_N_MR1, PKG_N_MR1), new Pair<>(true, false));
 
         when(mPermissionHelper.getNotificationPermissionValues(USER_SYSTEM))
                 .thenReturn(appPermissions);
@@ -1175,8 +1176,8 @@
                 mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
 
         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
-        appPermissions.put(new Pair(UID_P, PKG_P), new Pair(true, false));
-        appPermissions.put(new Pair(UID_O, PKG_O), new Pair(false, false));
+        appPermissions.put(new Pair<>(UID_P, PKG_P), new Pair<>(true, false));
+        appPermissions.put(new Pair<>(UID_O, PKG_O), new Pair<>(false, false));
         when(mPermissionHelper.getNotificationPermissionValues(USER_SYSTEM))
                 .thenReturn(appPermissions);
 
@@ -1254,11 +1255,11 @@
                 mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
 
         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
-        appPermissions.put(new Pair(1, "first"), new Pair(true, false));
-        appPermissions.put(new Pair(3, "third"), new Pair(false, false));
-        appPermissions.put(new Pair(UID_P, PKG_P), new Pair(true, false));
-        appPermissions.put(new Pair(UID_O, PKG_O), new Pair(false, false));
-        appPermissions.put(new Pair(UID_N_MR1, PKG_N_MR1), new Pair(true, false));
+        appPermissions.put(new Pair<>(1, "first"), new Pair<>(true, false));
+        appPermissions.put(new Pair<>(3, "third"), new Pair<>(false, false));
+        appPermissions.put(new Pair<>(UID_P, PKG_P), new Pair<>(true, false));
+        appPermissions.put(new Pair<>(UID_O, PKG_O), new Pair<>(false, false));
+        appPermissions.put(new Pair<>(UID_N_MR1, PKG_N_MR1), new Pair<>(true, false));
 
         when(mPermissionHelper.getNotificationPermissionValues(USER_SYSTEM))
                 .thenReturn(appPermissions);
@@ -1372,7 +1373,7 @@
     @Test
     public void testBackupRestoreXml_withNullSoundUri() throws Exception {
         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
-        appPermissions.put(new Pair(UID_N_MR1, PKG_N_MR1), new Pair(true, false));
+        appPermissions.put(new Pair<>(UID_N_MR1, PKG_N_MR1), new Pair<>(true, false));
 
         when(mPermissionHelper.getNotificationPermissionValues(USER_SYSTEM))
                 .thenReturn(appPermissions);
@@ -2605,10 +2606,8 @@
 
     @Test
     public void testClearData() {
-        ArraySet<String> pkg = new ArraySet<>();
-        pkg.add(PKG_O);
         ArraySet<Pair<String, Integer>> pkgPair = new ArraySet<>();
-        pkgPair.add(new Pair(PKG_O, UID_O));
+        pkgPair.add(new Pair<>(PKG_O, UID_O));
         mHelper.createNotificationChannel(PKG_O, UID_O, getChannel(), true, false);
         mHelper.createNotificationChannelGroup(
                 PKG_O, UID_O, new NotificationChannelGroup("1", "bye"), true);
@@ -2879,10 +2878,10 @@
 
         // package permissions map to be passed in
         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
-        appPermissions.put(new Pair(1, "first"), new Pair(true, false));    // not in local prefs
-        appPermissions.put(new Pair(3, "third"), new Pair(false, false));   // not in local prefs
-        appPermissions.put(new Pair(UID_P, PKG_P), new Pair(true, false));  // in local prefs
-        appPermissions.put(new Pair(UID_O, PKG_O), new Pair(false, false)); // in local prefs
+        appPermissions.put(new Pair<>(1, "first"), new Pair<>(true, false)); // not in local prefs
+        appPermissions.put(new Pair<>(3, "third"), new Pair<>(false, false)); // not in local prefs
+        appPermissions.put(new Pair<>(UID_P, PKG_P), new Pair<>(true, false)); // in local prefs
+        appPermissions.put(new Pair<>(UID_O, PKG_O), new Pair<>(false, false)); // in local prefs
 
         NotificationChannel channel1 =
                 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
@@ -2901,15 +2900,15 @@
         ArrayMap<Pair<Integer, String>, String> expected = new ArrayMap<>();
 
         // packages that only exist via the app permissions; should be present
-        expected.put(new Pair(UserHandle.getUserId(1), "first"), "DEFAULT");
-        expected.put(new Pair(UserHandle.getUserId(3), "third"), "NONE");
+        expected.put(new Pair<>(UserHandle.getUserId(1), "first"), "DEFAULT");
+        expected.put(new Pair<>(UserHandle.getUserId(3), "third"), "NONE");
 
         // packages that exist in both app permissions & local preferences
-        expected.put(new Pair(UserHandle.getUserId(UID_P), PKG_P), "DEFAULT");
-        expected.put(new Pair(UserHandle.getUserId(UID_O), PKG_O), "NONE");
+        expected.put(new Pair<>(UserHandle.getUserId(UID_P), PKG_P), "DEFAULT");
+        expected.put(new Pair<>(UserHandle.getUserId(UID_O), PKG_O), "NONE");
 
         // package that only exists in local preferences; expect no importance output
-        expected.put(new Pair(UserHandle.getUserId(UID_N_MR1), PKG_N_MR1), null);
+        expected.put(new Pair<>(UserHandle.getUserId(UID_N_MR1), PKG_N_MR1), null);
 
         JSONArray actual = (JSONArray) mHelper.dumpJson(
                 new NotificationManagerService.DumpFilter(), appPermissions)
@@ -2918,7 +2917,7 @@
         for (int i = 0; i < actual.length(); i++) {
             JSONObject pkgInfo = actual.getJSONObject(i);
             Pair<Integer, String> pkgKey =
-                    new Pair(pkgInfo.getInt("userId"), pkgInfo.getString("packageName"));
+                    new Pair<>(pkgInfo.getInt("userId"), pkgInfo.getString("packageName"));
             assertTrue(expected.containsKey(pkgKey));
             if (pkgInfo.has("importance")) {
                 assertThat(pkgInfo.getString("importance")).isEqualTo(expected.get(pkgKey));
@@ -2957,16 +2956,16 @@
         // have their permission set to false, and not based on PackagePreferences importance
 
         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
-        appPermissions.put(new Pair(1, "first"), new Pair(true, false));    // not in local prefs
-        appPermissions.put(new Pair(3, "third"), new Pair(false, false));   // not in local prefs
-        appPermissions.put(new Pair(UID_O, PKG_O), new Pair(false, false)); // in local prefs
+        appPermissions.put(new Pair<>(1, "first"), new Pair<>(true, false)); // not in local prefs
+        appPermissions.put(new Pair<>(3, "third"), new Pair<>(false, false)); // not in local prefs
+        appPermissions.put(new Pair<>(UID_O, PKG_O), new Pair<>(false, false)); // in local prefs
 
         mHelper.canShowBadge(PKG_O, UID_O);
 
         // expected output
         ArraySet<Pair<Integer, String>> expected = new ArraySet<>();
-        expected.add(new Pair(UserHandle.getUserId(3), "third"));
-        expected.add(new Pair(UserHandle.getUserId(UID_O), PKG_O));
+        expected.add(new Pair<>(UserHandle.getUserId(3), "third"));
+        expected.add(new Pair<>(UserHandle.getUserId(UID_O), PKG_O));
 
         // make sure that's the only thing in the package ban output
         JSONArray actual = mHelper.dumpBansJson(
@@ -2976,7 +2975,7 @@
         for (int i = 0; i < actual.length(); i++) {
             JSONObject ban = actual.getJSONObject(i);
             assertTrue(expected.contains(
-                    new Pair(ban.getInt("userId"), ban.getString("packageName"))));
+                    new Pair<>(ban.getInt("userId"), ban.getString("packageName"))));
         }
     }
 
@@ -2994,9 +2993,9 @@
         // confirm that the string resulting from dumpImpl contains only importances from permission
 
         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
-        appPermissions.put(new Pair(1, "first"), new Pair(true, false));    // not in local prefs
-        appPermissions.put(new Pair(3, "third"), new Pair(false, true));   // not in local prefs
-        appPermissions.put(new Pair(UID_O, PKG_O), new Pair(false, false)); // in local prefs
+        appPermissions.put(new Pair<>(1, "first"), new Pair<>(true, false)); // not in local prefs
+        appPermissions.put(new Pair<>(3, "third"), new Pair<>(false, true)); // not in local prefs
+        appPermissions.put(new Pair<>(UID_O, PKG_O), new Pair<>(false, false)); // in local prefs
 
         // local package preferences
         mHelper.canShowBadge(PKG_O, UID_O);
@@ -3055,9 +3054,9 @@
 
         // permissions -- these should take precedence
         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
-        appPermissions.put(new Pair(1, "first"), new Pair(true, false));    // not in local prefs
-        appPermissions.put(new Pair(3, "third"), new Pair(false, false));   // not in local prefs
-        appPermissions.put(new Pair(UID_O, PKG_O), new Pair(false, false)); // in local prefs
+        appPermissions.put(new Pair<>(1, "first"), new Pair<>(true, false)); // not in local prefs
+        appPermissions.put(new Pair<>(3, "third"), new Pair<>(false, false)); // not in local prefs
+        appPermissions.put(new Pair<>(UID_O, PKG_O), new Pair<>(false, false)); // in local prefs
 
         // local package preferences
         mHelper.canShowBadge(PKG_O, UID_O);
@@ -3067,14 +3066,14 @@
         // should have importance set (aka not PKG_P)
         // map format: (uid, package name) -> importance (int)
         ArrayMap<Pair<Integer, String>, Integer> expected = new ArrayMap<>();
-        expected.put(new Pair(1, "first"), IMPORTANCE_DEFAULT);
-        expected.put(new Pair(3, "third"), IMPORTANCE_NONE);
-        expected.put(new Pair(UID_O, PKG_O), IMPORTANCE_NONE);
+        expected.put(new Pair<>(1, "first"), IMPORTANCE_DEFAULT);
+        expected.put(new Pair<>(3, "third"), IMPORTANCE_NONE);
+        expected.put(new Pair<>(UID_O, PKG_O), IMPORTANCE_NONE);
 
         // unfortunately, due to how nano protos work, there's no distinction between unset
         // fields and default-value fields, so we have no choice here but to check for a value of 0.
         // at least we can make sure the local importance for PKG_P in this test is not 0 (NONE).
-        expected.put(new Pair(UID_P, PKG_P), 0);
+        expected.put(new Pair<>(UID_P, PKG_P), 0);
 
         // get the proto output and inspect its contents
         ProtoOutputStream proto = new ProtoOutputStream();
@@ -3084,7 +3083,7 @@
         assertThat(actual.records.length).isEqualTo(expected.size());
         for (int i = 0; i < actual.records.length; i++) {
             RankingHelperProto.RecordProto record = actual.records[i];
-            Pair<Integer, String> pkgKey = new Pair(record.uid, record.package_);
+            Pair<Integer, String> pkgKey = new Pair<>(record.uid, record.package_);
             assertTrue(expected.containsKey(pkgKey));
             assertThat(record.importance).isEqualTo(expected.get(pkgKey));
         }
@@ -3403,26 +3402,6 @@
     }
 
     @Test
-    public void testToggleNotificationDelegate() {
-        mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53);
-        mHelper.toggleNotificationDelegate(PKG_O, UID_O, false);
-
-        assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
-
-        mHelper.toggleNotificationDelegate(PKG_O, UID_O, true);
-        assertEquals("other", mHelper.getNotificationDelegate(PKG_O, UID_O));
-    }
-
-    @Test
-    public void testToggleNotificationDelegate_noDelegateExistsNoCrash() {
-        mHelper.toggleNotificationDelegate(PKG_O, UID_O, false);
-        assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
-
-        mHelper.toggleNotificationDelegate(PKG_O, UID_O, true);
-        assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
-    }
-
-    @Test
     public void testIsDelegateAllowed_noSource() {
         assertFalse(mHelper.isDelegateAllowed("does not exist", -1, "whatever", 0));
     }
@@ -3451,14 +3430,6 @@
     }
 
     @Test
-    public void testIsDelegateAllowed_delegateDisabledByUser() {
-        mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53);
-        mHelper.toggleNotificationDelegate(PKG_O, UID_O, false);
-
-        assertFalse(mHelper.isDelegateAllowed(PKG_O, UID_O, "other", 53));
-    }
-
-    @Test
     public void testIsDelegateAllowed() {
         mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53);
 
@@ -3503,46 +3474,8 @@
         loadStreamXml(baos, false, UserHandle.USER_ALL);
 
         assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
-    }
-
-    @Test
-    public void testDelegateXml_userDisabledDelegate() throws Exception {
-        mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53);
-        mHelper.toggleNotificationDelegate(PKG_O, UID_O, false);
-
-        ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
-        mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger,
-                mAppOpsManager, mStatsEventBuilderFactory, false);
-        loadStreamXml(baos, false, UserHandle.USER_ALL);
-
-        // appears disabled
-        assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
-
-        // but was loaded and can be toggled back on
-        mHelper.toggleNotificationDelegate(PKG_O, UID_O, true);
-        assertEquals("other", mHelper.getNotificationDelegate(PKG_O, UID_O));
-    }
-
-    @Test
-    public void testDelegateXml_entirelyDisabledDelegate() throws Exception {
-        mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53);
-        mHelper.toggleNotificationDelegate(PKG_O, UID_O, false);
-        mHelper.revokeNotificationDelegate(PKG_O, UID_O);
-
-        ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
-        mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mLogger,
-                mAppOpsManager, mStatsEventBuilderFactory, false);
-        loadStreamXml(baos, false, UserHandle.USER_ALL);
-
-        // appears disabled
-        assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
 
         mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53);
-        assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
-
-        mHelper.toggleNotificationDelegate(PKG_O, UID_O, true);
         assertEquals("other", mHelper.getNotificationDelegate(PKG_O, UID_O));
     }
 
@@ -3686,7 +3619,7 @@
     @Test
     public void testUpdateNotificationChannel_defaultApp() {
         ArraySet<Pair<String, Integer>> toAdd = new ArraySet<>();
-        toAdd.add(new Pair(PKG_O, UID_O));
+        toAdd.add(new Pair<>(PKG_O, UID_O));
         mHelper.updateDefaultApps(0, null, toAdd);
         NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
         mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false);
@@ -3820,7 +3753,7 @@
         mHelper.createNotificationChannel(PKG_O, UserHandle.PER_USER_RANGE + 1, c, true, true);
 
         ArraySet<Pair<String, Integer>> toAdd = new ArraySet<>();
-        toAdd.add(new Pair(PKG_O, UID_O));
+        toAdd.add(new Pair<>(PKG_O, UID_O));
         mHelper.updateDefaultApps(UserHandle.getUserId(UID_O), null, toAdd);
 
         assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false)
@@ -3840,7 +3773,7 @@
         mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, b, false, false);
 
         ArraySet<Pair<String, Integer>> toAdd = new ArraySet<>();
-        toAdd.add(new Pair(PKG_O, UID_O));
+        toAdd.add(new Pair<>(PKG_O, UID_O));
         mHelper.updateDefaultApps(UserHandle.getUserId(UID_O), null, toAdd);
 
         assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false)
@@ -3858,7 +3791,7 @@
         mHelper.createNotificationChannel(PKG_O, UID_O, b, false, false);
 
         ArraySet<Pair<String, Integer>> toAdd = new ArraySet<>();
-        toAdd.add(new Pair(PKG_O, UID_O));
+        toAdd.add(new Pair<>(PKG_O, UID_O));
         mHelper.updateDefaultApps(UserHandle.getUserId(UID_O), null, toAdd);
 
         assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false)
@@ -3884,7 +3817,7 @@
         mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, b, false, false);
 
         ArraySet<Pair<String, Integer>> toAdd = new ArraySet<>();
-        toAdd.add(new Pair(PKG_O, UID_O));
+        toAdd.add(new Pair<>(PKG_O, UID_O));
         mHelper.updateDefaultApps(UserHandle.getUserId(UID_O), null, toAdd);
 
 
@@ -3897,7 +3830,7 @@
         ArraySet<String> toRemove = new ArraySet<>();
         toRemove.add(PKG_O);
         toAdd = new ArraySet<>();
-        toAdd.add(new Pair(PKG_N_MR1, UID_N_MR1));
+        toAdd.add(new Pair<>(PKG_N_MR1, UID_N_MR1));
         mHelper.updateDefaultApps(USER.getIdentifier(), toRemove, toAdd);
 
         assertFalse(mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false)
@@ -3909,7 +3842,7 @@
     @Test
     public void testUpdateDefaultApps_appDoesNotExist_noCrash() {
         ArraySet<Pair<String, Integer>> toAdd = new ArraySet<>();
-        toAdd.add(new Pair(PKG_O, UID_O));
+        toAdd.add(new Pair<>(PKG_O, UID_O));
         ArraySet<String> toRemove = new ArraySet<>();
         toRemove.add(PKG_N_MR1);
         mHelper.updateDefaultApps(UserHandle.getUserId(UID_O), toRemove, toAdd);
@@ -3922,7 +3855,7 @@
         mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false);
 
         ArraySet<Pair<String, Integer>> toAdd = new ArraySet<>();
-        toAdd.add(new Pair(PKG_O, UID_O));
+        toAdd.add(new Pair<>(PKG_O, UID_O));
         mHelper.updateDefaultApps(UserHandle.getUserId(UID_O), null, toAdd);
 
         assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false)
@@ -3938,7 +3871,7 @@
         NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
         mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false);
         ArraySet<Pair<String, Integer>> toAdd = new ArraySet<>();
-        toAdd.add(new Pair(PKG_O, UID_O));
+        toAdd.add(new Pair<>(PKG_O, UID_O));
         mHelper.updateDefaultApps(UserHandle.getUserId(UID_O), null, toAdd);
 
         NotificationChannel update = new NotificationChannel("a", "a", IMPORTANCE_NONE);
@@ -3964,7 +3897,7 @@
     @Test
     public void testDefaultApp_appHasNoSettingsYet() {
         ArraySet<Pair<String, Integer>> toAdd = new ArraySet<>();
-        toAdd.add(new Pair(PKG_O, UID_O));
+        toAdd.add(new Pair<>(PKG_O, UID_O));
         mHelper.updateDefaultApps(UserHandle.getUserId(UID_O), null, toAdd);
 
         NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
@@ -4004,7 +3937,7 @@
     @Test
     public void testUpdateDefaultApps_thenNotFixedPermission() {
         ArraySet<Pair<String, Integer>> toAdd = new ArraySet<>();
-        toAdd.add(new Pair(PKG_O, UID_O));
+        toAdd.add(new Pair<>(PKG_O, UID_O));
         mHelper.updateDefaultApps(0, null, toAdd);
 
         UserInfo user = new UserInfo();
@@ -4043,7 +3976,7 @@
                 UID_O});
 
         ArraySet<Pair<String, Integer>> toAdd = new ArraySet<>();
-        toAdd.add(new Pair(PKG_O, UID_O));
+        toAdd.add(new Pair<>(PKG_O, UID_O));
         mHelper.updateDefaultApps(UserHandle.getUserId(UID_O), null, toAdd);
 
         TypedXmlPullParser parser = Xml.newFastPullParser();
@@ -4131,17 +4064,26 @@
     }
 
     @Test
-    public void testTooManyGroups() {
+    public void testTooManyGroups_fromTargetApp() {
+        testTooManyGroups(/* fromTargetApp= */ true);
+    }
+
+    @Test
+    public void testTooManyGroups_fromListener() {
+        testTooManyGroups(/* fromTargetApp= */ false);
+    }
+
+    private void testTooManyGroups(boolean fromTargetApp) {
         for (int i = 0; i < NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT; i++) {
             NotificationChannelGroup group = new NotificationChannelGroup(String.valueOf(i),
                     String.valueOf(i));
-            mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, true);
+            mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, fromTargetApp);
         }
         try {
             NotificationChannelGroup group = new NotificationChannelGroup(
                     String.valueOf(NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT),
                     String.valueOf(NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT));
-            mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, true);
+            mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, fromTargetApp);
             fail("Allowed to create too many notification channel groups");
         } catch (IllegalStateException e) {
             // great
@@ -5032,9 +4974,9 @@
 
         // build a collection of app permissions that should be passed in but ignored
         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
-        appPermissions.put(new Pair(1, "first"), new Pair(true, false));    // not in local prefs
-        appPermissions.put(new Pair(3, "third"), new Pair(false, true));   // not in local prefs
-        appPermissions.put(new Pair(UID_O, PKG_O), new Pair(false, true)); // in local prefs
+        appPermissions.put(new Pair<>(1, "first"), new Pair<>(true, false)); // not in local prefs
+        appPermissions.put(new Pair<>(3, "third"), new Pair<>(false, true)); // not in local prefs
+        appPermissions.put(new Pair<>(UID_O, PKG_O), new Pair<>(false, true)); // in local prefs
 
         // local preferences
         mHelper.canShowBadge(PKG_O, UID_O);
@@ -5043,10 +4985,10 @@
         // expected output. format: uid -> importance, as only uid (and not package name)
         // is in PackageNotificationPreferences
         ArrayMap<Integer, Pair<Integer, Boolean>> expected = new ArrayMap<>();
-        expected.put(1, new Pair(IMPORTANCE_DEFAULT, false));
-        expected.put(3, new Pair(IMPORTANCE_NONE, true));
-        expected.put(UID_O, new Pair(IMPORTANCE_NONE, true));     // banned by permissions
-        expected.put(UID_P, new Pair(IMPORTANCE_NONE, false));    // defaults to none, false
+        expected.put(1, new Pair<>(IMPORTANCE_DEFAULT, false));
+        expected.put(3, new Pair<>(IMPORTANCE_NONE, true));
+        expected.put(UID_O, new Pair<>(IMPORTANCE_NONE, true));     // banned by permissions
+        expected.put(UID_P, new Pair<>(IMPORTANCE_NONE, false));    // defaults to none, false
 
         ArrayList<StatsEvent> events = new ArrayList<>();
         mHelper.pullPackagePreferencesStats(events, appPermissions);
@@ -5100,4 +5042,72 @@
         assertTrue((channelB.getUserLockedFields() & USER_LOCKED_IMPORTANCE) == 0);
         assertTrue((channelC.getUserLockedFields() & USER_LOCKED_IMPORTANCE) == 0);
     }
+
+    @Test
+    public void createNotificationChannel_updateDifferent_requestsSort() {
+        NotificationChannel original = new NotificationChannel("id", "Bah", IMPORTANCE_DEFAULT);
+        mHelper.createNotificationChannel(PKG_P, 0, original, true, false);
+        clearInvocations(mHandler);
+
+        NotificationChannel updated = new NotificationChannel("id", "Wow", IMPORTANCE_DEFAULT);
+        mHelper.createNotificationChannel(PKG_P, 0, updated, true, false);
+
+        verify(mHandler).requestSort();
+    }
+
+    @Test
+    public void createNotificationChannel_updateSame_doesNotRequestSort() {
+        NotificationChannel original = new NotificationChannel("id", "Bah", IMPORTANCE_DEFAULT);
+        mHelper.createNotificationChannel(PKG_P, 0, original, true, false);
+        clearInvocations(mHandler);
+
+        NotificationChannel same = new NotificationChannel("id", "Bah", IMPORTANCE_DEFAULT);
+        mHelper.createNotificationChannel(PKG_P, 0, same, true, false);
+
+        verifyZeroInteractions(mHandler);
+    }
+
+    @Test
+    public void updateNotificationChannel_different_requestsSort() {
+        NotificationChannel original = new NotificationChannel("id", "Bah", IMPORTANCE_DEFAULT);
+        mHelper.createNotificationChannel(PKG_P, 0, original, true, false);
+        clearInvocations(mHandler);
+
+        NotificationChannel updated = new NotificationChannel("id", "Wow", IMPORTANCE_DEFAULT);
+        mHelper.updateNotificationChannel(PKG_P, 0, updated, false);
+
+        verify(mHandler).requestSort();
+    }
+
+    @Test
+    public void updateNotificationChannel_same_doesNotRequestSort() {
+        NotificationChannel original = new NotificationChannel("id", "Bah", IMPORTANCE_DEFAULT);
+        mHelper.createNotificationChannel(PKG_P, 0, original, true, false);
+        clearInvocations(mHandler);
+        // Note: Creating a NotificationChannel identical to the original is not equals(), because
+        // of mOriginalImportance. So we create a "true copy" instead.
+        Parcel parcel = Parcel.obtain();
+        original.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+        NotificationChannel same = NotificationChannel.CREATOR.createFromParcel(parcel);
+        parcel.recycle();
+
+        mHelper.updateNotificationChannel(PKG_P, 0, same, false);
+
+        verifyZeroInteractions(mHandler);
+    }
+
+    @Test
+    public void setShowBadge_update_requestsSort() {
+        mHelper.setShowBadge(PKG_P, 0, false);
+
+        verify(mHandler).requestSort();
+    }
+
+    @Test
+    public void setShowBadge_same_doesNotRequestSort() {
+        mHelper.setShowBadge(PKG_P, 0, true); // true == DEFAULT_SHOW_BADGE
+
+        verifyZeroInteractions(mHandler);
+    }
 }
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 12f124e..6f6e2242 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -38,11 +38,12 @@
 import static android.util.StatsLog.ANNOTATION_ID_IS_UID;
 
 import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;
-import static com.android.os.AtomsProto.DNDModeProto.CHANNELS_BYPASSING_FIELD_NUMBER;
-import static com.android.os.AtomsProto.DNDModeProto.ENABLED_FIELD_NUMBER;
-import static com.android.os.AtomsProto.DNDModeProto.ID_FIELD_NUMBER;
-import static com.android.os.AtomsProto.DNDModeProto.UID_FIELD_NUMBER;
-import static com.android.os.AtomsProto.DNDModeProto.ZEN_MODE_FIELD_NUMBER;
+import static com.android.os.dnd.DNDModeProto.CHANNELS_BYPASSING_FIELD_NUMBER;
+import static com.android.os.dnd.DNDModeProto.ENABLED_FIELD_NUMBER;
+import static com.android.os.dnd.DNDModeProto.ID_FIELD_NUMBER;
+import static com.android.os.dnd.DNDModeProto.UID_FIELD_NUMBER;
+import static com.android.os.dnd.DNDModeProto.ZEN_MODE_FIELD_NUMBER;
+import static com.android.os.dnd.DNDProtoEnums.ROOT_CONFIG;
 import static com.android.server.notification.ZenModeHelper.RULE_LIMIT_PER_PACKAGE;
 
 import static junit.framework.Assert.assertEquals;
@@ -95,7 +96,6 @@
 import android.provider.Settings;
 import android.provider.Settings.Global;
 import android.service.notification.Condition;
-import android.service.notification.DNDModeProto;
 import android.service.notification.ZenModeConfig;
 import android.service.notification.ZenModeConfig.ScheduleInfo;
 import android.service.notification.ZenPolicy;
@@ -898,7 +898,7 @@
         assertEquals(n + 1, events.size());
         for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) {
             if (builder.getAtomId() == DND_MODE_RULE) {
-                if (builder.getInt(ZEN_MODE_FIELD_NUMBER) == DNDModeProto.ROOT_CONFIG) {
+                if (builder.getInt(ZEN_MODE_FIELD_NUMBER) == ROOT_CONFIG) {
                     assertTrue(builder.getBoolean(ENABLED_FIELD_NUMBER));
                     assertFalse(builder.getBoolean(CHANNELS_BYPASSING_FIELD_NUMBER));
                 }
diff --git a/services/tests/voiceinteractiontests/src/com/android/server/soundtrigger_middleware/ConversionUtilTest.java b/services/tests/voiceinteractiontests/src/com/android/server/soundtrigger_middleware/ConversionUtilTest.java
index 5a2ce45..5661b12 100644
--- a/services/tests/voiceinteractiontests/src/com/android/server/soundtrigger_middleware/ConversionUtilTest.java
+++ b/services/tests/voiceinteractiontests/src/com/android/server/soundtrigger_middleware/ConversionUtilTest.java
@@ -16,15 +16,33 @@
 
 package com.android.server.soundtrigger_middleware;
 
+import static android.hardware.soundtrigger.ConversionUtil.aidl2apiAudioFormatWithDefault;
+import static android.hardware.soundtrigger.ConversionUtil.aidl2apiPhrase;
+import static android.hardware.soundtrigger.ConversionUtil.aidl2apiRecognitionConfig;
+import static android.hardware.soundtrigger.ConversionUtil.api2aidlPhrase;
+import static android.hardware.soundtrigger.ConversionUtil.api2aidlRecognitionConfig;
+import static android.hardware.soundtrigger.ConversionUtil.byteArrayToSharedMemory;
+import static android.hardware.soundtrigger.ConversionUtil.sharedMemoryToByteArray;
+import static android.hardware.soundtrigger.SoundTrigger.ConfidenceLevel;
+import static android.hardware.soundtrigger.SoundTrigger.RECOGNITION_MODE_GENERIC;
+import static android.hardware.soundtrigger.SoundTrigger.RECOGNITION_MODE_USER_AUTHENTICATION;
+import static android.hardware.soundtrigger.SoundTrigger.RECOGNITION_MODE_USER_IDENTIFICATION;
+import static android.hardware.soundtrigger.SoundTrigger.RECOGNITION_MODE_VOICE_TRIGGER;
+
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 
 import android.hardware.audio.common.V2_0.Uuid;
+import android.hardware.soundtrigger.SoundTrigger;
 
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.Locale;
+
 @RunWith(AndroidJUnit4.class)
 public class ConversionUtilTest {
     private static final String TAG = "ConversionUtilTest";
@@ -44,4 +62,54 @@
         Uuid reconstructed = ConversionUtil.aidl2hidlUuid(aidl);
         assertEquals(hidl, reconstructed);
     }
+
+    @Test
+    public void testDefaultAudioFormatConstruction() {
+        // This method should generate a real format when passed null
+        final var format = aidl2apiAudioFormatWithDefault(
+                null /** exercise default **/,
+                true /** isInput **/
+                );
+        assertNotNull(format);
+    }
+
+    @Test
+    public void testRecognitionConfigRoundTrip() {
+        final int flags = SoundTrigger.ModuleProperties.AUDIO_CAPABILITY_ECHO_CANCELLATION
+                | SoundTrigger.ModuleProperties.AUDIO_CAPABILITY_NOISE_SUPPRESSION;
+        final var data = new byte[] {0x11, 0x22};
+        final var keyphrases = new SoundTrigger.KeyphraseRecognitionExtra[2];
+        keyphrases[0] = new SoundTrigger.KeyphraseRecognitionExtra(99,
+                RECOGNITION_MODE_VOICE_TRIGGER | RECOGNITION_MODE_USER_IDENTIFICATION, 13,
+                    new ConfidenceLevel[] {new ConfidenceLevel(9999, 50),
+                                           new ConfidenceLevel(5000, 80)});
+        keyphrases[1] = new SoundTrigger.KeyphraseRecognitionExtra(101,
+                RECOGNITION_MODE_GENERIC, 8, new ConfidenceLevel[] {
+                    new ConfidenceLevel(7777, 30),
+                    new ConfidenceLevel(2222, 60)});
+
+        var apiconfig = new SoundTrigger.RecognitionConfig(true, false /** must be false **/,
+                keyphrases, data, flags);
+        assertEquals(apiconfig, aidl2apiRecognitionConfig(api2aidlRecognitionConfig(apiconfig)));
+    }
+
+    @Test
+    public void testByteArraySharedMemRoundTrip() {
+        final var data = new byte[] { 0x11, 0x22, 0x33, 0x44,
+                (byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef };
+        assertArrayEquals(data, sharedMemoryToByteArray(byteArrayToSharedMemory(data, "name"),
+                    10000000));
+
+    }
+
+    @Test
+    public void testPhraseRoundTrip() {
+        final var users = new int[] {10001, 10002};
+        final var apiphrase = new SoundTrigger.Keyphrase(17 /** id **/,
+                RECOGNITION_MODE_VOICE_TRIGGER | RECOGNITION_MODE_USER_AUTHENTICATION,
+                Locale.forLanguageTag("no_NO"),
+                "Hello Android", /** keyphrase **/
+                users);
+        assertEquals(apiphrase, aidl2apiPhrase(api2aidlPhrase(apiphrase)));
+    }
 }
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 6661e6a..6147633 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -2377,7 +2377,7 @@
                 .setScreenOrientation(SCREEN_ORIENTATION_BEHIND)
                 .build();
         final int topOrientation = activityTop.getRequestedConfigurationOrientation();
-        assertEquals(SCREEN_ORIENTATION_PORTRAIT, topOrientation);
+        assertEquals(ORIENTATION_PORTRAIT, topOrientation);
     }
 
     private void verifyProcessInfoUpdate(ActivityRecord activity, State state,
@@ -2897,7 +2897,7 @@
 
         // Make the top one invisible, and try transferring the starting window from the top to the
         // bottom one.
-        activityTop.setVisibility(false, false);
+        activityTop.setVisibility(false);
         activityBottom.transferStartingWindowFromHiddenAboveTokenIfNeeded();
         waitUntilHandlersIdle();
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index e3cb5fb..b46a3b9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -1728,7 +1728,7 @@
         final ActivityInfo info = new ActivityInfo();
         info.applicationInfo = new ApplicationInfo();
         info.taskAffinity = ActivityRecord.computeTaskAffinity("test", DEFAULT_FAKE_UID,
-                0 /* launchMode */);
+                0 /* launchMode */, null /* componentName */);
         info.requiredDisplayCategory = "automotive";
         final Task task = new TaskBuilder(mSupervisor).setCreateActivity(true).setActivityInfo(info)
                 .build();
@@ -1754,7 +1754,7 @@
         final ActivityInfo info = new ActivityInfo();
         info.applicationInfo = new ApplicationInfo();
         info.taskAffinity = ActivityRecord.computeTaskAffinity("test", DEFAULT_FAKE_UID,
-                0 /* launchMode */);
+                0 /* launchMode */, null /* componentName */);
         info.requiredDisplayCategory = "automotive";
         final Task task = new TaskBuilder(mSupervisor).setCreateActivity(true).setActivityInfo(info)
                 .build();
@@ -1780,7 +1780,7 @@
         final ActivityInfo info = new ActivityInfo();
         info.applicationInfo = new ApplicationInfo();
         info.taskAffinity = ActivityRecord.computeTaskAffinity("test", DEFAULT_FAKE_UID,
-                0 /* launchMode */);
+                0 /* launchMode */, null /* componentName */);
         info.requiredDisplayCategory = "automotive";
         final Task task = new TaskBuilder(mSupervisor).setCreateActivity(true).setActivityInfo(info)
                 .build();
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index 3dcae91..0044e2e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -66,6 +66,7 @@
 import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.IDisplayWindowListener;
+import android.view.WindowManager;
 
 import androidx.test.filters.MediumTest;
 
@@ -456,13 +457,15 @@
         mAtm.mSupportsNonResizableMultiWindow = 0;
 
         // Supports on large screen.
-        tda.getConfiguration().smallestScreenWidthDp = mAtm.mLargeScreenSmallestScreenWidthDp;
+        tda.getConfiguration().smallestScreenWidthDp =
+                WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP;
 
         assertTrue(activity.supportsMultiWindow());
         assertTrue(task.supportsMultiWindow());
 
         // Not supports on small screen.
-        tda.getConfiguration().smallestScreenWidthDp = mAtm.mLargeScreenSmallestScreenWidthDp - 1;
+        tda.getConfiguration().smallestScreenWidthDp =
+                WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP - 1;
 
         assertFalse(activity.supportsMultiWindow());
         assertFalse(task.supportsMultiWindow());
@@ -475,8 +478,10 @@
                 new ActivityInfo.WindowLayout(0, 0, 0, 0, 0,
                         // This is larger than the min dimensions device support in multi window,
                         // the activity will not be supported in multi window if the device respects
-                        /* minWidth= */(int) (mAtm.mLargeScreenSmallestScreenWidthDp * density),
-                        /* minHeight= */(int) (mAtm.mLargeScreenSmallestScreenWidthDp * density));
+                        /* minWidth= */
+                        (int) (WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP * density),
+                        /* minHeight= */
+                        (int) (WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP * density));
         final ActivityRecord activity = new ActivityBuilder(mAtm)
                 .setCreateTask(true)
                 .setWindowLayout(windowLayout)
@@ -501,13 +506,15 @@
         mAtm.mRespectsActivityMinWidthHeightMultiWindow = 0;
 
         // Ignore on large screen.
-        tda.getConfiguration().smallestScreenWidthDp = mAtm.mLargeScreenSmallestScreenWidthDp;
+        tda.getConfiguration().smallestScreenWidthDp =
+                WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP;
 
         assertTrue(activity.supportsMultiWindow());
         assertTrue(task.supportsMultiWindow());
 
         // Check on small screen.
-        tda.getConfiguration().smallestScreenWidthDp = mAtm.mLargeScreenSmallestScreenWidthDp - 1;
+        tda.getConfiguration().smallestScreenWidthDp =
+                WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP - 1;
 
         assertFalse(activity.supportsMultiWindow());
         assertFalse(task.supportsMultiWindow());
@@ -518,7 +525,7 @@
         // This is smaller than the min dimensions device support in multi window,
         // the activity will be supported in multi window
         final float density = mContext.getResources().getDisplayMetrics().density;
-        final int supportedWidth = (int) (mAtm.mLargeScreenSmallestScreenWidthDp
+        final int supportedWidth = (int) (WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP
                 * mAtm.mMinPercentageMultiWindowSupportWidth * density);
         final ActivityInfo.WindowLayout windowLayout =
                 new ActivityInfo.WindowLayout(0, 0, 0, 0, 0,
@@ -531,15 +538,17 @@
                 .build();
         final Task task = activity.getTask();
         final TaskDisplayArea tda = task.getDisplayArea();
-        tda.getConfiguration().smallestScreenWidthDp = mAtm.mLargeScreenSmallestScreenWidthDp - 1;
-        tda.getConfiguration().screenWidthDp = mAtm.mLargeScreenSmallestScreenWidthDp - 1;
+        tda.getConfiguration().smallestScreenWidthDp =
+                WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP - 1;
+        tda.getConfiguration().screenWidthDp =
+                WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP - 1;
         tda.getConfiguration().orientation = ORIENTATION_LANDSCAPE;
 
         assertFalse(activity.supportsMultiWindow());
         assertFalse(task.supportsMultiWindow());
 
         tda.getConfiguration().screenWidthDp = (int) Math.ceil(
-                mAtm.mLargeScreenSmallestScreenWidthDp
+                WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP
                         / mAtm.mMinPercentageMultiWindowSupportWidth);
 
         assertTrue(activity.supportsMultiWindow());
@@ -551,7 +560,7 @@
         // This is smaller than the min dimensions device support in multi window,
         // the activity will be supported in multi window
         final float density = mContext.getResources().getDisplayMetrics().density;
-        final int supportedHeight = (int) (mAtm.mLargeScreenSmallestScreenWidthDp
+        final int supportedHeight = (int) (WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP
                 * mAtm.mMinPercentageMultiWindowSupportHeight * density);
         final ActivityInfo.WindowLayout windowLayout =
                 new ActivityInfo.WindowLayout(0, 0, 0, 0, 0,
@@ -564,15 +573,17 @@
                 .build();
         final Task task = activity.getTask();
         final TaskDisplayArea tda = task.getDisplayArea();
-        tda.getConfiguration().smallestScreenWidthDp = mAtm.mLargeScreenSmallestScreenWidthDp - 1;
-        tda.getConfiguration().screenHeightDp = mAtm.mLargeScreenSmallestScreenWidthDp - 1;
+        tda.getConfiguration().smallestScreenWidthDp =
+                WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP - 1;
+        tda.getConfiguration().screenHeightDp =
+                WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP - 1;
         tda.getConfiguration().orientation = ORIENTATION_PORTRAIT;
 
         assertFalse(activity.supportsMultiWindow());
         assertFalse(task.supportsMultiWindow());
 
         tda.getConfiguration().screenHeightDp = (int) Math.ceil(
-                mAtm.mLargeScreenSmallestScreenWidthDp
+                WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP
                         / mAtm.mMinPercentageMultiWindowSupportHeight);
 
         assertTrue(activity.supportsMultiWindow());
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
index 4d71b30..6d13124 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
@@ -165,7 +165,7 @@
         assertTrue(mTask.isInChangeTransition());
 
         // Changing visibility should cancel the change transition and become closing
-        mActivity.setVisibility(false, false);
+        mActivity.setVisibility(false);
         assertEquals(0, mDisplayContent.mChangingContainers.size());
         assertFalse(mTask.isInChangeTransition());
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index 6b814e6..59cc4f5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -295,8 +295,8 @@
         dc2.prepareAppTransition(TRANSIT_CLOSE);
         // One activity window is visible for resuming & the other activity window is invisible
         // for finishing in different display.
-        activity1.setVisibility(true, false);
-        activity2.setVisibility(false, false);
+        activity1.setVisibility(true);
+        activity2.setVisibility(false);
 
         // Make sure each display is in animating stage.
         assertTrue(dc1.mOpeningApps.size() > 0);
@@ -365,7 +365,7 @@
         dc.prepareAppTransition(TRANSIT_CLOSE);
         assertTrue(dc.mAppTransition.containsTransitRequest(TRANSIT_CLOSE));
         dc.mAppTransition.overridePendingAppTransitionRemote(adapter);
-        exitingActivity.setVisibility(false, false);
+        exitingActivity.setVisibility(false);
         assertTrue(dc.mClosingApps.size() > 0);
 
         // Make sure window is in animating stage before freeze, and cancel after freeze.
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 56461f0..b80c3e8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
@@ -26,6 +26,7 @@
 import static android.window.BackNavigationInfo.typeToString;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
@@ -149,6 +150,28 @@
     }
 
     @Test
+    public void backTypeCrossActivityWithCustomizeExitAnimation() {
+        CrossActivityTestCase testCase = createTopTaskWithTwoActivities();
+        IOnBackInvokedCallback callback = withSystemCallback(testCase.task);
+        testCase.windowFront.mAttrs.windowAnimations = 0x10;
+        spyOn(mDisplayContent.mAppTransition.mTransitionAnimation);
+        doReturn(0xffff00AB).when(mDisplayContent.mAppTransition.mTransitionAnimation)
+                .getAnimationResId(any(), anyInt(), anyInt());
+        doReturn(0xffff00CD).when(mDisplayContent.mAppTransition.mTransitionAnimation)
+                .getDefaultAnimationResId(anyInt(), anyInt());
+
+        BackNavigationInfo backNavigationInfo = startBackNavigation();
+        assertWithMessage("BackNavigationInfo").that(backNavigationInfo).isNotNull();
+        assertThat(backNavigationInfo.getOnBackInvokedCallback()).isEqualTo(callback);
+        assertThat(backNavigationInfo.getCustomAnimationInfo().getWindowAnimations())
+                .isEqualTo(testCase.windowFront.mAttrs.windowAnimations);
+        assertThat(typeToString(backNavigationInfo.getType()))
+                .isEqualTo(typeToString(BackNavigationInfo.TYPE_CROSS_ACTIVITY));
+        // verify if back animation would start.
+        assertTrue("Animation scheduled", backNavigationInfo.isPrepareRemoteAnimation());
+    }
+
+    @Test
     public void backTypeCrossActivityWhenBackToPreviousActivity() {
         CrossActivityTestCase testCase = createTopTaskWithTwoActivities();
         IOnBackInvokedCallback callback = withSystemCallback(testCase.task);
@@ -158,6 +181,8 @@
         assertThat(backNavigationInfo.getOnBackInvokedCallback()).isEqualTo(callback);
         assertThat(typeToString(backNavigationInfo.getType()))
                 .isEqualTo(typeToString(BackNavigationInfo.TYPE_CROSS_ACTIVITY));
+        // verify if back animation would start.
+        assertTrue("Animation scheduled", backNavigationInfo.isPrepareRemoteAnimation());
 
         // reset drawing status
         testCase.recordFront.forAllWindows(w -> {
@@ -510,6 +535,8 @@
         testCase.task = task;
         testCase.recordBack = record1;
         testCase.recordFront = record2;
+        testCase.windowBack = window1;
+        testCase.windowFront = window2;
         return testCase;
     }
 
@@ -525,6 +552,8 @@
     private class CrossActivityTestCase {
         public Task task;
         public ActivityRecord recordBack;
+        public WindowState windowBack;
         public ActivityRecord recordFront;
+        public WindowState windowFront;
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java b/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java
index 8cc362c..17f6d51a7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java
@@ -35,6 +35,8 @@
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.never;
 
+import android.app.WindowConfiguration;
+import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -45,6 +47,7 @@
 import android.provider.DeviceConfig;
 import android.util.DisplayMetrics;
 import android.view.ContentRecordingSession;
+import android.view.Gravity;
 import android.view.Surface;
 import android.view.SurfaceControl;
 
@@ -258,8 +261,17 @@
 
     @Test
     public void testOnTaskBoundsConfigurationChanged_notifiesCallback() {
+        mTask.getRootTask().setWindowingMode(WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW);
+
         final int recordedWidth = 333;
         final int recordedHeight = 999;
+
+        final ActivityInfo info = new ActivityInfo();
+        info.windowLayout = new ActivityInfo.WindowLayout(-1 /* width */,
+                        -1 /* widthFraction */, -1 /* height */, -1 /* heightFraction */,
+                        Gravity.NO_GRAVITY, recordedWidth, recordedHeight);
+        mTask.setMinDimensions(info);
+
         // WHEN a recording is ongoing.
         mContentRecorder.setContentRecordingSession(mTaskSession);
         mContentRecorder.updateRecording();
@@ -267,7 +279,6 @@
 
         // WHEN a configuration change arrives, and the recorded content is a different size.
         mTask.setBounds(new Rect(0, 0, recordedWidth, recordedHeight));
-        mContentRecorder.onConfigurationChanged(mDefaultDisplay.getLastOrientation());
         assertThat(mContentRecorder.isCurrentlyRecording()).isTrue();
 
         // THEN content in the captured DisplayArea is scaled to fit the surface size.
diff --git a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
index 7830e90..3a456fb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
@@ -16,8 +16,9 @@
 
 package com.android.server.wm;
 
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.util.DisplayMetrics.DENSITY_DEFAULT;
 
 import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_BOUNDS;
@@ -79,24 +80,24 @@
     }
 
     @Test
-    public void testReturnsSkipIfTaskNotInFreeform() {
-        final Task task = new TaskBuilder(mSupervisor).setWindowingMode(
-                WINDOWING_MODE_FULLSCREEN).build();
+    public void testReturnsSkipIfTaskNotUsingActivityTypeStandard() {
+        final Task task = new TaskBuilder(mSupervisor).setActivityType(
+                ACTIVITY_TYPE_ASSISTANT).build();
         assertEquals(RESULT_SKIP, new CalculateRequestBuilder().setTask(task).calculate());
     }
 
     @Test
     public void testReturnsSkipIfCurrentParamsHasBounds() {
-        final Task task = new TaskBuilder(mSupervisor).setWindowingMode(
-                WINDOWING_MODE_FREEFORM).build();
+        final Task task = new TaskBuilder(mSupervisor).setActivityType(
+                ACTIVITY_TYPE_STANDARD).build();
         mCurrent.mBounds.set(/* left */ 0, /* top */ 0, /* right */ 100, /* bottom */ 100);
         assertEquals(RESULT_SKIP, new CalculateRequestBuilder().setTask(task).calculate());
     }
 
     @Test
     public void testUsesDefaultBounds() {
-        final Task task = new TaskBuilder(mSupervisor).setWindowingMode(
-                WINDOWING_MODE_FREEFORM).build();
+        final Task task = new TaskBuilder(mSupervisor).setActivityType(
+                ACTIVITY_TYPE_STANDARD).build();
         assertEquals(RESULT_DONE, new CalculateRequestBuilder().setTask(task).calculate());
         assertEquals(dpiToPx(task, 840), mResult.mBounds.width());
         assertEquals(dpiToPx(task, 630), mResult.mBounds.height());
@@ -104,8 +105,8 @@
 
     @Test
     public void testUsesDisplayAreaAndWindowingModeFromSource() {
-        final Task task = new TaskBuilder(mSupervisor).setWindowingMode(
-                WINDOWING_MODE_FREEFORM).build();
+        final Task task = new TaskBuilder(mSupervisor).setActivityType(
+                ACTIVITY_TYPE_STANDARD).build();
         TaskDisplayArea mockTaskDisplayArea = mock(TaskDisplayArea.class);
         mCurrent.mPreferredTaskDisplayArea = mockTaskDisplayArea;
         mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
diff --git a/services/tests/wmtests/src/com/android/server/wm/DeviceStateControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DeviceStateControllerTests.java
index 2723289..9d1fde4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DeviceStateControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DeviceStateControllerTests.java
@@ -21,6 +21,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 
 import android.content.Context;
@@ -55,6 +56,7 @@
     private DeviceStateManager mMockDeviceStateManager;
     private DeviceStateController.DeviceState mCurrentState =
             DeviceStateController.DeviceState.UNKNOWN;
+    private Consumer<DeviceStateController.DeviceState> mDelegate;
 
     @Before
     public void setUp() {
@@ -64,10 +66,10 @@
 
     private void initialize(boolean supportFold, boolean supportHalfFold) {
         mBuilder.setSupportFold(supportFold, supportHalfFold);
-        Consumer<DeviceStateController.DeviceState> delegate = (newFoldState) -> {
+        mDelegate = (newFoldState) -> {
             mCurrentState = newFoldState;
         };
-        mBuilder.setDelegate(delegate);
+        mBuilder.setDelegate(mDelegate);
         mBuilder.build();
         verify(mMockDeviceStateManager).registerCallback(any(), any());
     }
@@ -111,6 +113,24 @@
         assertEquals(DeviceStateController.DeviceState.CONCURRENT, mCurrentState);
     }
 
+    @Test
+    public void testUnregisterDeviceStateCallback() {
+        initialize(true /* supportFold */, true /* supportHalfFolded */);
+        assertEquals(1, mTarget.mDeviceStateCallbacks.size());
+        assertEquals(mDelegate, mTarget.mDeviceStateCallbacks.get(0));
+
+        mTarget.onStateChanged(mOpenDeviceStates[0]);
+        assertEquals(DeviceStateController.DeviceState.OPEN, mCurrentState);
+        mTarget.onStateChanged(mFoldedStates[0]);
+        assertEquals(DeviceStateController.DeviceState.FOLDED, mCurrentState);
+
+        // The callback should not receive state change when the it is unregistered.
+        mTarget.unregisterDeviceStateCallback(mDelegate);
+        assertTrue(mTarget.mDeviceStateCallbacks.isEmpty());
+        mTarget.onStateChanged(mOpenDeviceStates[0]);
+        assertEquals(DeviceStateController.DeviceState.FOLDED /* unchanged */, mCurrentState);
+    }
+
     private final int[] mFoldedStates = {0};
     private final int[] mOpenDeviceStates = {1};
     private final int[] mHalfFoldedStates = {2};
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 aaeae23..d071f13 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -34,7 +34,6 @@
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
 import static android.view.DisplayCutout.fromBoundingRect;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
 import static android.view.Surface.ROTATION_0;
 import static android.view.Surface.ROTATION_180;
 import static android.view.Surface.ROTATION_270;
@@ -1557,15 +1556,16 @@
         assertFalse(mNotificationShadeWindow.isAnimating(PARENTS, ANIMATION_TYPE_TOKEN_TRANSFORM));
 
         // If the visibility of insets state is changed, the rotated state should be updated too.
+        final int statusBarId = mStatusBarWindow.getControllableInsetProvider().getSource().getId();
         final InsetsState rotatedState = app.getFixedRotationTransformInsetsState();
         final InsetsState state = mDisplayContent.getInsetsStateController().getRawInsetsState();
-        assertEquals(state.isSourceOrDefaultVisible(ITYPE_STATUS_BAR, statusBars()),
-                rotatedState.isSourceOrDefaultVisible(ITYPE_STATUS_BAR, statusBars()));
-        state.setSourceVisible(ITYPE_STATUS_BAR,
-                !rotatedState.isSourceOrDefaultVisible(ITYPE_STATUS_BAR, statusBars()));
+        assertEquals(state.isSourceOrDefaultVisible(statusBarId, statusBars()),
+                rotatedState.isSourceOrDefaultVisible(statusBarId, statusBars()));
+        state.setSourceVisible(statusBarId,
+                !rotatedState.isSourceOrDefaultVisible(statusBarId, statusBars()));
         mDisplayContent.getInsetsStateController().notifyInsetsChanged();
-        assertEquals(state.isSourceOrDefaultVisible(ITYPE_STATUS_BAR, statusBars()),
-                rotatedState.isSourceOrDefaultVisible(ITYPE_STATUS_BAR, statusBars()));
+        assertEquals(state.isSourceOrDefaultVisible(statusBarId, statusBars()),
+                rotatedState.isSourceOrDefaultVisible(statusBarId, statusBars()));
 
         final Rect outFrame = new Rect();
         final Rect outInsets = new Rect();
@@ -1620,7 +1620,6 @@
 
         // If the rotated activity requests to show IME, the IME window should use the
         // transformation from activity to lay out in the same orientation.
-        mDisplayContent.setImeLayeringTarget(mAppWindow);
         LocalServices.getService(WindowManagerInternal.class).onToggleImeRequested(true /* show */,
                 app.token, app.token, mDisplayContent.mDisplayId);
         assertTrue(asyncRotationController.isTargetToken(mImeWindow.mToken));
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index 6656f4c..695a72e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -16,37 +16,32 @@
 
 package com.android.server.wm;
 
-import static android.view.InsetsState.ITYPE_CLIMATE_BAR;
-import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
-import static android.view.InsetsState.ITYPE_TOP_GESTURES;
 import static android.view.Surface.ROTATION_0;
 import static android.view.Surface.ROTATION_90;
 import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.spy;
-import static org.testng.Assert.expectThrows;
 
-import android.graphics.Insets;
 import android.graphics.Rect;
+import android.os.Binder;
 import android.platform.test.annotations.Presubmit;
+import android.util.SparseArray;
 import android.view.DisplayInfo;
 import android.view.InsetsFrameProvider;
 import android.view.InsetsSource;
 import android.view.InsetsState;
 import android.view.PrivacyIndicatorBounds;
 import android.view.RoundedCorners;
+import android.view.WindowInsets;
 
 import androidx.test.filters.SmallTest;
 
@@ -151,74 +146,23 @@
     public void addingWindow_withInsetsTypes() {
         mDisplayPolicy.removeWindowLw(mStatusBarWindow);  // Removes the existing one.
 
-        WindowState win = createWindow(null, TYPE_STATUS_BAR_SUB_PANEL, "StatusBarSubPanel");
+        final WindowState win = createWindow(null, TYPE_STATUS_BAR_SUB_PANEL, "statusBar");
+        final Binder owner = new Binder();
         win.mAttrs.providedInsets = new InsetsFrameProvider[] {
-                new InsetsFrameProvider(ITYPE_STATUS_BAR),
-                new InsetsFrameProvider(ITYPE_TOP_GESTURES)
+                new InsetsFrameProvider(owner, 0, WindowInsets.Type.statusBars()),
+                new InsetsFrameProvider(owner, 0, WindowInsets.Type.systemGestures())
         };
-        win.getFrame().set(0, 0, 500, 100);
-
         addWindow(win);
-        win.updateSourceFrame(win.getFrame());
-        InsetsStateController controller = mDisplayContent.getInsetsStateController();
-        controller.onPostLayout();
-
-        InsetsSourceProvider statusBarProvider = controller.peekSourceProvider(ITYPE_STATUS_BAR);
-        assertEquals(new Rect(0, 0, 500, 100), statusBarProvider.getSource().getFrame());
-        assertEquals(Insets.of(0, 100, 0, 0),
-                statusBarProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500),
-                        false /* ignoreVisibility */));
-
-        InsetsSourceProvider topGesturesProvider = controller.peekSourceProvider(
-                ITYPE_TOP_GESTURES);
-        assertEquals(new Rect(0, 0, 500, 100), topGesturesProvider.getSource().getFrame());
-        assertEquals(Insets.of(0, 100, 0, 0),
-                topGesturesProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500),
-                        false /* ignoreVisibility */));
-
-        InsetsSourceProvider navigationBarProvider = controller.peekSourceProvider(
-                ITYPE_NAVIGATION_BAR);
-        assertNotEquals(new Rect(0, 0, 500, 100), navigationBarProvider.getSource().getFrame());
-    }
-
-    @Test
-    public void addingWindow_InWindowTypeWithPredefinedInsets() {
-        mDisplayPolicy.removeWindowLw(mStatusBarWindow);  // Removes the existing one.
-        WindowState win = createWindow(null, TYPE_STATUS_BAR, "StatusBar");
-        win.mAttrs.providedInsets = new InsetsFrameProvider[] {
-                new InsetsFrameProvider(ITYPE_STATUS_BAR)
-        };
         win.getFrame().set(0, 0, 500, 100);
-
-        addWindow(win);
         win.updateSourceFrame(win.getFrame());
         mDisplayContent.getInsetsStateController().onPostLayout();
 
-        InsetsSourceProvider provider =
-                mDisplayContent.getInsetsStateController().peekSourceProvider(ITYPE_STATUS_BAR);
-        // In the new flexible insets setup, the insets frame should always respect the window
-        // layout result.
-        assertEquals(new Rect(0, 0, 500, 100), provider.getSource().getFrame());
-    }
-
-    @Test
-    public void addingWindow_throwsException_WithMultipleInsetTypes() {
-        WindowState win1 = createWindow(null, TYPE_STATUS_BAR_SUB_PANEL, "StatusBarSubPanel");
-        win1.mAttrs.providedInsets = new InsetsFrameProvider[] {
-                new InsetsFrameProvider(ITYPE_STATUS_BAR),
-                new InsetsFrameProvider(ITYPE_NAVIGATION_BAR)
-        };
-
-        expectThrows(IllegalArgumentException.class, () -> addWindow(win1));
-
-        WindowState win2 = createWindow(null, TYPE_STATUS_BAR_SUB_PANEL, "StatusBarSubPanel");
-
-        win2.mAttrs.providedInsets = new InsetsFrameProvider[] {
-                new InsetsFrameProvider(ITYPE_CLIMATE_BAR),
-                new InsetsFrameProvider(ITYPE_EXTRA_NAVIGATION_BAR)
-        };
-
-        expectThrows(IllegalArgumentException.class, () -> addWindow(win2));
+        assertTrue(win.hasInsetsSourceProvider());
+        final SparseArray<InsetsSourceProvider> providers = win.getInsetsSourceProviders();
+        for (int i = providers.size() - 1; i >= 0; i--) {
+            final InsetsSourceProvider provider = providers.valueAt(i);
+            assertEquals(new Rect(0, 0, 500, 100), provider.getSource().getFrame());
+        }
     }
 
     /**
@@ -272,9 +216,10 @@
                 .rotationForActivityInDifferentOrientation(eq(mWindow.mActivityRecord));
         mWindow.mAboveInsetsState.set(
                 mDisplayContent.getInsetsStateController().getRawInsetsState());
-        final Rect frame = mWindow.getInsetsState().peekSource(ITYPE_STATUS_BAR).getFrame();
+        final int statusBarId = mStatusBarWindow.getControllableInsetProvider().getSource().getId();
+        final Rect frame = mWindow.getInsetsState().peekSource(statusBarId).getFrame();
         mDisplayContent.rotateInDifferentOrientationIfNeeded(mWindow.mActivityRecord);
-        final Rect rotatedFrame = mWindow.getInsetsState().peekSource(ITYPE_STATUS_BAR).getFrame();
+        final Rect rotatedFrame = mWindow.getInsetsState().peekSource(statusBarId).getFrame();
 
         assertEquals(DISPLAY_WIDTH, frame.width());
         assertEquals(DISPLAY_HEIGHT, rotatedFrame.width());
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index c694707..20d410c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -18,8 +18,6 @@
 
 import static android.view.DisplayCutout.NO_CUTOUT;
 import static android.view.InsetsSource.ID_IME;
-import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
 import static android.view.RoundedCorners.NO_ROUNDED_CORNERS;
 import static android.view.Surface.ROTATION_0;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
@@ -180,7 +178,8 @@
         mDisplayContent.setLayoutNeeded();
         mDisplayContent.performLayout(true /* initial */, false /* updateImeWindows */);
 
-        final InsetsSource navSource = new InsetsSource(ITYPE_NAVIGATION_BAR, navigationBars());
+        final InsetsSource navSource = new InsetsSource(
+                InsetsSource.createId(null, 0, navigationBars()), navigationBars());
         navSource.setFrame(mNavBarWindow.getFrame());
         opaqueDarkNavBar.mAboveInsetsState.addSource(navSource);
         opaqueLightNavBar.mAboveInsetsState.addSource(navSource);
@@ -250,15 +249,16 @@
 
     @Test
     public void testOverlappingWithNavBar() {
-        final InsetsSource navSource = new InsetsSource(ITYPE_NAVIGATION_BAR, navigationBars());
+        final InsetsSource navSource = new InsetsSource(
+                InsetsSource.createId(null, 0, navigationBars()), navigationBars());
         navSource.setFrame(new Rect(100, 200, 200, 300));
         testOverlappingWithNavBarType(navSource);
     }
 
     @Test
     public void testOverlappingWithExtraNavBar() {
-        final InsetsSource navSource =
-                new InsetsSource(ITYPE_EXTRA_NAVIGATION_BAR, navigationBars());
+        final InsetsSource navSource = new InsetsSource(
+                InsetsSource.createId(null, 1, navigationBars()), navigationBars());
         navSource.setFrame(new Rect(100, 200, 200, 300));
         testOverlappingWithNavBarType(navSource);
     }
@@ -331,7 +331,8 @@
         displayPolicy.layoutWindowLw(mImeWindow, null, mDisplayContent.mDisplayFrames);
 
         final InsetsSource imeSource = state.peekSource(ID_IME);
-        final InsetsSource navBarSource = state.peekSource(ITYPE_NAVIGATION_BAR);
+        final InsetsSource navBarSource = state.peekSource(
+                mNavBarWindow.getControllableInsetProvider().getSource().getId());
 
         assertNotNull(imeSource);
         assertNotNull(navBarSource);
@@ -358,7 +359,8 @@
 
         displayPolicy.layoutWindowLw(mNavBarWindow, null, mDisplayContent.mDisplayFrames);
         final InsetsState state = mDisplayContent.getInsetsStateController().getRawInsetsState();
-        final InsetsSource navBarSource = state.peekSource(ITYPE_NAVIGATION_BAR);
+        final InsetsSource navBarSource = state.peekSource(
+                mNavBarWindow.getControllableInsetProvider().getSource().getId());
         assertEquals(attrs.height - 10, navBarSource.getFrame().height());
     }
 
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 1a126cf..2065540 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -19,12 +19,6 @@
 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.InsetsState.ITYPE_BOTTOM_MANDATORY_GESTURES;
-import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
-import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
-import static android.view.InsetsState.ITYPE_TOP_MANDATORY_GESTURES;
-import static android.view.InsetsState.ITYPE_TOP_TAPPABLE_ELEMENT;
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 import static android.view.WindowInsets.Type.navigationBars;
 import static android.view.WindowInsets.Type.statusBars;
@@ -51,6 +45,7 @@
 import static org.mockito.Mockito.verify;
 
 import android.app.StatusBarManager;
+import android.os.Binder;
 import android.platform.test.annotations.Presubmit;
 import android.view.InsetsFrameProvider;
 import android.view.InsetsSource;
@@ -158,7 +153,7 @@
     @Test
     public void testControlsForDispatch_remoteInsetsControllerControlsBars_appHasNoControl() {
         mDisplayContent.setRemoteInsetsController(createDisplayWindowInsetsController());
-        mDisplayContent.getInsetsPolicy().setRemoteInsetsControllerControlsSystemBars(true);
+        mDisplayContent.getDisplayPolicy().setRemoteInsetsControllerControlsSystemBars(true);
         addStatusBar();
         addNavigationBar();
 
@@ -261,11 +256,15 @@
     @Test
     public void testShowTransientBars_bothCanBeTransient_appGetsBothFakeControls() {
         final WindowState statusBar = addStatusBar();
+        final InsetsSourceProvider statusBarProvider = statusBar.getControllableInsetProvider();
+        final int statusBarId = statusBarProvider.getSource().getId();
         statusBar.setHasSurface(true);
-        statusBar.getControllableInsetProvider().setServerVisible(true);
+        statusBarProvider.setServerVisible(true);
         final WindowState navBar = addNavigationBar();
+        final InsetsSourceProvider navBarProvider = statusBar.getControllableInsetProvider();
+        final int navBarId = statusBarProvider.getSource().getId();
         navBar.setHasSurface(true);
-        navBar.getControllableInsetProvider().setServerVisible(true);
+        navBarProvider.setServerVisible(true);
         final InsetsPolicy policy = mDisplayContent.getInsetsPolicy();
         spyOn(policy);
         doNothing().when(policy).startAnimation(anyBoolean(), any());
@@ -276,9 +275,9 @@
         policy.updateBarControlTarget(mAppWindow);
         waitUntilWindowAnimatorIdle();
         assertFalse(mDisplayContent.getInsetsStateController().getRawInsetsState()
-                .isSourceOrDefaultVisible(ITYPE_STATUS_BAR, statusBars()));
+                .isSourceOrDefaultVisible(statusBarId, statusBars()));
         assertFalse(mDisplayContent.getInsetsStateController().getRawInsetsState()
-                .isSourceOrDefaultVisible(ITYPE_NAVIGATION_BAR, navigationBars()));
+                .isSourceOrDefaultVisible(navBarId, navigationBars()));
 
         policy.showTransient(navigationBars() | statusBars(), true /* isGestureOnSystemBar */);
         waitUntilWindowAnimatorIdle();
@@ -292,9 +291,9 @@
         }
 
         assertTrue(mDisplayContent.getInsetsStateController().getRawInsetsState()
-                .isSourceOrDefaultVisible(ITYPE_STATUS_BAR, statusBars()));
+                .isSourceOrDefaultVisible(statusBarId, statusBars()));
         assertTrue(mDisplayContent.getInsetsStateController().getRawInsetsState()
-                .isSourceOrDefaultVisible(ITYPE_NAVIGATION_BAR, navigationBars()));
+                .isSourceOrDefaultVisible(navBarId, navigationBars()));
     }
 
     @SetupWindows(addWindows = W_ACTIVITY)
@@ -356,16 +355,16 @@
         }
 
         final InsetsState state = mAppWindow.getInsetsState();
-        state.setSourceVisible(ITYPE_STATUS_BAR, true);
-        state.setSourceVisible(ITYPE_NAVIGATION_BAR, true);
+        state.setSourceVisible(statusBarSource.getId(), true);
+        state.setSourceVisible(navBarSource.getId(), true);
 
         final InsetsState clientState = mAppWindow.getInsetsState();
         // The transient bar states for client should be invisible.
-        assertFalse(clientState.isSourceOrDefaultVisible(ITYPE_STATUS_BAR, statusBars()));
-        assertFalse(clientState.isSourceOrDefaultVisible(ITYPE_NAVIGATION_BAR, navigationBars()));
+        assertFalse(clientState.isSourceOrDefaultVisible(statusBarSource.getId(), statusBars()));
+        assertFalse(clientState.isSourceOrDefaultVisible(navBarSource.getId(), navigationBars()));
         // The original state shouldn't be modified.
-        assertTrue(state.isSourceOrDefaultVisible(ITYPE_STATUS_BAR, statusBars()));
-        assertTrue(state.isSourceOrDefaultVisible(ITYPE_NAVIGATION_BAR, navigationBars()));
+        assertTrue(state.isSourceOrDefaultVisible(statusBarSource.getId(), statusBars()));
+        assertTrue(state.isSourceOrDefaultVisible(navBarSource.getId(), navigationBars()));
 
         mAppWindow.setRequestedVisibleTypes(
                 navigationBars() | statusBars(), navigationBars() | statusBars());
@@ -402,24 +401,26 @@
     }
 
     private WindowState addNavigationBar() {
+        final Binder owner = new Binder();
         final WindowState win = createWindow(null, TYPE_NAVIGATION_BAR, "navBar");
         win.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
         win.mAttrs.providedInsets = new InsetsFrameProvider[] {
-                new InsetsFrameProvider(ITYPE_NAVIGATION_BAR),
-                new InsetsFrameProvider(ITYPE_BOTTOM_MANDATORY_GESTURES),
-                new InsetsFrameProvider(ITYPE_BOTTOM_TAPPABLE_ELEMENT)
+                new InsetsFrameProvider(owner, 0, WindowInsets.Type.navigationBars()),
+                new InsetsFrameProvider(owner, 0, WindowInsets.Type.tappableElement()),
+                new InsetsFrameProvider(owner, 0, WindowInsets.Type.mandatorySystemGestures())
         };
         mDisplayContent.getDisplayPolicy().addWindowLw(win, win.mAttrs);
         return win;
     }
 
     private WindowState addStatusBar() {
+        final Binder owner = new Binder();
         final WindowState win = createWindow(null, TYPE_STATUS_BAR, "statusBar");
         win.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
         win.mAttrs.providedInsets = new InsetsFrameProvider[] {
-                new InsetsFrameProvider(ITYPE_STATUS_BAR),
-                new InsetsFrameProvider(ITYPE_TOP_TAPPABLE_ELEMENT),
-                new InsetsFrameProvider(ITYPE_TOP_MANDATORY_GESTURES)
+                new InsetsFrameProvider(owner, 0, WindowInsets.Type.statusBars()),
+                new InsetsFrameProvider(owner, 0, WindowInsets.Type.tappableElement()),
+                new InsetsFrameProvider(owner, 0, WindowInsets.Type.mandatorySystemGestures())
         };
         mDisplayContent.getDisplayPolicy().addWindowLw(win, win.mAttrs);
         return win;
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index 74dd361..12f9a9e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -448,12 +448,15 @@
         final String taskAffinity = "affinity";
         final int uid = 10123;
         final Task task1 = createTaskBuilder(".Task1").build();
-        task1.affinity = ActivityRecord.computeTaskAffinity(taskAffinity, uid, LAUNCH_MULTIPLE);
+        final ComponentName componentName = getUniqueComponentName();
+        task1.affinity = ActivityRecord.computeTaskAffinity(taskAffinity, uid, LAUNCH_MULTIPLE,
+                componentName);
         mRecentTasks.add(task1);
 
         // Add another task to recents, and make sure the previous task was removed.
         final Task task2 = createTaskBuilder(".Task2").build();
-        task2.affinity = ActivityRecord.computeTaskAffinity(taskAffinity, uid, LAUNCH_MULTIPLE);
+        task2.affinity = ActivityRecord.computeTaskAffinity(taskAffinity, uid, LAUNCH_MULTIPLE,
+                componentName);
         mRecentTasks.add(task2);
         assertEquals(1, mRecentTasks.getRecentTasks(MAX_VALUE, 0 /* flags */,
                 true /* getTasksAllowed */, TEST_USER_0_ID, 0).getList().size());
@@ -461,7 +464,7 @@
         // Add another single-instance task to recents, and make sure no task is removed.
         final Task task3 = createTaskBuilder(".Task3").build();
         task3.affinity = ActivityRecord.computeTaskAffinity(taskAffinity, uid,
-                LAUNCH_SINGLE_INSTANCE);
+                LAUNCH_SINGLE_INSTANCE, componentName);
         mRecentTasks.add(task3);
         assertEquals(2, mRecentTasks.getRecentTasks(MAX_VALUE, 0 /* flags */,
                 true /* getTasksAllowed */, TEST_USER_0_ID, 0).getList().size());
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index d242a5f..753cc62 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -28,9 +28,6 @@
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.provider.DeviceConfig.NAMESPACE_CONSTRAIN_DISPLAY_APIS;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
-import static android.view.InsetsState.ITYPE_TOP_MANDATORY_GESTURES;
-import static android.view.InsetsState.ITYPE_TOP_TAPPABLE_ELEMENT;
 import static android.view.Surface.ROTATION_0;
 import static android.view.Surface.ROTATION_180;
 import static android.view.Surface.ROTATION_270;
@@ -88,6 +85,7 @@
 import android.content.pm.ActivityInfo.ScreenOrientation;
 import android.content.res.Configuration;
 import android.graphics.Rect;
+import android.os.Binder;
 import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
 import android.provider.DeviceConfig;
@@ -95,6 +93,7 @@
 import android.view.InsetsFrameProvider;
 import android.view.InsetsSource;
 import android.view.InsetsState;
+import android.view.WindowInsets;
 import android.view.WindowManager;
 
 import androidx.test.filters.MediumTest;
@@ -117,6 +116,8 @@
 import org.mockito.ArgumentCaptor;
 
 import java.util.List;
+import java.util.function.Consumer;
+import java.util.function.Function;
 
 /**
  * Tests for Size Compatibility mode.
@@ -172,6 +173,156 @@
     }
 
     @Test
+    public void testHorizontalReachabilityEnabledForTranslucentActivities() {
+        setUpDisplaySizeWithApp(2500, 1000);
+        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+        final LetterboxConfiguration config = mWm.mLetterboxConfiguration;
+        config.setTranslucentLetterboxingOverrideEnabled(true);
+        config.setLetterboxHorizontalPositionMultiplier(0.5f);
+        config.setIsHorizontalReachabilityEnabled(true);
+
+        // Opaque activity
+        prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
+        addWindowToActivity(mActivity);
+        mActivity.mRootWindowContainer.performSurfacePlacement();
+
+        // Translucent Activity
+        final ActivityRecord translucentActivity = new ActivityBuilder(mAtm)
+                .setLaunchedFromUid(mActivity.getUid())
+                .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT)
+                .build();
+        doReturn(false).when(translucentActivity).fillsParent();
+        mTask.addChild(translucentActivity);
+
+        spyOn(translucentActivity.mLetterboxUiController);
+        doReturn(true).when(translucentActivity.mLetterboxUiController)
+                .shouldShowLetterboxUi(any());
+
+        addWindowToActivity(translucentActivity);
+        translucentActivity.mRootWindowContainer.performSurfacePlacement();
+
+        final Function<ActivityRecord, Rect> innerBoundsOf =
+                (ActivityRecord a) -> {
+                    final Rect bounds = new Rect();
+                    a.mLetterboxUiController.getLetterboxInnerBounds(bounds);
+                    return bounds;
+                };
+        final Runnable checkLetterboxPositions = () -> assertEquals(innerBoundsOf.apply(mActivity),
+                innerBoundsOf.apply(translucentActivity));
+        final Runnable checkIsLeft = () -> assertThat(
+                innerBoundsOf.apply(translucentActivity).left).isEqualTo(0);
+        final Runnable checkIsRight = () -> assertThat(
+                innerBoundsOf.apply(translucentActivity).right).isEqualTo(2500);
+        final Runnable checkIsCentered = () -> assertThat(
+                innerBoundsOf.apply(translucentActivity).left > 0
+                        && innerBoundsOf.apply(translucentActivity).right < 2500).isTrue();
+
+        final Consumer<Integer> doubleClick =
+                (Integer x) -> {
+                    mActivity.mLetterboxUiController.handleHorizontalDoubleTap(x);
+                    mActivity.mRootWindowContainer.performSurfacePlacement();
+                };
+
+        // Initial state
+        checkIsCentered.run();
+
+        // Double-click left
+        doubleClick.accept(/* x */ 10);
+        checkLetterboxPositions.run();
+        checkIsLeft.run();
+
+        // Double-click right
+        doubleClick.accept(/* x */ 1990);
+        checkLetterboxPositions.run();
+        checkIsCentered.run();
+
+        // Double-click right
+        doubleClick.accept(/* x */ 1990);
+        checkLetterboxPositions.run();
+        checkIsRight.run();
+
+        // Double-click left
+        doubleClick.accept(/* x */ 10);
+        checkLetterboxPositions.run();
+        checkIsCentered.run();
+    }
+
+    @Test
+    public void testVerticalReachabilityEnabledForTranslucentActivities() {
+        setUpDisplaySizeWithApp(1000, 2500);
+        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+        final LetterboxConfiguration config = mWm.mLetterboxConfiguration;
+        config.setTranslucentLetterboxingOverrideEnabled(true);
+        config.setLetterboxVerticalPositionMultiplier(0.5f);
+        config.setIsVerticalReachabilityEnabled(true);
+
+        // Opaque activity
+        prepareUnresizable(mActivity, SCREEN_ORIENTATION_LANDSCAPE);
+        addWindowToActivity(mActivity);
+        mActivity.mRootWindowContainer.performSurfacePlacement();
+
+        // Translucent Activity
+        final ActivityRecord translucentActivity = new ActivityBuilder(mAtm)
+                .setLaunchedFromUid(mActivity.getUid())
+                .setScreenOrientation(SCREEN_ORIENTATION_LANDSCAPE)
+                .build();
+        doReturn(false).when(translucentActivity).fillsParent();
+        mTask.addChild(translucentActivity);
+
+        spyOn(translucentActivity.mLetterboxUiController);
+        doReturn(true).when(translucentActivity.mLetterboxUiController)
+                .shouldShowLetterboxUi(any());
+
+        addWindowToActivity(translucentActivity);
+        translucentActivity.mRootWindowContainer.performSurfacePlacement();
+
+        final Function<ActivityRecord, Rect> innerBoundsOf =
+                (ActivityRecord a) -> {
+                    final Rect bounds = new Rect();
+                    a.mLetterboxUiController.getLetterboxInnerBounds(bounds);
+                    return bounds;
+                };
+        final Runnable checkLetterboxPositions = () -> assertEquals(innerBoundsOf.apply(mActivity),
+                innerBoundsOf.apply(translucentActivity));
+        final Runnable checkIsTop = () -> assertThat(
+                innerBoundsOf.apply(translucentActivity).top).isEqualTo(0);
+        final Runnable checkIsBottom = () -> assertThat(
+                innerBoundsOf.apply(translucentActivity).bottom).isEqualTo(2500);
+        final Runnable checkIsCentered = () -> assertThat(
+                innerBoundsOf.apply(translucentActivity).top > 0
+                        && innerBoundsOf.apply(translucentActivity).bottom < 2500).isTrue();
+
+        final Consumer<Integer> doubleClick =
+                (Integer y) -> {
+                    mActivity.mLetterboxUiController.handleVerticalDoubleTap(y);
+                    mActivity.mRootWindowContainer.performSurfacePlacement();
+                };
+
+        // Initial state
+        checkIsCentered.run();
+
+        // Double-click top
+        doubleClick.accept(/* y */ 10);
+        checkLetterboxPositions.run();
+        checkIsTop.run();
+
+        // Double-click bottom
+        doubleClick.accept(/* y */ 1990);
+        checkLetterboxPositions.run();
+        checkIsCentered.run();
+
+        // Double-click bottom
+        doubleClick.accept(/* y */ 1990);
+        checkLetterboxPositions.run();
+        checkIsBottom.run();
+
+        // Double-click top
+        doubleClick.accept(/* y */ 10);
+        checkLetterboxPositions.run();
+        checkIsCentered.run();
+    }
+
+    @Test
     public void testApplyStrategyToTranslucentActivities() {
         mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true);
         setUpDisplaySizeWithApp(2000, 1000);
@@ -233,7 +384,25 @@
     }
 
     @Test
-    public void testTranslucentActivitiesDontGoInSizeCompactMode() {
+    public void testNotApplyStrategyToTranslucentActivitiesOverEmbeddedActivities() {
+        mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true);
+        setUpDisplaySizeWithApp(2000, 1000);
+        mActivity.info.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
+        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+        // Mock the activity as embedded without additional TaskFragment layer in the task for
+        // simplicity.
+        doReturn(true).when(mActivity).isEmbedded();
+        // Translucent Activity
+        final ActivityRecord translucentActivity = new ActivityBuilder(mAtm).build();
+        doReturn(false).when(translucentActivity).matchParentBounds();
+        doReturn(false).when(translucentActivity).fillsParent();
+        mTask.addChild(translucentActivity);
+        // Check the strategy has not being applied
+        assertFalse(translucentActivity.mLetterboxUiController.hasInheritedLetterboxBehavior());
+    }
+
+    @Test
+    public void testTranslucentActivitiesDontGoInSizeCompatMode() {
         mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true);
         setUpDisplaySizeWithApp(2800, 1400);
         mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
@@ -822,7 +991,7 @@
                 .setResizeMode(ActivityInfo.RESIZE_MODE_UNRESIZEABLE)
                 .setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
                 .build();
-        assertFalse(activity.shouldCreateCompatDisplayInsets());
+        assertTrue(activity.shouldCreateCompatDisplayInsets());
 
         // The non-resizable activity should not be size compat because it is on a resizable task
         // in multi-window mode.
@@ -855,7 +1024,7 @@
     }
 
     @Test
-    public void testShouldNotCreateCompatDisplayInsetsWhenRootActivityIsResizeable() {
+    public void testShouldCreateCompatDisplayInsetsWhenUnresizeableAndSupportsSizeChangesFalse() {
         setUpDisplaySizeWithApp(1000, 2500);
 
         // Make the task root resizable.
@@ -864,7 +1033,7 @@
         // Create an activity on the same task.
         final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
                 RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
-        assertFalse(activity.shouldCreateCompatDisplayInsets());
+        assertTrue(activity.shouldCreateCompatDisplayInsets());
     }
 
     @Test
@@ -2321,11 +2490,11 @@
         assertFalse(mActivity.inSizeCompatMode());
 
         mActivity.setRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED);
-
-        assertTrue(mActivity.inSizeCompatMode());
-        // We should remember the original orientation.
+        // Activity is not in size compat mode because the orientation change request came from the
+        // app itself
+        assertFalse(mActivity.inSizeCompatMode());
         assertEquals(mActivity.getResolvedOverrideConfiguration().orientation,
-                Configuration.ORIENTATION_PORTRAIT);
+                Configuration.ORIENTATION_UNDEFINED);
     }
 
     @Test
@@ -2900,6 +3069,25 @@
     }
 
     @Test
+    public void testAppRequestsOrientationChange_notInSizeCompat() {
+        setUpDisplaySizeWithApp(2200, 1800);
+        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+
+        prepareUnresizable(mActivity, SCREEN_ORIENTATION_LANDSCAPE);
+
+        mActivity.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
+
+        // Activity is not in size compat mode because the orientation change request came from the
+        // app itself
+        assertFalse(mActivity.inSizeCompatMode());
+
+        rotateDisplay(mActivity.mDisplayContent, ROTATION_270);
+        // Activity should go into size compat mode now because the orientation change came from the
+        // system (device rotation)
+        assertTrue(mActivity.inSizeCompatMode());
+    }
+
+    @Test
     public void testLetterboxDetailsForStatusBar_noLetterbox() {
         setUpDisplaySizeWithApp(2800, 1000);
         addStatusBar(mActivity.mDisplayContent);
@@ -3923,14 +4111,15 @@
                 TYPE_STATUS_BAR, displayContent);
         final WindowManager.LayoutParams attrs =
                 new WindowManager.LayoutParams(TYPE_STATUS_BAR);
+        final Binder owner = new Binder();
         attrs.gravity = android.view.Gravity.TOP;
         attrs.layoutInDisplayCutoutMode =
                 WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
         attrs.setFitInsetsTypes(0 /* types */);
         attrs.providedInsets = new InsetsFrameProvider[] {
-                new InsetsFrameProvider(ITYPE_STATUS_BAR),
-                new InsetsFrameProvider(ITYPE_TOP_TAPPABLE_ELEMENT),
-                new InsetsFrameProvider(ITYPE_TOP_MANDATORY_GESTURES)
+                new InsetsFrameProvider(owner, 0, WindowInsets.Type.statusBars()),
+                new InsetsFrameProvider(owner, 0, WindowInsets.Type.tappableElement()),
+                new InsetsFrameProvider(owner, 0, WindowInsets.Type.mandatorySystemGestures())
         };
         final TestWindowState statusBar = new TestWindowState(
                 displayContent.mWmService, mock(Session.class), new TestIWindow(), attrs, token);
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceSyncGroupTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceSyncGroupTest.java
index c538727..e30206e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceSyncGroupTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceSyncGroupTest.java
@@ -41,6 +41,7 @@
 @Presubmit
 public class SurfaceSyncGroupTest {
     private static final String TAG = "SurfaceSyncGroupTest";
+    private static final int TIMEOUT_MS = 100;
 
     private final Executor mExecutor = Runnable::run;
 
@@ -86,7 +87,7 @@
 
         syncTarget2.markSyncReady();
 
-        finishedLatch.await(5, TimeUnit.SECONDS);
+        finishedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
         assertEquals(0, finishedLatch.getCount());
     }
 
@@ -124,13 +125,13 @@
 
         syncTarget1.markSyncReady();
 
-        finishedLatch1.await(5, TimeUnit.SECONDS);
+        finishedLatch1.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
         assertEquals(0, finishedLatch1.getCount());
         assertNotEquals(0, finishedLatch2.getCount());
 
         syncTarget2.markSyncReady();
 
-        finishedLatch2.await(5, TimeUnit.SECONDS);
+        finishedLatch2.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
         assertEquals(0, finishedLatch2.getCount());
     }
 
@@ -156,17 +157,17 @@
         // Finish syncTarget2 first to test that the syncGroup is not complete until the merged sync
         // is also done.
         syncTarget2.markSyncReady();
-        finishedLatch2.await(1, TimeUnit.SECONDS);
+        finishedLatch2.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
         // Sync did not complete yet
         assertNotEquals(0, finishedLatch2.getCount());
 
         syncTarget1.markSyncReady();
 
         // The first sync will still get a callback when it's sync requirements are done.
-        finishedLatch1.await(5, TimeUnit.SECONDS);
+        finishedLatch1.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
         assertEquals(0, finishedLatch1.getCount());
 
-        finishedLatch2.await(5, TimeUnit.SECONDS);
+        finishedLatch2.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
         assertEquals(0, finishedLatch2.getCount());
     }
 
@@ -189,7 +190,7 @@
         syncTarget1.markSyncReady();
 
         // The first sync will still get a callback when it's sync requirements are done.
-        finishedLatch1.await(5, TimeUnit.SECONDS);
+        finishedLatch1.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
         assertEquals(0, finishedLatch1.getCount());
 
         syncGroup2.add(syncGroup1, null /* runnable */);
@@ -198,7 +199,7 @@
 
         // Verify that the second sync will receive complete since the merged sync was already
         // completed before the merge.
-        finishedLatch2.await(5, TimeUnit.SECONDS);
+        finishedLatch2.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
         assertEquals(0, finishedLatch2.getCount());
     }
 
@@ -232,8 +233,8 @@
         syncTarget3.markSyncReady();
 
         // Neither SyncGroup will be ready.
-        finishedLatch1.await(1, TimeUnit.SECONDS);
-        finishedLatch2.await(1, TimeUnit.SECONDS);
+        finishedLatch1.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+        finishedLatch2.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
 
         assertEquals(1, finishedLatch1.getCount());
         assertEquals(1, finishedLatch2.getCount());
@@ -241,8 +242,8 @@
         syncTarget2.markSyncReady();
 
         // Both sync groups should be ready after target2 completed.
-        finishedLatch1.await(5, TimeUnit.SECONDS);
-        finishedLatch2.await(5, TimeUnit.SECONDS);
+        finishedLatch1.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+        finishedLatch2.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
         assertEquals(0, finishedLatch1.getCount());
         assertEquals(0, finishedLatch2.getCount());
     }
@@ -275,8 +276,8 @@
         syncTarget1.markSyncReady();
 
         // Only SyncGroup1 will be ready, but SyncGroup2 still needs its own targets to be ready.
-        finishedLatch1.await(1, TimeUnit.SECONDS);
-        finishedLatch2.await(1, TimeUnit.SECONDS);
+        finishedLatch1.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+        finishedLatch2.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
 
         assertEquals(0, finishedLatch1.getCount());
         assertEquals(1, finishedLatch2.getCount());
@@ -284,7 +285,7 @@
         syncTarget3.markSyncReady();
 
         // SyncGroup2 is finished after target3 completed.
-        finishedLatch2.await(1, TimeUnit.SECONDS);
+        finishedLatch2.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
         assertEquals(0, finishedLatch2.getCount());
     }
 
@@ -357,6 +358,27 @@
         } catch (InterruptedException e) {
             throw new RuntimeException(e);
         }
+
+        assertEquals(0, finishedLatch.getCount());
+    }
+
+    public void testSurfaceSyncGroupTimeout() throws InterruptedException {
+        final CountDownLatch finishedLatch = new CountDownLatch(1);
+        SurfaceSyncGroup syncGroup = new SurfaceSyncGroup(TAG);
+        syncGroup.addSyncCompleteCallback(mExecutor, finishedLatch::countDown);
+        SurfaceSyncGroup syncTarget1 = new SurfaceSyncGroup("FakeSyncTarget1");
+        SurfaceSyncGroup syncTarget2 = new SurfaceSyncGroup("FakeSyncTarget2");
+
+        syncGroup.add(syncTarget1, null /* runnable */);
+        syncGroup.add(syncTarget2, null /* runnable */);
+        syncGroup.markSyncReady();
+
+        syncTarget1.markSyncReady();
+        assertNotEquals(0, finishedLatch.getCount());
+
+        // Never finish syncTarget2 so it forces the timeout. Timeout is 1 second so wait a little
+        // over 1 second to make sure it completes.
+        finishedLatch.await(1100, TimeUnit.MILLISECONDS);
         assertEquals(0, finishedLatch.getCount());
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java b/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
index aff9c1a..8e91ca2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
@@ -22,7 +22,6 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
-import static com.android.server.wm.BLASTSyncEngine.METHOD_BLAST;
 import static com.android.server.wm.BLASTSyncEngine.METHOD_NONE;
 import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
 import static com.android.server.wm.WindowContainer.POSITION_TOP;
@@ -363,7 +362,8 @@
         BLASTSyncEngine.TransactionReadyListener listener = mock(
                 BLASTSyncEngine.TransactionReadyListener.class);
 
-        int id = startSyncSet(bse, listener, METHOD_NONE);
+        final int id = startSyncSet(bse, listener);
+        bse.setSyncMethod(id, METHOD_NONE);
         bse.addToSyncSet(id, mAppWindow.mToken);
         mAppWindow.prepareSync();
         assertFalse(mAppWindow.shouldSyncWithBuffers());
@@ -373,12 +373,7 @@
 
     static int startSyncSet(BLASTSyncEngine engine,
             BLASTSyncEngine.TransactionReadyListener listener) {
-        return startSyncSet(engine, listener, METHOD_BLAST);
-    }
-
-    static int startSyncSet(BLASTSyncEngine engine,
-            BLASTSyncEngine.TransactionReadyListener listener, int method) {
-        return engine.startSyncSet(listener, BLAST_TIMEOUT_DURATION, "", method);
+        return engine.startSyncSet(listener, BLAST_TIMEOUT_DURATION, "Test");
     }
 
     static class TestWindowContainer extends WindowContainer {
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index f4a266c..013c6d5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -545,7 +545,6 @@
             mDevEnableNonResizableMultiWindow = false;
             mMinPercentageMultiWindowSupportHeight = 0.3f;
             mMinPercentageMultiWindowSupportWidth = 0.5f;
-            mLargeScreenSmallestScreenWidthDp = 600;
             mSupportsNonResizableMultiWindow = 0;
             mRespectsActivityMinWidthHeightMultiWindow = 0;
             mForceResizableActivities = false;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
index df3af7d..49d8da1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
@@ -351,8 +351,8 @@
         final TaskFragment taskFragment1 = createTaskFragmentWithEmbeddedActivity(task, mOrganizer);
         final ActivityRecord activity0 = taskFragment0.getTopMostActivity();
         final ActivityRecord activity1 = taskFragment1.getTopMostActivity();
-        activity0.setVisibility(true /* visible */, false /* deferHidingClient */);
-        activity1.setVisibility(true /* visible */, false /* deferHidingClient */);
+        activity0.setVisibility(true);
+        activity1.setVisibility(true);
         spyOn(mAtm.mTaskFragmentOrganizerController);
 
         // Move activity to pinned.
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index 2bfc5ec..739737e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -30,10 +30,6 @@
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.util.DisplayMetrics.DENSITY_DEFAULT;
 import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.InsetsState.ITYPE_CLIMATE_BAR;
-import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
 import static android.window.DisplayAreaOrganizer.FEATURE_RUNTIME_TASK_CONTAINER_FIRST;
 
 import static com.android.server.wm.ActivityStarter.Request;
@@ -55,6 +51,7 @@
 import android.os.Build;
 import android.platform.test.annotations.Presubmit;
 import android.view.Gravity;
+import android.view.InsetsSource;
 import android.view.InsetsState;
 import android.view.WindowInsets;
 
@@ -1916,22 +1913,24 @@
         final int st = stableFrame.top;
         final int sr = stableFrame.right;
         final int sb = stableFrame.bottom;
+        final @WindowInsets.Type.InsetsType int statusBarType = WindowInsets.Type.statusBars();
+        final @WindowInsets.Type.InsetsType int navBarType = WindowInsets.Type.navigationBars();
 
         state.setDisplayFrame(displayFrame);
         if (sl > dl) {
-            state.getOrCreateSource(ITYPE_CLIMATE_BAR, WindowInsets.Type.statusBars())
+            state.getOrCreateSource(InsetsSource.createId(null, 0, statusBarType), statusBarType)
                     .setFrame(dl, dt, sl, db);
         }
         if (st > dt) {
-            state.getOrCreateSource(ITYPE_STATUS_BAR, WindowInsets.Type.statusBars())
+            state.getOrCreateSource(InsetsSource.createId(null, 1, statusBarType), statusBarType)
                     .setFrame(dl, dt, dr, st);
         }
         if (sr < dr) {
-            state.getOrCreateSource(ITYPE_EXTRA_NAVIGATION_BAR, WindowInsets.Type.navigationBars())
+            state.getOrCreateSource(InsetsSource.createId(null, 0, navBarType), navBarType)
                     .setFrame(sr, dt, dr, db);
         }
         if (sb < db) {
-            state.getOrCreateSource(ITYPE_NAVIGATION_BAR, WindowInsets.Type.navigationBars())
+            state.getOrCreateSource(InsetsSource.createId(null, 1, navBarType), navBarType)
                     .setFrame(dl, sb, dr, db);
         }
         // Recompute config and push to children.
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index 9cd80a3..5208e5a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -535,6 +535,34 @@
         assertEquals(reqBounds.height(), task.getBounds().height());
     }
 
+    /** Tests that the task bounds adjust properly to changes between FULLSCREEN and FREEFORM */
+    @Test
+    public void testBoundsOnModeChangeFreeformToFullscreen() {
+        DisplayContent display = mAtm.mRootWindowContainer.getDefaultDisplay();
+        Task rootTask = new TaskBuilder(mSupervisor).setDisplay(display).setCreateActivity(true)
+                .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
+        Task task = rootTask.getBottomMostTask();
+        task.getRootActivity().setOrientation(SCREEN_ORIENTATION_UNSPECIFIED);
+        DisplayInfo info = new DisplayInfo();
+        display.mDisplay.getDisplayInfo(info);
+        final Rect fullScreenBounds = new Rect(0, 0, info.logicalWidth, info.logicalHeight);
+        final Rect freeformBounds = new Rect(fullScreenBounds);
+        freeformBounds.inset((int) (freeformBounds.width() * 0.2),
+                (int) (freeformBounds.height() * 0.2));
+        task.setBounds(freeformBounds);
+
+        assertEquals(freeformBounds, task.getBounds());
+
+        // FULLSCREEN inherits bounds
+        rootTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+        assertEquals(fullScreenBounds, task.getBounds());
+        assertEquals(freeformBounds, task.mLastNonFullscreenBounds);
+
+        // FREEFORM restores bounds
+        rootTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
+        assertEquals(freeformBounds, task.getBounds());
+    }
+
     /**
      * Tests that a task with forced orientation has orientation-consistent bounds within the
      * parent.
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
index fec079b..7e4a9de 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
@@ -30,6 +30,9 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -39,6 +42,7 @@
 import android.graphics.Rect;
 import android.hardware.display.DisplayManagerGlobal;
 import android.util.DisplayMetrics;
+import android.util.TypedValue;
 import android.view.Display;
 import android.view.DisplayCutout;
 import android.view.DisplayInfo;
@@ -47,6 +51,8 @@
 
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
 
 class TestDisplayContent extends DisplayContent {
 
@@ -197,10 +203,21 @@
             MockitoAnnotations.initMocks(this);
             doReturn(mMockContext).when(mService.mContext).createConfigurationContext(any());
             doReturn(mResources).when(mMockContext).getResources();
-            doReturn(valueDp * mDisplayMetrics.density)
-                    .when(mResources)
-                    .getDimension(
-                        com.android.internal.R.dimen.default_minimal_size_resizable_task);
+            doAnswer(
+                    new Answer() {
+                        @Override
+                        public Object answer(InvocationOnMock i) {
+                            Object[] args = i.getArguments();
+                            TypedValue v = (TypedValue) args[1];
+                            v.type = TypedValue.TYPE_DIMENSION;
+                            v.data = TypedValue.createComplexDimension(valueDp,
+                                    TypedValue.COMPLEX_UNIT_DIP);
+                            return null;
+                        }
+                    }
+            ).when(mResources).getValue(
+                    eq(com.android.internal.R.dimen.default_minimal_size_resizable_task),
+                    any(TypedValue.class), eq(true));
             return this;
         }
         Builder setDeviceStateController(@NonNull DeviceStateController deviceStateController) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index 3f14217..3045812 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -19,6 +19,7 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
@@ -519,6 +520,47 @@
     }
 
     @Test
+    public void testCreateInfo_MultiDisplay() {
+        DisplayContent otherDisplay = createNewDisplay();
+        final Transition transition = createTestTransition(TRANSIT_OPEN);
+        ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges;
+        ArraySet<WindowContainer> participants = transition.mParticipants;
+
+        final Task display0Task = createTask(mDisplayContent);
+        final Task display1Task = createTask(otherDisplay);
+        // Start states.
+        changes.put(display0Task,
+                new Transition.ChangeInfo(display0Task, false /* vis */, true /* exChg */));
+        changes.put(display1Task,
+                new Transition.ChangeInfo(display1Task, false /* vis */, true /* exChg */));
+        fillChangeMap(changes, display0Task);
+        fillChangeMap(changes, display1Task);
+        // End states.
+        display0Task.setVisibleRequested(true);
+        display1Task.setVisibleRequested(true);
+
+        final int transit = transition.mType;
+        int flags = 0;
+
+        participants.add(display0Task);
+        participants.add(display1Task);
+        ArrayList<Transition.ChangeInfo> targets =
+                Transition.calculateTargets(participants, changes);
+        TransitionInfo info = Transition.calculateTransitionInfo(transit, flags, targets, mMockT);
+        assertEquals(2, info.getRootCount());
+        // Check that the changes are assigned to the correct display
+        assertEquals(mDisplayContent.getDisplayId(), info.getChange(
+                display0Task.mRemoteToken.toWindowContainerToken()).getEndDisplayId());
+        assertEquals(otherDisplay.getDisplayId(), info.getChange(
+                display1Task.mRemoteToken.toWindowContainerToken()).getEndDisplayId());
+        // Check that roots can be found by display and have the correct display
+        assertEquals(mDisplayContent.getDisplayId(),
+                info.getRoot(info.findRootIndex(mDisplayContent.getDisplayId())).getDisplayId());
+        assertEquals(otherDisplay.getDisplayId(),
+                info.getRoot(info.findRootIndex(otherDisplay.getDisplayId())).getDisplayId());
+    }
+
+    @Test
     public void testTargets_noIntermediatesToWallpaper() {
         final Transition transition = createTestTransition(TRANSIT_OPEN);
 
@@ -1376,6 +1418,9 @@
         enteringAnimReports.clear();
         closeTransition.finishTransition();
 
+        assertEquals(ActivityTaskManagerService.APP_SWITCH_DISALLOW, mAtm.getBalAppSwitchesState());
+        assertFalse(activity1.app.hasActivityInVisibleTask());
+
         verify(snapshotController, times(1)).recordSnapshot(eq(task1), eq(false));
         assertTrue(enteringAnimReports.contains(activity2));
     }
@@ -1696,10 +1741,12 @@
     @Test
     public void testTransitionVisibleChange() {
         registerTestTransitionPlayer();
-        final ActivityRecord app = createActivityRecord(mDisplayContent);
+        final ActivityRecord app = createActivityRecord(
+                mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
         final Transition transition = new Transition(TRANSIT_OPEN, 0 /* flags */,
                 app.mTransitionController, mWm.mSyncEngine);
-        app.mTransitionController.moveToCollecting(transition, BLASTSyncEngine.METHOD_NONE);
+        app.mTransitionController.moveToCollecting(transition);
+        mWm.mSyncEngine.setSyncMethod(transition.getSyncId(), BLASTSyncEngine.METHOD_NONE);
         final ArrayList<WindowContainer> freezeCalls = new ArrayList<>();
         transition.setContainerFreezer(new Transition.IContainerFreezer() {
             @Override
@@ -1746,10 +1793,12 @@
     @Test
     public void testVisibleChange_snapshot() {
         registerTestTransitionPlayer();
-        final ActivityRecord app = createActivityRecord(mDisplayContent);
+        final ActivityRecord app = createActivityRecord(
+                mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
         final Transition transition = new Transition(TRANSIT_CHANGE, 0 /* flags */,
                 app.mTransitionController, mWm.mSyncEngine);
-        app.mTransitionController.moveToCollecting(transition, BLASTSyncEngine.METHOD_NONE);
+        app.mTransitionController.moveToCollecting(transition);
+        mWm.mSyncEngine.setSyncMethod(transition.getSyncId(), BLASTSyncEngine.METHOD_NONE);
         final SurfaceControl mockSnapshot = mock(SurfaceControl.class);
         transition.setContainerFreezer(new Transition.IContainerFreezer() {
             @Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
index 2fccb88a..75a8dd8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
@@ -92,11 +92,11 @@
 
     @Test
     public void testRemoveFinishingInvisibleActivityFromUnknown() {
-        final ActivityRecord activity = createNonAttachedActivityRecord(mDisplayContent);
+        final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
         mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
         activity.finishing = true;
         activity.setVisibleRequested(true);
-        activity.setVisibility(false, false);
+        activity.setVisibility(false);
         assertTrue(mDisplayContent.mUnknownAppVisibilityController.allResolved());
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
index ef2b691..65631ea 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
@@ -52,6 +52,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
+import android.util.MergedConfiguration;
 import android.view.DisplayCutout;
 import android.view.DisplayInfo;
 import android.view.DisplayShape;
@@ -62,6 +63,7 @@
 import android.view.Surface;
 import android.view.SurfaceControl;
 import android.view.WindowManager;
+import android.window.ClientWindowFrames;
 
 import androidx.test.filters.SmallTest;
 
@@ -340,6 +342,29 @@
     }
 
     @Test
+    public void testWallpaperReportConfigChange() {
+        final WindowState wallpaperWindow = createWallpaperWindow(mDisplayContent);
+        createWallpaperTargetWindow(mDisplayContent);
+        final WallpaperWindowToken wallpaperToken = wallpaperWindow.mToken.asWallpaperToken();
+        makeWindowVisible(wallpaperWindow);
+        wallpaperWindow.mLayoutSeq = mDisplayContent.mLayoutSeq;
+        // Assume the token was invisible and the latest config was reported.
+        wallpaperToken.commitVisibility(false);
+        wallpaperWindow.fillClientWindowFramesAndConfiguration(new ClientWindowFrames(),
+                new MergedConfiguration(), true /* useLatestConfig */, false /* relayoutVisible */);
+        assertTrue(wallpaperWindow.isLastConfigReportedToClient());
+
+        final Rect bounds = wallpaperToken.getBounds();
+        wallpaperToken.setBounds(new Rect(0, 0, bounds.width() / 2, bounds.height() / 2));
+        assertFalse(wallpaperWindow.isLastConfigReportedToClient());
+        // If there is a pending config change when changing to visible, it should tell the client
+        // to redraw by WindowState#reportResized.
+        wallpaperToken.commitVisibility(true);
+        waitUntilHandlersIdle();
+        assertTrue(wallpaperWindow.isLastConfigReportedToClient());
+    }
+
+    @Test
     public void testWallpaperTokenVisibility() {
         final DisplayContent dc = mWm.mRoot.getDefaultDisplay();
         final WindowState wallpaperWindow = createWallpaperWindow(dc);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerInsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerInsetsSourceProviderTest.java
index 7d13de8..ef20f2b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerInsetsSourceProviderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerInsetsSourceProviderTest.java
@@ -17,7 +17,6 @@
 package com.android.server.wm;
 
 import static android.view.InsetsSource.ID_IME;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
 import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowInsets.Type.statusBars;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -45,7 +44,8 @@
 @RunWith(WindowTestRunner.class)
 public class WindowContainerInsetsSourceProviderTest extends WindowTestsBase {
 
-    private InsetsSource mSource = new InsetsSource(ITYPE_STATUS_BAR, statusBars());
+    private InsetsSource mSource = new InsetsSource(
+            InsetsSource.createId(null, 0, statusBars()), statusBars());
     private WindowContainerInsetsSourceProvider mProvider;
     private InsetsSource mImeSource = new InsetsSource(ID_IME, ime());
     private WindowContainerInsetsSourceProvider mImeProvider;
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index d7e4c55..a68a573 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -42,7 +42,6 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
 import static com.android.server.wm.ActivityRecord.State.RESUMED;
-import static com.android.server.wm.BLASTSyncEngine.METHOD_BLAST;
 import static com.android.server.wm.WindowContainer.POSITION_TOP;
 import static com.android.server.wm.WindowContainer.SYNC_STATE_READY;
 import static com.android.server.wm.WindowState.BLAST_TIMEOUT_DURATION;
@@ -1001,7 +1000,7 @@
         BLASTSyncEngine.TransactionReadyListener transactionListener =
                 mock(BLASTSyncEngine.TransactionReadyListener.class);
 
-        int id = bse.startSyncSet(transactionListener, BLAST_TIMEOUT_DURATION, "", METHOD_BLAST);
+        final int id = bse.startSyncSet(transactionListener, BLAST_TIMEOUT_DURATION, "Test");
         bse.addToSyncSet(id, task);
         bse.setReady(id);
         bse.onSurfacePlacement();
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerMapTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerMapTests.java
index c2ee079..2a3c9bc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerMapTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerMapTests.java
@@ -22,6 +22,8 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
 
 import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
@@ -129,4 +131,14 @@
         assertEquals(uid2processes.size(), 1);
         assertEquals(mProcessMap.getProcess(FAKE_PID1), pid1uid2);
     }
+
+    @Test
+    public void testRemove_callsDestroy() {
+        var proc = spy(pid1uid1);
+        mProcessMap.put(FAKE_PID1, proc);
+
+        mProcessMap.remove(FAKE_PID1);
+
+        verify(proc).destroy();
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
index d6cfd00..cf83981 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
@@ -159,6 +159,17 @@
     }
 
     @Test
+    public void testDestroy_unregistersDisplayAreaListener() {
+        final TestDisplayContent testDisplayContent1 = createTestDisplayContentInContainer();
+        final DisplayArea imeContainer1 = testDisplayContent1.getImeContainer();
+        mWpc.registerDisplayAreaConfigurationListener(imeContainer1);
+
+        mWpc.destroy();
+
+        assertNull(mWpc.getDisplayArea());
+    }
+
+    @Test
     public void testSetRunningRecentsAnimation() {
         mWpc.setRunningRecentsAnimation(true);
         mWpc.setRunningRecentsAnimation(false);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 3aee2cd..b48fd7d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -21,8 +21,6 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.view.InsetsSource.ID_IME;
-import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
 import static android.view.Surface.ROTATION_0;
 import static android.view.Surface.ROTATION_270;
 import static android.view.Surface.ROTATION_90;
@@ -425,15 +423,16 @@
         final WindowState app = mAppWindow;
         statusBar.mHasSurface = true;
         assertTrue(statusBar.isVisible());
+        final int statusBarId = InsetsSource.createId(null, 0, statusBars());
         mDisplayContent.getInsetsStateController()
-                .getOrCreateSourceProvider(ITYPE_STATUS_BAR, statusBars())
+                .getOrCreateSourceProvider(statusBarId, statusBars())
                 .setWindowContainer(statusBar, null /* frameProvider */,
                         null /* imeFrameProvider */);
         mDisplayContent.getInsetsStateController().onBarControlTargetChanged(
                 app, null /* fakeTopControlling */, app, null /* fakeNavControlling */);
         app.setRequestedVisibleTypes(0, statusBars());
         mDisplayContent.getInsetsStateController()
-                .getOrCreateSourceProvider(ITYPE_STATUS_BAR, statusBars())
+                .getOrCreateSourceProvider(statusBarId, statusBars())
                 .updateClientVisibility(app);
         waitUntilHandlersIdle();
         assertFalse(statusBar.isVisible());
@@ -914,15 +913,15 @@
 
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app", uid);
         app.mActivityRecord.setVisible(false);
-        app.mActivityRecord.setVisibility(false /* visible */, false /* deferHidingClient */);
+        app.mActivityRecord.setVisibility(false);
         assertFalse(mAtm.hasActiveVisibleWindow(uid));
 
-        app.mActivityRecord.setVisibility(true /* visible */, false /* deferHidingClient */);
+        app.mActivityRecord.setVisibility(true);
         assertTrue(mAtm.hasActiveVisibleWindow(uid));
 
         // Make the activity invisible and add a visible toast. The uid should have no active
         // visible window because toast can be misused by legacy app to bypass background check.
-        app.mActivityRecord.setVisibility(false /* visible */, false /* deferHidingClient */);
+        app.mActivityRecord.setVisibility(false);
         final WindowState overlay = createWindow(null, TYPE_APPLICATION_OVERLAY, "overlay", uid);
         final WindowState toast = createWindow(null, TYPE_TOAST, app.mToken, "toast", uid);
         toast.onSurfaceShownChanged(true);
@@ -1004,21 +1003,18 @@
     @SetupWindows(addWindows = { W_INPUT_METHOD, W_ACTIVITY })
     @Test
     public void testImeAlwaysReceivesVisibleNavigationBarInsets() {
-        final InsetsSource navSource = new InsetsSource(ITYPE_NAVIGATION_BAR, navigationBars());
+        final int navId = InsetsSource.createId(null, 0, navigationBars());
+        final InsetsSource navSource = new InsetsSource(navId, navigationBars());
         mImeWindow.mAboveInsetsState.addSource(navSource);
         mAppWindow.mAboveInsetsState.addSource(navSource);
 
         navSource.setVisible(false);
-        assertTrue(mImeWindow.getInsetsState().isSourceOrDefaultVisible(
-                ITYPE_NAVIGATION_BAR, navigationBars()));
-        assertFalse(mAppWindow.getInsetsState().isSourceOrDefaultVisible(
-                ITYPE_NAVIGATION_BAR, navigationBars()));
+        assertTrue(mImeWindow.getInsetsState().isSourceOrDefaultVisible(navId, navigationBars()));
+        assertFalse(mAppWindow.getInsetsState().isSourceOrDefaultVisible(navId, navigationBars()));
 
         navSource.setVisible(true);
-        assertTrue(mImeWindow.getInsetsState().isSourceOrDefaultVisible(
-                ITYPE_NAVIGATION_BAR, navigationBars()));
-        assertTrue(mAppWindow.getInsetsState().isSourceOrDefaultVisible(
-                ITYPE_NAVIGATION_BAR, navigationBars()));
+        assertTrue(mImeWindow.getInsetsState().isSourceOrDefaultVisible(navId, navigationBars()));
+        assertTrue(mAppWindow.getInsetsState().isSourceOrDefaultVisible(navId, navigationBars()));
     }
 
     @Test
@@ -1157,12 +1153,12 @@
     public void testRequestedVisibility() {
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
         app.mActivityRecord.setVisible(false);
-        app.mActivityRecord.setVisibility(false /* visible */, false /* deferHidingClient */);
+        app.mActivityRecord.setVisibility(false);
         assertFalse(app.isVisibleRequested());
 
         // It doesn't have a surface yet, but should still be visible requested.
         app.setHasSurface(false);
-        app.mActivityRecord.setVisibility(true /* visible */, false /* deferHidingClient */);
+        app.mActivityRecord.setVisibility(true);
 
         assertFalse(app.isVisible());
         assertTrue(app.isVisibleRequested());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index fafe90a..ce6cd90 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -26,12 +26,6 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.os.Process.SYSTEM_UID;
-import static android.view.InsetsState.ITYPE_BOTTOM_MANDATORY_GESTURES;
-import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
-import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
-import static android.view.InsetsState.ITYPE_TOP_MANDATORY_GESTURES;
-import static android.view.InsetsState.ITYPE_TOP_TAPPABLE_ELEMENT;
 import static android.view.View.VISIBLE;
 import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
 import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL;
@@ -99,6 +93,7 @@
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Transaction;
 import android.view.View;
+import android.view.WindowInsets;
 import android.view.WindowManager;
 import android.view.WindowManager.DisplayImePolicy;
 import android.view.inputmethod.ImeTracker;
@@ -312,7 +307,7 @@
         beforeCreateTestDisplay();
         mDisplayContent = createNewDisplayWithImeSupport(DISPLAY_IME_POLICY_LOCAL);
         addCommonWindows(annotation.addAllCommonWindows(), annotation.addWindows());
-        mDisplayContent.getInsetsPolicy().setRemoteInsetsControllerControlsSystemBars(false);
+        mDisplayContent.getDisplayPolicy().setRemoteInsetsControllerControlsSystemBars(false);
 
         // Adding a display will cause freezing the display. Make sure to wait until it's
         // unfrozen to not run into race conditions with the tests.
@@ -338,10 +333,11 @@
             mStatusBarWindow.mAttrs.layoutInDisplayCutoutMode =
                     LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
             mStatusBarWindow.mAttrs.setFitInsetsTypes(0);
+            final IBinder owner = new Binder();
             mStatusBarWindow.mAttrs.providedInsets = new InsetsFrameProvider[] {
-                    new InsetsFrameProvider(ITYPE_STATUS_BAR),
-                    new InsetsFrameProvider(ITYPE_TOP_TAPPABLE_ELEMENT),
-                    new InsetsFrameProvider(ITYPE_TOP_MANDATORY_GESTURES)
+                    new InsetsFrameProvider(owner, 0, WindowInsets.Type.statusBars()),
+                    new InsetsFrameProvider(owner, 0, WindowInsets.Type.tappableElement()),
+                    new InsetsFrameProvider(owner, 0, WindowInsets.Type.mandatorySystemGestures())
             };
         }
         if (addAll || ArrayUtils.contains(requestedWindows, W_NOTIFICATION_SHADE)) {
@@ -358,14 +354,15 @@
                     LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
             mNavBarWindow.mAttrs.privateFlags |=
                     WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT;
+            final IBinder owner = new Binder();
             mNavBarWindow.mAttrs.providedInsets = new InsetsFrameProvider[] {
-                    new InsetsFrameProvider(ITYPE_NAVIGATION_BAR),
-                    new InsetsFrameProvider(ITYPE_BOTTOM_MANDATORY_GESTURES),
-                    new InsetsFrameProvider(ITYPE_BOTTOM_TAPPABLE_ELEMENT)
+                    new InsetsFrameProvider(owner, 0, WindowInsets.Type.navigationBars()),
+                    new InsetsFrameProvider(owner, 0, WindowInsets.Type.tappableElement()),
+                    new InsetsFrameProvider(owner, 0, WindowInsets.Type.mandatorySystemGestures())
             };
             for (int rot = Surface.ROTATION_0; rot <= Surface.ROTATION_270; rot++) {
                 mNavBarWindow.mAttrs.paramsForRotation[rot] =
-                        getNavBarLayoutParamsForRotation(rot);
+                        getNavBarLayoutParamsForRotation(rot, owner);
             }
         }
         if (addAll || ArrayUtils.contains(requestedWindows, W_DOCK_DIVIDER)) {
@@ -388,7 +385,8 @@
         }
     }
 
-    private WindowManager.LayoutParams getNavBarLayoutParamsForRotation(int rotation) {
+    private WindowManager.LayoutParams getNavBarLayoutParamsForRotation(
+            int rotation, IBinder owner) {
         int width = WindowManager.LayoutParams.MATCH_PARENT;
         int height = WindowManager.LayoutParams.MATCH_PARENT;
         int gravity = Gravity.BOTTOM;
@@ -417,9 +415,9 @@
                 WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT;
         lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
         lp.providedInsets = new InsetsFrameProvider[] {
-                new InsetsFrameProvider(ITYPE_NAVIGATION_BAR),
-                new InsetsFrameProvider(ITYPE_BOTTOM_MANDATORY_GESTURES),
-                new InsetsFrameProvider(ITYPE_BOTTOM_TAPPABLE_ELEMENT)
+                new InsetsFrameProvider(owner, 0, WindowInsets.Type.navigationBars()),
+                new InsetsFrameProvider(owner, 0, WindowInsets.Type.tappableElement()),
+                new InsetsFrameProvider(owner, 0, WindowInsets.Type.mandatorySystemGestures())
         };
         return lp;
     }
@@ -454,8 +452,10 @@
 
     WindowState createNavBarWithProvidedInsets(DisplayContent dc) {
         final WindowState navbar = createWindow(null, TYPE_NAVIGATION_BAR, dc, "navbar");
+        final Binder owner = new Binder();
         navbar.mAttrs.providedInsets = new InsetsFrameProvider[] {
-                new InsetsFrameProvider(ITYPE_NAVIGATION_BAR, Insets.of(0, 0, 0, NAV_BAR_HEIGHT))
+                new InsetsFrameProvider(owner, 0, WindowInsets.Type.navigationBars())
+                        .setInsetsSize(Insets.of(0, 0, 0, NAV_BAR_HEIGHT))
         };
         dc.getDisplayPolicy().addWindowLw(navbar, navbar.mAttrs);
         return navbar;
diff --git a/services/usage/java/com/android/server/usage/TEST_MAPPING b/services/usage/java/com/android/server/usage/TEST_MAPPING
index 1c0c71b..a3fe6f2 100644
--- a/services/usage/java/com/android/server/usage/TEST_MAPPING
+++ b/services/usage/java/com/android/server/usage/TEST_MAPPING
@@ -18,9 +18,7 @@
           "exclude-filter": "com.android.server.usage.StorageStatsServiceTest"
         }
       ]
-    }
-  ],
-  "presubmit-large": [
+    },
     {
       "name": "CtsUsageStatsTestCases",
       "options": [
diff --git a/services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java b/services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java
index 0dcf8ce..b1cd994 100644
--- a/services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.content.Context;
 import android.hardware.usb.UsbConfiguration;
-import android.hardware.usb.UsbConstants;
 import android.hardware.usb.UsbDevice;
 import android.hardware.usb.UsbDeviceConnection;
 import android.hardware.usb.UsbEndpoint;
@@ -35,9 +34,12 @@
 import android.service.usb.UsbDirectMidiDeviceProto;
 import android.util.Log;
 
+import com.android.internal.midi.MidiEventMultiScheduler;
 import com.android.internal.midi.MidiEventScheduler;
 import com.android.internal.midi.MidiEventScheduler.MidiEvent;
 import com.android.internal.util.dump.DualDumpOutputStream;
+import com.android.server.usb.descriptors.UsbACMidi10Endpoint;
+import com.android.server.usb.descriptors.UsbDescriptor;
 import com.android.server.usb.descriptors.UsbDescriptorParser;
 import com.android.server.usb.descriptors.UsbEndpointDescriptor;
 import com.android.server.usb.descriptors.UsbInterfaceDescriptor;
@@ -45,6 +47,7 @@
 
 import libcore.io.IoUtils;
 
+import java.io.ByteArrayOutputStream;
 import java.io.Closeable;
 import java.io.IOException;
 import java.nio.ByteBuffer;
@@ -56,7 +59,7 @@
  */
 public final class UsbDirectMidiDevice implements Closeable {
     private static final String TAG = "UsbDirectMidiDevice";
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = true;
 
     private Context mContext;
     private String mName;
@@ -74,9 +77,6 @@
 
     private MidiDeviceServer mServer;
 
-    // event schedulers for each input port of the physical device
-    private MidiEventScheduler[] mEventSchedulers;
-
     // Timeout for sending a packet to a device.
     // If bulkTransfer times out, retry sending the packet up to 20 times.
     private static final int BULK_TRANSFER_TIMEOUT_MILLISECONDS = 50;
@@ -86,8 +86,21 @@
     private static final int THREAD_JOIN_TIMEOUT_MILLISECONDS = 200;
 
     private ArrayList<UsbDeviceConnection> mUsbDeviceConnections;
+
+    // Array of endpoints by device connection.
     private ArrayList<ArrayList<UsbEndpoint>> mInputUsbEndpoints;
     private ArrayList<ArrayList<UsbEndpoint>> mOutputUsbEndpoints;
+
+    // Array of cable counts by device connection.
+    // Each number here maps to an entry in mInputUsbEndpoints or mOutputUsbEndpoints.
+    // This is needed because this info is part of UsbEndpointDescriptor but not UsbEndpoint.
+    private ArrayList<ArrayList<Integer>> mInputUsbEndpointCableCounts;
+    private ArrayList<ArrayList<Integer>> mOutputUsbEndpointCableCounts;
+
+    // Array of event schedulers by device connection.
+    // Each number here maps to an entry in mOutputUsbEndpoints.
+    private ArrayList<ArrayList<MidiEventMultiScheduler>> mMidiEventMultiSchedulers;
+
     private ArrayList<Thread> mThreads;
 
     private UsbMidiBlockParser mMidiBlockParser = new UsbMidiBlockParser();
@@ -97,8 +110,6 @@
     private boolean mIsOpen;
     private boolean mServerAvailable;
 
-    private UsbMidiPacketConverter mUsbMidiPacketConverter;
-
     private PowerBoostSetter mPowerBoostSetter = null;
 
     private static final byte MESSAGE_TYPE_MIDI_1_CHANNEL_VOICE = 0x02;
@@ -238,9 +249,9 @@
                         interfaceDescriptor.getEndpointDescriptor(endpointIndex);
                 // 0 is output, 1 << 7 is input.
                 if (endpoint.getDirection() == 0) {
-                    numOutputs++;
+                    numOutputs += getNumJacks(endpoint);
                 } else {
-                    numInputs++;
+                    numInputs += getNumJacks(endpoint);
                 }
             }
         }
@@ -307,19 +318,21 @@
         Log.d(TAG, "openLocked()");
         UsbManager manager = mContext.getSystemService(UsbManager.class);
 
-        // Converting from raw MIDI to USB MIDI is not thread-safe.
-        // UsbMidiPacketConverter creates a converter from raw MIDI
-        // to USB MIDI for each USB output.
-        mUsbMidiPacketConverter = new UsbMidiPacketConverter(mNumOutputs);
-
         mUsbDeviceConnections = new ArrayList<UsbDeviceConnection>();
         mInputUsbEndpoints = new ArrayList<ArrayList<UsbEndpoint>>();
         mOutputUsbEndpoints = new ArrayList<ArrayList<UsbEndpoint>>();
+        mInputUsbEndpointCableCounts = new ArrayList<ArrayList<Integer>>();
+        mOutputUsbEndpointCableCounts = new ArrayList<ArrayList<Integer>>();
+        mMidiEventMultiSchedulers = new ArrayList<ArrayList<MidiEventMultiScheduler>>();
         mThreads = new ArrayList<Thread>();
 
         for (int interfaceIndex = 0; interfaceIndex < mUsbInterfaces.size(); interfaceIndex++) {
             ArrayList<UsbEndpoint> inputEndpoints = new ArrayList<UsbEndpoint>();
             ArrayList<UsbEndpoint> outputEndpoints = new ArrayList<UsbEndpoint>();
+            ArrayList<Integer> inputEndpointCableCounts = new ArrayList<Integer>();
+            ArrayList<Integer> outputEndpointCableCounts = new ArrayList<Integer>();
+            ArrayList<MidiEventMultiScheduler> midiEventMultiSchedulers =
+                    new ArrayList<MidiEventMultiScheduler>();
             UsbInterfaceDescriptor interfaceDescriptor = mUsbInterfaces.get(interfaceIndex);
             for (int endpointIndex = 0; endpointIndex < interfaceDescriptor.getNumEndpoints();
                     endpointIndex++) {
@@ -328,8 +341,13 @@
                 // 0 is output, 1 << 7 is input.
                 if (endpoint.getDirection() == 0) {
                     outputEndpoints.add(endpoint.toAndroid(mParser));
+                    outputEndpointCableCounts.add(getNumJacks(endpoint));
+                    MidiEventMultiScheduler scheduler =
+                            new MidiEventMultiScheduler(getNumJacks(endpoint));
+                    midiEventMultiSchedulers.add(scheduler);
                 } else {
                     inputEndpoints.add(endpoint.toAndroid(mParser));
+                    inputEndpointCableCounts.add(getNumJacks(endpoint));
                 }
             }
             if (!outputEndpoints.isEmpty() || !inputEndpoints.isEmpty()) {
@@ -341,40 +359,69 @@
                 mUsbDeviceConnections.add(connection);
                 mInputUsbEndpoints.add(inputEndpoints);
                 mOutputUsbEndpoints.add(outputEndpoints);
+                mInputUsbEndpointCableCounts.add(inputEndpointCableCounts);
+                mOutputUsbEndpointCableCounts.add(outputEndpointCableCounts);
+                mMidiEventMultiSchedulers.add(midiEventMultiSchedulers);
             }
         }
 
-        mEventSchedulers = new MidiEventScheduler[mNumOutputs];
-
-        for (int i = 0; i < mNumOutputs; i++) {
-            MidiEventScheduler scheduler = new MidiEventScheduler();
-            mEventSchedulers[i] = scheduler;
-            mMidiInputPortReceivers[i].setReceiver(scheduler.getReceiver());
+        // Set up event schedulers
+        int outputIndex = 0;
+        for (int connectionIndex = 0; connectionIndex < mMidiEventMultiSchedulers.size();
+                connectionIndex++) {
+            for (int endpointIndex = 0;
+                    endpointIndex < mMidiEventMultiSchedulers.get(connectionIndex).size();
+                    endpointIndex++) {
+                int cableCount =
+                        mOutputUsbEndpointCableCounts.get(connectionIndex).get(endpointIndex);
+                MidiEventMultiScheduler multiScheduler =
+                        mMidiEventMultiSchedulers.get(connectionIndex).get(endpointIndex);
+                for (int cableNumber = 0; cableNumber < cableCount; cableNumber++) {
+                    MidiEventScheduler scheduler = multiScheduler.getEventScheduler(cableNumber);
+                    mMidiInputPortReceivers[outputIndex].setReceiver(scheduler.getReceiver());
+                    outputIndex++;
+                }
+            }
         }
 
         final MidiReceiver[] outputReceivers = mServer.getOutputPortReceivers();
 
         // Create input thread for each input port of the physical device
-        int portNumber = 0;
+        int portStartNumber = 0;
         for (int connectionIndex = 0; connectionIndex < mInputUsbEndpoints.size();
                 connectionIndex++) {
             for (int endpointIndex = 0;
                     endpointIndex < mInputUsbEndpoints.get(connectionIndex).size();
                     endpointIndex++) {
+                // Each USB endpoint maps to one or more outputReceivers. USB MIDI data from an
+                // endpoint should be sent to the appropriate outputReceiver. A new thread is
+                // created and waits for incoming USB data. Once the data is received, it is added
+                // to the packet converter. The packet converter acts as an inverse multiplexer.
+                // With a for loop, data is pulled per cable and sent to the correct output
+                // receiver. The first byte of each legacy MIDI 1.0 USB message indicates which
+                // cable the data should be used and is how the reverse multiplexer directs data.
+                // For MIDI UMP endpoints, a multiplexer is not needed as we are just swapping
+                // the endianness of the packets.
                 final UsbDeviceConnection connectionFinal =
                         mUsbDeviceConnections.get(connectionIndex);
                 final UsbEndpoint endpointFinal =
                         mInputUsbEndpoints.get(connectionIndex).get(endpointIndex);
-                final int portFinal = portNumber;
+                final int portStartFinal = portStartNumber;
+                final int cableCountFinal =
+                        mInputUsbEndpointCableCounts.get(connectionIndex).get(endpointIndex);
 
-                Thread newThread = new Thread("UsbDirectMidiDevice input thread " + portFinal) {
+                Thread newThread = new Thread("UsbDirectMidiDevice input thread "
+                        + portStartFinal) {
                     @Override
                     public void run() {
                         final UsbRequest request = new UsbRequest();
+                        final UsbMidiPacketConverter packetConverter = new UsbMidiPacketConverter();
+                        packetConverter.createDecoders(cableCountFinal);
                         try {
                             request.initialize(connectionFinal, endpointFinal);
                             byte[] inputBuffer = new byte[endpointFinal.getMaxPacketSize()];
-                            while (true) {
+                            boolean keepGoing = true;
+                            while (keepGoing) {
                                 if (Thread.currentThread().interrupted()) {
                                     Log.w(TAG, "input thread interrupted");
                                     break;
@@ -404,42 +451,56 @@
                                         logByteArray("Input before conversion ", inputBuffer,
                                                 0, bytesRead);
                                     }
+
+                                    // Add packets into the packet decoder.
+                                    if (!mIsUniversalMidiDevice) {
+                                        packetConverter.decodeMidiPackets(inputBuffer, bytesRead);
+                                    }
+
                                     byte[] convertedArray;
-                                    if (mIsUniversalMidiDevice) {
-                                        // For USB, each 32 bit word of a UMP is
-                                        // sent with the least significant byte first.
-                                        convertedArray = swapEndiannessPerWord(inputBuffer,
-                                                bytesRead);
-                                    } else {
-                                        if (mUsbMidiPacketConverter == null) {
-                                            Log.w(TAG, "mUsbMidiPacketConverter is null");
+                                    for (int cableNumber = 0; cableNumber < cableCountFinal;
+                                            cableNumber++) {
+                                        if (mIsUniversalMidiDevice) {
+                                            // For USB, each 32 bit word of a UMP is
+                                            // sent with the least significant byte first.
+                                            convertedArray = swapEndiannessPerWord(inputBuffer,
+                                                    bytesRead);
+                                        } else {
+                                            convertedArray =
+                                                    packetConverter.pullDecodedMidiPackets(
+                                                            cableNumber);
+                                        }
+
+                                        if (DEBUG) {
+                                            logByteArray("Input " + cableNumber
+                                                    + " after conversion ", convertedArray, 0,
+                                                    convertedArray.length);
+                                        }
+
+                                        if (convertedArray.length == 0) {
+                                            continue;
+                                        }
+
+                                        if ((outputReceivers == null)
+                                                || (outputReceivers[portStartFinal + cableNumber]
+                                                == null)) {
+                                            Log.w(TAG, "outputReceivers is null");
+                                            keepGoing = false;
                                             break;
                                         }
-                                        convertedArray =
-                                                mUsbMidiPacketConverter.usbMidiToRawMidi(
-                                                         inputBuffer, bytesRead);
-                                    }
+                                        outputReceivers[portStartFinal + cableNumber].send(
+                                                convertedArray, 0, convertedArray.length,
+                                                timestamp);
 
-                                    if (DEBUG) {
-                                        logByteArray("Input after conversion ", convertedArray,
-                                                0, convertedArray.length);
-                                    }
-
-                                    if ((outputReceivers == null)
-                                            || (outputReceivers[portFinal] == null)) {
-                                        Log.w(TAG, "outputReceivers is null");
-                                        break;
-                                    }
-                                    outputReceivers[portFinal].send(convertedArray, 0,
-                                            convertedArray.length, timestamp);
-
-                                    // Boost power if there seems to be a voice message.
-                                    // For legacy devices, boost when message is more than size 1.
-                                    // For UMP devices, boost for channel voice messages.
-                                    if ((mPowerBoostSetter != null && convertedArray.length > 1)
-                                            && (!mIsUniversalMidiDevice
-                                            || isChannelVoiceMessage(convertedArray))) {
-                                        mPowerBoostSetter.boostPower();
+                                        // Boost power if there seems to be a voice message.
+                                        // For legacy devices, boost if message length > 1.
+                                        // For UMP devices, boost for channel voice messages.
+                                        if ((mPowerBoostSetter != null
+                                                && convertedArray.length > 1)
+                                                && (!mIsUniversalMidiDevice
+                                                || isChannelVoiceMessage(convertedArray))) {
+                                            mPowerBoostSetter.boostPower();
+                                        }
                                     }
                                 }
                             }
@@ -455,64 +516,93 @@
                 };
                 newThread.start();
                 mThreads.add(newThread);
-                portNumber++;
+                portStartNumber += cableCountFinal;
             }
         }
 
         // Create output thread for each output port of the physical device
-        portNumber = 0;
+        portStartNumber = 0;
         for (int connectionIndex = 0; connectionIndex < mOutputUsbEndpoints.size();
                 connectionIndex++) {
             for (int endpointIndex = 0;
                     endpointIndex < mOutputUsbEndpoints.get(connectionIndex).size();
                     endpointIndex++) {
+                // Each USB endpoint maps to one or more MIDI ports. Each port has an event
+                // scheduler that is used to pull incoming raw MIDI bytes from Android apps.
+                // With a MidiEventMultiScheduler, data can be pulled if any of the schedulers
+                // have new incoming data. This data is then packaged as USB MIDI packets before
+                // getting sent through USB. One thread will be created per endpoint that pulls
+                // data from all relevant event schedulers. Raw MIDI from the event schedulers
+                // will be converted to the correct USB MIDI format before getting sent through
+                // USB.
+
                 final UsbDeviceConnection connectionFinal =
                         mUsbDeviceConnections.get(connectionIndex);
                 final UsbEndpoint endpointFinal =
                         mOutputUsbEndpoints.get(connectionIndex).get(endpointIndex);
-                final int portFinal = portNumber;
-                final MidiEventScheduler eventSchedulerFinal = mEventSchedulers[portFinal];
+                final int portStartFinal = portStartNumber;
+                final int cableCountFinal =
+                        mOutputUsbEndpointCableCounts.get(connectionIndex).get(endpointIndex);
+                final MidiEventMultiScheduler multiSchedulerFinal =
+                            mMidiEventMultiSchedulers.get(connectionIndex).get(endpointIndex);
 
-                Thread newThread = new Thread("UsbDirectMidiDevice output thread " + portFinal) {
+                Thread newThread = new Thread("UsbDirectMidiDevice output write thread "
+                        + portStartFinal) {
                     @Override
                     public void run() {
                         try {
-                            while (true) {
-                                if (Thread.currentThread().interrupted()) {
-                                    Log.w(TAG, "output thread interrupted");
+                            final ByteArrayOutputStream midi2ByteStream =
+                                    new ByteArrayOutputStream();
+                            final UsbMidiPacketConverter packetConverter =
+                                    new UsbMidiPacketConverter();
+                            packetConverter.createEncoders(cableCountFinal);
+                            boolean isInterrupted = false;
+                            while (!isInterrupted) {
+                                boolean wasSuccessful = multiSchedulerFinal.waitNextEvent();
+                                if (!wasSuccessful) {
+                                    Log.d(TAG, "output thread closed");
                                     break;
                                 }
-                                MidiEvent event;
-                                try {
-                                    event = (MidiEvent) eventSchedulerFinal.waitNextEvent();
-                                } catch (InterruptedException e) {
-                                    Log.w(TAG, "event scheduler interrupted");
-                                    break;
-                                }
-                                if (event == null) {
-                                    Log.w(TAG, "event is null");
-                                    break;
-                                }
-
-                                if (DEBUG) {
-                                    logByteArray("Output before conversion ", event.data, 0,
-                                            event.count);
-                                }
-
-                                byte[] convertedArray;
-                                if (mIsUniversalMidiDevice) {
-                                    // For USB, each 32 bit word of a UMP is
-                                    // sent with the least significant byte first.
-                                    convertedArray = swapEndiannessPerWord(event.data,
-                                            event.count);
-                                } else {
-                                    if (mUsbMidiPacketConverter == null) {
-                                        Log.w(TAG, "mUsbMidiPacketConverter is null");
-                                        break;
+                                long now = System.nanoTime();
+                                for (int cableNumber = 0; cableNumber < cableCountFinal;
+                                        cableNumber++) {
+                                    MidiEventScheduler eventScheduler =
+                                            multiSchedulerFinal.getEventScheduler(cableNumber);
+                                    MidiEvent event =
+                                            (MidiEvent) eventScheduler.getNextEvent(now);
+                                    while (event != null) {
+                                        if (DEBUG) {
+                                            logByteArray("Output before conversion ",
+                                                    event.data, 0, event.count);
+                                        }
+                                        if (mIsUniversalMidiDevice) {
+                                            // For USB, each 32 bit word of a UMP is
+                                            // sent with the least significant byte first.
+                                            byte[] convertedArray = swapEndiannessPerWord(
+                                                    event.data, event.count);
+                                            midi2ByteStream.write(convertedArray, 0,
+                                                    convertedArray.length);
+                                        } else {
+                                            packetConverter.encodeMidiPackets(event.data,
+                                                    event.count, cableNumber);
+                                        }
+                                        eventScheduler.addEventToPool(event);
+                                        event = (MidiEvent) eventScheduler.getNextEvent(now);
                                     }
+                                }
+
+                                if (Thread.currentThread().interrupted()) {
+                                    Log.d(TAG, "output thread interrupted");
+                                    break;
+                                }
+
+                                byte[] convertedArray = new byte[0];
+                                if (mIsUniversalMidiDevice) {
+                                    convertedArray = midi2ByteStream.toByteArray();
+                                    midi2ByteStream.reset();
+                                } else {
                                     convertedArray =
-                                            mUsbMidiPacketConverter.rawMidiToUsbMidi(
-                                                     event.data, event.count, portFinal);
+                                            packetConverter.pullEncodedMidiPackets();
                                 }
 
                                 if (DEBUG) {
@@ -520,7 +610,6 @@
                                             convertedArray.length);
                                 }
 
-                                boolean isInterrupted = false;
                                 // Split the packet into multiple if they are greater than the
                                 // endpoint's max packet size.
                                 for (int curPacketStart = 0;
@@ -558,11 +647,9 @@
                                         }
                                     }
                                 }
-                                if (isInterrupted == true) {
-                                    break;
-                                }
-                                eventSchedulerFinal.addEventToPool(event);
                             }
+                        } catch (InterruptedException e) {
+                            Log.w(TAG, "output thread: ", e);
                         } catch (NullPointerException e) {
                             Log.e(TAG, "output thread: ", e);
                         }
@@ -571,7 +658,7 @@
                 };
                 newThread.start();
                 mThreads.add(newThread);
-                portNumber++;
+                portStartNumber += cableCountFinal;
             }
         }
 
@@ -667,11 +754,21 @@
         }
         mThreads = null;
 
-        for (int i = 0; i < mEventSchedulers.length; i++) {
+        for (int i = 0; i < mMidiInputPortReceivers.length; i++) {
             mMidiInputPortReceivers[i].setReceiver(null);
-            mEventSchedulers[i].close();
         }
-        mEventSchedulers = null;
+
+        for (int connectionIndex = 0; connectionIndex < mMidiEventMultiSchedulers.size();
+                connectionIndex++) {
+            for (int endpointIndex = 0;
+                    endpointIndex < mMidiEventMultiSchedulers.get(connectionIndex).size();
+                    endpointIndex++) {
+                MidiEventMultiScheduler multiScheduler =
+                        mMidiEventMultiSchedulers.get(connectionIndex).get(endpointIndex);
+                multiScheduler.close();
+            }
+        }
+        mMidiEventMultiSchedulers = null;
 
         for (UsbDeviceConnection connection : mUsbDeviceConnections) {
             connection.close();
@@ -679,8 +776,8 @@
         mUsbDeviceConnections = null;
         mInputUsbEndpoints = null;
         mOutputUsbEndpoints = null;
-
-        mUsbMidiPacketConverter = null;
+        mInputUsbEndpointCableCounts = null;
+        mOutputUsbEndpointCableCounts = null;
 
         mIsOpen = false;
     }
@@ -788,4 +885,19 @@
         return messageType == MESSAGE_TYPE_MIDI_1_CHANNEL_VOICE
                 || messageType == MESSAGE_TYPE_MIDI_2_CHANNEL_VOICE;
     }
+
+    // Returns the number of jacks for MIDI 1.0 endpoints.
+    // For MIDI 2.0 endpoints, this concept does not exist and each endpoint should be treated as
+    // one port.
+    private int getNumJacks(UsbEndpointDescriptor usbEndpointDescriptor) {
+        UsbDescriptor classSpecificEndpointDescriptor =
+                usbEndpointDescriptor.getClassSpecificEndpointDescriptor();
+        if (classSpecificEndpointDescriptor != null
+                && (classSpecificEndpointDescriptor instanceof UsbACMidi10Endpoint)) {
+            UsbACMidi10Endpoint midiEndpoint =
+                    (UsbACMidi10Endpoint) classSpecificEndpointDescriptor;
+            return midiEndpoint.getNumJacks();
+        }
+        return 1;
+    }
 }
diff --git a/services/usb/java/com/android/server/usb/UsbMidiPacketConverter.java b/services/usb/java/com/android/server/usb/UsbMidiPacketConverter.java
index 56bb236..65d7a41 100644
--- a/services/usb/java/com/android/server/usb/UsbMidiPacketConverter.java
+++ b/services/usb/java/com/android/server/usb/UsbMidiPacketConverter.java
@@ -16,12 +16,17 @@
 
 package com.android.server.usb;
 
+import android.util.Log;
+
 import java.io.ByteArrayOutputStream;
 
 /**
- * Converts between MIDI packets and USB MIDI 1.0 packets.
+ * Converts between raw MIDI packets and USB MIDI 1.0 packets.
+ * This is NOT thread-safe. Please handle locking outside this function for multiple threads.
+ * For data mapping to an invalid cable number, this converter will use the first cable.
  */
 public class UsbMidiPacketConverter {
+    private static final String TAG = "UsbMidiPacketConverter";
 
     // Refer to Table 4-1 in USB MIDI 1.0 spec.
     private static final int[] PAYLOAD_SIZE = new int[]{
@@ -74,54 +79,133 @@
     private static final byte SYSEX_START_EXCLUSIVE = (byte) 0xF0;
     private static final byte SYSEX_END_EXCLUSIVE = (byte) 0xF7;
 
-    private UsbMidiDecoder mUsbMidiDecoder = new UsbMidiDecoder();
     private UsbMidiEncoder[] mUsbMidiEncoders;
+    private ByteArrayOutputStream mEncoderOutputStream = new ByteArrayOutputStream();
 
-    public UsbMidiPacketConverter(int numEncoders) {
-        mUsbMidiEncoders = new UsbMidiEncoder[numEncoders];
-        for (int i = 0; i < numEncoders; i++) {
-            mUsbMidiEncoders[i] = new UsbMidiEncoder();
-        }
-    }
+    private UsbMidiDecoder mUsbMidiDecoder;
 
     /**
-     * Converts a USB MIDI array into a raw MIDI array.
+     * Creates encoders.
      *
-     * @param usbMidiBytes the USB MIDI bytes to convert
-     * @param size the size of usbMidiBytes
-     * @return byte array of raw MIDI packets
+     * createEncoders() must be called before raw MIDI can be converted to USB MIDI.
+     *
+     * @param size the number of encoders to create
      */
-    public byte[] usbMidiToRawMidi(byte[] usbMidiBytes, int size) {
-        return mUsbMidiDecoder.decode(usbMidiBytes, size);
+    public void createEncoders(int size) {
+        mUsbMidiEncoders = new UsbMidiEncoder[size];
+        for (int i = 0; i < size; i++) {
+            mUsbMidiEncoders[i] = new UsbMidiEncoder(i);
+        }
     }
 
     /**
      * Converts a raw MIDI array into a USB MIDI array.
      *
+     * Call pullEncodedMidiPackets to retrieve the byte array.
+     *
      * @param midiBytes the raw MIDI bytes to convert
      * @param size the size of usbMidiBytes
      * @param encoderId which encoder to use
+     */
+    public void encodeMidiPackets(byte[] midiBytes, int size, int encoderId) {
+        // Use the first encoder if the encoderId is invalid.
+        if (encoderId >= mUsbMidiEncoders.length) {
+            Log.w(TAG, "encoderId " + encoderId + " invalid");
+            encoderId = 0;
+        }
+        byte[] encodedPacket = mUsbMidiEncoders[encoderId].encode(midiBytes, size);
+        mEncoderOutputStream.write(encodedPacket, 0, encodedPacket.length);
+    }
+
+    /**
+     * Returns the encoded MIDI packets from encodeMidiPackets
+     *
      * @return byte array of USB MIDI packets
      */
-    public byte[] rawMidiToUsbMidi(byte[] midiBytes, int size, int encoderId) {
-        return mUsbMidiEncoders[encoderId].encode(midiBytes, size);
+    public byte[] pullEncodedMidiPackets() {
+        byte[] output = mEncoderOutputStream.toByteArray();
+        mEncoderOutputStream.reset();
+        return output;
+    }
+
+    /**
+     * Creates decoders.
+     *
+     * createDecoders() must be called before USB MIDI can be converted to raw MIDI.
+     *
+     * @param size the number of decoders to create
+     */
+    public void createDecoders(int size) {
+        mUsbMidiDecoder = new UsbMidiDecoder(size);
+    }
+
+    /**
+     * Converts a USB MIDI array into a multiple MIDI arrays, one per cable.
+     *
+     * Call pullDecodedMidiPackets to retrieve the byte array.
+     *
+     * @param usbMidiBytes the USB MIDI bytes to convert
+     * @param size the size of usbMidiBytes
+     */
+    public void decodeMidiPackets(byte[] usbMidiBytes, int size) {
+        mUsbMidiDecoder.decode(usbMidiBytes, size);
+    }
+
+    /**
+     * Returns the decoded MIDI packets from decodeMidiPackets
+     *
+     * @param cableNumber the cable to pull data from
+     * @return byte array of raw MIDI packets
+     */
+    public byte[] pullDecodedMidiPackets(int cableNumber) {
+        return mUsbMidiDecoder.pullBytes(cableNumber);
     }
 
     private class UsbMidiDecoder {
+        int mNumJacks;
+        ByteArrayOutputStream[] mDecodedByteArrays;
+
+        UsbMidiDecoder(int numJacks) {
+            mNumJacks = numJacks;
+            mDecodedByteArrays = new ByteArrayOutputStream[numJacks];
+            for (int i = 0; i < numJacks; i++) {
+                mDecodedByteArrays[i] = new ByteArrayOutputStream();
+            }
+        }
+
         // Decodes the data from USB MIDI to raw MIDI.
         // Each valid 4 byte input maps to a 1-3 byte output.
         // Reference the USB MIDI 1.0 spec for more info.
-        public byte[] decode(byte[] usbMidiBytes, int size) {
+        public void decode(byte[] usbMidiBytes, int size) {
             ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+            if (size % 4 != 0) {
+                Log.w(TAG, "size " + size + " not multiple of 4");
+            }
             for (int i = 0; i + 3 < size; i += 4) {
+                int cableNumber = (usbMidiBytes[i] >> 4) & 0x0f;
                 int codeIndex = usbMidiBytes[i] & 0x0f;
                 int numPayloadBytes = PAYLOAD_SIZE[codeIndex];
                 if (numPayloadBytes < 0) {
                     continue;
                 }
-                outputStream.write(usbMidiBytes, i + 1, numPayloadBytes);
+                // Use the first cable if the cable number is invalid.
+                if (cableNumber >= mNumJacks) {
+                    Log.w(TAG, "cableNumber " + cableNumber + " invalid");
+                    cableNumber = 0;
+                }
+                mDecodedByteArrays[cableNumber].write(usbMidiBytes, i + 1, numPayloadBytes);
             }
-            return outputStream.toByteArray();
+        }
+
+        public byte[] pullBytes(int cableNumber) {
+            // Use the first cable if the cable number is invalid.
+            if (cableNumber >= mNumJacks) {
+                Log.w(TAG, "cableNumber " + cableNumber + " invalid");
+                cableNumber = 0;
+            }
+            byte[] output = mDecodedByteArrays[cableNumber].toByteArray();
+            mDecodedByteArrays[cableNumber].reset();
+            return output;
         }
     }
 
@@ -135,6 +219,13 @@
 
         private byte[] mEmptyBytes = new byte[3]; // Used to fill out extra data
 
+        private byte mShiftedCableNumber;
+
+        UsbMidiEncoder(int cableNumber) {
+            // Jack Id is always the left nibble of every byte so shift this now.
+            mShiftedCableNumber = (byte) (cableNumber << 4);
+        }
+
         // Encodes the data from raw MIDI to USB MIDI.
         // Each valid 1-3 byte input maps to a 4 byte output.
         // Reference the USB MIDI 1.0 spec for more info.
@@ -153,7 +244,8 @@
                                 midiBytes[curLocation];
                         mNumStoredSystemExclusiveBytes++;
                         if (mNumStoredSystemExclusiveBytes == 3) {
-                            outputStream.write(CODE_INDEX_NUMBER_SYSEX_STARTS_OR_CONTINUES);
+                            outputStream.write(CODE_INDEX_NUMBER_SYSEX_STARTS_OR_CONTINUES
+                                    | mShiftedCableNumber);
                             outputStream.write(mStoredSystemExclusiveBytes, 0, 3);
                             mNumStoredSystemExclusiveBytes = 0;
                         }
@@ -179,7 +271,7 @@
                     byte codeIndexNumber = (byte) ((midiBytes[curLocation] >> 4) & 0x0f);
                     int channelMessageSize = PAYLOAD_SIZE[codeIndexNumber];
                     if (curLocation + channelMessageSize <= size) {
-                        outputStream.write(codeIndexNumber);
+                        outputStream.write(codeIndexNumber | mShiftedCableNumber);
                         outputStream.write(midiBytes, curLocation, channelMessageSize);
                         // Fill in the rest of the bytes with 0.
                         outputStream.write(mEmptyBytes, 0, 3 - channelMessageSize);
@@ -197,8 +289,8 @@
                     curLocation++;
                 } else if (midiBytes[curLocation] == SYSEX_END_EXCLUSIVE) {
                     // 1 byte is 0x05, 2 bytes is 0x06, and 3 bytes is 0x07
-                    outputStream.write(CODE_INDEX_NUMBER_SYSEX_END_SINGLE_BYTE
-                            + mNumStoredSystemExclusiveBytes);
+                    outputStream.write((CODE_INDEX_NUMBER_SYSEX_END_SINGLE_BYTE
+                            + mNumStoredSystemExclusiveBytes) | mShiftedCableNumber);
                     mStoredSystemExclusiveBytes[mNumStoredSystemExclusiveBytes] =
                             midiBytes[curLocation];
                     mNumStoredSystemExclusiveBytes++;
@@ -218,7 +310,7 @@
                     } else {
                         int systemMessageSize = PAYLOAD_SIZE[codeIndexNumber];
                         if (curLocation + systemMessageSize <= size) {
-                            outputStream.write(codeIndexNumber);
+                            outputStream.write(codeIndexNumber | mShiftedCableNumber);
                             outputStream.write(midiBytes, curLocation, systemMessageSize);
                             // Fill in the rest of the bytes with 0.
                             outputStream.write(mEmptyBytes, 0, 3 - systemMessageSize);
@@ -236,7 +328,7 @@
         }
 
         private void writeSingleByte(ByteArrayOutputStream outputStream, byte byteToWrite) {
-            outputStream.write(CODE_INDEX_NUMBER_SINGLE_BYTE);
+            outputStream.write(CODE_INDEX_NUMBER_SINGLE_BYTE | mShiftedCableNumber);
             outputStream.write(byteToWrite);
             outputStream.write(0);
             outputStream.write(0);
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java b/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java
index 1f448ac..117a3d9 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java
@@ -118,7 +118,7 @@
         mClassSpecificEndpointDescriptor = descriptor;
     }
 
-    UsbDescriptor getClassSpecificEndpointDescriptor() {
+    public UsbDescriptor getClassSpecificEndpointDescriptor() {
         return mClassSpecificEndpointDescriptor;
     }
 
diff --git a/services/usb/java/com/android/server/usb/hal/gadget/UsbGadgetHidl.java b/services/usb/java/com/android/server/usb/hal/gadget/UsbGadgetHidl.java
index 2c5fcb8..68067d2 100644
--- a/services/usb/java/com/android/server/usb/hal/gadget/UsbGadgetHidl.java
+++ b/services/usb/java/com/android/server/usb/hal/gadget/UsbGadgetHidl.java
@@ -191,9 +191,9 @@
     public void reset(long transactionId) {
         try {
             synchronized(mGadgetProxyLock) {
-                if (android.hardware.usb.gadget.V1_2.IUsbGadget.castFrom(mGadgetProxy) != null) {
-                    android.hardware.usb.gadget.V1_2.IUsbGadget gadgetProxy =
-                    android.hardware.usb.gadget.V1_2.IUsbGadget.castFrom(mGadgetProxy);
+                if (android.hardware.usb.gadget.V1_1.IUsbGadget.castFrom(mGadgetProxy) != null) {
+                    android.hardware.usb.gadget.V1_1.IUsbGadget gadgetProxy =
+                    android.hardware.usb.gadget.V1_1.IUsbGadget.castFrom(mGadgetProxy);
                     gadgetProxy.reset();
                 }
             }
diff --git a/services/voiceinteraction/TEST_MAPPING b/services/voiceinteraction/TEST_MAPPING
index d6c6964..5fe1c8d 100644
--- a/services/voiceinteraction/TEST_MAPPING
+++ b/services/voiceinteraction/TEST_MAPPING
@@ -1,5 +1,5 @@
 {
-  "presubmit-large": [
+  "presubmit": [
     {
       "name": "CtsVoiceInteractionTestCases",
       "options": [
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java b/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java
index ce1157e..7d5750e 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java
@@ -30,11 +30,14 @@
 import android.media.soundtrigger_middleware.ISoundTriggerCallback;
 import android.media.soundtrigger_middleware.ISoundTriggerModule;
 import android.media.soundtrigger_middleware.SoundTriggerModuleDescriptor;
+import android.os.BatteryStatsInternal;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.os.SystemClock;
 import android.util.Log;
 
 import com.android.internal.util.LatencyTracker;
+import com.android.server.LocalServices;
 
 import java.io.PrintWriter;
 import java.text.SimpleDateFormat;
@@ -291,6 +294,8 @@
             public void onRecognition(int modelHandle, RecognitionEvent event, int captureSession)
                     throws RemoteException {
                 try {
+                    BatteryStatsHolder.INSTANCE.noteWakingSoundTrigger(
+                            SystemClock.elapsedRealtime(), mOriginatorIdentity.uid);
                     mCallbackDelegate.onRecognition(modelHandle, event, captureSession);
                     logVoidReturn("onRecognition", modelHandle, event);
                 } catch (Exception e) {
@@ -304,6 +309,8 @@
                     int captureSession)
                     throws RemoteException {
                 try {
+                    BatteryStatsHolder.INSTANCE.noteWakingSoundTrigger(
+                            SystemClock.elapsedRealtime(), mOriginatorIdentity.uid);
                     startKeyphraseEventLatencyTracking(event);
                     mCallbackDelegate.onPhraseRecognition(modelHandle, event, captureSession);
                     logVoidReturn("onPhraseRecognition", modelHandle, event);
@@ -387,6 +394,12 @@
         }
     }
 
+    private static class BatteryStatsHolder {
+        private static final BatteryStatsInternal INSTANCE =
+                LocalServices.getService(BatteryStatsInternal.class);
+    }
+
+
     ////////////////////////////////////////////////////////////////////////////////////////////////
     // Actual logging logic below.
     private static final int NUM_EVENTS_TO_DUMP = 64;
diff --git a/telecomm/java/android/telecom/CallControl.java b/telecomm/java/android/telecom/CallControl.java
index 97538c1..50f2ad4 100644
--- a/telecomm/java/android/telecom/CallControl.java
+++ b/telecomm/java/android/telecom/CallControl.java
@@ -294,18 +294,21 @@
     /**
      * Raises an event to the {@link android.telecom.InCallService} implementations tracking this
      * call via {@link android.telecom.Call.Callback#onConnectionEvent(Call, String, Bundle)}.
-     * These events and the associated extra keys for the {@code Bundle} parameter are defined
-     * in Android X. This API is used to relay additional information about a call other than
-     * what is specified in the {@link android.telecom.CallAttributes} to
-     * {@link android.telecom.InCallService}s. This might include, for example, a change to the list
-     * of participants in a meeting, or the name of the speakers who have their hand raised. Where
-     * appropriate, the {@link InCallService}s tracking this call may choose to render this
-     * additional information about the call. An automotive calling UX, for example may have enough
-     * screen real estate to indicate the number of participants in a meeting, but to prevent
-     * distractions could suppress the list of participants.
+     * These events and the associated extra keys for the {@code Bundle} parameter are mutually
+     * defined by a VoIP application and {@link android.telecom.InCallService}. This API is used to
+     * relay additional information about a call other than what is specified in the
+     * {@link android.telecom.CallAttributes} to {@link android.telecom.InCallService}s. This might
+     * include, for example, a change to the list of participants in a meeting, or the name of the
+     * speakers who have their hand raised. Where appropriate, the {@link InCallService}s tracking
+     * this call may choose to render this additional information about the call. An automotive
+     * calling UX, for example may have enough screen real estate to indicate the number of
+     * participants in a meeting, but to prevent distractions could suppress the list of
+     * participants.
      *
-     * @param event  that is defined in AndroidX (ex. The number of participants changed)
-     * @param extras the updated value in relation to the event (ex. 4 participants)
+     * @param event a string event identifier agreed upon between a VoIP application and an
+     *              {@link android.telecom.InCallService}
+     * @param extras a {@link android.os.Bundle} containing information about the event, as agreed
+     *              upon between a VoIP application and {@link android.telecom.InCallService}.
      */
     public void sendEvent(@NonNull String event, @NonNull Bundle extras) {
         Objects.requireNonNull(event);
diff --git a/telecomm/java/android/telecom/CallEventCallback.java b/telecomm/java/android/telecom/CallEventCallback.java
index d96c406..a41c011 100644
--- a/telecomm/java/android/telecom/CallEventCallback.java
+++ b/telecomm/java/android/telecom/CallEventCallback.java
@@ -60,14 +60,17 @@
 
     /**
      * Informs this {@link android.telecom.CallEventCallback} on events raised from a
-     * {@link android.telecom.InCallService} presenting this call. The event key and extra values
-     * are defined in AndroidX. This enables alternative calling surfaces, such as an automotive
-     * UI, to relay requests to perform other non-standard call actions to the app. For example,
-     * an automotive calling solution may offer the ability for the user to raise their hand
-     * during a meeting.
+     * {@link android.telecom.InCallService} presenting this call. These events and the
+     * associated extra keys for the {@code Bundle} parameter are mutually defined by a VoIP
+     * application and {@link android.telecom.InCallService}. This enables alternative calling
+     * surfaces, such as an automotive UI, to relay requests to perform other non-standard call
+     * actions to the app. For example, an automotive calling solution may offer the ability for
+     * the user to raise their hand during a meeting.
      *
-     * @param event that is defined in AndroidX (ex. the number of participants changed)
-     * @param extras the updated value in relation to the event (ex. 4 participants)
+     * @param event a string event identifier agreed upon between a VoIP application and an
+     *              {@link android.telecom.InCallService}
+     * @param extras a {@link android.os.Bundle} containing information about the event, as agreed
+     *              upon between a VoIP application and {@link android.telecom.InCallService}.
      */
     void onEvent(@NonNull String event, @NonNull Bundle extras);
 }
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 6138f67..943d8d6 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -87,7 +87,7 @@
  * must call {@link #destroy()} to signal to the framework that the {@code Connection} is no
  * longer used and associated resources may be recovered.
  * <p>
- * Subclasses of {@code Connection} override the {@code on*} methods to provide the the
+ * Subclasses of {@code Connection} override the {@code on*} methods to provide the
  * {@link ConnectionService}'s implementation of calling functionality.  The {@code on*} methods are
  * called by Telecom to inform an instance of a {@code Connection} of actions specific to that
  * {@code Connection} instance.
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index de99ebf..e39af5a 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -895,9 +895,13 @@
             "android.telecom.extra.NOTIFICATION_PHONE_NUMBER";
 
     /**
-     * The intent to clear missed calls.
+     * Included in the extras of the {@link #ACTION_SHOW_MISSED_CALLS_NOTIFICATION}, provides a
+     * pending intent which can be used to clear the missed calls notification and mark unread
+     * missed call log entries as read.
      * @hide
+     * @deprecated Use {@link #cancelMissedCallsNotification()} instead.
      */
+    @Deprecated
     @SystemApi
     public static final String EXTRA_CLEAR_MISSED_CALLS_INTENT =
             "android.telecom.extra.CLEAR_MISSED_CALLS_INTENT";
@@ -2073,6 +2077,14 @@
      * {@link #getPhoneAccount}. Self-managed {@link ConnectionService}s must have
      * {@link android.Manifest.permission#MANAGE_OWN_CALLS} to add a new incoming call.
      * <p>
+     * Specify the address associated with the incoming call using
+     * {@link #EXTRA_INCOMING_CALL_ADDRESS}.  If an incoming call is from an anonymous source, omit
+     * this extra and ensure you specify a valid number presentation via
+     * {@link Connection#setAddress(Uri, int)} on the {@link Connection} instance you return in
+     * your
+     * {@link ConnectionService#onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)}
+     * implementation.
+     * <p>
      * The incoming call you are adding is assumed to have a video state of
      * {@link VideoProfile#STATE_AUDIO_ONLY}, unless the extra value
      * {@link #EXTRA_INCOMING_VIDEO_STATE} is specified.
@@ -2254,9 +2266,10 @@
     }
 
     /**
-     * Removes the missed-call notification if one is present.
+     * Removes the missed-call notification if one is present and marks missed calls in the call
+     * log as read.
      * <p>
-     * Requires that the method-caller be set as the system dialer app.
+     * Requires that the method-caller be set as the default dialer app.
      * </p>
      */
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
diff --git a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
index cbac34f..0325ba6 100644
--- a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
+++ b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
@@ -31,6 +31,7 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.provider.DeviceConfig;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyFrameworkInitializer;
 import android.telephony.TelephonyManager;
@@ -258,6 +259,9 @@
      */
     public static void showErrorIfSubscriptionAssociatedWithManagedProfile(Context context,
             int subId) {
+        if (!isSwitchToManagedProfileDialogFlagEnabled()) {
+            return;
+        }
         final long token = Binder.clearCallingIdentity();
         try {
             SubscriptionManager subscriptionManager = context.getSystemService(
@@ -286,6 +290,11 @@
         }
     }
 
+    public static boolean isSwitchToManagedProfileDialogFlagEnabled() {
+        return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_DEVICE_POLICY_MANAGER,
+                "enable_switch_to_managed_profile_dialog", false);
+    }
+
     /**
      * Check if the process with given uid is foreground.
      *
diff --git a/telephony/java/android/service/euicc/EuiccProfileInfo.java b/telephony/java/android/service/euicc/EuiccProfileInfo.java
index 728dfa6..f7c8237 100644
--- a/telephony/java/android/service/euicc/EuiccProfileInfo.java
+++ b/telephony/java/android/service/euicc/EuiccProfileInfo.java
@@ -453,7 +453,7 @@
                 + ", accessRules="
                 + Arrays.toString(mAccessRules)
                 + ", iccid="
-                + SubscriptionInfo.givePrintableIccid(mIccid)
+                + SubscriptionInfo.getPrintableId(mIccid)
                 + ")";
     }
 }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 43f7a42..d334d17 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -537,10 +537,9 @@
 
     /**
      * CDMA activation goes through OTASP.
-     * <p>
-     * TODO: This should be combined with config_use_hfa_for_provisioning and implemented as an enum
-     * (NONE, HFA, OTASP).
      */
+    // TODO: This should be combined with config_use_hfa_for_provisioning and implemented as an enum
+    // (NONE, HFA, OTASP).
     public static final String KEY_USE_OTASP_FOR_PROVISIONING_BOOL =
             "use_otasp_for_provisioning_bool";
 
@@ -7610,6 +7609,55 @@
         public static final String KEY_EMERGENCY_REQUIRES_VOLTE_ENABLED_BOOL =
                 KEY_PREFIX + "emergency_requires_volte_enabled_bool";
 
+        /**
+         * This values indicates that the cross SIM redialing timer shall be disabled.
+         *
+         * @see #KEY_CROSS_STACK_REDIAL_TIMER_SEC_INT
+         * @see #KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT
+         * @hide
+         */
+        public static final int REDIAL_TIMER_DISABLED = 0;
+
+        /**
+         * A timer to guard the max attempting time on current SIM slot so that modem will not
+         * stuck in current SIM slot for long time. On timer expiry, if emergency call on the
+         * other SIM slot is preferable, telephony shall cancel the emergency call and place the
+         * call on the other SIM slot. If this value is set to {@link #REDIAL_TIMER_DISABLED}, then
+         * the timer will never be started and domain selection continues on the current SIM slot.
+         * This value should be greater than the value of {@link #KEY_EMERGENCY_SCAN_TIMER_SEC_INT}.
+         *
+         * The default value for the timer is 120 seconds.
+         * @hide
+         */
+        public static final String KEY_CROSS_STACK_REDIAL_TIMER_SEC_INT =
+                KEY_PREFIX + "cross_stack_redial_timer_sec_int";
+
+        /**
+         * If emergency calls are only allowed with normal-registered service and UE should get
+         * normal service in a short time with acquired band information, telephony
+         * expects dialing emergency call will be completed in a short time.
+         * If dialing is not completed with in a certain timeout, telephony shall place on
+         * another SIM slot. If this value is set to {@link #REDIAL_TIMER_DISABLED}, then the timer
+         * will never be started and domain selection continues on the current SIM slot.
+         * The timer shall be started for the first trial of each subscription and shall be ignored
+         * in the roaming networks and non-domestic networks.
+         *
+         * The default value for the timer is {@link #REDIAL_TIMER_DISABLED}.
+         * @hide
+         */
+        public static final String KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT =
+                KEY_PREFIX + "quick_cross_stack_redial_timer_sec_int";
+
+        /**
+         * Indicates whether the quick cross stack redial timer will be triggered only when
+         * the device is registered to the network.
+         *
+         * The default value is {@code true}.
+         * @hide
+         */
+        public static final String KEY_START_QUICK_CROSS_STACK_REDIAL_TIMER_WHEN_REGISTERED_BOOL =
+                KEY_PREFIX + "start_quick_cross_stack_redial_timer_when_registered_bool";
+
         private static PersistableBundle getDefaults() {
             PersistableBundle defaults = new PersistableBundle();
             defaults.putBoolean(KEY_RETRY_EMERGENCY_ON_IMS_PDN_BOOL, false);
@@ -7676,6 +7724,10 @@
             defaults.putBoolean(KEY_EMERGENCY_REQUIRES_VOLTE_ENABLED_BOOL, false);
             defaults.putStringArray(KEY_EMERGENCY_CDMA_PREFERRED_NUMBERS_STRING_ARRAY,
                     new String[0]);
+            defaults.putInt(KEY_CROSS_STACK_REDIAL_TIMER_SEC_INT, 120);
+            defaults.putInt(KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT, REDIAL_TIMER_DISABLED);
+            defaults.putBoolean(KEY_START_QUICK_CROSS_STACK_REDIAL_TIMER_WHEN_REGISTERED_BOOL,
+                    true);
 
             return defaults;
         }
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index c4d760f..dd7e2d7 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -997,7 +997,8 @@
      */
     public static final int IWLAN_CONGESTION = 0x3C8C;
 
-    /** IKE configuration error resulting in failure  */
+    // Below IWLAN error codes are defined by the UE and do not relate to any 3GPP spec value
+    /** IKE configuration error resulting in failure */
     public static final int IWLAN_IKEV2_CONFIG_FAILURE = 0x4000;
     /**
      * Sent in the response to an IKE_AUTH message when, for some reason,
@@ -1014,6 +1015,57 @@
     public static final int IWLAN_DNS_RESOLUTION_TIMEOUT = 0x4005;
     /** Expected to update or bring down an ePDG tunnel, but no tunnel found*/
     public static final int IWLAN_TUNNEL_NOT_FOUND = 0x4006;
+    /**
+     * Failed to apply tunnel transform
+     *
+     * @hide
+     */
+    public static final int IWLAN_TUNNEL_TRANSFORM_FAILED = 0x4007;
+    /**
+     * IWLAN PDN setup failed due to Wi-Fi lost during IKE tunnel setup,
+     * match exception reported by IKE module
+     *
+     * @hide
+     */
+    public static final int IWLAN_IKE_NETWORK_LOST_EXCEPTION = 0x4008;
+    /**
+     * Carrier-specific error codes during IKEv2 SA setup
+     *
+     * @hide
+     */
+    public static final int IWLAN_IKE_PRIVATE_PROTOCOL_ERROR = 0x4009;
+    /**
+     * IKE Session closed before child session opened
+     *
+     * @hide
+     */
+    public static final int IWLAN_IKE_SESSION_CLOSED_BEFORE_CHILD_SESSION_OPENED = 0x400A;
+    /**
+     * IKE Init timeout, no response from EPDG
+     *
+     * @hide
+     */
+    public static final int IWLAN_IKE_INIT_TIMEOUT = 0x400B;
+    /**
+     * DPD message does not get an ack after the re-tx attempts and duration, i.e., times out.
+     *
+     * @hide
+     */
+    public static final int IWLAN_IKE_DPD_TIMEOUT = 0x400C;
+    /**
+     * The Wi-Fi to Wi-Fi handover of the IMS PDN fails because the network does not respond to the
+     * MOBIKE/rekey mobility message in the expected manner
+     *
+     * @hide
+     */
+    public static final int IWLAN_IKE_MOBILITY_TIMEOUT = 0x400D;
+    /**
+     * IKE client sent "IKE AUTH request 3" to the network but got "Internal address failure" from
+     * the network since no internal addresses can be assigned.
+     *
+     * @hide
+     */
+    public static final int IWLAN_EPDG_INTERNAL_ADDRESS_FAILURE = 0x400E;
 
     // OEM sepecific error codes. To be used by OEMs when they don't
     // want to reveal error code which would be replaced by ERROR_UNSPECIFIED
@@ -1508,6 +1560,16 @@
         sFailCauseMap.put(IWLAN_DNS_RESOLUTION_NAME_FAILURE, "IWLAN_DNS_RESOLUTION_NAME_FAILURE");
         sFailCauseMap.put(IWLAN_DNS_RESOLUTION_TIMEOUT, "IWLAN_DNS_RESOLUTION_TIMEOUT");
         sFailCauseMap.put(IWLAN_TUNNEL_NOT_FOUND, "IWLAN_TUNNEL_NOT_FOUND");
+        sFailCauseMap.put(IWLAN_TUNNEL_TRANSFORM_FAILED, "IWLAN_TUNNEL_TRANSFORM_FAILED");
+        sFailCauseMap.put(IWLAN_IKE_INIT_TIMEOUT, "IWLAN_IKE_INIT_TIMEOUT");
+        sFailCauseMap.put(IWLAN_IKE_NETWORK_LOST_EXCEPTION, "IWLAN_IKE_NETWORK_LOST_EXCEPTION");
+        sFailCauseMap.put(IWLAN_IKE_PRIVATE_PROTOCOL_ERROR, "IWLAN_IKE_PRIVATE_PROTOCOL_ERROR");
+        sFailCauseMap.put(IWLAN_IKE_SESSION_CLOSED_BEFORE_CHILD_SESSION_OPENED,
+                "IWLAN_IKE_SESSION_CLOSED_BEFORE_CHILD_SESSION_OPENED");
+        sFailCauseMap.put(IWLAN_IKE_DPD_TIMEOUT, "IWLAN_IKE_DPD_TIMEOUT");
+        sFailCauseMap.put(IWLAN_IKE_MOBILITY_TIMEOUT, "IWLAN_IKE_MOBILITY_TIMEOUT");
+        sFailCauseMap.put(IWLAN_EPDG_INTERNAL_ADDRESS_FAILURE,
+                "IWLAN_EPDG_INTERNAL_ADDRESS_FAILURE");
         sFailCauseMap.put(OEM_DCFAILCAUSE_1, "OEM_DCFAILCAUSE_1");
         sFailCauseMap.put(OEM_DCFAILCAUSE_2, "OEM_DCFAILCAUSE_2");
         sFailCauseMap.put(OEM_DCFAILCAUSE_3, "OEM_DCFAILCAUSE_3");
diff --git a/telephony/java/android/telephony/DomainSelectionService.java b/telephony/java/android/telephony/DomainSelectionService.java
index c352f2b..abcce5f 100644
--- a/telephony/java/android/telephony/DomainSelectionService.java
+++ b/telephony/java/android/telephony/DomainSelectionService.java
@@ -537,9 +537,9 @@
         }
 
         @Override
-        public void onWlanSelected() {
+        public void onWlanSelected(boolean useEmergencyPdn) {
             try {
-                mCallback.onWlanSelected();
+                mCallback.onWlanSelected(useEmergencyPdn);
             } catch (Exception e) {
                 Rlog.e(TAG, "onWlanSelected e=" + e);
             }
@@ -702,9 +702,10 @@
         }
 
         @Override
-        public void onDomainSelected(@NetworkRegistrationInfo.Domain int domain) {
+        public void onDomainSelected(@NetworkRegistrationInfo.Domain int domain,
+                boolean useEmergencyPdn) {
             try {
-                mCallback.onDomainSelected(domain);
+                mCallback.onDomainSelected(domain, useEmergencyPdn);
             } catch (Exception e) {
                 Rlog.e(TAG, "onDomainSelected e=" + e);
             }
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index b9008c4..cf0561d 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1526,10 +1526,14 @@
      * Formats the specified {@code phoneNumber} to the E.164 representation.
      *
      * @param phoneNumber the phone number to format.
-     * @param defaultCountryIso the ISO 3166-1 two letters country code.
+     * @param defaultCountryIso the ISO 3166-1 two letters country code in UPPER CASE.
      * @return the E.164 representation, or null if the given phone number is not valid.
      */
     public static String formatNumberToE164(String phoneNumber, String defaultCountryIso) {
+        if (defaultCountryIso != null) {
+            defaultCountryIso = defaultCountryIso.toUpperCase(Locale.ROOT);
+        }
+
         return formatNumberInternal(phoneNumber, defaultCountryIso, PhoneNumberFormat.E164);
     }
 
@@ -1537,10 +1541,14 @@
      * Formats the specified {@code phoneNumber} to the RFC3966 representation.
      *
      * @param phoneNumber the phone number to format.
-     * @param defaultCountryIso the ISO 3166-1 two letters country code.
+     * @param defaultCountryIso the ISO 3166-1 two letters country code in UPPER CASE.
      * @return the RFC3966 representation, or null if the given phone number is not valid.
      */
     public static String formatNumberToRFC3966(String phoneNumber, String defaultCountryIso) {
+        if (defaultCountryIso != null) {
+            defaultCountryIso = defaultCountryIso.toUpperCase(Locale.ROOT);
+        }
+
         return formatNumberInternal(phoneNumber, defaultCountryIso, PhoneNumberFormat.RFC3966);
     }
 
@@ -1591,6 +1599,10 @@
             return false;
         }
 
+        if (defaultCountryIso != null) {
+            defaultCountryIso = defaultCountryIso.toUpperCase(Locale.ROOT);
+        }
+
         PhoneNumberUtil util = PhoneNumberUtil.getInstance();
         try {
             PhoneNumber pn = util.parseAndKeepRawInput(phoneNumber, defaultCountryIso);
@@ -1619,6 +1631,10 @@
             return phoneNumber;
         }
 
+        if (defaultCountryIso != null) {
+            defaultCountryIso = defaultCountryIso.toUpperCase(Locale.ROOT);
+        }
+
         PhoneNumberUtil util = PhoneNumberUtil.getInstance();
         String result = null;
         try {
@@ -1671,6 +1687,10 @@
      */
     public static String formatNumber(
             String phoneNumber, String phoneNumberE164, String defaultCountryIso) {
+        if (defaultCountryIso != null) {
+            defaultCountryIso = defaultCountryIso.toUpperCase(Locale.ROOT);
+        }
+
         int len = phoneNumber.length();
         for (int i = 0; i < len; i++) {
             if (!isDialable(phoneNumber.charAt(i))) {
@@ -2900,7 +2920,11 @@
         PhoneNumberUtil util = PhoneNumberUtil.getInstance();
         PhoneNumber n1;
         PhoneNumber n2;
-        defaultCountryIso = defaultCountryIso.toUpperCase(Locale.ROOT);
+
+        if (defaultCountryIso != null) {
+            defaultCountryIso = defaultCountryIso.toUpperCase(Locale.ROOT);
+        }
+
         try {
             n1 = util.parseAndKeepRawInput(number1, defaultCountryIso);
             n2 = util.parseAndKeepRawInput(number2, defaultCountryIso);
diff --git a/telephony/java/android/telephony/PreciseDisconnectCause.java b/telephony/java/android/telephony/PreciseDisconnectCause.java
index 3b4cf75..1cfd22c 100644
--- a/telephony/java/android/telephony/PreciseDisconnectCause.java
+++ b/telephony/java/android/telephony/PreciseDisconnectCause.java
@@ -235,6 +235,23 @@
     /** Call failed/dropped because of a network detach. */
     public static final int NETWORK_DETACH                                   = 261;
 
+    /**
+     * Dialing emergency calls is currently unavailable.
+     * The call should be redialed on the other subscription silently.
+     * If there is no other subscription available, the call may be redialed
+     * on this subscription again.
+     * @hide
+     */
+    public static final int EMERGENCY_TEMP_FAILURE                           = 325;
+    /**
+     * Dialing emergency calls is currently unavailable.
+     * The call should be redialed on the other subscription silently.
+     * Even if there is no other subscription available, the call should not
+     * be redialed on this subscription again.
+     * @hide
+     */
+    public static final int EMERGENCY_PERM_FAILURE                           = 326;
+
     /** Mobile station (MS) is locked until next power cycle. */
     public static final int CDMA_LOCKED_UNTIL_POWER_CYCLE                    = 1000;
     /** Drop call. */
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 3b84b65..faf97b5 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -947,29 +947,30 @@
     }
 
     /**
-     * Get ICCID stripped PII information on user build.
+     * Get stripped PII information from the id.
      *
-     * @param iccId The original ICCID.
+     * @param id The raw id (e.g. ICCID, IMSI, etc...).
      * @return The stripped string.
      *
      * @hide
      */
-    public static String givePrintableIccid(String iccId) {
-        String iccIdToPrint = null;
-        if (iccId != null) {
-            if (iccId.length() > 9 && !TelephonyUtils.IS_DEBUGGABLE) {
-                iccIdToPrint = iccId.substring(0, 9) + Rlog.pii(false, iccId.substring(9));
+    @Nullable
+    public static String getPrintableId(@Nullable String id) {
+        String idToPrint = null;
+        if (id != null) {
+            if (id.length() > 9 && !TelephonyUtils.IS_DEBUGGABLE) {
+                idToPrint = id.substring(0, 9) + Rlog.pii(false, id.substring(9));
             } else {
-                iccIdToPrint = iccId;
+                idToPrint = id;
             }
         }
-        return iccIdToPrint;
+        return idToPrint;
     }
 
     @Override
     public String toString() {
-        String iccIdToPrint = givePrintableIccid(mIccId);
-        String cardStringToPrint = givePrintableIccid(mCardString);
+        String iccIdToPrint = getPrintableId(mIccId);
+        String cardStringToPrint = getPrintableId(mCardString);
         return "[SubscriptionInfo: id=" + mId
                 + " iccId=" + iccIdToPrint
                 + " simSlotIndex=" + mSimSlotIndex
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 3e2c7c4..5cbbe37 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -3964,7 +3964,12 @@
 
     /** @hide */
     public static void invalidateActiveDataSubIdCaches() {
-        PropertyInvalidatedCache.invalidateCache(CACHE_KEY_ACTIVE_DATA_SUB_ID_PROPERTY);
+        if (isSubscriptionManagerServiceEnabled()) {
+            PropertyInvalidatedCache.invalidateCache(
+                    CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY);
+        } else {
+            PropertyInvalidatedCache.invalidateCache(CACHE_KEY_ACTIVE_DATA_SUB_ID_PROPERTY);
+        }
     }
 
     /** @hide */
@@ -4369,7 +4374,6 @@
      *
      * @hide
      */
-    @SystemApi
     @RequiresPermission(Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION)
     public void setSubscriptionUserHandle(int subscriptionId, @Nullable UserHandle userHandle) {
         if (!isValidSubscriptionId(subscriptionId)) {
@@ -4404,7 +4408,6 @@
      *
      * @hide
      */
-    @SystemApi
     @RequiresPermission(Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION)
     public @Nullable UserHandle getSubscriptionUserHandle(int subscriptionId) {
         if (!isValidSubscriptionId(subscriptionId)) {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 66711df..39d7cc1 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -15132,14 +15132,6 @@
     @TestApi
     public static final int HAL_SERVICE_IMS = 7;
 
-    /**
-     * HAL service type that supports the HAL APIs implementation of IRadioSatellite
-     * {@link RadioSatelliteProxy}
-     * @hide
-     */
-    @TestApi
-    public static final int HAL_SERVICE_SATELLITE = 8;
-
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = {"HAL_SERVICE_"},
@@ -15152,7 +15144,6 @@
                     HAL_SERVICE_SIM,
                     HAL_SERVICE_VOICE,
                     HAL_SERVICE_IMS,
-                    HAL_SERVICE_SATELLITE
             })
     public @interface HalService {}
 
diff --git a/telephony/java/android/telephony/TransportSelectorCallback.java b/telephony/java/android/telephony/TransportSelectorCallback.java
index d396790..04752e4 100644
--- a/telephony/java/android/telephony/TransportSelectorCallback.java
+++ b/telephony/java/android/telephony/TransportSelectorCallback.java
@@ -35,8 +35,10 @@
 
     /**
      * Notify that WLAN transport has been selected.
+     *
+     * @param useEmergencyPdn Indicates whether Wi-Fi emergency services use emergency PDN or not.
      */
-    void onWlanSelected();
+    void onWlanSelected(boolean useEmergencyPdn);
 
     /**
      * Notify that WWAN transport has been selected.
diff --git a/telephony/java/android/telephony/UiccPortInfo.java b/telephony/java/android/telephony/UiccPortInfo.java
index 6fb0470..41e743c 100644
--- a/telephony/java/android/telephony/UiccPortInfo.java
+++ b/telephony/java/android/telephony/UiccPortInfo.java
@@ -165,7 +165,7 @@
         return "UiccPortInfo (isActive="
                 + mIsActive
                 + ", iccId="
-                + SubscriptionInfo.givePrintableIccid(mIccId)
+                + SubscriptionInfo.getPrintableId(mIccId)
                 + ", portIndex="
                 + mPortIndex
                 + ", mLogicalSlotIndex="
diff --git a/telephony/java/android/telephony/UiccSlotInfo.java b/telephony/java/android/telephony/UiccSlotInfo.java
index 5e02532..1863a03b 100644
--- a/telephony/java/android/telephony/UiccSlotInfo.java
+++ b/telephony/java/android/telephony/UiccSlotInfo.java
@@ -281,7 +281,7 @@
                 + ", mIsEuicc="
                 + mIsEuicc
                 + ", mCardId="
-                + SubscriptionInfo.givePrintableIccid(mCardId)
+                + SubscriptionInfo.getPrintableId(mCardId)
                 + ", cardState="
                 + mCardStateInfo
                 + ", mIsExtendedApduSupported="
diff --git a/telephony/java/android/telephony/WwanSelectorCallback.java b/telephony/java/android/telephony/WwanSelectorCallback.java
index b3682ca..f9c2620 100644
--- a/telephony/java/android/telephony/WwanSelectorCallback.java
+++ b/telephony/java/android/telephony/WwanSelectorCallback.java
@@ -46,6 +46,7 @@
      * this interface can be discarded.
      *
      * @param domain The selected domain.
+     * @param useEmergencyPdn Indicates whether emergency services use emergency PDN or not.
      */
-    void onDomainSelected(@NetworkRegistrationInfo.Domain int domain);
+    void onDomainSelected(@NetworkRegistrationInfo.Domain int domain, boolean useEmergencyPdn);
 }
diff --git a/telephony/java/android/telephony/satellite/ISatelliteDatagramCallback.aidl b/telephony/java/android/telephony/satellite/ISatelliteDatagramCallback.aidl
index c15374a..2954c2d 100644
--- a/telephony/java/android/telephony/satellite/ISatelliteDatagramCallback.aidl
+++ b/telephony/java/android/telephony/satellite/ISatelliteDatagramCallback.aidl
@@ -16,9 +16,10 @@
 
 package android.telephony.satellite;
 
-import android.telephony.satellite.ISatelliteDatagramReceiverAck;
 import android.telephony.satellite.SatelliteDatagram;
 
+import com.android.internal.telephony.ILongConsumer;
+
 /**
  * Interface for satellite datagrams callback.
  * @hide
@@ -30,10 +31,10 @@
      * @param datagramId An id that uniquely identifies incoming datagram.
      * @param datagram Datagram received from satellite.
      * @param pendingCount Number of datagrams yet to be received from satellite.
-     * @param callback This callback will be used by datagram receiver app to send ack back to
-     *                 Telephony. If the callback is not received within five minutes,
-     *                 Telephony will resend the datagrams.
+     * @param callback This callback will be used by datagram receiver app to send received
+     *                 datagramId to Telephony. If the callback is not received within five minutes,
+     *                 Telephony will resend the datagram.
      */
     void onSatelliteDatagramReceived(long datagramId, in SatelliteDatagram datagram,
-            int pendingCount, ISatelliteDatagramReceiverAck callback);
+            int pendingCount, ILongConsumer callback);
 }
diff --git a/telephony/java/android/telephony/satellite/ISatelliteDatagramReceiverAck.aidl b/telephony/java/android/telephony/satellite/ISatelliteDatagramReceiverAck.aidl
deleted file mode 100644
index eeb0ac5..0000000
--- a/telephony/java/android/telephony/satellite/ISatelliteDatagramReceiverAck.aidl
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.satellite;
-
-import android.telephony.satellite.PointingInfo;
-import android.telephony.satellite.SatelliteDatagram;
-
-/**
- * Interface for satellite datagram receiver acknowledgement.
- * @hide
- */
-oneway interface ISatelliteDatagramReceiverAck {
-     /**
-      * This callback will be used by datagram receiver app to send ack back to
-      * Telephony. If the callback is not received within five minutes,
-      * then Telephony will resend the datagram again.
-      *
-      * @param datagramId An id that uniquely identifies datagram
-      *                   received by satellite datagram receiver app.
-      *                   This should match with datagramId passed in
-      *                   {@link SatelliteDatagramCallback#onSatelliteDatagramReceived(
-      *                   long, SatelliteDatagram, int, ISatelliteDatagramReceiverAck)}.
-      *                   Upon receiving the ack, Telephony will remove the datagram from
-      *                   the persistent memory.
-      */
-    void acknowledgeSatelliteDatagramReceived(in long datagramId);
-}
diff --git a/telephony/java/android/telephony/satellite/ISatelliteStateCallback.aidl b/telephony/java/android/telephony/satellite/ISatelliteStateCallback.aidl
index 98221c9..cd9d81e 100644
--- a/telephony/java/android/telephony/satellite/ISatelliteStateCallback.aidl
+++ b/telephony/java/android/telephony/satellite/ISatelliteStateCallback.aidl
@@ -22,13 +22,6 @@
  */
 oneway interface ISatelliteStateCallback {
     /**
-     * Indicates that the satellite has pending datagrams for the device to be pulled.
-     *
-     * @param count Number of pending datagrams.
-     */
-    void onPendingDatagramCount(in int count);
-
-    /**
      * Indicates that the satellite modem state has changed.
      *
      * @param state The current satellite modem state.
diff --git a/telephony/java/android/telephony/satellite/ISatellitePositionUpdateCallback.aidl b/telephony/java/android/telephony/satellite/ISatelliteTransmissionUpdateCallback.aidl
similarity index 96%
rename from telephony/java/android/telephony/satellite/ISatellitePositionUpdateCallback.aidl
rename to telephony/java/android/telephony/satellite/ISatelliteTransmissionUpdateCallback.aidl
index d3f1091..2442083 100644
--- a/telephony/java/android/telephony/satellite/ISatellitePositionUpdateCallback.aidl
+++ b/telephony/java/android/telephony/satellite/ISatelliteTransmissionUpdateCallback.aidl
@@ -22,7 +22,7 @@
  * Interface for position update and datagram transfer state change callback.
  * @hide
  */
-oneway interface ISatellitePositionUpdateCallback {
+oneway interface ISatelliteTransmissionUpdateCallback {
     /**
      * Called when satellite datagram transfer state changed.
      *
diff --git a/telephony/java/android/telephony/satellite/PointingInfo.java b/telephony/java/android/telephony/satellite/PointingInfo.java
index a3c3f19..7c794473 100644
--- a/telephony/java/android/telephony/satellite/PointingInfo.java
+++ b/telephony/java/android/telephony/satellite/PointingInfo.java
@@ -30,31 +30,12 @@
     /** Satellite elevation in degrees */
     private float mSatelliteElevationDegrees;
 
-    /** Antenna azimuth in degrees */
-    private float mAntennaAzimuthDegrees;
-
-    /**
-     * Angle of rotation about the x axis. This value represents the angle between a plane
-     * parallel to the device's screen and a plane parallel to the ground.
-     */
-    private float mAntennaPitchDegrees;
-
-    /**
-     * Angle of rotation about the y axis. This value represents the angle between a plane
-     * perpendicular to the device's screen and a plane parallel to the ground.
-     */
-    private float mAntennaRollDegrees;
-
     /**
      * @hide
      */
-    public PointingInfo(float satelliteAzimuthDegrees, float satelliteElevationDegrees,
-            float antennaAzimuthDegrees, float antennaPitchDegrees, float antennaRollDegrees) {
+    public PointingInfo(float satelliteAzimuthDegrees, float satelliteElevationDegrees) {
         mSatelliteAzimuthDegrees = satelliteAzimuthDegrees;
         mSatelliteElevationDegrees = satelliteElevationDegrees;
-        mAntennaAzimuthDegrees = antennaAzimuthDegrees;
-        mAntennaPitchDegrees = antennaPitchDegrees;
-        mAntennaRollDegrees = antennaRollDegrees;
     }
 
     private PointingInfo(Parcel in) {
@@ -70,9 +51,6 @@
     public void writeToParcel(@NonNull Parcel out, int flags) {
         out.writeFloat(mSatelliteAzimuthDegrees);
         out.writeFloat(mSatelliteElevationDegrees);
-        out.writeFloat(mAntennaAzimuthDegrees);
-        out.writeFloat(mAntennaPitchDegrees);
-        out.writeFloat(mAntennaRollDegrees);
     }
 
     public static final @android.annotation.NonNull Creator<PointingInfo> CREATOR =
@@ -99,18 +77,6 @@
 
         sb.append("SatelliteElevationDegrees:");
         sb.append(mSatelliteElevationDegrees);
-        sb.append(",");
-
-        sb.append("AntennaAzimuthDegrees:");
-        sb.append(mAntennaAzimuthDegrees);
-        sb.append(",");
-
-        sb.append("AntennaPitchDegrees:");
-        sb.append(mAntennaPitchDegrees);
-        sb.append(",");
-
-        sb.append("AntennaRollDegrees:");
-        sb.append(mAntennaRollDegrees);
         return sb.toString();
     }
 
@@ -122,23 +88,8 @@
         return mSatelliteElevationDegrees;
     }
 
-    public float getAntennaAzimuthDegrees() {
-        return mAntennaAzimuthDegrees;
-    }
-
-    public float getAntennaPitchDegrees() {
-        return mAntennaPitchDegrees;
-    }
-
-    public float getAntennaRollDegrees() {
-        return mAntennaRollDegrees;
-    }
-
     private void readFromParcel(Parcel in) {
         mSatelliteAzimuthDegrees = in.readFloat();
         mSatelliteElevationDegrees = in.readFloat();
-        mAntennaAzimuthDegrees = in.readFloat();
-        mAntennaPitchDegrees = in.readFloat();
-        mAntennaRollDegrees = in.readFloat();
     }
 }
diff --git a/telephony/java/android/telephony/satellite/SatelliteCapabilities.java b/telephony/java/android/telephony/satellite/SatelliteCapabilities.java
index 889856b..df80159 100644
--- a/telephony/java/android/telephony/satellite/SatelliteCapabilities.java
+++ b/telephony/java/android/telephony/satellite/SatelliteCapabilities.java
@@ -33,31 +33,24 @@
     @NonNull @SatelliteManager.NTRadioTechnology private Set<Integer> mSupportedRadioTechnologies;
 
     /**
-     * Whether satellite modem is always on.
-     * This indicates the power impact of keeping it on is very minimal.
-     */
-    private boolean mIsAlwaysOn;
-
-    /**
      * Whether UE needs to point to a satellite to send and receive data.
      */
-    private boolean mNeedsPointingToSatellite;
+    private boolean mIsPointingRequired;
 
     /**
-     * Whether UE needs a separate SIM profile to communicate with the satellite network.
+     * The maximum number of bytes per datagram that can be sent over satellite.
      */
-    private boolean mNeedsSeparateSimProfile;
+    private int mMaxBytesPerOutgoingDatagram;
 
     /**
      * @hide
      */
-    public SatelliteCapabilities(Set<Integer> supportedRadioTechnologies, boolean isAlwaysOn,
-            boolean needsPointingToSatellite, boolean needsSeparateSimProfile) {
+    public SatelliteCapabilities(Set<Integer> supportedRadioTechnologies,
+            boolean isPointingRequired, int maxBytesPerOutgoingDatagram) {
         mSupportedRadioTechnologies = supportedRadioTechnologies == null
                 ? new HashSet<>() : supportedRadioTechnologies;
-        mIsAlwaysOn = isAlwaysOn;
-        mNeedsPointingToSatellite = needsPointingToSatellite;
-        mNeedsSeparateSimProfile = needsSeparateSimProfile;
+        mIsPointingRequired = isPointingRequired;
+        mMaxBytesPerOutgoingDatagram = maxBytesPerOutgoingDatagram;
     }
 
     private SatelliteCapabilities(Parcel in) {
@@ -80,9 +73,8 @@
             out.writeInt(0);
         }
 
-        out.writeBoolean(mIsAlwaysOn);
-        out.writeBoolean(mNeedsPointingToSatellite);
-        out.writeBoolean(mNeedsSeparateSimProfile);
+        out.writeBoolean(mIsPointingRequired);
+        out.writeInt(mMaxBytesPerOutgoingDatagram);
     }
 
     @NonNull public static final Creator<SatelliteCapabilities> CREATOR = new Creator<>() {
@@ -111,16 +103,12 @@
             sb.append("none,");
         }
 
-        sb.append("isAlwaysOn:");
-        sb.append(mIsAlwaysOn);
+        sb.append("isPointingRequired:");
+        sb.append(mIsPointingRequired);
         sb.append(",");
 
-        sb.append("needsPointingToSatellite:");
-        sb.append(mNeedsPointingToSatellite);
-        sb.append(",");
-
-        sb.append("needsSeparateSimProfile:");
-        sb.append(mNeedsSeparateSimProfile);
+        sb.append("maxBytesPerOutgoingDatagram");
+        sb.append(mMaxBytesPerOutgoingDatagram);
         return sb.toString();
     }
 
@@ -133,33 +121,22 @@
     }
 
     /**
-     * Get whether the satellite modem is always on.
-     * This indicates the power impact of keeping it on is very minimal.
-     *
-     * @return {@code true} if the satellite modem is always on and {@code false} otherwise.
-     */
-    public boolean isAlwaysOn() {
-        return mIsAlwaysOn;
-    }
-
-    /**
      * Get whether UE needs to point to a satellite to send and receive data.
      *
-     * @return {@code true} if UE needs to pointing to a satellite to send and receive data and
+     * @return {@code true} if UE needs to point to a satellite to send and receive data and
      *         {@code false} otherwise.
      */
-    public boolean needsPointingToSatellite() {
-        return mNeedsPointingToSatellite;
+    public boolean isPointingRequired() {
+        return mIsPointingRequired;
     }
 
     /**
-     * Get whether UE needs a separate SIM profile to communicate with the satellite network.
+     * The maximum number of bytes per datagram that can be sent over satellite.
      *
-     * @return {@code true} if UE needs a separate SIM profile to comunicate with the satellite
-     *         network and {@code false} otherwise.
+     * @return The maximum number of bytes per datagram that can be sent over satellite.
      */
-    public boolean needsSeparateSimProfile() {
-        return mNeedsSeparateSimProfile;
+    public int getMaxBytesPerOutgoingDatagram() {
+        return mMaxBytesPerOutgoingDatagram;
     }
 
     private void readFromParcel(Parcel in) {
@@ -171,8 +148,7 @@
             }
         }
 
-        mIsAlwaysOn = in.readBoolean();
-        mNeedsPointingToSatellite = in.readBoolean();
-        mNeedsSeparateSimProfile = in.readBoolean();
+        mIsPointingRequired = in.readBoolean();
+        mMaxBytesPerOutgoingDatagram = in.readInt();
     }
 }
diff --git a/telephony/java/android/telephony/satellite/SatelliteDatagram.java b/telephony/java/android/telephony/satellite/SatelliteDatagram.java
index cc5a9f4..d3cb8a0 100644
--- a/telephony/java/android/telephony/satellite/SatelliteDatagram.java
+++ b/telephony/java/android/telephony/satellite/SatelliteDatagram.java
@@ -17,7 +17,6 @@
 package android.telephony.satellite;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -28,7 +27,7 @@
     /**
      * Datagram to be sent or received over satellite.
      */
-    private byte[] mData;
+    @NonNull private byte[] mData;
 
     /**
      * @hide
@@ -51,8 +50,8 @@
         out.writeByteArray(mData);
     }
 
-    public static final @android.annotation.NonNull Creator<SatelliteDatagram> CREATOR =
-            new Creator<SatelliteDatagram>() {
+    @NonNull public static final Creator<SatelliteDatagram> CREATOR =
+            new Creator<>() {
                 @Override
                 public SatelliteDatagram createFromParcel(Parcel in) {
                     return new SatelliteDatagram(in);
@@ -64,8 +63,7 @@
                 }
             };
 
-    @Nullable
-    public byte[] getSatelliteDatagram() {
+    @NonNull public byte[] getSatelliteDatagram() {
         return mData;
     }
 
diff --git a/telephony/java/android/telephony/satellite/SatelliteDatagramCallback.java b/telephony/java/android/telephony/satellite/SatelliteDatagramCallback.java
index 8ccc993..f237ada 100644
--- a/telephony/java/android/telephony/satellite/SatelliteDatagramCallback.java
+++ b/telephony/java/android/telephony/satellite/SatelliteDatagramCallback.java
@@ -17,64 +17,25 @@
 package android.telephony.satellite;
 
 import android.annotation.NonNull;
-import android.os.Binder;
 
-import java.util.concurrent.Executor;
+import com.android.internal.telephony.ILongConsumer;
 
 /**
  * A callback class for listening to satellite datagrams.
  *
  * @hide
  */
-public class SatelliteDatagramCallback {
-    private final CallbackBinder mBinder = new CallbackBinder(this);
-
-    private static class CallbackBinder extends ISatelliteDatagramCallback.Stub {
-        private final SatelliteDatagramCallback mLocalCallback;
-        private Executor mExecutor;
-
-        private CallbackBinder(SatelliteDatagramCallback localCallback) {
-            mLocalCallback = localCallback;
-        }
-
-        @Override
-        public void onSatelliteDatagramReceived(long datagramId, SatelliteDatagram datagram,
-                int pendingCount, ISatelliteDatagramReceiverAck callback) {
-            final long callingIdentity = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mLocalCallback.onSatelliteDatagramReceived(datagramId,
-                        datagram, pendingCount, callback));
-            } finally {
-                restoreCallingIdentity(callingIdentity);
-            }
-        }
-
-        private void setExecutor(Executor executor) {
-            mExecutor = executor;
-        }
-    }
-
+public interface SatelliteDatagramCallback {
     /**
      * Called when there is an incoming datagram to be received.
+     *
      * @param datagramId An id that uniquely identifies incoming datagram.
      * @param datagram Datagram to be received over satellite.
      * @param pendingCount Number of datagrams yet to be received by the app.
-     * @param callback This callback will be used by datagram receiver app to send ack back to
-     *                 Telephony.
+     * @param callback This callback will be used by datagram receiver app to send received
+     *                 datagramId to Telephony. If the callback is not received within five minutes,
+     *                 Telephony will resend the datagram.
      */
-    public void onSatelliteDatagramReceived(long datagramId, SatelliteDatagram datagram,
-            int pendingCount, ISatelliteDatagramReceiverAck callback) {
-        // Base Implementation
-    }
-
-    /** @hide */
-    @NonNull
-    public final ISatelliteDatagramCallback getBinder() {
-        return mBinder;
-    }
-
-    /** @hide */
-    public void setExecutor(@NonNull Executor executor) {
-        mBinder.setExecutor(executor);
-    }
+    void onSatelliteDatagramReceived(long datagramId, @NonNull SatelliteDatagram datagram,
+            int pendingCount, @NonNull ILongConsumer callback);
 }
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index c352266..d0abfbf 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -36,12 +36,15 @@
 import android.telephony.TelephonyFrameworkInitializer;
 
 import com.android.internal.telephony.IIntegerConsumer;
+import com.android.internal.telephony.ILongConsumer;
 import com.android.internal.telephony.ITelephony;
 import com.android.telephony.Rlog;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.time.Duration;
 import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executor;
 import java.util.function.Consumer;
 
@@ -55,6 +58,17 @@
 public class SatelliteManager {
     private static final String TAG = "SatelliteManager";
 
+    private static final ConcurrentHashMap<SatelliteDatagramCallback, ISatelliteDatagramCallback>
+            sSatelliteDatagramCallbackMap = new ConcurrentHashMap<>();
+    private static final ConcurrentHashMap<SatelliteProvisionStateCallback,
+            ISatelliteProvisionStateCallback> sSatelliteProvisionStateCallbackMap =
+            new ConcurrentHashMap<>();
+    private static final ConcurrentHashMap<SatelliteStateCallback, ISatelliteStateCallback>
+            sSatelliteStateCallbackMap = new ConcurrentHashMap<>();
+    private static final ConcurrentHashMap<SatelliteTransmissionUpdateCallback,
+            ISatelliteTransmissionUpdateCallback> sSatelliteTransmissionUpdateCallbackMap =
+            new ConcurrentHashMap<>();
+
     private final int mSubId;
 
     /**
@@ -66,6 +80,7 @@
      * Create an instance of the SatelliteManager.
      *
      * @param context The context the SatelliteManager belongs to.
+     * @hide
      */
     public SatelliteManager(@Nullable Context context) {
         this(context, SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
@@ -116,7 +131,7 @@
 
     /**
      * Bundle key to get the response from
-     * {@link #requestIsSatelliteDemoModeEnabled(Executor, OutcomeReceiver)}.
+     * {@link #requestIsDemoModeEnabled(Executor, OutcomeReceiver)}.
      * @hide
      */
     public static final String KEY_DEMO_MODE_ENABLED = "demo_mode_enabled";
@@ -137,14 +152,6 @@
 
     /**
      * Bundle key to get the response from
-     * {@link #requestMaxSizePerSendingDatagram(Executor, OutcomeReceiver)} .
-     * @hide
-     */
-    public static final String KEY_MAX_CHARACTERS_PER_SATELLITE_TEXT =
-            "max_characters_per_satellite_text";
-
-    /**
-     * Bundle key to get the response from
      * {@link #requestIsSatelliteProvisioned(Executor, OutcomeReceiver)}.
      * @hide
      */
@@ -166,13 +173,6 @@
     public static final String KEY_SATELLITE_NEXT_VISIBILITY = "satellite_next_visibility";
 
     /**
-     * Bundle key to get the respoonse from
-     * {@link #sendSatelliteDatagram(long, int, SatelliteDatagram, Executor, OutcomeReceiver)}.
-     * @hide
-     */
-    public static final String KEY_SEND_SATELLITE_DATAGRAM = "send_satellite_datagram";
-
-    /**
      * The request was successfully processed.
      */
     public static final int SATELLITE_ERROR_NONE = 0;
@@ -239,6 +239,8 @@
     public static final int SATELLITE_SERVICE_PROVISION_IN_PROGRESS = 14;
     /**
      * The ongoing request was aborted by either the satellite modem or the network.
+     * This error is also returned when framework decides to abort current send request as one
+     * of the previous send request failed.
      */
     public static final int SATELLITE_REQUEST_ABORTED = 15;
     /**
@@ -291,56 +293,58 @@
     public @interface SatelliteError {}
 
     /**
-     * 3GPP NB-IoT (Narrowband Internet of Things) over Non-Terrestrial-Networks technology.
-     */
-    public static final int NT_RADIO_TECHNOLOGY_NB_IOT_NTN = 0;
-    /**
-     * 3GPP 5G NR over Non-Terrestrial-Networks technology.
-     */
-    public static final int NT_RADIO_TECHNOLOGY_NR_NTN = 1;
-    /**
-     * 3GPP eMTC (enhanced Machine-Type Communication) over Non-Terrestrial-Networks technology.
-     */
-    public static final int NT_RADIO_TECHNOLOGY_EMTC_NTN = 2;
-    /**
-     * Proprietary technology.
-     */
-    public static final int NT_RADIO_TECHNOLOGY_PROPRIETARY = 3;
-    /**
      * Unknown Non-Terrestrial radio technology. This generic radio technology should be used
      * only when the radio technology cannot be mapped to other specific radio technologies.
      */
-    public static final int NT_RADIO_TECHNOLOGY_UNKNOWN = -1;
+    public static final int NT_RADIO_TECHNOLOGY_UNKNOWN = 0;
+    /**
+     * 3GPP NB-IoT (Narrowband Internet of Things) over Non-Terrestrial-Networks technology.
+     */
+    public static final int NT_RADIO_TECHNOLOGY_NB_IOT_NTN = 1;
+    /**
+     * 3GPP 5G NR over Non-Terrestrial-Networks technology.
+     */
+    public static final int NT_RADIO_TECHNOLOGY_NR_NTN = 2;
+    /**
+     * 3GPP eMTC (enhanced Machine-Type Communication) over Non-Terrestrial-Networks technology.
+     */
+    public static final int NT_RADIO_TECHNOLOGY_EMTC_NTN = 3;
+    /**
+     * Proprietary technology.
+     */
+    public static final int NT_RADIO_TECHNOLOGY_PROPRIETARY = 4;
 
     /** @hide */
     @IntDef(prefix = "NT_RADIO_TECHNOLOGY_", value = {
+            NT_RADIO_TECHNOLOGY_UNKNOWN,
             NT_RADIO_TECHNOLOGY_NB_IOT_NTN,
             NT_RADIO_TECHNOLOGY_NR_NTN,
             NT_RADIO_TECHNOLOGY_EMTC_NTN,
-            NT_RADIO_TECHNOLOGY_PROPRIETARY,
-            NT_RADIO_TECHNOLOGY_UNKNOWN
+            NT_RADIO_TECHNOLOGY_PROPRIETARY
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface NTRadioTechnology {}
 
     /**
-     * Request to enable or disable the satellite modem. If the satellite modem is enabled, this
-     * will also disable the cellular modem, and if the satellite modem is disabled, this will also
-     * re-enable the cellular modem.
+     * Request to enable or disable the satellite modem and demo mode. If the satellite modem is
+     * enabled, this may also disable the cellular modem, and if the satellite modem is disabled,
+     * this may also re-enable the cellular modem.
      *
-     * @param enable {@code true} to enable the satellite modem and {@code false} to disable.
+     * @param enableSatellite {@code true} to enable the satellite modem and
+     *                        {@code false} to disable.
+     * @param enableDemoMode {@code true} to enable demo mode and {@code false} to disable.
      * @param executor The executor on which the error code listener will be called.
-     * @param errorCodeListener Listener for the {@link SatelliteError} result of the operation.
+     * @param resultListener Listener for the {@link SatelliteError} result of the operation.
      *
      * @throws SecurityException if the caller doesn't have required permission.
      * @throws IllegalStateException if the Telephony process is not currently available.
      */
     @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
-    public void requestSatelliteEnabled(
-            boolean enable, @NonNull @CallbackExecutor Executor executor,
-            @NonNull Consumer<Integer> errorCodeListener) {
+    public void requestSatelliteEnabled(boolean enableSatellite, boolean enableDemoMode,
+            @NonNull @CallbackExecutor Executor executor,
+            @SatelliteError @NonNull Consumer<Integer> resultListener) {
         Objects.requireNonNull(executor);
-        Objects.requireNonNull(errorCodeListener);
+        Objects.requireNonNull(resultListener);
 
         try {
             ITelephony telephony = getITelephony();
@@ -349,10 +353,11 @@
                     @Override
                     public void accept(int result) {
                         executor.execute(() -> Binder.withCleanCallingIdentity(
-                                () -> errorCodeListener.accept(result)));
+                                () -> resultListener.accept(result)));
                     }
                 };
-                telephony.requestSatelliteEnabled(mSubId, enable, errorCallback);
+                telephony.requestSatelliteEnabled(mSubId, enableSatellite, enableDemoMode,
+                        errorCallback);
             } else {
                 throw new IllegalStateException("telephony service is null.");
             }
@@ -417,50 +422,13 @@
     }
 
     /**
-     * Request to enable or disable the satellite service demo mode.
-     *
-     * @param enable {@code true} to enable the satellite demo mode and {@code false} to disable.
-     * @param executor The executor on which the error code listener will be called.
-     * @param errorCodeListener Listener for the {@link SatelliteError} result of the operation.
-     *
-     * @throws SecurityException if the caller doesn't have required permission.
-     * @throws IllegalStateException if the Telephony process is not currently available.
-     */
-    @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
-    public void requestSatelliteDemoModeEnabled(boolean enable,
-            @NonNull @CallbackExecutor Executor executor,
-            @NonNull Consumer<Integer> errorCodeListener) {
-        Objects.requireNonNull(executor);
-        Objects.requireNonNull(errorCodeListener);
-
-        try {
-            ITelephony telephony = getITelephony();
-            if (telephony != null) {
-                IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() {
-                    @Override
-                    public void accept(int result) {
-                        executor.execute(() -> Binder.withCleanCallingIdentity(
-                                () -> errorCodeListener.accept(result)));
-                    }
-                };
-                telephony.requestSatelliteDemoModeEnabled(mSubId, enable, errorCallback);
-            } else {
-                throw new IllegalStateException("telephony service is null.");
-            }
-        } catch (RemoteException ex) {
-            Rlog.e(TAG, "requestSatelliteDemoModeEnabled() RemoteException: ", ex);
-            ex.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Request to get whether the satellite service demo mode is enabled.
      *
      * @param executor The executor on which the callback will be called.
      * @param callback The callback object to which the result will be delivered.
      *                 If the request is successful, {@link OutcomeReceiver#onResult(Object)}
-     *                 will return a {@code boolean} with value {@code true} if the satellite
-     *                 demo mode is enabled and {@code false} otherwise.
+     *                 will return a {@code boolean} with value {@code true} if demo mode is enabled
+     *                 and {@code false} otherwise.
      *                 If the request is not successful, {@link OutcomeReceiver#onError(Throwable)}
      *                 will return a {@link SatelliteException} with the {@link SatelliteError}.
      *
@@ -468,7 +436,7 @@
      * @throws IllegalStateException if the Telephony process is not currently available.
      */
     @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
-    public void requestIsSatelliteDemoModeEnabled(@NonNull @CallbackExecutor Executor executor,
+    public void requestIsDemoModeEnabled(@NonNull @CallbackExecutor Executor executor,
             @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) {
         Objects.requireNonNull(executor);
         Objects.requireNonNull(callback);
@@ -497,12 +465,12 @@
                         }
                     }
                 };
-                telephony.requestIsSatelliteDemoModeEnabled(mSubId, receiver);
+                telephony.requestIsDemoModeEnabled(mSubId, receiver);
             } else {
                 throw new IllegalStateException("telephony service is null.");
             }
         } catch (RemoteException ex) {
-            loge("requestIsSatelliteDemoModeEnabled() RemoteException: " + ex);
+            loge("requestIsDemoModeEnabled() RemoteException: " + ex);
             ex.rethrowFromSystemServer();
         }
     }
@@ -701,6 +669,10 @@
      */
     public static final int SATELLITE_MODEM_STATE_OFF = 4;
     /**
+     * Satellite modem is unavailable.
+     */
+    public static final int SATELLITE_MODEM_STATE_UNAVAILABLE = 5;
+    /**
      * Satellite modem state is unknown. This generic modem state should be used only when the
      * modem state cannot be mapped to other specific modem states.
      */
@@ -713,174 +685,147 @@
             SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING,
             SATELLITE_MODEM_STATE_DATAGRAM_RETRYING,
             SATELLITE_MODEM_STATE_OFF,
+            SATELLITE_MODEM_STATE_UNAVAILABLE,
             SATELLITE_MODEM_STATE_UNKNOWN
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface SatelliteModemState {}
 
     /**
+     * Datagram type is unknown. This generic datagram type should be used only when the
+     * datagram type cannot be mapped to other specific datagram types.
+     */
+    public static final int DATAGRAM_TYPE_UNKNOWN = 0;
+    /**
      * Datagram type indicating that the datagram to be sent or received is of type SOS message.
      */
-    public static final int DATAGRAM_TYPE_SOS_MESSAGE = 0;
+    public static final int DATAGRAM_TYPE_SOS_MESSAGE = 1;
     /**
      * Datagram type indicating that the datagram to be sent or received is of type
      * location sharing.
      */
-    public static final int DATAGRAM_TYPE_LOCATION_SHARING = 1;
-    /**
-     * Datagram type is unknown. This generic datagram type should be used only when the
-     * datagram type cannot be mapped to other specific datagram types.
-     */
-    public static final int DATAGRAM_TYPE_UNKNOWN = -1;
+    public static final int DATAGRAM_TYPE_LOCATION_SHARING = 2;
 
     @IntDef(prefix = "DATAGRAM_TYPE_", value = {
+            DATAGRAM_TYPE_UNKNOWN,
             DATAGRAM_TYPE_SOS_MESSAGE,
-            DATAGRAM_TYPE_LOCATION_SHARING,
-            DATAGRAM_TYPE_UNKNOWN
+            DATAGRAM_TYPE_LOCATION_SHARING
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface DatagramType {}
 
     /**
-     * Start receiving satellite position updates.
+     * Start receiving satellite transmission updates.
      * This can be called by the pointing UI when the user starts pointing to the satellite.
      * Modem should continue to report the pointing input as the device or satellite moves.
-     * Satellite position updates are started only on {@link #SATELLITE_ERROR_NONE}.
+     * Satellite transmission updates are started only on {@link #SATELLITE_ERROR_NONE}.
      * All other results indicate that this operation failed.
-     * Once satellite position updates begin, datagram transfer state updates will be sent
-     * through {@link SatellitePositionUpdateCallback}.
+     * Once satellite transmission updates begin, position and datagram transfer state updates
+     * will be sent through {@link SatelliteTransmissionUpdateCallback}.
      *
      * @param executor The executor on which the callback and error code listener will be called.
-     * @param errorCodeListener Listener for the {@link SatelliteError} result of the operation.
-     * @param callback The callback to notify of changes in satellite position.
+     * @param resultListener Listener for the {@link SatelliteError} result of the operation.
+     * @param callback The callback to notify of satellite transmission updates.
      *
      * @throws SecurityException if the caller doesn't have required permission.
      * @throws IllegalStateException if the Telephony process is not currently available.
      */
     @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
-    public void startSatellitePositionUpdates(@NonNull @CallbackExecutor Executor executor,
-            @NonNull Consumer<Integer> errorCodeListener,
-            @NonNull SatellitePositionUpdateCallback callback) {
+    public void startSatelliteTransmissionUpdates(@NonNull @CallbackExecutor Executor executor,
+            @SatelliteError @NonNull Consumer<Integer> resultListener,
+            @NonNull SatelliteTransmissionUpdateCallback callback) {
         Objects.requireNonNull(executor);
-        Objects.requireNonNull(errorCodeListener);
+        Objects.requireNonNull(resultListener);
         Objects.requireNonNull(callback);
 
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                callback.setExecutor(executor);
                 IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() {
                     @Override
                     public void accept(int result) {
                         executor.execute(() -> Binder.withCleanCallingIdentity(
-                                () -> errorCodeListener.accept(result)));
+                                () -> resultListener.accept(result)));
                     }
                 };
-                telephony.startSatellitePositionUpdates(
-                        mSubId, errorCallback, callback.getBinder());
+                ISatelliteTransmissionUpdateCallback internalCallback =
+                        new ISatelliteTransmissionUpdateCallback.Stub() {
+                            @Override
+                            public void onDatagramTransferStateChanged(int state,
+                                    int sendPendingCount, int receivePendingCount, int errorCode) {
+                                executor.execute(() -> Binder.withCleanCallingIdentity(
+                                        () -> callback.onDatagramTransferStateChanged(
+                                                state, sendPendingCount, receivePendingCount,
+                                                errorCode)));
+                            }
+
+                            @Override
+                            public void onSatellitePositionChanged(PointingInfo pointingInfo) {
+                                executor.execute(() -> Binder.withCleanCallingIdentity(
+                                        () -> callback.onSatellitePositionChanged(pointingInfo)));
+                            }
+                        };
+                sSatelliteTransmissionUpdateCallbackMap.put(callback, internalCallback);
+                telephony.startSatelliteTransmissionUpdates(mSubId, errorCallback,
+                        internalCallback);
             } else {
                 throw new IllegalStateException("telephony service is null.");
             }
         } catch (RemoteException ex) {
-            loge("startSatellitePositionUpdates() RemoteException: " + ex);
+            loge("startSatelliteTransmissionUpdates() RemoteException: " + ex);
             ex.rethrowFromSystemServer();
         }
     }
 
     /**
-     * Stop receiving satellite position updates.
+     * Stop receiving satellite transmission updates.
      * This can be called by the pointing UI when the user stops pointing to the satellite.
-     * Satellite position updates are stopped and the callback is unregistered only on
+     * Satellite transmission updates are stopped and the callback is unregistered only on
      * {@link #SATELLITE_ERROR_NONE}. All other results that this operation failed.
      *
-     * @param callback The callback that was passed to
-     * {@link #startSatellitePositionUpdates(Executor, Consumer, SatellitePositionUpdateCallback)}.
+     * @param callback The callback that was passed to {@link
+     * #startSatelliteTransmissionUpdates(Executor, Consumer, SatelliteTransmissionUpdateCallback)}.
      * @param executor The executor on which the error code listener will be called.
-     * @param errorCodeListener Listener for the {@link SatelliteError} result of the operation.
+     * @param resultListener Listener for the {@link SatelliteError} result of the operation.
      *
      * @throws SecurityException if the caller doesn't have required permission.
      * @throws IllegalStateException if the Telephony process is not currently available.
      */
     @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
-    public void stopSatellitePositionUpdates(@NonNull SatellitePositionUpdateCallback callback,
+    public void stopSatelliteTransmissionUpdates(
+            @NonNull SatelliteTransmissionUpdateCallback callback,
             @NonNull @CallbackExecutor Executor executor,
-            @NonNull Consumer<Integer> errorCodeListener) {
+            @SatelliteError @NonNull Consumer<Integer> resultListener) {
         Objects.requireNonNull(callback);
         Objects.requireNonNull(executor);
-        Objects.requireNonNull(errorCodeListener);
+        Objects.requireNonNull(resultListener);
+        ISatelliteTransmissionUpdateCallback internalCallback =
+                sSatelliteTransmissionUpdateCallbackMap.remove(callback);
 
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() {
-                    @Override
-                    public void accept(int result) {
-                        executor.execute(() -> Binder.withCleanCallingIdentity(
-                                () -> errorCodeListener.accept(result)));
-                    }
-                };
-                telephony.stopSatellitePositionUpdates(mSubId, errorCallback,
-                        callback.getBinder());
-                // TODO: Notify SmsHandler that pointing UI stopped
-            } else {
-                throw new IllegalStateException("telephony service is null.");
-            }
-        } catch (RemoteException ex) {
-            loge("stopSatellitePositionUpdates() RemoteException: " + ex);
-            ex.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Request to get the maximum number of bytes per datagram that can be sent to satellite.
-     *
-     * @param executor The executor on which the callback will be called.
-     * @param callback The callback object to which the result will be delivered.
-     *                 If the request is successful, {@link OutcomeReceiver#onResult(Object)}
-     *                 will return the maximum number of bytes per datagram that can be sent to
-     *                 satellite.
-     *                 If the request is not successful, {@link OutcomeReceiver#onError(Throwable)}
-     *
-     * @throws SecurityException if the caller doesn't have required permission.
-     * @throws IllegalStateException if the Telephony process is not currently available.
-     */
-    @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
-    public void requestMaxSizePerSendingDatagram(
-            @NonNull @CallbackExecutor Executor executor,
-            @NonNull OutcomeReceiver<Integer, SatelliteException> callback) {
-        Objects.requireNonNull(executor);
-        Objects.requireNonNull(callback);
-
-        try {
-            ITelephony telephony = getITelephony();
-            if (telephony != null) {
-                ResultReceiver receiver = new ResultReceiver(null) {
-                    @Override
-                    protected void onReceiveResult(int resultCode, Bundle resultData) {
-                        if (resultCode == SATELLITE_ERROR_NONE) {
-                            if (resultData.containsKey(KEY_MAX_CHARACTERS_PER_SATELLITE_TEXT)) {
-                                int maxCharacters =
-                                        resultData.getInt(KEY_MAX_CHARACTERS_PER_SATELLITE_TEXT);
-                                executor.execute(() -> Binder.withCleanCallingIdentity(() ->
-                                        callback.onResult(maxCharacters)));
-                            } else {
-                                loge("KEY_MAX_CHARACTERS_PER_SATELLITE_TEXT does not exist.");
-                                executor.execute(() -> Binder.withCleanCallingIdentity(() ->
-                                        callback.onError(
-                                                new SatelliteException(SATELLITE_REQUEST_FAILED))));
-                            }
-                        } else {
-                            executor.execute(() -> Binder.withCleanCallingIdentity(() ->
-                                    callback.onError(new SatelliteException(resultCode))));
+                if (internalCallback != null) {
+                    IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() {
+                        @Override
+                        public void accept(int result) {
+                            executor.execute(() -> Binder.withCleanCallingIdentity(
+                                    () -> resultListener.accept(result)));
                         }
-                    }
-                };
-                telephony.requestMaxSizePerSendingDatagram(mSubId, receiver);
+                    };
+                    telephony.stopSatelliteTransmissionUpdates(mSubId, errorCallback,
+                            internalCallback);
+                    // TODO: Notify SmsHandler that pointing UI stopped
+                } else {
+                    loge("stopSatelliteTransmissionUpdates: No internal callback.");
+                    executor.execute(() -> Binder.withCleanCallingIdentity(
+                            () -> resultListener.accept(SATELLITE_INVALID_ARGUMENTS)));
+                }
             } else {
                 throw new IllegalStateException("telephony service is null.");
             }
         } catch (RemoteException ex) {
-            loge("requestMaxCharactersPerSatelliteTextMessage() RemoteException: " + ex);
+            loge("stopSatelliteTransmissionUpdates() RemoteException: " + ex);
             ex.rethrowFromSystemServer();
         }
     }
@@ -891,23 +836,24 @@
      *
      * @param token The token to be used as a unique identifier for provisioning with satellite
      *              gateway.
+     * @param regionId The region ID for the device's current location.
      * @param cancellationSignal The optional signal used by the caller to cancel the provision
      *                           request. Even when the cancellation is signaled, Telephony will
      *                           still trigger the callback to return the result of this request.
      * @param executor The executor on which the error code listener will be called.
-     * @param errorCodeListener Listener for the {@link SatelliteError} result of the operation.
+     * @param resultListener Listener for the {@link SatelliteError} result of the operation.
      *
      * @throws SecurityException if the caller doesn't have required permission.
      * @throws IllegalStateException if the Telephony process is not currently available.
      */
     @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
-    public void provisionSatelliteService(@NonNull String token,
+    public void provisionSatelliteService(@NonNull String token, @NonNull String regionId,
             @Nullable CancellationSignal cancellationSignal,
             @NonNull @CallbackExecutor Executor executor,
-            @SatelliteError @NonNull Consumer<Integer> errorCodeListener) {
+            @SatelliteError @NonNull Consumer<Integer> resultListener) {
         Objects.requireNonNull(token);
         Objects.requireNonNull(executor);
-        Objects.requireNonNull(errorCodeListener);
+        Objects.requireNonNull(resultListener);
 
         ICancellationSignal cancelRemote = null;
         try {
@@ -917,10 +863,11 @@
                     @Override
                     public void accept(int result) {
                         executor.execute(() -> Binder.withCleanCallingIdentity(
-                                () -> errorCodeListener.accept(result)));
+                                () -> resultListener.accept(result)));
                     }
                 };
-                cancelRemote = telephony.provisionSatelliteService(mSubId, token, errorCallback);
+                cancelRemote = telephony.provisionSatelliteService(mSubId, token, regionId,
+                        errorCallback);
             } else {
                 throw new IllegalStateException("telephony service is null.");
             }
@@ -942,7 +889,7 @@
      * {@link #provisionSatelliteService(String, CancellationSignal, Executor, Consumer)}.
      *
      * @param token The token of the device/subscription to be deprovisioned.
-     * @param errorCodeListener Listener for the {@link SatelliteError} result of the operation.
+     * @param resultListener Listener for the {@link SatelliteError} result of the operation.
      *
      * @throws SecurityException if the caller doesn't have required permission.
      * @throws IllegalStateException if the Telephony process is not currently available.
@@ -950,10 +897,10 @@
     @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
     public void deprovisionSatelliteService(@NonNull String token,
             @NonNull @CallbackExecutor Executor executor,
-            @SatelliteError @NonNull Consumer<Integer> errorCodeListener) {
+            @SatelliteError @NonNull Consumer<Integer> resultListener) {
         Objects.requireNonNull(token);
         Objects.requireNonNull(executor);
-        Objects.requireNonNull(errorCodeListener);
+        Objects.requireNonNull(resultListener);
 
         try {
             ITelephony telephony = getITelephony();
@@ -962,7 +909,7 @@
                     @Override
                     public void accept(int result) {
                         executor.execute(() -> Binder.withCleanCallingIdentity(
-                                () -> errorCodeListener.accept(result)));
+                                () -> resultListener.accept(result)));
                     }
                 };
                 telephony.deprovisionSatelliteService(mSubId, token, errorCallback);
@@ -996,9 +943,18 @@
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                callback.setExecutor(executor);
+                ISatelliteProvisionStateCallback internalCallback =
+                        new ISatelliteProvisionStateCallback.Stub() {
+                            @Override
+                            public void onSatelliteProvisionStateChanged(boolean provisioned) {
+                                executor.execute(() -> Binder.withCleanCallingIdentity(
+                                        () -> callback.onSatelliteProvisionStateChanged(
+                                                provisioned)));
+                            }
+                        };
+                sSatelliteProvisionStateCallbackMap.put(callback, internalCallback);
                 return telephony.registerForSatelliteProvisionStateChanged(
-                        mSubId, callback.getBinder());
+                        mSubId, internalCallback);
             } else {
                 throw new IllegalStateException("telephony service is null.");
             }
@@ -1023,11 +979,17 @@
     public void unregisterForSatelliteProvisionStateChanged(
             @NonNull SatelliteProvisionStateCallback callback) {
         Objects.requireNonNull(callback);
+        ISatelliteProvisionStateCallback internalCallback =
+                sSatelliteProvisionStateCallbackMap.remove(callback);
 
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                telephony.unregisterForSatelliteProvisionStateChanged(mSubId, callback.getBinder());
+                if (internalCallback != null) {
+                    telephony.unregisterForSatelliteProvisionStateChanged(mSubId, internalCallback);
+                } else {
+                    loge("unregisterForSatelliteProvisionStateChanged: No internal callback.");
+                }
             } else {
                 throw new IllegalStateException("telephony service is null.");
             }
@@ -1112,9 +1074,15 @@
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                callback.setExecutor(executor);
-                return telephony.registerForSatelliteModemStateChanged(mSubId,
-                        callback.getBinder());
+                ISatelliteStateCallback internalCallback = new ISatelliteStateCallback.Stub() {
+                    @Override
+                    public void onSatelliteModemStateChanged(int state) {
+                        executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+                                callback.onSatelliteModemStateChanged(state)));
+                    }
+                };
+                sSatelliteStateCallbackMap.put(callback, internalCallback);
+                return telephony.registerForSatelliteModemStateChanged(mSubId, internalCallback);
             } else {
                 throw new IllegalStateException("telephony service is null.");
             }
@@ -1138,11 +1106,16 @@
     @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
     public void unregisterForSatelliteModemStateChanged(@NonNull SatelliteStateCallback callback) {
         Objects.requireNonNull(callback);
+        ISatelliteStateCallback internalCallback = sSatelliteStateCallbackMap.remove(callback);
 
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                telephony.unregisterForSatelliteModemStateChanged(mSubId, callback.getBinder());
+                if (internalCallback != null) {
+                    telephony.unregisterForSatelliteModemStateChanged(mSubId, internalCallback);
+                } else {
+                    loge("unregisterForSatelliteModemStateChanged: No internal callback.");
+                }
             } else {
                 throw new IllegalStateException("telephony service is null.");
             }
@@ -1155,8 +1128,6 @@
     /**
      * Register to receive incoming datagrams over satellite.
      *
-     * @param datagramType datagram type indicating whether the datagram is of type
-     *                     SOS_SMS or LOCATION_SHARING.
      * @param executor The executor on which the callback will be called.
      * @param callback The callback to handle incoming datagrams over satellite.
      *                 This callback with be invoked when a new datagram is received from satellite.
@@ -1167,7 +1138,7 @@
      * @throws IllegalStateException if the Telephony process is not currently available.
      */
     @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
-    @SatelliteError public int registerForSatelliteDatagram(@DatagramType int datagramType,
+    @SatelliteError public int registerForSatelliteDatagram(
             @NonNull @CallbackExecutor Executor executor,
             @NonNull SatelliteDatagramCallback callback) {
         Objects.requireNonNull(executor);
@@ -1176,9 +1147,19 @@
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                callback.setExecutor(executor);
-                return telephony.registerForSatelliteDatagram(mSubId, datagramType,
-                            callback.getBinder());
+                ISatelliteDatagramCallback internalCallback =
+                        new ISatelliteDatagramCallback.Stub() {
+                            @Override
+                            public void onSatelliteDatagramReceived(long datagramId,
+                                    @NonNull SatelliteDatagram datagram, int pendingCount,
+                                    @NonNull ILongConsumer ack) {
+                                executor.execute(() -> Binder.withCleanCallingIdentity(
+                                        () -> callback.onSatelliteDatagramReceived(
+                                                datagramId, datagram, pendingCount, ack)));
+                            }
+                        };
+                sSatelliteDatagramCallbackMap.put(callback, internalCallback);
+                return telephony.registerForSatelliteDatagram(mSubId, internalCallback);
             } else {
                 throw new IllegalStateException("telephony service is null.");
             }
@@ -1194,7 +1175,7 @@
      * If callback was not registered before, the request will be ignored.
      *
      * @param callback The callback that was passed to
-     * {@link #registerForSatelliteDatagram(int, Executor, SatelliteDatagramCallback)}.
+     * {@link #registerForSatelliteDatagram(Executor, SatelliteDatagramCallback)}.
      *
      * @throws SecurityException if the caller doesn't have required permission.
      * @throws IllegalStateException if the Telephony process is not currently available.
@@ -1202,11 +1183,17 @@
     @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
     public void unregisterForSatelliteDatagram(@NonNull SatelliteDatagramCallback callback) {
         Objects.requireNonNull(callback);
+        ISatelliteDatagramCallback internalCallback =
+                sSatelliteDatagramCallbackMap.remove(callback);
 
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                telephony.unregisterForSatelliteDatagram(mSubId, callback.getBinder());
+                if (internalCallback != null) {
+                    telephony.unregisterForSatelliteDatagram(mSubId, internalCallback);
+                } else {
+                    loge("unregisterForSatelliteDatagram: No internal callback.");
+                }
             } else {
                 throw new IllegalStateException("telephony service is null.");
             }
@@ -1222,7 +1209,7 @@
      * This method requests modem to check if there are any pending datagrams to be received over
      * satellite. If there are any incoming datagrams, they will be received via
      * {@link SatelliteDatagramCallback#onSatelliteDatagramReceived(long, SatelliteDatagram, int,
-     *          ISatelliteDatagramReceiverAck)}
+     *        ILongConsumer)}
      *
      * @param executor The executor on which the result listener will be called.
      * @param resultListener Listener for the {@link SatelliteError} result of the operation.
@@ -1263,7 +1250,6 @@
      * input to this method. Datagram received here will be passed down to modem without any
      * encoding or encryption.
      *
-     * @param datagramId An id that uniquely identifies datagram requested to be sent.
      * @param datagramType datagram type indicating whether the datagram is of type
      *                     SOS_SMS or LOCATION_SHARING.
      * @param datagram encoded gateway datagram which is encrypted by the caller.
@@ -1278,51 +1264,32 @@
      *                                 user activity and the application's ability to determine the
      *                                 best possible UX experience for the user.
      * @param executor The executor on which the result listener will be called.
-     * @param callback The callback object to which the result will be returned.
-     *                 If datagram is sent successfully, then
-     *                 {@link OutcomeReceiver#onResult(Object)} will return datagramId.
-     *                 If the request is not successful, {@link OutcomeReceiver#onError(Throwable)}
-     *                 will return a {@link SatelliteException} with the {@link SatelliteError}.
+     * @param resultListener Listener for the {@link SatelliteError} result of the operation.
      *
      * @throws SecurityException if the caller doesn't have required permission.
      * @throws IllegalStateException if the Telephony process is not currently available.
      */
     @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
-    public void sendSatelliteDatagram(long datagramId, @DatagramType int datagramType,
+    public void sendSatelliteDatagram(@DatagramType int datagramType,
             @NonNull SatelliteDatagram datagram, boolean needFullScreenPointingUI,
             @NonNull @CallbackExecutor Executor executor,
-            @NonNull OutcomeReceiver<Long, SatelliteException> callback) {
+            @SatelliteError @NonNull Consumer<Integer> resultListener) {
         Objects.requireNonNull(datagram);
         Objects.requireNonNull(executor);
-        Objects.requireNonNull(callback);
+        Objects.requireNonNull(resultListener);
 
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                ResultReceiver receiver = new ResultReceiver(null) {
+                IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() {
                     @Override
-                    protected void onReceiveResult(int resultCode, Bundle resultData) {
-                        if (resultCode == SATELLITE_ERROR_NONE) {
-                            if (resultData.containsKey(KEY_SEND_SATELLITE_DATAGRAM)) {
-                                long resultDatagramId = resultData
-                                        .getLong(KEY_SEND_SATELLITE_DATAGRAM);
-                                executor.execute(() -> Binder.withCleanCallingIdentity(() ->
-                                        callback.onResult(resultDatagramId)));
-                            } else {
-                                loge("KEY_SEND_SATELLITE_DATAGRAM does not exist.");
-                                executor.execute(() -> Binder.withCleanCallingIdentity(() ->
-                                        callback.onError(
-                                                new SatelliteException(SATELLITE_REQUEST_FAILED))));
-                            }
-
-                        } else {
-                            executor.execute(() -> Binder.withCleanCallingIdentity(() ->
-                                    callback.onError(new SatelliteException(resultCode))));
-                        }
+                    public void accept(int result) {
+                        executor.execute(() -> Binder.withCleanCallingIdentity(
+                                () -> resultListener.accept(result)));
                     }
                 };
-                telephony.sendSatelliteDatagram(mSubId, datagramId, datagramType, datagram,
-                        needFullScreenPointingUI, receiver);
+                telephony.sendSatelliteDatagram(mSubId, datagramType, datagram,
+                        needFullScreenPointingUI, internalCallback);
             } else {
                 throw new IllegalStateException("telephony service is null.");
             }
@@ -1391,9 +1358,8 @@
     }
 
     /**
-     * Request to get the time after which the satellite will be visible. This is an
-     * {@code int} representing the duration in seconds after which the satellite will be visible.
-     * This will return {@code 0} if the satellite is currently visible.
+     * Request to get the duration in seconds after which the satellite will be visible.
+     * This will be {@link Duration#ZERO} if the satellite is currently visible.
      *
      * @param executor The executor on which the callback will be called.
      * @param callback The callback object to which the result will be delivered.
@@ -1407,7 +1373,7 @@
      */
     @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
     public void requestTimeForNextSatelliteVisibility(@NonNull @CallbackExecutor Executor executor,
-            @NonNull OutcomeReceiver<Integer, SatelliteException> callback) {
+            @NonNull OutcomeReceiver<Duration, SatelliteException> callback) {
         Objects.requireNonNull(executor);
         Objects.requireNonNull(callback);
 
@@ -1422,7 +1388,8 @@
                                 int nextVisibilityDuration =
                                         resultData.getInt(KEY_SATELLITE_NEXT_VISIBILITY);
                                 executor.execute(() -> Binder.withCleanCallingIdentity(() ->
-                                        callback.onResult(nextVisibilityDuration)));
+                                        callback.onResult(
+                                                Duration.ofSeconds(nextVisibilityDuration))));
                             } else {
                                 loge("KEY_SATELLITE_NEXT_VISIBILITY does not exist.");
                                 executor.execute(() -> Binder.withCleanCallingIdentity(() ->
diff --git a/telephony/java/android/telephony/satellite/SatellitePositionUpdateCallback.java b/telephony/java/android/telephony/satellite/SatellitePositionUpdateCallback.java
deleted file mode 100644
index e3e4171..0000000
--- a/telephony/java/android/telephony/satellite/SatellitePositionUpdateCallback.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.satellite;
-
-import android.annotation.NonNull;
-import android.os.Binder;
-
-import java.util.concurrent.Executor;
-
-/**
- * A callback class for monitoring satellite position update and datagram transfer state change
- * events.
- *
- * @hide
- */
-public class SatellitePositionUpdateCallback {
-    private final CallbackBinder mBinder = new CallbackBinder(this);
-
-    private static class CallbackBinder extends ISatellitePositionUpdateCallback.Stub {
-        private final SatellitePositionUpdateCallback mLocalCallback;
-        private Executor mExecutor;
-
-        private CallbackBinder(SatellitePositionUpdateCallback localCallback) {
-            mLocalCallback = localCallback;
-        }
-
-        @Override
-        public void onSatellitePositionChanged(@NonNull PointingInfo pointingInfo) {
-            final long callingIdentity = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() ->
-                        mLocalCallback.onSatellitePositionChanged(pointingInfo));
-            } finally {
-                restoreCallingIdentity(callingIdentity);
-            }
-        }
-
-        @Override
-        public void onDatagramTransferStateChanged(
-                @SatelliteManager.SatelliteDatagramTransferState int state, int sendPendingCount,
-                int receivePendingCount, @SatelliteManager.SatelliteError int errorCode) {
-            final long callingIdentity = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() ->
-                        mLocalCallback.onDatagramTransferStateChanged(
-                                state, sendPendingCount, receivePendingCount, errorCode));
-            } finally {
-                restoreCallingIdentity(callingIdentity);
-            }
-        }
-
-        private void setExecutor(Executor executor) {
-            mExecutor = executor;
-        }
-    }
-
-    /**
-     * Called when the satellite position changed.
-     *
-     * @param pointingInfo The pointing info containing the satellite location.
-     */
-    public void onSatellitePositionChanged(@NonNull PointingInfo pointingInfo) {
-        // Base Implementation
-    }
-
-    /**
-     * Called when satellite datagram transfer state changed.
-     *
-     * @param state The new datagram transfer state.
-     * @param sendPendingCount The number of datagrams that are currently being sent.
-     * @param receivePendingCount The number of datagrams that are currently being received.
-     * @param errorCode If datagram transfer failed, the reason for failure.
-     */
-    public void onDatagramTransferStateChanged(
-            @SatelliteManager.SatelliteDatagramTransferState int state, int sendPendingCount,
-            int receivePendingCount, @SatelliteManager.SatelliteError int errorCode) {
-        // Base Implementation
-    }
-
-    /**@hide*/
-    @NonNull
-    public final ISatellitePositionUpdateCallback getBinder() {
-        return mBinder;
-    }
-
-    /**@hide*/
-    public void setExecutor(@NonNull Executor executor) {
-        mBinder.setExecutor(executor);
-    }
-}
diff --git a/telephony/java/android/telephony/satellite/SatelliteProvisionStateCallback.java b/telephony/java/android/telephony/satellite/SatelliteProvisionStateCallback.java
index cd084c9..a62eb8b 100644
--- a/telephony/java/android/telephony/satellite/SatelliteProvisionStateCallback.java
+++ b/telephony/java/android/telephony/satellite/SatelliteProvisionStateCallback.java
@@ -16,61 +16,17 @@
 
 package android.telephony.satellite;
 
-import android.annotation.NonNull;
-import android.os.Binder;
-
-import java.util.concurrent.Executor;
-
 /**
  * A callback class for monitoring satellite provision state change events.
  *
  * @hide
  */
-public class SatelliteProvisionStateCallback {
-    private final CallbackBinder mBinder = new CallbackBinder(this);
-
-    private static class CallbackBinder extends ISatelliteProvisionStateCallback.Stub {
-        private final SatelliteProvisionStateCallback mLocalCallback;
-        private Executor mExecutor;
-
-        private CallbackBinder(SatelliteProvisionStateCallback localCallback) {
-            mLocalCallback = localCallback;
-        }
-
-        @Override
-        public void onSatelliteProvisionStateChanged(boolean provisioned) {
-            final long callingIdentity = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() ->
-                        mLocalCallback.onSatelliteProvisionStateChanged(provisioned));
-            } finally {
-                restoreCallingIdentity(callingIdentity);
-            }
-        }
-
-        private void setExecutor(Executor executor) {
-            mExecutor = executor;
-        }
-    }
-
+public interface SatelliteProvisionStateCallback {
     /**
      * Called when satellite provision state changes.
      *
      * @param provisioned The new provision state. {@code true} means satellite is provisioned
      *                    {@code false} means satellite is not provisioned.
      */
-    public void onSatelliteProvisionStateChanged(boolean provisioned) {
-        // Base Implementation
-    }
-
-    /**@hide*/
-    @NonNull
-    public final ISatelliteProvisionStateCallback getBinder() {
-        return mBinder;
-    }
-
-    /**@hide*/
-    public void setExecutor(@NonNull Executor executor) {
-        mBinder.setExecutor(executor);
-    }
+    void onSatelliteProvisionStateChanged(boolean provisioned);
 }
diff --git a/telephony/java/android/telephony/satellite/SatelliteStateCallback.java b/telephony/java/android/telephony/satellite/SatelliteStateCallback.java
index d24bee6..d9ecaa3 100644
--- a/telephony/java/android/telephony/satellite/SatelliteStateCallback.java
+++ b/telephony/java/android/telephony/satellite/SatelliteStateCallback.java
@@ -16,80 +16,15 @@
 
 package android.telephony.satellite;
 
-import android.annotation.NonNull;
-import android.os.Binder;
-
-import java.util.concurrent.Executor;
-
 /**
  * A callback class for monitoring satellite modem state change events.
  *
  * @hide
  */
-public class SatelliteStateCallback {
-    private final CallbackBinder mBinder = new CallbackBinder(this);
-
-    private static class CallbackBinder extends ISatelliteStateCallback.Stub {
-        private final SatelliteStateCallback mLocalCallback;
-        private Executor mExecutor;
-
-        private CallbackBinder(SatelliteStateCallback localCallback) {
-            mLocalCallback = localCallback;
-        }
-
-        @Override
-        public void onSatelliteModemStateChanged(@SatelliteManager.SatelliteModemState int state) {
-            final long callingIdentity = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() ->
-                        mLocalCallback.onSatelliteModemStateChanged(state));
-            } finally {
-                restoreCallingIdentity(callingIdentity);
-            }
-        }
-
-        @Override
-        public void onPendingDatagramCount(int count) {
-            final long callingIdentity = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() ->
-                        mLocalCallback.onPendingDatagramCount(count));
-            } finally {
-                restoreCallingIdentity(callingIdentity);
-            }
-        }
-
-        private void setExecutor(Executor executor) {
-            mExecutor = executor;
-        }
-    }
-
+public interface SatelliteStateCallback {
     /**
      * Called when satellite modem state changes.
      * @param state The new satellite modem state.
      */
-    public void onSatelliteModemStateChanged(@SatelliteManager.SatelliteModemState int state) {
-        // Base Implementation
-    }
-
-    /**
-     * Called when there are pending datagrams to be received from satellite.
-     * @param count Pending datagram count.
-     */
-    public void onPendingDatagramCount(int count) {
-        // Base Implementation
-    }
-
-    //TODO: Add an API for datagram transfer state update here.
-
-    /**@hide*/
-    @NonNull
-    public final ISatelliteStateCallback getBinder() {
-        return mBinder;
-    }
-
-    /**@hide*/
-    public void setExecutor(@NonNull Executor executor) {
-        mBinder.setExecutor(executor);
-    }
+    void onSatelliteModemStateChanged(@SatelliteManager.SatelliteModemState int state);
 }
diff --git a/telephony/java/android/telephony/satellite/ISatellitePositionUpdateCallback.aidl b/telephony/java/android/telephony/satellite/SatelliteTransmissionUpdateCallback.java
similarity index 68%
copy from telephony/java/android/telephony/satellite/ISatellitePositionUpdateCallback.aidl
copy to telephony/java/android/telephony/satellite/SatelliteTransmissionUpdateCallback.java
index d3f1091..0efbd1f 100644
--- a/telephony/java/android/telephony/satellite/ISatellitePositionUpdateCallback.aidl
+++ b/telephony/java/android/telephony/satellite/SatelliteTransmissionUpdateCallback.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 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,13 +16,22 @@
 
 package android.telephony.satellite;
 
-import android.telephony.satellite.PointingInfo;
+import android.annotation.NonNull;
 
 /**
- * Interface for position update and datagram transfer state change callback.
+ * A callback class for monitoring satellite position update and datagram transfer state change
+ * events.
+ *
  * @hide
  */
-oneway interface ISatellitePositionUpdateCallback {
+public interface SatelliteTransmissionUpdateCallback {
+    /**
+     * Called when the satellite position changed.
+     *
+     * @param pointingInfo The pointing info containing the satellite location.
+     */
+    void onSatellitePositionChanged(@NonNull PointingInfo pointingInfo);
+
     /**
      * Called when satellite datagram transfer state changed.
      *
@@ -31,13 +40,7 @@
      * @param receivePendingCount The number of datagrams that are currently being received.
      * @param errorCode If datagram transfer failed, the reason for failure.
      */
-    void onDatagramTransferStateChanged(in int state, in int sendPendingCount,
-            in int receivePendingCount, in int errorCode);
-
-    /**
-     * Called when the satellite position changed.
-     *
-     * @param pointingInfo The pointing info containing the satellite location.
-     */
-    void onSatellitePositionChanged(in PointingInfo pointingInfo);
+    void onDatagramTransferStateChanged(@SatelliteManager.SatelliteDatagramTransferState int state,
+            int sendPendingCount, int receivePendingCount,
+            @SatelliteManager.SatelliteError int errorCode);
 }
diff --git a/telephony/java/android/telephony/satellite/stub/ISatellite.aidl b/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
index 5dc1a65..a780cb9 100644
--- a/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
+++ b/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
@@ -31,7 +31,6 @@
      * Register the callback interface with satellite service.
      *
      * @param listener The callback interface to handle satellite service indications.
-     * @param errorCallback The callback to receive the error code result of the operation.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
@@ -43,15 +42,16 @@
      *   SatelliteError:REQUEST_NOT_SUPPORTED
      *   SatelliteError:NO_RESOURCES
      */
-    void setSatelliteListener(in ISatelliteListener listener, in IIntegerConsumer errorCallback);
+    void setSatelliteListener(in ISatelliteListener listener);
 
     /**
      * Request to enable or disable the satellite service listening mode.
      * Listening mode allows the satellite service to listen for incoming pages.
      *
      * @param enable True to enable satellite listening mode and false to disable.
-     * @param isDemoMode Whether demo mode is enabled.
-     * @param errorCallback The callback to receive the error code result of the operation.
+     * @param timeout How long the satellite modem should wait for the next incoming page before
+     *                disabling listening mode.
+     * @param resultCallback The callback to receive the error code result of the operation.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
@@ -63,16 +63,17 @@
      *   SatelliteError:REQUEST_NOT_SUPPORTED
      *   SatelliteError:NO_RESOURCES
      */
-    void requestSatelliteListeningEnabled(in boolean enable, in boolean isDemoMode,
-            in IIntegerConsumer errorCallback);
+    void requestSatelliteListeningEnabled(in boolean enable, in int timeout,
+            in IIntegerConsumer resultCallback);
 
     /**
-     * Request to enable or disable the satellite modem. If the satellite modem is enabled,
-     * this will also disable the cellular modem, and if the satellite modem is disabled,
-     * this will also re-enable the cellular modem.
+     * Request to enable or disable the satellite modem and demo mode. If the satellite modem
+     * is enabled, this may also disable the cellular modem, and if the satellite modem is disabled,
+     * this may also re-enable the cellular modem.
      *
-     * @param enable True to enable the satellite modem and false to disable.
-     * @param errorCallback The callback to receive the error code result of the operation.
+     * @param enableSatellite True to enable the satellite modem and false to disable.
+     * @param enableDemoMode True to enable demo mode and false to disable.
+     * @param resultCallback The callback to receive the error code result of the operation.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
@@ -84,13 +85,14 @@
      *   SatelliteError:REQUEST_NOT_SUPPORTED
      *   SatelliteError:NO_RESOURCES
      */
-    void requestSatelliteEnabled(in boolean enabled, in IIntegerConsumer errorCallback);
+    void requestSatelliteEnabled(in boolean enableSatellite, in boolean enableDemoMode,
+            in IIntegerConsumer resultCallback);
 
     /**
      * Request to get whether the satellite modem is enabled.
      *
-     * @param errorCallback The callback to receive the error code result of the operation.
-     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
+     * @param resultCallback The callback to receive the error code result of the operation.
+     *                       This must only be sent when the error is not SatelliteError#ERROR_NONE.
      * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
      *                 whether the satellite modem is enabled.
      *
@@ -104,13 +106,13 @@
      *   SatelliteError:REQUEST_NOT_SUPPORTED
      *   SatelliteError:NO_RESOURCES
      */
-    void requestIsSatelliteEnabled(in IIntegerConsumer errorCallback, in IBooleanConsumer callback);
+    void requestIsSatelliteEnabled(in IIntegerConsumer resultCallback, in IBooleanConsumer callback);
 
     /**
      * Request to get whether the satellite service is supported on the device.
      *
-     * @param errorCallback The callback to receive the error code result of the operation.
-     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
+     * @param resultCallback The callback to receive the error code result of the operation.
+     *                       This must only be sent when the error is not SatelliteError#ERROR_NONE.
      * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
      *                 whether the satellite service is supported on the device.
      *
@@ -124,14 +126,14 @@
      *   SatelliteError:REQUEST_NOT_SUPPORTED
      *   SatelliteError:NO_RESOURCES
      */
-    void requestIsSatelliteSupported(in IIntegerConsumer errorCallback,
+    void requestIsSatelliteSupported(in IIntegerConsumer resultCallback,
             in IBooleanConsumer callback);
 
     /**
      * Request to get the SatelliteCapabilities of the satellite service.
      *
-     * @param errorCallback The callback to receive the error code result of the operation.
-     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
+     * @param resultCallback The callback to receive the error code result of the operation.
+     *                       This must only be sent when the error is not SatelliteError#ERROR_NONE.
      * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
      *                 the SatelliteCapabilities of the satellite service.
      *
@@ -145,7 +147,7 @@
      *   SatelliteError:REQUEST_NOT_SUPPORTED
      *   SatelliteError:NO_RESOURCES
      */
-    void requestSatelliteCapabilities(in IIntegerConsumer errorCallback,
+    void requestSatelliteCapabilities(in IIntegerConsumer resultCallback,
             in ISatelliteCapabilitiesConsumer callback);
 
     /**
@@ -153,7 +155,7 @@
      * The satellite service should report the satellite pointing info via
      * ISatelliteListener#onSatellitePositionChanged as the user device/satellite moves.
      *
-     * @param errorCallback The callback to receive the error code result of the operation.
+     * @param resultCallback The callback to receive the error code result of the operation.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
@@ -165,13 +167,13 @@
      *   SatelliteError:REQUEST_NOT_SUPPORTED
      *   SatelliteError:NO_RESOURCES
      */
-    void startSendingSatellitePointingInfo(in IIntegerConsumer errorCallback);
+    void startSendingSatellitePointingInfo(in IIntegerConsumer resultCallback);
 
     /**
      * User stopped pointing to the satellite.
      * The satellite service should stop reporting satellite pointing info to the framework.
      *
-     * @param errorCallback The callback to receive the error code result of the operation.
+     * @param resultCallback The callback to receive the error code result of the operation.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
@@ -183,28 +185,7 @@
      *   SatelliteError:REQUEST_NOT_SUPPORTED
      *   SatelliteError:NO_RESOURCES
      */
-    void stopSendingSatellitePointingInfo(in IIntegerConsumer errorCallback);
-
-    /**
-     * Request to get the maximum number of characters per MO text message on satellite.
-     *
-     * @param errorCallback The callback to receive the error code result of the operation.
-     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
-     * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
-     *                 the maximum number of characters per MO text message on satellite.
-     *
-     * Valid error codes returned:
-     *   SatelliteError:ERROR_NONE
-     *   SatelliteError:SERVICE_ERROR
-     *   SatelliteError:MODEM_ERROR
-     *   SatelliteError:INVALID_MODEM_STATE
-     *   SatelliteError:INVALID_ARGUMENTS
-     *   SatelliteError:RADIO_NOT_AVAILABLE
-     *   SatelliteError:REQUEST_NOT_SUPPORTED
-     *   SatelliteError:NO_RESOURCES
-     */
-    void requestMaxCharactersPerMOTextMessage(in IIntegerConsumer errorCallback,
-            in IIntegerConsumer callback);
+    void stopSendingSatellitePointingInfo(in IIntegerConsumer resultCallback);
 
     /**
      * Provision the device with a satellite provider.
@@ -213,7 +194,8 @@
      *
      * @param token The token to be used as a unique identifier for provisioning with satellite
      *              gateway.
-     * @param errorCallback The callback to receive the error code result of the operation.
+     * @param regionId The region ID for the device's current location.
+     * @param resultCallback The callback to receive the error code result of the operation.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
@@ -228,7 +210,8 @@
      *   SatelliteError:REQUEST_ABORTED
      *   SatelliteError:NETWORK_TIMEOUT
      */
-    void provisionSatelliteService(in String token, in IIntegerConsumer errorCallback);
+    void provisionSatelliteService(in String token, in String regionId,
+            in IIntegerConsumer resultCallback);
 
     /**
      * Deprovision the device with the satellite provider.
@@ -236,7 +219,7 @@
      * Once deprovisioned, ISatelliteListener#onSatelliteProvisionStateChanged should report false.
      *
      * @param token The token of the device/subscription to be deprovisioned.
-     * @param errorCallback The callback to receive the error code result of the operation.
+     * @param resultCallback The callback to receive the error code result of the operation.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
@@ -251,13 +234,13 @@
      *   SatelliteError:REQUEST_ABORTED
      *   SatelliteError:NETWORK_TIMEOUT
      */
-    void deprovisionSatelliteService(in String token, in IIntegerConsumer errorCallback);
+    void deprovisionSatelliteService(in String token, in IIntegerConsumer resultCallback);
 
     /**
      * Request to get whether this device is provisioned with a satellite provider.
      *
-     * @param errorCallback The callback to receive the error code result of the operation.
-     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
+     * @param resultCallback The callback to receive the error code result of the operation.
+     *                       This must only be sent when the error is not SatelliteError#ERROR_NONE.
      * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
      *                 whether this device is provisioned with a satellite provider.
      *
@@ -271,7 +254,7 @@
      *   SatelliteError:REQUEST_NOT_SUPPORTED
      *   SatelliteError:NO_RESOURCES
      */
-    void requestIsSatelliteProvisioned(in IIntegerConsumer errorCallback,
+    void requestIsSatelliteProvisioned(in IIntegerConsumer resultCallback,
             in IBooleanConsumer callback);
 
     /**
@@ -279,7 +262,7 @@
      * The satellite service should check if there are any pending datagrams to be received over
      * satellite and report them via ISatelliteListener#onSatelliteDatagramsReceived.
      *
-     * @param errorCallback The callback to receive the error code result of the operation.
+     * @param resultCallback The callback to receive the error code result of the operation.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
@@ -296,15 +279,14 @@
      *   SatelliteError:SATELLITE_NOT_REACHABLE
      *   SatelliteError:NOT_AUTHORIZED
      */
-    void pollPendingSatelliteDatagrams(in IIntegerConsumer errorCallback);
+    void pollPendingSatelliteDatagrams(in IIntegerConsumer resultCallback);
 
     /**
      * Send datagram over satellite.
      *
      * @param datagram Datagram to send in byte format.
-     * @param isDemoMode Whether demo mode is enabled.
      * @param isEmergency Whether this is an emergency datagram.
-     * @param errorCallback The callback to receive the error code result of the operation.
+     * @param resultCallback The callback to receive the error code result of the operation.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
@@ -322,16 +304,16 @@
      *   SatelliteError:SATELLITE_NOT_REACHABLE
      *   SatelliteError:NOT_AUTHORIZED
      */
-    void sendSatelliteDatagram(in SatelliteDatagram datagram, in boolean isDemoMode,
-            in boolean isEmergency, in IIntegerConsumer errorCallback);
+    void sendSatelliteDatagram(in SatelliteDatagram datagram, in boolean isEmergency,
+            in IIntegerConsumer resultCallback);
 
     /**
      * Request the current satellite modem state.
      * The satellite service should report the current satellite modem state via
      * ISatelliteListener#onSatelliteModemStateChanged.
      *
-     * @param errorCallback The callback to receive the error code result of the operation.
-     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
+     * @param resultCallback The callback to receive the error code result of the operation.
+     *                       This must only be sent when the error is not SatelliteError#ERROR_NONE.
      * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
      *                 the current satellite modem state.
      *
@@ -345,14 +327,14 @@
      *   SatelliteError:REQUEST_NOT_SUPPORTED
      *   SatelliteError:NO_RESOURCES
      */
-    void requestSatelliteModemState(in IIntegerConsumer errorCallback,
+    void requestSatelliteModemState(in IIntegerConsumer resultCallback,
             in IIntegerConsumer callback);
 
     /**
      * Request to get whether satellite communication is allowed for the current location.
      *
-     * @param errorCallback The callback to receive the error code result of the operation.
-     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
+     * @param resultCallback The callback to receive the error code result of the operation.
+     *                       This must only be sent when the error is not SatelliteError#ERROR_NONE.
      * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
      *                 whether satellite communication is allowed for the current location.
      *
@@ -367,15 +349,15 @@
      *   SatelliteError:NO_RESOURCES
      */
     void requestIsSatelliteCommunicationAllowedForCurrentLocation(
-            in IIntegerConsumer errorCallback, in IBooleanConsumer callback);
+            in IIntegerConsumer resultCallback, in IBooleanConsumer callback);
 
     /**
      * Request to get the time after which the satellite will be visible. This is an int
      * representing the duration in seconds after which the satellite will be visible.
      * This will return 0 if the satellite is currently visible.
      *
-     * @param errorCallback The callback to receive the error code result of the operation.
-     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
+     * @param resultCallback The callback to receive the error code result of the operation.
+     *                       This must only be sent when the error is not SatelliteError#ERROR_NONE.
      * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
      *                 the time after which the satellite will be visible.
      *
@@ -389,6 +371,6 @@
      *   SatelliteError:REQUEST_NOT_SUPPORTED
      *   SatelliteError:NO_RESOURCES
      */
-    void requestTimeForNextSatelliteVisibility(in IIntegerConsumer errorCallback,
+    void requestTimeForNextSatelliteVisibility(in IIntegerConsumer resultCallback,
             in IIntegerConsumer callback);
 }
diff --git a/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl b/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl
index e24e892e..5e69215 100644
--- a/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl
+++ b/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl
@@ -36,17 +36,15 @@
     /**
      * Indicates that new datagrams have been received on the device.
      *
-     * @param datagrams Array of new datagrams received.
-     * @param pendingCount The number of datagrams that are pending.
+     * @param datagram New datagram that was received.
+     * @param pendingCount Number of additional datagrams yet to be received.
      */
-    void onSatelliteDatagramsReceived(in SatelliteDatagram[] datagrams, in int pendingCount);
+    void onSatelliteDatagramReceived(in SatelliteDatagram datagram, in int pendingCount);
 
     /**
      * Indicates that the satellite has pending datagrams for the device to be pulled.
-     *
-     * @param count Number of pending datagrams.
      */
-    void onPendingDatagramCount(in int count);
+    void onPendingDatagrams();
 
     /**
      * Indicates that the satellite pointing input has changed.
@@ -61,11 +59,4 @@
      * @param state The current satellite modem state.
      */
     void onSatelliteModemStateChanged(in SatelliteModemState state);
-
-    /**
-     * Indicates that the satellite radio technology has changed.
-     *
-     * @param technology The current satellite radio technology.
-     */
-    void onSatelliteRadioTechnologyChanged(in NTRadioTechnology technology);
 }
diff --git a/telephony/java/android/telephony/satellite/stub/PointingInfo.aidl b/telephony/java/android/telephony/satellite/stub/PointingInfo.aidl
index 83392dd..52a36d8 100644
--- a/telephony/java/android/telephony/satellite/stub/PointingInfo.aidl
+++ b/telephony/java/android/telephony/satellite/stub/PointingInfo.aidl
@@ -29,21 +29,4 @@
      * Satellite elevation in degrees.
      */
     float satelliteElevation;
-
-    /**
-     * Antenna azimuth in degrees.
-     */
-    float antennaAzimuth;
-
-    /**
-     * Angle of rotation about the x axis. This value represents the angle between a plane
-     * parallel to the device's screen and a plane parallel to the ground.
-     */
-    float antennaPitch;
-
-    /**
-     * Angle of rotation about the y axis. This value represents the angle between a plane
-     * perpendicular to the device's screen and a plane parallel to the ground.
-     */
-    float antennaRoll;
 }
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteCapabilities.aidl b/telephony/java/android/telephony/satellite/stub/SatelliteCapabilities.aidl
index 10c2ea3..cd69da1 100644
--- a/telephony/java/android/telephony/satellite/stub/SatelliteCapabilities.aidl
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteCapabilities.aidl
@@ -28,18 +28,12 @@
     NTRadioTechnology[] supportedRadioTechnologies;
 
     /**
-     * Whether satellite modem is always on.
-     * This indicates the power impact of keeping it on is very minimal.
-     */
-    boolean isAlwaysOn;
-
-    /**
      * Whether UE needs to point to a satellite to send and receive data.
      */
-    boolean needsPointingToSatellite;
+    boolean isPointingRequired;
 
     /**
-     * Whether UE needs a separate SIM profile to communicate with the satellite network.
+     * The maximum number of bytes per datagram that can be sent over satellite.
      */
-    boolean needsSeparateSimProfile;
+    int maxBytesPerOutgoingDatagram;
 }
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java b/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
index df51432..debb394 100644
--- a/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
@@ -63,27 +63,28 @@
 
     private final IBinder mBinder = new ISatellite.Stub() {
         @Override
-        public void setSatelliteListener(ISatelliteListener listener,
-                IIntegerConsumer errorCallback) throws RemoteException {
+        public void setSatelliteListener(ISatelliteListener listener) throws RemoteException {
             executeMethodAsync(
-                    () -> SatelliteImplBase.this.setSatelliteListener(listener, errorCallback),
+                    () -> SatelliteImplBase.this.setSatelliteListener(listener),
                     "setSatelliteListener");
         }
 
         @Override
-        public void requestSatelliteListeningEnabled(boolean enable, boolean isDemoMode,
+        public void requestSatelliteListeningEnabled(boolean enable, int timeout,
                 IIntegerConsumer errorCallback) throws RemoteException {
             executeMethodAsync(
                     () -> SatelliteImplBase.this
-                            .requestSatelliteListeningEnabled(enable, isDemoMode, errorCallback),
+                            .requestSatelliteListeningEnabled(enable, timeout, errorCallback),
                     "requestSatelliteListeningEnabled");
         }
 
         @Override
-        public void requestSatelliteEnabled(boolean enable, IIntegerConsumer errorCallback)
-                throws RemoteException {
+        public void requestSatelliteEnabled(boolean enableSatellite, boolean enableDemoMode,
+                IIntegerConsumer errorCallback) throws RemoteException {
             executeMethodAsync(
-                    () -> SatelliteImplBase.this.requestSatelliteEnabled(enable, errorCallback),
+                    () -> SatelliteImplBase.this
+                            .requestSatelliteEnabled(
+                                    enableSatellite, enableDemoMode, errorCallback),
                     "requestSatelliteEnabled");
         }
 
@@ -131,19 +132,11 @@
         }
 
         @Override
-        public void requestMaxCharactersPerMOTextMessage(IIntegerConsumer errorCallback,
-                IIntegerConsumer callback) throws RemoteException {
+        public void provisionSatelliteService(String token, String regionId,
+                IIntegerConsumer errorCallback) throws RemoteException {
             executeMethodAsync(
                     () -> SatelliteImplBase.this
-                            .requestMaxCharactersPerMOTextMessage(errorCallback, callback),
-                    "requestMaxCharactersPerMOTextMessage");
-        }
-
-        @Override
-        public void provisionSatelliteService(String token, IIntegerConsumer errorCallback)
-                throws RemoteException {
-            executeMethodAsync(
-                    () -> SatelliteImplBase.this.provisionSatelliteService(token, errorCallback),
+                            .provisionSatelliteService(token, regionId, errorCallback),
                     "provisionSatelliteService");
         }
 
@@ -173,12 +166,11 @@
         }
 
         @Override
-        public void sendSatelliteDatagram(SatelliteDatagram datagram, boolean isDemoMode,
-                boolean isEmergency, IIntegerConsumer errorCallback) throws RemoteException {
+        public void sendSatelliteDatagram(SatelliteDatagram datagram, boolean isEmergency,
+                IIntegerConsumer errorCallback) throws RemoteException {
             executeMethodAsync(
                     () -> SatelliteImplBase.this
-                            .sendSatelliteDatagram(
-                                    datagram, isDemoMode, isEmergency, errorCallback),
+                            .sendSatelliteDatagram(datagram, isEmergency, errorCallback),
                     "sendSatelliteDatagram");
         }
 
@@ -229,7 +221,6 @@
      * Register the callback interface with satellite service.
      *
      * @param listener The callback interface to handle satellite service indications.
-     * @param errorCallback The callback to receive the error code result of the operation.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
@@ -241,8 +232,7 @@
      *   SatelliteError:REQUEST_NOT_SUPPORTED
      *   SatelliteError:NO_RESOURCES
      */
-    public void setSatelliteListener(@NonNull ISatelliteListener listener,
-            @NonNull IIntegerConsumer errorCallback) {
+    public void setSatelliteListener(@NonNull ISatelliteListener listener) {
         // stub implementation
     }
 
@@ -251,7 +241,8 @@
      * Listening mode allows the satellite service to listen for incoming pages.
      *
      * @param enable True to enable satellite listening mode and false to disable.
-     * @param isDemoMode Whether demo mode is enabled.
+     * @param timeout How long the satellite modem should wait for the next incoming page before
+     *                disabling listening mode.
      * @param errorCallback The callback to receive the error code result of the operation.
      *
      * Valid error codes returned:
@@ -264,17 +255,18 @@
      *   SatelliteError:REQUEST_NOT_SUPPORTED
      *   SatelliteError:NO_RESOURCES
      */
-    public void requestSatelliteListeningEnabled(boolean enable, boolean isDemoMode,
+    public void requestSatelliteListeningEnabled(boolean enable, int timeout,
             @NonNull IIntegerConsumer errorCallback) {
         // stub implementation
     }
 
     /**
-     * Request to enable or disable the satellite modem. If the satellite modem is enabled,
-     * this will also disable the cellular modem, and if the satellite modem is disabled,
-     * this will also re-enable the cellular modem.
+     * Request to enable or disable the satellite modem and demo mode. If the satellite modem is
+     * enabled, this may also disable the cellular modem, and if the satellite modem is disabled,
+     * this may also re-enable the cellular modem.
      *
-     * @param enable True to enable the satellite modem and false to disable.
+     * @param enableSatellite True to enable the satellite modem and false to disable.
+     * @param enableDemoMode True to enable demo mode and false to disable.
      * @param errorCallback The callback to receive the error code result of the operation.
      *
      * Valid error codes returned:
@@ -287,7 +279,8 @@
      *   SatelliteError:REQUEST_NOT_SUPPORTED
      *   SatelliteError:NO_RESOURCES
      */
-    public void requestSatelliteEnabled(boolean enable, @NonNull IIntegerConsumer errorCallback) {
+    public void requestSatelliteEnabled(boolean enableSatellite, boolean enableDemoMode,
+            @NonNull IIntegerConsumer errorCallback) {
         // stub implementation
     }
 
@@ -402,35 +395,13 @@
     }
 
     /**
-     * Request to get the maximum number of characters per MO text message on satellite.
-     *
-     * @param errorCallback The callback to receive the error code result of the operation.
-     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
-     * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
-     *                 the maximum number of characters per MO text message on satellite.
-     *
-     * Valid error codes returned:
-     *   SatelliteError:ERROR_NONE
-     *   SatelliteError:SERVICE_ERROR
-     *   SatelliteError:MODEM_ERROR
-     *   SatelliteError:INVALID_MODEM_STATE
-     *   SatelliteError:INVALID_ARGUMENTS
-     *   SatelliteError:RADIO_NOT_AVAILABLE
-     *   SatelliteError:REQUEST_NOT_SUPPORTED
-     *   SatelliteError:NO_RESOURCES
-     */
-    public void requestMaxCharactersPerMOTextMessage(@NonNull IIntegerConsumer errorCallback,
-            @NonNull IIntegerConsumer callback) {
-        // stub implementation
-    }
-
-    /**
      * Provision the device with a satellite provider.
      * This is needed if the provider allows dynamic registration.
      * Once provisioned, ISatelliteListener#onSatelliteProvisionStateChanged should report true.
      *
      * @param token The token to be used as a unique identifier for provisioning with satellite
      *              gateway.
+     * @param regionId The region ID for the device's current location.
      * @param errorCallback The callback to receive the error code result of the operation.
      *
      * Valid error codes returned:
@@ -446,7 +417,7 @@
      *   SatelliteError:REQUEST_ABORTED
      *   SatelliteError:NETWORK_TIMEOUT
      */
-    public void provisionSatelliteService(@NonNull String token,
+    public void provisionSatelliteService(@NonNull String token, @NonNull String regionId,
             @NonNull IIntegerConsumer errorCallback) {
         // stub implementation
     }
@@ -530,7 +501,6 @@
      * Send datagram over satellite.
      *
      * @param datagram Datagram to send in byte format.
-     * @param isDemoMode Whether demo mode is enabled.
      * @param isEmergency Whether this is an emergency datagram.
      * @param errorCallback The callback to receive the error code result of the operation.
      *
@@ -550,8 +520,8 @@
      *   SatelliteError:SATELLITE_NOT_REACHABLE
      *   SatelliteError:NOT_AUTHORIZED
      */
-    public void sendSatelliteDatagram(@NonNull SatelliteDatagram datagram, boolean isDemoMode,
-            boolean isEmergency, @NonNull IIntegerConsumer errorCallback) {
+    public void sendSatelliteDatagram(@NonNull SatelliteDatagram datagram, boolean isEmergency,
+            @NonNull IIntegerConsumer errorCallback) {
         // stub implementation
     }
 
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl b/telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl
index 5ee7f9a..e4f9413 100644
--- a/telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl
@@ -42,6 +42,10 @@
      */
     SATELLITE_MODEM_STATE_OFF = 4,
     /**
+     * Satellite modem is unavailable.
+     */
+    SATELLITE_MODEM_STATE_UNAVAILABLE = 5,
+    /**
      * Satellite modem state is unknown. This generic modem state should be used only when the
      * modem state cannot be mapped to other specific modem states.
      */
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl b/telephony/java/com/android/internal/telephony/ILongConsumer.aidl
similarity index 66%
copy from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
copy to telephony/java/com/android/internal/telephony/ILongConsumer.aidl
index 35d5c15..2f0d4a0 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/ILongConsumer.aidl
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -14,6 +14,12 @@
  * limitations under the License.
  */
 
-package android.net.wifi.sharedconnectivity.app;
+ package com.android.internal.telephony;
 
-parcelable DeviceInfo;
\ No newline at end of file
+ /**
+  * Copies consumer pattern for an operation that requires long result from another process to
+  * finish.
+  */
+ oneway interface ILongConsumer {
+    void accept(long result);
+ }
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index ef9dc3e..d0de3ac 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -68,7 +68,7 @@
 import android.telephony.ims.aidl.IImsRegistrationCallback;
 import android.telephony.ims.aidl.IRcsConfigCallback;
 import android.telephony.satellite.ISatelliteDatagramCallback;
-import android.telephony.satellite.ISatellitePositionUpdateCallback;
+import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
 import android.telephony.satellite.ISatelliteProvisionStateCallback;
 import android.telephony.satellite.ISatelliteStateCallback;
 import android.telephony.satellite.SatelliteCapabilities;
@@ -1848,6 +1848,22 @@
             String gid2, String plmn, String spn, String carrierPrivilegeRules, String apn);
 
     /**
+     * Forcibly sets a package as a carrier provisioning package.
+     *
+     * This override is ephemeral, and will disappear upon phone process restart (including
+     * device reboot).
+     *
+     * WARNING: This API is meant for testing purposes only. This enables automated testing for
+     * cases where the carrier service package is used as a permissioning gate for features such as
+     * restricted carrier network access (restricted APNs and Merged Carrier Wifi)
+     *
+     * @param carrierServicePackage The package that should be marked as the carrier service
+     *     package, or {@code null} to disable the override.
+     */
+    void setCarrierServicePackageOverride(int subId, String carrierServicePackage,
+                String callingPackage);
+
+    /**
      * A test API to return installed carrier id list version.
      */
     int getCarrierIdListVersion(int subId);
@@ -2710,11 +2726,13 @@
      *
      * @param subId The subId of the subscription to enable or disable the satellite modem for.
      * @param enable True to enable the satellite modem and false to disable.
-     * @param callback The callback to get the error code of the request.
+     * @param isDemoModeEnabled True if demo mode is enabled and false otherwise.
+     * @param callback The callback to get the result of the request.
      */
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
             + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
-    void requestSatelliteEnabled(int subId, boolean enable, in IIntegerConsumer callback);
+    void requestSatelliteEnabled(int subId, boolean enable, boolean isDemoModeEnabled,
+            in IIntegerConsumer callback);
 
     /**
      * Request to get whether the satellite modem is enabled.
@@ -2728,17 +2746,6 @@
     void requestIsSatelliteEnabled(int subId, in ResultReceiver receiver);
 
     /**
-     * Request to enable or disable the satellite service demo mode.
-     *
-     * @param subId The subId of the subscription to enable or disable the satellite demo mode for.
-     * @param enable True to enable the satellite demo mode and false to disable.
-     * @param callback The callback to get the error code of the request.
-     */
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
-            + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
-    void requestSatelliteDemoModeEnabled(int subId, boolean enable, in IIntegerConsumer callback);
-
-    /**
      * Request to get whether the satellite service demo mode is enabled.
      *
      * @param subId The subId of the subscription to request whether the satellite demo mode is
@@ -2748,7 +2755,7 @@
      */
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
             + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
-    void requestIsSatelliteDemoModeEnabled(int subId, in ResultReceiver receiver);
+    void requestIsDemoModeEnabled(int subId, in ResultReceiver receiver);
 
     /**
      * Request to get whether the satellite service is supported on the device.
@@ -2771,39 +2778,28 @@
     void requestSatelliteCapabilities(int subId, in ResultReceiver receiver);
 
     /**
-     * Start receiving satellite pointing updates.
+     * Start receiving satellite transmission updates.
      *
-     * @param subId The subId of the subscription to stop satellite position updates for.
-     * @param errorCallback The callback to get the error code of the request.
-     * @param callback The callback to handle position updates.
+     * @param subId The subId of the subscription to stop satellite transmission updates for.
+     * @param resultCallback The callback to get the result of the request.
+     * @param callback The callback to handle transmission updates.
      */
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
             + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
-    void startSatellitePositionUpdates(int subId, in IIntegerConsumer errorCallback,
-            in ISatellitePositionUpdateCallback callback);
+    void startSatelliteTransmissionUpdates(int subId, in IIntegerConsumer resultCallback,
+            in ISatelliteTransmissionUpdateCallback callback);
 
     /**
-     * Stop receiving satellite pointing updates.
+     * Stop receiving satellite transmission updates.
      *
-     * @param subId The subId of the subscritpion to stop satellite position updates for.
-     * @param errorCallback The callback to get the error code of the request.
-     * @param callback The callback that was passed to startSatellitePositionUpdates.
+     * @param subId The subId of the subscritpion to stop satellite transmission updates for.
+     * @param resultCallback The callback to get the result of the request.
+     * @param callback The callback that was passed to startSatelliteTransmissionUpdates.
      */
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
             + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
-    void stopSatellitePositionUpdates(int subId, in IIntegerConsumer errorCallback,
-            in ISatellitePositionUpdateCallback callback);
-
-    /**
-     * Request to get the maximum number of bytes per datagram that can be sent to satellite.
-     *
-     * @param subId The subId of the subscription to get the maximum number of characters for.
-     * @param receiver Result receiver to get the error code of the request and the requested
-     *                 maximum number of bytes per datagram that can be sent to satellite.
-     */
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
-            + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
-    void requestMaxSizePerSendingDatagram(int subId, in ResultReceiver receiver);
+    void stopSatelliteTransmissionUpdates(int subId, in IIntegerConsumer resultCallback,
+            in ISatelliteTransmissionUpdateCallback callback);
 
     /**
      * Register the subscription with a satellite provider.
@@ -2812,13 +2808,14 @@
      * @param subId The subId of the subscription to be provisioned.
      * @param token The token to be used as a unique identifier for provisioning with satellite
      *              gateway.
-     * @param callback The callback to get the error code of the request.
+     * @param regionId The region ID for the device's current location.
+     * @param callback The callback to get the result of the request.
      *
      * @return The signal transport used by callers to cancel the provision request.
      */
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
             + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
-    ICancellationSignal provisionSatelliteService(int subId, in String token,
+    ICancellationSignal provisionSatelliteService(int subId, in String token, in String regionId,
             in IIntegerConsumer callback);
 
     /**
@@ -2830,7 +2827,7 @@
      *
      * @param subId The subId of the subscription to be deprovisioned.
      * @param token The token of the device/subscription to be deprovisioned.
-     * @param callback The callback to get the error code of the request.
+     * @param callback The callback to get the result of the request.
      */
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
             + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
@@ -2900,15 +2897,13 @@
      * Register to receive incoming datagrams over satellite.
      *
      * @param subId The subId of the subscription to register for incoming satellite datagrams.
-     * @param datagramType Type of datagram.
      * @param callback The callback to handle the incoming datagrams.
      *
      * @return The {@link SatelliteError} result of the operation.
      */
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
             + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
-    int registerForSatelliteDatagram(
-            int subId, int datagramType, ISatelliteDatagramCallback callback);
+    int registerForSatelliteDatagram(int subId, ISatelliteDatagramCallback callback);
 
    /**
      * Unregister to stop receiving incoming datagrams over satellite.
@@ -2925,7 +2920,7 @@
     * Poll pending satellite datagrams over satellite.
     *
     * @param subId The subId of the subscription used for receiving datagrams.
-    * @param callback The callback to get the error code of the request.
+    * @param callback The callback to get the result of the request.
     */
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
                 + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
@@ -2935,19 +2930,17 @@
     * Send datagram over satellite.
     *
     * @param subId The subId of the subscription to send satellite datagrams for.
-    * @param datagramId An id that uniquely identifies datagram requested to be sent.
     * @param datagramType Type of datagram.
     * @param datagram Datagram to send over satellite.
     * @param needFullScreenPointingUI this is used to indicate pointingUI app to open in
     *                                 full screen mode.
-    * @param receiver Result receiver to get the datagramId if datagram is sent successfully else
-    *                 error code of the request.
+    * @param callback The callback to get the result of the request.
     */
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
             + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
-    void sendSatelliteDatagram(int subId, long datagramId, int datagramType,
+    void sendSatelliteDatagram(int subId, int datagramType,
              in SatelliteDatagram datagram, in boolean needFullScreenPointingUI,
-             in ResultReceiver receiver);
+             IIntegerConsumer callback);
 
     /**
      * Request to get whether satellite communication is allowed for the current location.
diff --git a/telephony/java/com/android/internal/telephony/ITransportSelectorCallback.aidl b/telephony/java/com/android/internal/telephony/ITransportSelectorCallback.aidl
index aca83f4..6777256d 100644
--- a/telephony/java/com/android/internal/telephony/ITransportSelectorCallback.aidl
+++ b/telephony/java/com/android/internal/telephony/ITransportSelectorCallback.aidl
@@ -22,7 +22,7 @@
 
 interface ITransportSelectorCallback {
     oneway void onCreated(in IDomainSelector selector);
-    oneway void onWlanSelected();
+    oneway void onWlanSelected(boolean useEmergencyPdn);
     IWwanSelectorCallback onWwanSelected();
     oneway void onWwanSelectedAsync(in ITransportSelectorResultCallback cb);
     oneway void onSelectionTerminated(int cause);
diff --git a/telephony/java/com/android/internal/telephony/IWwanSelectorCallback.aidl b/telephony/java/com/android/internal/telephony/IWwanSelectorCallback.aidl
index 339fbee..94e7c87 100644
--- a/telephony/java/com/android/internal/telephony/IWwanSelectorCallback.aidl
+++ b/telephony/java/com/android/internal/telephony/IWwanSelectorCallback.aidl
@@ -21,6 +21,6 @@
 oneway interface IWwanSelectorCallback {
     void onRequestEmergencyNetworkScan(in int[] preferredNetworks,
             int scanType, in IWwanSelectorResultCallback cb);
-    void onDomainSelected(int domain);
+    void onDomainSelected(int domain, boolean useEmergencyPdn);
     void onCancel();
 }
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 45daab3..8ed60c1 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -571,22 +571,6 @@
     int RIL_REQUEST_UPDATE_IMS_CALL_STATUS = 240;
     int RIL_REQUEST_SET_N1_MODE_ENABLED = 241;
     int RIL_REQUEST_IS_N1_MODE_ENABLED = 242;
-    int RIL_REQUEST_SET_LOCATION_PRIVACY_SETTING = 243;
-    int RIL_REQUEST_GET_LOCATION_PRIVACY_SETTING = 244;
-    int RIL_REQUEST_GET_SATELLITE_CAPABILITIES = 245;
-    int RIL_REQUEST_SET_SATELLITE_POWER = 246;
-    int RIL_REQUEST_GET_SATELLITE_POWER = 247;
-    int RIL_REQUEST_PROVISION_SATELLITE_SERVICE = 248;
-    int RIL_REQUEST_ADD_ALLOWED_SATELLITE_CONTACTS = 249;
-    int RIL_REQUEST_REMOVE_ALLOWED_SATELLITE_CONTACTS = 250;
-    int RIL_REQUEST_SEND_SATELLITE_MESSAGES = 251;
-    int RIL_REQUEST_GET_PENDING_SATELLITE_MESSAGES = 252;
-    int RIL_REQUEST_GET_SATELLITE_MODE = 253;
-    int RIL_REQUEST_SET_SATELLITE_INDICATION_FILTER = 254;
-    int RIL_REQUEST_START_SENDING_SATELLITE_POINTING_INFO = 255;
-    int RIL_REQUEST_STOP_SENDING_SATELLITE_POINTING_INFO = 256;
-    int RIL_REQUEST_GET_MAX_CHARACTERS_PER_SATELLITE_TEXT_MESSAGE = 257;
-    int RIL_REQUEST_GET_TIME_FOR_NEXT_SATELLITE_VISIBILITY = 258;
 
     /* Responses begin */
     int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
@@ -648,13 +632,6 @@
     int RIL_UNSOL_RESPONSE_SIM_PHONEBOOK_CHANGED = 1053;
     int RIL_UNSOL_RESPONSE_SIM_PHONEBOOK_RECORDS_RECEIVED = 1054;
     int RIL_UNSOL_SLICING_CONFIG_CHANGED = 1055;
-    int RIL_UNSOL_PENDING_SATELLITE_MESSAGE_COUNT = 1056;
-    int RIL_UNSOL_NEW_SATELLITE_MESSAGES = 1057;
-    int RIL_UNSOL_SATELLITE_MESSAGES_TRANSFER_COMPLETE = 1058;
-    int RIL_UNSOL_SATELLITE_POINTING_INFO_CHANGED = 1059;
-    int RIL_UNSOL_SATELLITE_MODE_CHANGED = 1060;
-    int RIL_UNSOL_SATELLITE_RADIO_TECHNOLOGY_CHANGED = 1061;
-    int RIL_UNSOL_SATELLITE_PROVISION_STATE_CHANGED = 1062;
 
     /* The following unsols are not defined in RIL.h */
     int RIL_UNSOL_HAL_NON_RIL_BASE = 1100;
diff --git a/tests/EnforcePermission/Android.bp b/tests/EnforcePermission/Android.bp
new file mode 100644
index 0000000..719a898
--- /dev/null
+++ b/tests/EnforcePermission/Android.bp
@@ -0,0 +1,22 @@
+// 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 {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+filegroup {
+    name: "frameworks-enforce-permission-test-aidl",
+    srcs: ["aidl/**/*.aidl"],
+}
diff --git a/tests/EnforcePermission/OWNERS b/tests/EnforcePermission/OWNERS
new file mode 100644
index 0000000..39550a3
--- /dev/null
+++ b/tests/EnforcePermission/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 315013
+tweek@google.com
+brufino@google.com
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl b/tests/EnforcePermission/aidl/android/tests/enforcepermission/INested.aidl
similarity index 71%
copy from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
copy to tests/EnforcePermission/aidl/android/tests/enforcepermission/INested.aidl
index 35d5c15..1eb773d 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
+++ b/tests/EnforcePermission/aidl/android/tests/enforcepermission/INested.aidl
@@ -14,6 +14,12 @@
  * limitations under the License.
  */
 
-package android.net.wifi.sharedconnectivity.app;
+package android.tests.enforcepermission;
 
-parcelable DeviceInfo;
\ No newline at end of file
+interface INested {
+    @EnforcePermission("ACCESS_NETWORK_STATE")
+    void ProtectedByAccessNetworkState();
+
+    @EnforcePermission("READ_SYNC_SETTINGS")
+    void ProtectedByReadSyncSettings();
+}
diff --git a/tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl b/tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl
new file mode 100644
index 0000000..18e3aec
--- /dev/null
+++ b/tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl
@@ -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 android.tests.enforcepermission;
+
+interface IProtected {
+    @EnforcePermission("INTERNET")
+    void ProtectedByInternet();
+
+    @EnforcePermission("VIBRATE")
+    void ProtectedByVibrate();
+
+    @EnforcePermission("INTERNET")
+    void ProtectedByInternetAndVibrateImplicitly();
+
+    @EnforcePermission("INTERNET")
+    void ProtectedByInternetAndAccessNetworkStateImplicitly();
+
+    @EnforcePermission("INTERNET")
+    void ProtectedByInternetAndReadSyncSettingsImplicitly();
+}
diff --git a/tests/EnforcePermission/service-app/Android.bp b/tests/EnforcePermission/service-app/Android.bp
new file mode 100644
index 0000000..a4ac1d7
--- /dev/null
+++ b/tests/EnforcePermission/service-app/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test_helper_app {
+    name: "EnforcePermissionTestHelper",
+    srcs: [
+        "src/**/*.java",
+        ":frameworks-enforce-permission-test-aidl",
+    ],
+    platform_apis: true,
+    certificate: "platform",
+}
diff --git a/services/tests/PackageManagerServiceTests/apks/install_uses_sdk/AndroidManifest-r1000.xml b/tests/EnforcePermission/service-app/AndroidManifest.xml
similarity index 64%
copy from services/tests/PackageManagerServiceTests/apks/install_uses_sdk/AndroidManifest-r1000.xml
copy to tests/EnforcePermission/service-app/AndroidManifest.xml
index 9bf9254..ddafe15 100644
--- a/services/tests/PackageManagerServiceTests/apks/install_uses_sdk/AndroidManifest-r1000.xml
+++ b/tests/EnforcePermission/service-app/AndroidManifest.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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,13 +14,14 @@
      limitations under the License.
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.frameworks.servicestests.install_uses_sdk">
-
-    <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="29">
-        <!-- This will fail to install, because minExtensionVersion is not met -->
-        <extension-sdk android:sdkVersion="30" android:minExtensionVersion="1000" />
-    </uses-sdk>
-
+  package="android.tests.enforcepermission.service">
     <application>
+        <service
+          android:name=".TestService"
+          android:exported="true" />
+
+        <service
+          android:name=".NestedTestService"
+          android:exported="true" />
     </application>
 </manifest>
diff --git a/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java
new file mode 100644
index 0000000..7879a12
--- /dev/null
+++ b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java
@@ -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 android.tests.enforcepermission.service;
+
+import android.annotation.EnforcePermission;
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.tests.enforcepermission.INested;
+import android.util.Log;
+
+public class NestedTestService extends Service {
+    private static final String TAG = "EnforcePermission.NestedTestService";
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        Log.i(TAG, "onBind");
+        return mBinder;
+    }
+
+    private final INested.Stub mBinder = new INested.Stub() {
+        @Override
+        @EnforcePermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
+        public void ProtectedByAccessNetworkState() {
+            ProtectedByAccessNetworkState_enforcePermission();
+        }
+
+        @Override
+        @EnforcePermission(android.Manifest.permission.READ_SYNC_SETTINGS)
+        public void ProtectedByReadSyncSettings() {
+            ProtectedByReadSyncSettings_enforcePermission();
+        }
+    };
+}
diff --git a/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java
new file mode 100644
index 0000000..e9b897d
--- /dev/null
+++ b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java
@@ -0,0 +1,119 @@
+/**
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.tests.enforcepermission.service;
+
+import android.annotation.EnforcePermission;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.tests.enforcepermission.INested;
+import android.tests.enforcepermission.IProtected;
+import android.util.Log;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public class TestService extends Service {
+
+    private static final String TAG = "EnforcePermission.TestService";
+    private volatile ServiceConnection mNestedServiceConnection;
+
+    @Override
+    public void onCreate() {
+        mNestedServiceConnection = new ServiceConnection();
+        Intent intent = new Intent(this, NestedTestService.class);
+        boolean bound = bindService(intent, mNestedServiceConnection, Context.BIND_AUTO_CREATE);
+        if (!bound) {
+            Log.wtf(TAG, "bindService() on NestedTestService failed");
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        unbindService(mNestedServiceConnection);
+    }
+
+    private static final class ServiceConnection implements android.content.ServiceConnection {
+        private volatile CompletableFuture<INested> mFuture = new CompletableFuture<>();
+
+        public INested get() {
+            try {
+                return mFuture.get(1, TimeUnit.SECONDS);
+            } catch (ExecutionException | InterruptedException | TimeoutException e) {
+                throw new RuntimeException("Unable to reach NestedTestService: " + e.getMessage());
+            }
+        }
+
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            mFuture.complete(INested.Stub.asInterface(service));
+        }
+
+        public void onServiceDisconnected(ComponentName className) {
+            mFuture = new CompletableFuture<>();
+        }
+    };
+
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mBinder;
+    }
+
+    private final IProtected.Stub mBinder = new IProtected.Stub() {
+        @Override
+        @EnforcePermission(android.Manifest.permission.INTERNET)
+        public void ProtectedByInternet() {
+            ProtectedByInternet_enforcePermission();
+        }
+
+        @Override
+        @EnforcePermission(android.Manifest.permission.VIBRATE)
+        public void ProtectedByVibrate() {
+            ProtectedByVibrate_enforcePermission();
+        }
+
+        @Override
+        @EnforcePermission(android.Manifest.permission.INTERNET)
+        public void ProtectedByInternetAndVibrateImplicitly() {
+            ProtectedByInternetAndVibrateImplicitly_enforcePermission();
+
+            ProtectedByVibrate();
+        }
+
+        @Override
+        @EnforcePermission(android.Manifest.permission.INTERNET)
+        public void ProtectedByInternetAndAccessNetworkStateImplicitly() throws RemoteException {
+            ProtectedByInternetAndAccessNetworkStateImplicitly_enforcePermission();
+
+            mNestedServiceConnection.get().ProtectedByAccessNetworkState();
+
+        }
+
+        @Override
+        @EnforcePermission(android.Manifest.permission.INTERNET)
+        public void ProtectedByInternetAndReadSyncSettingsImplicitly() throws RemoteException {
+            ProtectedByInternetAndReadSyncSettingsImplicitly_enforcePermission();
+
+            mNestedServiceConnection.get().ProtectedByReadSyncSettings();
+        }
+    };
+}
diff --git a/tests/EnforcePermission/test-app/Android.bp b/tests/EnforcePermission/test-app/Android.bp
new file mode 100644
index 0000000..305ed8f
--- /dev/null
+++ b/tests/EnforcePermission/test-app/Android.bp
@@ -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 {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+    name: "EnforcePermissionTests",
+    srcs: [
+        "src/**/*.java",
+        ":frameworks-enforce-permission-test-aidl",
+    ],
+    static_libs: [
+        "androidx.test.rules",
+    ],
+    libs: [
+        "android.test.base",
+        "android.test.runner",
+    ],
+    data: [
+        ":EnforcePermissionTestHelper",
+    ],
+    platform_apis: true,
+    certificate: "platform",
+    test_suites: ["general-tests"],
+}
diff --git a/tests/EnforcePermission/test-app/AndroidManifest.xml b/tests/EnforcePermission/test-app/AndroidManifest.xml
new file mode 100644
index 0000000..4a0c6a8
--- /dev/null
+++ b/tests/EnforcePermission/test-app/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+  package="android.tests.enforcepermission.tests">
+
+    <!-- Expected for the tests (not actually used) -->
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
+
+    <queries>
+        <package android:name="android.tests.enforcepermission.service" />
+    </queries>
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="android.tests.enforcepermission.tests"/>
+</manifest>
diff --git a/tests/EnforcePermission/test-app/AndroidTest.xml b/tests/EnforcePermission/test-app/AndroidTest.xml
new file mode 100644
index 0000000..120381a
--- /dev/null
+++ b/tests/EnforcePermission/test-app/AndroidTest.xml
@@ -0,0 +1,28 @@
+<?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.
+-->
+<configuration description="Runs EnforcePermission End-to-End Tests">
+    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+      <option name="test-file-name" value="EnforcePermissionTestHelper.apk"/>
+      <option name="test-file-name" value="EnforcePermissionTests.apk"/>
+      <option name="cleanup-apks" value="true" />
+    </target_preparer>
+
+    <option name="test-tag" value="EnforcePermissionTests"/>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="android.tests.enforcepermission.tests"/>
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner"/>
+    </test>
+</configuration>
diff --git a/tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java b/tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java
new file mode 100644
index 0000000..d2a4a03
--- /dev/null
+++ b/tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java
@@ -0,0 +1,129 @@
+/**
+ * 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.tests.enforcepermission.tests;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.tests.enforcepermission.IProtected;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+@RunWith(AndroidJUnit4.class)
+public class ServiceTest {
+
+    private static final String TAG = "EnforcePermission.Tests";
+    private static final String SERVICE_NAME = "android.tests.enforcepermission.service";
+    private static final int SERVICE_TIMEOUT_SEC = 5;
+
+    private Context mContext;
+    private volatile ServiceConnection mServiceConnection;
+
+    @Before
+    public void bindTestService() throws Exception {
+        Log.d(TAG, "bindTestService");
+        mContext = InstrumentationRegistry.getTargetContext();
+        mServiceConnection = new ServiceConnection();
+        Intent intent = new Intent();
+        intent.setClassName(SERVICE_NAME, SERVICE_NAME + ".TestService");
+        assertTrue(mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE));
+    }
+
+    @After
+    public void unbindTestService() throws Exception {
+        mContext.unbindService(mServiceConnection);
+    }
+
+    private static final class ServiceConnection implements android.content.ServiceConnection {
+        private volatile CompletableFuture<IProtected> mFuture = new CompletableFuture<>();
+
+        @Override
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            mFuture.complete(IProtected.Stub.asInterface(service));
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName className) {
+            mFuture = new CompletableFuture<>();
+        }
+
+        public IProtected get() {
+            try {
+                return mFuture.get(SERVICE_TIMEOUT_SEC, TimeUnit.SECONDS);
+            } catch (ExecutionException | InterruptedException | TimeoutException e) {
+                throw new RuntimeException("Unable to reach TestService: " + e.toString());
+            }
+        }
+    }
+
+    @Test
+    public void testImmediatePermissionGranted_succeeds()
+            throws RemoteException {
+        mServiceConnection.get().ProtectedByInternet();
+    }
+
+    @Test
+    public void testImmediatePermissionNotGranted_fails()
+            throws RemoteException {
+        final Exception ex = assertThrows(SecurityException.class,
+                () -> mServiceConnection.get().ProtectedByVibrate());
+        assertThat(ex.getMessage(), containsString("VIBRATE"));
+    }
+
+    @Test
+    public void testImmediatePermissionGrantedButImplicitLocalNotGranted_fails()
+            throws RemoteException {
+        final Exception ex = assertThrows(SecurityException.class,
+                () -> mServiceConnection.get().ProtectedByInternetAndVibrateImplicitly());
+        assertThat(ex.getMessage(), containsString("VIBRATE"));
+    }
+
+    @Test
+    public void testImmediatePermissionGrantedButImplicitNestedNotGranted_fails()
+            throws RemoteException {
+        final Exception ex = assertThrows(SecurityException.class,
+                () -> mServiceConnection.get()
+                      .ProtectedByInternetAndAccessNetworkStateImplicitly());
+        assertThat(ex.getMessage(), containsString("ACCESS_NETWORK_STATE"));
+    }
+
+    @Test
+    public void testImmediatePermissionGrantedAndImplicitNestedGranted_succeeds()
+            throws RemoteException {
+        mServiceConnection.get().ProtectedByInternetAndReadSyncSettingsImplicitly();
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
index 9dc4bf0..9c3460c 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
@@ -317,7 +317,8 @@
             assertion.then().isVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
         }
         if (ignoreSplashscreen) {
-            assertion.then().isSplashScreenVisibleFor(newLayer, isOptional = true)
+            assertion.then().isSplashScreenVisibleFor(
+                    ComponentNameMatcher(newLayer.packageName, className = ""), isOptional = true)
         }
 
         assertion.then().isVisible(newLayer)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
index 0e852b6..de57d06 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
@@ -58,7 +58,48 @@
     }
 
     /**
-     * Expands the PIP window my using the pinch out gesture.
+     * Drags the PIP window away from the screen edge while not crossing the display center.
+     *
+     * @throws IllegalStateException if default display bounds are not available
+     */
+    fun dragPipWindowAwayFromEdge(wmHelper: WindowManagerStateHelper, steps: Int) {
+        val initWindowRect = getWindowRect(wmHelper).clone()
+
+        // initial pointer at the center of the window
+        val startX = initWindowRect.centerX()
+        val y = initWindowRect.centerY()
+
+        val displayRect = wmHelper.currentState.wmState.getDefaultDisplay()?.displayRect
+                ?: throw IllegalStateException("Default display is null")
+
+        // the offset to the right of the display center to drag the window to
+        val offset = 20
+
+        // the actual final x coordinate with the offset included
+        // if the pip window is closer to the right edge of the display the offset is positive
+        // otherwise the offset is negative
+        val endX = displayRect.centerX() + offset * (if (isCloserToRightEdge(wmHelper)) 1 else -1)
+
+        // drag the window to the left but not beyond the center of the display
+        uiDevice.drag(startX, y, endX, y, steps)
+    }
+
+    /**
+     * Returns true if PIP window is closer to the right edge of the display than left.
+     *
+     * @throws IllegalStateException if default display bounds are not available
+     */
+    fun isCloserToRightEdge(wmHelper: WindowManagerStateHelper): Boolean {
+        val windowRect = getWindowRect(wmHelper)
+
+        val displayRect = wmHelper.currentState.wmState.getDefaultDisplay()?.displayRect
+                ?: throw IllegalStateException("Default display is null")
+
+        return windowRect.centerX() > displayRect.centerX()
+    }
+
+    /**
+     * Expands the PIP window by using the pinch out gesture.
      *
      * @param percent The percentage by which to increase the pip window size.
      * @throws IllegalArgumentException if percentage isn't between 0.0f and 1.0f
@@ -106,7 +147,7 @@
     }
 
     /**
-     * Minimizes the PIP window my using the pinch in gesture.
+     * Minimizes the PIP window by using the pinch in gesture.
      *
      * @param percent The percentage by which to decrease the pip window size.
      * @throws IllegalArgumentException if percentage isn't between 0.0f and 1.0f
@@ -223,7 +264,10 @@
         closePipWindow(WindowManagerStateHelper(mInstrumentation))
     }
 
-    private fun getWindowRect(wmHelper: WindowManagerStateHelper): Rect {
+    /**
+     * Returns the pip window bounds.
+     */
+    fun getWindowRect(wmHelper: WindowManagerStateHelper): Rect {
         val windowRegion = wmHelper.getWindowRegion(this)
         require(!windowRegion.isEmpty) { "Unable to find a PIP window in the current state" }
         return windowRegion.bounds
@@ -307,6 +351,28 @@
             .waitForAndVerify()
     }
 
+    /**
+     * Waits until the PIP window snaps horizontally to the provided bounds.
+     *
+     * @param finalBounds the bounds to wait for PIP window to snap to
+     */
+    fun waitForPipToSnapTo(wmHelper: WindowManagerStateHelper, finalBounds: android.graphics.Rect) {
+        wmHelper
+            .StateSyncBuilder()
+            .add("pipWindowSnapped") {
+                val pipAppWindow =
+                    it.wmState.visibleWindows.firstOrNull { window ->
+                        this.windowMatchesAnyOf(window)
+                    }
+                        ?: return@add false
+                val pipRegionBounds = pipAppWindow.frameRegion.bounds
+                return@add pipRegionBounds.left == finalBounds.left &&
+                    pipRegionBounds.right == finalBounds.right
+            }
+            .add(ConditionsFactory.isWMStateComplete())
+            .waitForAndVerify()
+    }
+
     companion object {
         private const val TAG = "PipAppHelper"
         private const val ENTER_PIP_BUTTON_ID = "enter_pip"
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt
index c23cf34..d72f528 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt
@@ -37,7 +37,7 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class CloseImeOnDismissPopupDialogTest(flicker: FlickerTest) : BaseTest(flicker) {
+open class CloseImeOnDismissPopupDialogTest(flicker: FlickerTest) : BaseTest(flicker) {
     private val imeTestApp = ImeEditorPopupDialogAppHelper(instrumentation)
 
     /** {@inheritDoc} */
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnStartWhenLaunchingAppCfArmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTestCfArm.kt
similarity index 68%
copy from tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnStartWhenLaunchingAppCfArmTest.kt
copy to tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTestCfArm.kt
index 194c86b..432df20 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnStartWhenLaunchingAppCfArmTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTestCfArm.kt
@@ -16,8 +16,10 @@
 
 package com.android.server.wm.flicker.ime
 
+import android.tools.common.Rotation
 import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
@@ -26,5 +28,15 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class ShowImeOnStartWhenLaunchingAppCfArmTest(flicker: FlickerTest) :
-    ShowImeOnAppStartWhenLaunchingAppTest(flicker)
+class CloseImeOnDismissPopupDialogTestCfArm(flicker: FlickerTest) :
+    CloseImeOnDismissPopupDialogTest(flicker) {
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests(
+                supportedRotations = listOf(Rotation.ROTATION_0)
+            )
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnStartWhenLaunchingAppCfArmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppCfArmTest.kt
similarity index 93%
rename from tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnStartWhenLaunchingAppCfArmTest.kt
rename to tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppCfArmTest.kt
index 194c86b..03f21f9 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnStartWhenLaunchingAppCfArmTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppCfArmTest.kt
@@ -26,5 +26,5 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class ShowImeOnStartWhenLaunchingAppCfArmTest(flicker: FlickerTest) :
+class ShowImeOnAppStartWhenLaunchingAppCfArmTest(flicker: FlickerTest) :
     ShowImeOnAppStartWhenLaunchingAppTest(flicker)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnStartWhenLaunchingAppCfArmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTestCfArm.kt
similarity index 66%
copy from tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnStartWhenLaunchingAppCfArmTest.kt
copy to tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTestCfArm.kt
index 194c86b..efda0ff 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnStartWhenLaunchingAppCfArmTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTestCfArm.kt
@@ -16,8 +16,10 @@
 
 package com.android.server.wm.flicker.ime
 
+import android.tools.common.Rotation
 import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
@@ -26,5 +28,16 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class ShowImeOnStartWhenLaunchingAppCfArmTest(flicker: FlickerTest) :
-    ShowImeOnAppStartWhenLaunchingAppTest(flicker)
+class ShowImeOnAppStartWhenLaunchingAppFromOverviewTestCfArm(flicker: FlickerTest) :
+    ShowImeOnAppStartWhenLaunchingAppFromOverviewTest(flicker) {
+
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests(
+                supportedRotations = listOf(Rotation.ROTATION_0)
+            )
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt
index 954f589..daee332 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt
@@ -16,13 +16,11 @@
 
 package com.android.server.wm.flicker.ime
 
-import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.Presubmit
 import android.tools.common.NavBar
 import android.tools.common.Rotation
 import android.tools.common.datatypes.component.ComponentNameMatcher
 import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
-import android.tools.device.flicker.isShellTransitionsEnabled
 import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.device.flicker.legacy.FlickerBuilder
 import android.tools.device.flicker.legacy.FlickerTest
@@ -31,8 +29,6 @@
 import com.android.server.wm.flicker.BaseTest
 import com.android.server.wm.flicker.helpers.SimpleAppHelper
 import com.android.server.wm.flicker.helpers.setRotation
-import org.junit.Assume
-import org.junit.Before
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -54,11 +50,6 @@
     private val imeTestApp =
         ImeShownOnAppStartHelper(instrumentation, flicker.scenario.startRotation)
 
-    @Before
-    open fun before() {
-        Assume.assumeFalse(isShellTransitionsEnabled)
-    }
-
     /** {@inheritDoc} */
     override val transition: FlickerBuilder.() -> Unit = {
         setup {
@@ -95,7 +86,7 @@
         }
     }
     /** {@inheritDoc} */
-    @FlakyTest(bugId = 265016201)
+    @Presubmit
     @Test
     override fun entireScreenCovered() = super.entireScreenCovered()
 
@@ -115,7 +106,7 @@
         }
     }
 
-    @FlakyTest(bugId = 244414110)
+    @Presubmit
     @Test
     open fun imeLayerIsVisibleWhenSwitchingToImeApp() {
         flicker.assertLayersStart { isVisible(ComponentNameMatcher.IME) }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestShellTransit.kt
deleted file mode 100644
index a927102..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestShellTransit.kt
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm.flicker.ime
-
-import android.platform.test.annotations.Presubmit
-import android.tools.device.flicker.isShellTransitionsEnabled
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
-import android.tools.device.flicker.legacy.FlickerTest
-import androidx.test.filters.RequiresDevice
-import org.junit.Assume
-import org.junit.Before
-import org.junit.FixMethodOrder
-import org.junit.Ignore
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test IME windows switching with 2-Buttons or gestural navigation. To run this test: `atest
- * FlickerTests:SwitchImeWindowsFromGestureNavTest`
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestShellTransit(flicker: FlickerTest) :
-    ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest(flicker) {
-    @Before
-    override fun before() {
-        Assume.assumeTrue(isShellTransitionsEnabled)
-    }
-
-    @Presubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
-
-    @Presubmit
-    @Test
-    override fun imeLayerIsVisibleWhenSwitchingToImeApp() =
-        super.imeLayerIsVisibleWhenSwitchingToImeApp()
-
-    @Presubmit
-    @Test
-    override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
-        super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
-    @Presubmit
-    @Test
-    override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
-        super.visibleWindowsShownMoreThanOneConsecutiveEntry()
-
-    /** {@inheritDoc} */
-    @Ignore("Nav bar window becomes invisible during quick switch")
-    @Test
-    override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt
index 99b9bd2bfc..a57aa5b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt
@@ -45,7 +45,7 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class ShowImeWhileDismissingThemedPopupDialogTest(flicker: FlickerTest) : BaseTest(flicker) {
+open class ShowImeWhileDismissingThemedPopupDialogTest(flicker: FlickerTest) : BaseTest(flicker) {
     private val testApp = ImeShownOnAppStartHelper(instrumentation, flicker.scenario.startRotation)
 
     /** {@inheritDoc} */
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTestCfArm.kt
new file mode 100644
index 0000000..cffc05d
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTestCfArm.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.server.wm.flicker.ime
+
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class ShowImeWhileDismissingThemedPopupDialogTestCfArm(flicker: FlickerTest) :
+    ShowImeWhileDismissingThemedPopupDialogTest(flicker) {
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            return FlickerTestFactory.nonRotationTests(
+                supportedRotations = listOf(Rotation.ROTATION_0)
+            )
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt
index 19ecf6a..05abf9f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt
@@ -53,7 +53,7 @@
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class OpenAppColdFromIcon(flicker: FlickerTest) : OpenAppFromLauncherTransition(flicker) {
+open class OpenAppColdFromIcon(flicker: FlickerTest) : OpenAppFromLauncherTransition(flicker) {
     /** {@inheritDoc} */
     override val transition: FlickerBuilder.() -> Unit
         get() = {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIconCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIconCfArm.kt
new file mode 100644
index 0000000..ccbe74f
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIconCfArm.kt
@@ -0,0 +1,59 @@
+/*
+ * 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.flicker.launch
+
+import android.platform.test.annotations.FlakyTest
+import android.tools.common.NavBar
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/** Some assertions will fail because of b/264415996 */
+@FlickerServiceCompatible
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class OpenAppColdFromIconCfArm(flicker: FlickerTest) : OpenAppColdFromIcon(flicker) {
+    @Test
+    @FlakyTest
+    override fun visibleLayersShownMoreThanOneConsecutiveEntry() {
+        super.visibleLayersShownMoreThanOneConsecutiveEntry()
+    }
+
+    companion object {
+        /**
+         * Creates the test configurations.
+         *
+         * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+         * navigation modes.
+         */
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun getParams(): Collection<FlickerTest> {
+            // TAPL fails on landscape mode b/240916028
+            return FlickerTestFactory.nonRotationTests(
+                supportedNavigationModes = listOf(NavBar.MODE_3BUTTON)
+            )
+        }
+    }
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraOnDoubleClickPowerButton.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraOnDoubleClickPowerButton.kt
index 6005a81..786bb32 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraOnDoubleClickPowerButton.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraOnDoubleClickPowerButton.kt
@@ -16,9 +16,10 @@
 
 package com.android.server.wm.flicker.launch
 
+import android.os.SystemClock
 import android.platform.test.annotations.Postsubmit
 import android.tools.device.apphelpers.CameraAppHelper
-import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.apphelpers.StandardAppHelper
 import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.device.flicker.legacy.FlickerBuilder
 import android.tools.device.flicker.legacy.FlickerTest
@@ -54,13 +55,14 @@
  * ```
  */
 @RequiresDevice
-@FlickerServiceCompatible
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class OpenCameraOnDoubleClickPowerButton(flicker: FlickerTest) :
     OpenAppFromLauncherTransition(flicker) {
     private val cameraApp = CameraAppHelper(instrumentation)
+    override val testApp: StandardAppHelper
+        get() = cameraApp
 
     override val transition: FlickerBuilder.() -> Unit
         get() = {
@@ -70,6 +72,7 @@
             }
             transitions {
                 device.pressKeyCode(KeyEvent.KEYCODE_POWER)
+                SystemClock.sleep(100)
                 device.pressKeyCode(KeyEvent.KEYCODE_POWER)
                 wmHelper.StateSyncBuilder().withWindowSurfaceAppeared(cameraApp).waitForAndVerify()
             }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt
index da98523..b848e63 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt
@@ -93,8 +93,7 @@
                 .then()
                 // Animation starts, but the app may not be drawn yet which means the Splash
                 // may be visible.
-                .isInvisible(testApp, isOptional = true)
-                .isVisible(ComponentNameMatcher.SPLASH_SCREEN, isOptional = true)
+                .isSplashScreenVisibleFor(testApp, isOptional = true)
                 .then()
                 // App shows up with the custom animation starting at alpha=1.
                 .isVisible(testApp)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
index 78cee3c..eadeef5 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
@@ -16,11 +16,11 @@
 
 package com.android.server.wm.flicker.quickswitch
 
+import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.Presubmit
 import android.tools.common.NavBar
 import android.tools.common.datatypes.Rect
 import android.tools.common.datatypes.component.ComponentNameMatcher
-import android.tools.device.flicker.isShellTransitionsEnabled
 import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.device.flicker.legacy.FlickerBuilder
 import android.tools.device.flicker.legacy.FlickerTest
@@ -29,9 +29,8 @@
 import com.android.server.wm.flicker.BaseTest
 import com.android.server.wm.flicker.helpers.NonResizeableAppHelper
 import com.android.server.wm.flicker.helpers.SimpleAppHelper
-import org.junit.Assume
-import org.junit.Before
 import org.junit.FixMethodOrder
+import org.junit.Ignore
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
@@ -57,11 +56,6 @@
     private val testApp1 = SimpleAppHelper(instrumentation)
     private val testApp2 = NonResizeableAppHelper(instrumentation)
 
-    @Before
-    open fun before() {
-        Assume.assumeFalse(isShellTransitionsEnabled)
-    }
-
     /** {@inheritDoc} */
     override val transition: FlickerBuilder.() -> Unit = {
         setup {
@@ -102,7 +96,7 @@
      * Checks that the transition starts with [testApp2]'s layers filling/covering exactly the
      * entirety of the display.
      */
-    @Presubmit
+    @FlakyTest(bugId = 250520840)
     @Test
     open fun startsWithApp2LayersCoverFullScreen() {
         flicker.assertLayersStart { this.visibleRegion(testApp2).coversExactly(startDisplayBounds) }
@@ -230,6 +224,20 @@
         }
     }
 
+    /** {@inheritDoc} */
+    @Ignore("Nav bar window becomes invisible during quick switch")
+    @Test
+    override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
+
+    @FlakyTest(bugId = 246284708)
+    @Test
+    override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        super.visibleLayersShownMoreThanOneConsecutiveEntry()
+
+    @FlakyTest(bugId = 250518877)
+    @Test
+    override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
+
     companion object {
         private var startDisplayBounds = Rect.EMPTY
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt
deleted file mode 100644
index 2b69e9b..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm.flicker.quickswitch
-
-import android.platform.test.annotations.FlakyTest
-import android.tools.device.flicker.isShellTransitionsEnabled
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
-import android.tools.device.flicker.legacy.FlickerTest
-import androidx.test.filters.RequiresDevice
-import org.junit.Assume
-import org.junit.Before
-import org.junit.FixMethodOrder
-import org.junit.Ignore
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test quick switching back to previous app from last opened app
- *
- * To run this test: `atest FlickerTests:QuickSwitchBetweenTwoAppsBackTest`
- *
- * Actions:
- * ```
- *     Launch an app [testApp1]
- *     Launch another app [testApp2]
- *     Swipe right from the bottom of the screen to quick switch back to the first app [testApp1]
- * ```
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class QuickSwitchBetweenTwoAppsBackTest_ShellTransit(flicker: FlickerTest) :
-    QuickSwitchBetweenTwoAppsBackTest(flicker) {
-    @Before
-    override fun before() {
-        Assume.assumeTrue(isShellTransitionsEnabled)
-    }
-
-    /** {@inheritDoc} */
-    @Ignore("Nav bar window becomes invisible during quick switch")
-    @Test
-    override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
-
-    /** {@inheritDoc} */
-    @FlakyTest(bugId = 250520840)
-    @Test
-    override fun startsWithApp2LayersCoverFullScreen() = super.startsWithApp2LayersCoverFullScreen()
-
-    @FlakyTest(bugId = 246284708)
-    @Test
-    override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
-        super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
-    @FlakyTest(bugId = 250518877)
-    @Test
-    override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
index cd7d6fa..1360495 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
@@ -16,11 +16,11 @@
 
 package com.android.server.wm.flicker.quickswitch
 
+import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.Presubmit
 import android.tools.common.NavBar
 import android.tools.common.datatypes.Rect
 import android.tools.common.datatypes.component.ComponentNameMatcher
-import android.tools.device.flicker.isShellTransitionsEnabled
 import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.device.flicker.legacy.FlickerBuilder
 import android.tools.device.flicker.legacy.FlickerTest
@@ -29,9 +29,8 @@
 import com.android.server.wm.flicker.BaseTest
 import com.android.server.wm.flicker.helpers.NonResizeableAppHelper
 import com.android.server.wm.flicker.helpers.SimpleAppHelper
-import org.junit.Assume
-import org.junit.Before
 import org.junit.FixMethodOrder
+import org.junit.Ignore
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
@@ -58,11 +57,6 @@
     private val testApp1 = SimpleAppHelper(instrumentation)
     private val testApp2 = NonResizeableAppHelper(instrumentation)
 
-    @Before
-    open fun before() {
-        Assume.assumeFalse(isShellTransitionsEnabled)
-    }
-
     /** {@inheritDoc} */
     override val transition: FlickerBuilder.() -> Unit = {
         setup {
@@ -113,7 +107,7 @@
      * Checks that the transition starts with [testApp1]'s layers filling/covering exactly the
      * entirety of the display.
      */
-    @Presubmit
+    @FlakyTest(bugId = 250522691)
     @Test
     open fun startsWithApp1LayersCoverFullScreen() {
         flicker.assertLayersStart { this.visibleRegion(testApp1).coversExactly(startDisplayBounds) }
@@ -248,6 +242,20 @@
     @Test
     override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
 
+    /** {@inheritDoc} */
+    @Ignore("Nav bar window becomes invisible during quick switch")
+    @Test
+    override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
+
+    @FlakyTest(bugId = 246284708)
+    @Test
+    override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
+        super.visibleLayersShownMoreThanOneConsecutiveEntry()
+
+    @FlakyTest(bugId = 250518877)
+    @Test
+    override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
+
     companion object {
         private var startDisplayBounds = Rect.EMPTY
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt
deleted file mode 100644
index b0d4e27..0000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm.flicker.quickswitch
-
-import android.platform.test.annotations.FlakyTest
-import android.tools.device.flicker.isShellTransitionsEnabled
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
-import android.tools.device.flicker.legacy.FlickerTest
-import androidx.test.filters.RequiresDevice
-import org.junit.Assume
-import org.junit.Before
-import org.junit.FixMethodOrder
-import org.junit.Ignore
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test quick switching back to previous app from last opened app
- *
- * To run this test: `atest FlickerTests:QuickSwitchBetweenTwoAppsForwardTest`
- *
- * Actions:
- * ```
- *     Launch an app [testApp1]
- *     Launch another app [testApp2]
- *     Swipe right from the bottom of the screen to quick switch back to the first app [testApp1]
- *     Swipe left from the bottom of the screen to quick switch forward to the second app [testApp2]
- * ```
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class QuickSwitchBetweenTwoAppsForwardTest_ShellTransit(flicker: FlickerTest) :
-    QuickSwitchBetweenTwoAppsForwardTest(flicker) {
-    @Before
-    override fun before() {
-        Assume.assumeTrue(isShellTransitionsEnabled)
-    }
-
-    /** {@inheritDoc} */
-    @Ignore("Nav bar window becomes invisible during quick switch")
-    @Test
-    override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
-
-    @FlakyTest(bugId = 246284708)
-    @Test
-    override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
-        super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
-    @FlakyTest(bugId = 250518877)
-    @Test
-    override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
-
-    @FlakyTest(bugId = 250522691)
-    @Test
-    override fun startsWithApp1LayersCoverFullScreen() = super.startsWithApp1LayersCoverFullScreen()
-}
diff --git a/tests/Input/src/com/android/test/input/MotionPredictorTest.kt b/tests/Input/src/com/android/test/input/MotionPredictorTest.kt
index 8b1b06f..24a5671 100644
--- a/tests/Input/src/com/android/test/input/MotionPredictorTest.kt
+++ b/tests/Input/src/com/android/test/input/MotionPredictorTest.kt
@@ -124,14 +124,12 @@
         predictor.record(moveEvent)
 
         val predicted = predictor.predict(Duration.ofMillis(8).toNanos())
-        assertEquals(1, predicted.size)
-        val event = predicted[0]
-        assertNotNull(event)
+        assertNotNull(predicted)
 
         // Prediction will happen for t=12 (since it is the next input interval after the requested
         // time, 8, plus the model offset, 1).
-        assertEquals(12, event.eventTime)
-        assertEquals(30f, event.x, /*delta=*/5f)
-        assertEquals(60f, event.y, /*delta=*/15f)
+        assertEquals(12, predicted!!.eventTime)
+        assertEquals(30f, predicted.x, /*delta=*/5f)
+        assertEquals(60f, predicted.y, /*delta=*/15f)
     }
 }
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/NotificationTest.java b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/NotificationTest.java
index 573b3b69..d2708ad 100644
--- a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/NotificationTest.java
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/NotificationTest.java
@@ -42,6 +42,7 @@
 import androidx.test.uiautomator.By;
 import androidx.test.uiautomator.BySelector;
 import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
 import androidx.test.uiautomator.Until;
 
 import org.junit.After;
@@ -74,7 +75,7 @@
 
     // This is for AOSP System UI for phones. When testing customized System UI, please modify here.
     private static final BySelector REPLY_SEND_BUTTON_SELECTOR =
-            By.res("com.android.systemui", "remote_input_send");
+            By.res("com.android.systemui", "remote_input_send").enabled(true);
 
     @Rule
     public UnlockScreenRule mUnlockScreenRule = new UnlockScreenRule();
@@ -119,7 +120,15 @@
         mUiDevice.pressKeyCode(KeyEvent.KEYCODE_A);
         mUiDevice.pressKeyCode(KeyEvent.KEYCODE_B);
         mUiDevice.pressKeyCode(KeyEvent.KEYCODE_C);
-        mUiDevice.wait(Until.findObject(REPLY_SEND_BUTTON_SELECTOR.enabled(true)), TIMEOUT).click();
+        UiObject2 sendButton = mUiDevice.wait(
+                Until.findObject(REPLY_SEND_BUTTON_SELECTOR), TIMEOUT);
+        if (sendButton == null) {
+            // If the screen is too small, sendButton may be hidden by IME.
+            // Dismiss IME and try again.
+            mUiDevice.pressBack();
+            sendButton = mUiDevice.wait(Until.findObject(REPLY_SEND_BUTTON_SELECTOR), TIMEOUT);
+        }
+        sendButton.click();
         // Verify that IME is gone.
         assertThat(mUiDevice.wait(Until.gone(By.pkg(getImePackage(mContext))), TIMEOUT)).isTrue();
     }
diff --git a/tests/Internal/src/com/android/internal/app/LocaleStoreTest.java b/tests/Internal/src/com/android/internal/app/LocaleStoreTest.java
index e704cc2..46ebfed 100644
--- a/tests/Internal/src/com/android/internal/app/LocaleStoreTest.java
+++ b/tests/Internal/src/com/android/internal/app/LocaleStoreTest.java
@@ -35,6 +35,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.IllformedLocaleException;
 import java.util.List;
 import java.util.Locale;
@@ -141,14 +142,118 @@
 
         HashMap<String, LocaleInfo> result =
                 LocaleStore.convertExplicitLocales(locales, supportedLocale);
-
         assertEquals("en", result.get("en").getId());
         assertEquals("en-US", result.get("en-US").getId());
         assertNull(result.get("en-Latn-US"));
     }
 
+    @Test
+    public void getLevelLocales_languageTier_returnAllSupportLanguages() {
+        LocaleList testSupportedLocales =
+                LocaleList.forLanguageTags(
+                        "en-US,zh-Hant-TW,ja-JP,en-GB,bn-IN-u-nu-arab,ks-Arab-IN,bn-IN");
+
+        Set<String> ignorableLocales = new HashSet<>();
+        ignorableLocales.add("zh-Hant-HK");
+        LocaleInfo parent = null;
+
+        Set<LocaleInfo> localeInfos = LocaleStore.getLevelLocales(
+                null, ignorableLocales, parent, false, testSupportedLocales);
+
+        assertEquals(5, localeInfos.size());
+        localeInfos.forEach(localeInfo -> {
+            assertTrue(localeInfo.getLocale().getCountry().isEmpty());
+        });
+        assertTrue(localeInfos.stream().anyMatch(
+                info -> info.getLocale().toLanguageTag().equals("en")));
+        assertTrue(localeInfos.stream().anyMatch(
+                info -> info.getLocale().toLanguageTag().equals("zh-Hant")));
+        assertTrue(localeInfos.stream().anyMatch(
+                info -> info.getLocale().toLanguageTag().equals("ja")));
+        assertTrue(localeInfos.stream().anyMatch(
+                info -> info.getLocale().toLanguageTag().equals("bn")));
+        assertTrue(localeInfos.stream().anyMatch(
+                info -> info.getLocale().toLanguageTag().equals("ks-Arab")));
+    }
+
+    @Test
+    public void getLevelLocales_regionTierAndParentIsEn_returnEnLocales() {
+        LocaleList testSupportedLocales =
+                LocaleList.forLanguageTags(
+                        "en-US,en-GB,bn-IN-u-nu-arab,ks-Arab-IN,en-ZA,bn-IN");
+        Set<String> ignorableLocales = new HashSet<>();
+        ignorableLocales.add("zh-Hant-HK");
+        LocaleInfo parent = LocaleStore.fromLocale(Locale.forLanguageTag("en"));
+
+        Set<LocaleInfo> localeInfos = LocaleStore.getLevelLocales(
+                null, ignorableLocales, parent, false, testSupportedLocales);
+
+        assertEquals(3, localeInfos.size());
+        localeInfos.forEach(localeInfo -> {
+            assertEquals("en", localeInfo.getLocale().getLanguage());
+        });
+        assertTrue(localeInfos.stream().anyMatch(
+                info -> info.getLocale().toLanguageTag().equals("en-US")));
+        assertTrue(localeInfos.stream().anyMatch(
+                info -> info.getLocale().toLanguageTag().equals("en-GB")));
+        assertTrue(localeInfos.stream().anyMatch(
+                info -> info.getLocale().toLanguageTag().equals("en-ZA")));
+    }
+
+    @Test
+    public void getLevelLocales_numberingTierAndParentIsBnIn_returnBnInLocales() {
+        LocaleList testSupportedLocales =
+                LocaleList.forLanguageTags(
+                        "en-US,zh-Hant-TW,bn-IN-u-nu-arab,ks-Arab-IN,en-ZA,bn-IN,bn-IN-u-nu-adlm");
+        Set<String> ignorableLocales = new HashSet<>();
+        ignorableLocales.add("zh-Hant-HK");
+        LocaleInfo parent = LocaleStore.fromLocale(Locale.forLanguageTag("bn"));
+
+        Set<LocaleInfo> localeInfos = LocaleStore.getLevelLocales(
+                null, ignorableLocales, parent, false, testSupportedLocales);
+
+        assertEquals(1, localeInfos.size());
+        assertEquals("bn-IN", localeInfos.iterator().next().getLocale().toLanguageTag());
+    }
+
+    @Test
+    public void getLevelLocales_regionTierAndParentIsBnInAndIgnoreBn_returnEmpty() {
+        LocaleList testSupportedLocales =
+                LocaleList.forLanguageTags(
+                        "en-US,zh-Hant-TW,bn-IN-u-nu-arab,ks-Arab-IN,en-ZA,bn-IN,bn-IN-u-nu-adlm");
+        Set<String> ignorableLocales = new HashSet<>();
+        ignorableLocales.add("bn-IN");
+        LocaleInfo parent = LocaleStore.fromLocale(Locale.forLanguageTag("bn-IN"));
+
+        Set<LocaleInfo> localeInfos = LocaleStore.getLevelLocales(
+                null, ignorableLocales, parent, false, testSupportedLocales);
+
+        assertEquals(0, localeInfos.size());
+    }
+
+    @Test
+    public void getLevelLocales_regionTierAndParentIsBnIn_returnBnLocaleFamily() {
+        LocaleList testSupportedLocales =
+                LocaleList.forLanguageTags(
+                        "en-US,zh-Hant-TW,bn-IN-u-nu-arab,ks-Arab-IN,en-ZA,bn-IN,bn-IN-u-nu-adlm");
+        Set<String> ignorableLocales = new HashSet<>();
+        ignorableLocales.add("en-US");
+        LocaleInfo parent = LocaleStore.fromLocale(Locale.forLanguageTag("bn-IN"));
+
+        Set<LocaleInfo> localeInfos = LocaleStore.getLevelLocales(
+                null, ignorableLocales, parent, false, testSupportedLocales);
+
+        assertEquals(3, localeInfos.size());
+        assertTrue(localeInfos.stream().anyMatch(
+                info -> info.getLocale().toLanguageTag().equals("bn-IN-u-nu-adlm")));
+        assertTrue(localeInfos.stream().anyMatch(
+                info -> info.getLocale().toLanguageTag().equals("bn-IN-u-nu-arab")));
+        assertTrue(localeInfos.stream().anyMatch(
+                info -> info.getLocale().toLanguageTag().equals("bn-IN")));
+    }
+
     private ArrayList<LocaleInfo> getFakeSupportedLocales() {
-        String[] locales = {"en-US", "zh-Hant-TW", "ja-JP", "en-GB"};
+        String[] locales = {"en-US", "zh-Hant-TW", "ja-JP", "en-GB", "en-US-u-nu-arab"};
         ArrayList<LocaleInfo> supportedLocales = new ArrayList<>();
         for (String localeTag : locales) {
             supportedLocales.add(LocaleStore.fromLocale(Locale.forLanguageTag(localeTag)));
diff --git a/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java b/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java
index 2cdb945..7deb8c7 100644
--- a/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java
+++ b/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java
@@ -86,7 +86,7 @@
         mFile = testContext.getFileStreamPath("tracing_test.dat");
         //noinspection ResultOfMethodCallIgnored
         mFile.delete();
-        mProtoLog = new ProtoLogImpl(mFile, 1024 * 1024, mReader);
+        mProtoLog = new ProtoLogImpl(mFile, 1024 * 1024, mReader, 1024);
     }
 
     @After
diff --git a/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
index c7e5a5e..e59071b 100644
--- a/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
+++ b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
@@ -29,6 +29,7 @@
 import android.content.pm.ResolveInfo;
 import android.os.Bundle;
 import android.os.Debug.MemoryInfo;
+import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.test.InstrumentationTestCase;
@@ -40,6 +41,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * This test is intended to measure the amount of memory applications use when
@@ -313,17 +315,19 @@
 
         public void run() {
             try {
-                String mimeType = mLaunchIntent.getType();
-                if (mimeType == null && mLaunchIntent.getData() != null
+                AtomicReference<String> mimeType = new AtomicReference<>(mLaunchIntent.getType());
+                if (mimeType.get() == null && mLaunchIntent.getData() != null
                         && "content".equals(mLaunchIntent.getData().getScheme())) {
-                    mimeType = mAm.getProviderMimeType(mLaunchIntent.getData(),
-                            UserHandle.USER_CURRENT);
+                    mAm.getMimeTypeFilterAsync(mLaunchIntent.getData(), UserHandle.USER_CURRENT,
+                            new RemoteCallback(result -> {
+                                mimeType.set(result.getPairValue());
+                            }));
                 }
 
                 mAtm.startActivityAndWait(null,
                         getInstrumentation().getContext().getBasePackageName(),
                         getInstrumentation().getContext().getAttributionTag(), mLaunchIntent,
-                        mimeType, null, null, 0, mLaunchIntent.getFlags(), null, null,
+                        mimeType.get(), null, null, 0, mLaunchIntent.getFlags(), null, null,
                         UserHandle.USER_CURRENT_OR_SELF);
             } catch (RemoteException e) {
                 Log.w(TAG, "Error launching app", e);
diff --git a/tests/MidiTests/Android.bp b/tests/MidiTests/Android.bp
new file mode 100644
index 0000000..254770d
--- /dev/null
+++ b/tests/MidiTests/Android.bp
@@ -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 {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+    name: "MidiTests",
+    srcs: ["**/*.java"],
+    static_libs: [
+        "androidx.test.rules",
+        "mockito-target-inline-minus-junit4",
+        "platform-test-annotations",
+        "services.midi",
+        "truth-prebuilt",
+    ],
+    jni_libs: ["libdexmakerjvmtiagent"],
+    certificate: "platform",
+    platform_apis: true,
+    test_suites: ["device-tests"],
+}
diff --git a/tests/MidiTests/AndroidManifest.xml b/tests/MidiTests/AndroidManifest.xml
new file mode 100644
index 0000000..0ee1b449
--- /dev/null
+++ b/tests/MidiTests/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.server.midi" >
+
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+    <uses-permission android:name="android.permission.MANAGE_USERS" />
+
+    <application android:debuggable="true">
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.server.midi"
+                     android:label="MidiTests"/>
+</manifest>
diff --git a/tests/MidiTests/AndroidTest.xml b/tests/MidiTests/AndroidTest.xml
new file mode 100644
index 0000000..9320f0a
--- /dev/null
+++ b/tests/MidiTests/AndroidTest.xml
@@ -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.
+-->
+<configuration description="Runs sample instrumentation test.">
+    <target_preparer class="com.android.tradefed.targetprep.TestFilePushSetup"/>
+    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+        <option name="test-file-name" value="MidiTests.apk"/>
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"/>
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"/>
+    <option name="test-suite-tag" value="apct"/>
+    <option name="test-tag" value="MidiTests"/>
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="com.android.server.midi"/>
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner"/>
+        <option name="hidden-api-checks" value="false"/>
+    </test>
+</configuration>
diff --git a/tests/MidiTests/OWNERS b/tests/MidiTests/OWNERS
new file mode 100644
index 0000000..af273a6
--- /dev/null
+++ b/tests/MidiTests/OWNERS
@@ -0,0 +1 @@
+include /services/midi/OWNERS
diff --git a/tests/MidiTests/TEST_MAPPING b/tests/MidiTests/TEST_MAPPING
new file mode 100644
index 0000000..60416a8
--- /dev/null
+++ b/tests/MidiTests/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "MidiTests"
+    }
+  ]
+}
diff --git a/tests/MidiTests/src/com/android/server/midi/MidiEventMultiSchedulerTest.java b/tests/MidiTests/src/com/android/server/midi/MidiEventMultiSchedulerTest.java
new file mode 100644
index 0000000..1659cc0
--- /dev/null
+++ b/tests/MidiTests/src/com/android/server/midi/MidiEventMultiSchedulerTest.java
@@ -0,0 +1,342 @@
+/*
+ * 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.midi;
+
+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.assertTrue;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.midi.MidiEventMultiScheduler;
+import com.android.internal.midi.MidiEventScheduler;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Random;
+
+/**
+ * Unit tests for com.android.internal.midi.MidiEventMultiScheduler.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class MidiEventMultiSchedulerTest {
+    private byte[] generateRandomByteStream(Random rnd, int size) {
+        byte[] output = new byte[size];
+        rnd.nextBytes(output);
+        return output;
+    }
+
+    private void compareByteArrays(byte[] expectedArray, byte[] outputArray) {
+        assertEquals(expectedArray.length, outputArray.length);
+        for (int i = 0; i < outputArray.length; i++) {
+            assertEquals(expectedArray[i], outputArray[i]);
+        }
+    }
+
+    private long timeFromNow(long milliseconds) {
+        return System.nanoTime() + 1000000L * milliseconds;
+    }
+
+    @Test
+    public void testMultiScheduler() {
+        try {
+            MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(3);
+            assertEquals(3, multiScheduler.getNumEventSchedulers());
+            MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+            MidiEventScheduler scheduler1 = multiScheduler.getEventScheduler(1);
+            MidiEventScheduler scheduler2 = multiScheduler.getEventScheduler(2);
+
+            scheduler0.add(scheduler0.createScheduledEvent(new byte[]{(byte) 0xf0, (byte) 0xf7},
+                    0, 2, timeFromNow(100)));
+            scheduler1.add(scheduler1.createScheduledEvent(new byte[]{(byte) 0xf1, (byte) 0xf2},
+                    0, 2, timeFromNow(200)));
+            scheduler2.add(scheduler2.createScheduledEvent(new byte[]{(byte) 0xf3, (byte) 0xf4},
+                    0, 2, timeFromNow(300)));
+            scheduler0.add(scheduler0.createScheduledEvent(new byte[]{(byte) 0xf5, (byte) 0xf6},
+                    0, 2, timeFromNow(400)));
+            assertTrue(multiScheduler.waitNextEvent());
+            assertNotNull(scheduler0.getNextEvent(System.nanoTime()));
+            assertNull(scheduler1.getNextEvent(System.nanoTime()));
+            assertNull(scheduler2.getNextEvent(System.nanoTime()));
+            assertTrue(multiScheduler.waitNextEvent());
+            assertNull(scheduler0.getNextEvent(System.nanoTime()));
+            assertNotNull(scheduler1.getNextEvent(System.nanoTime()));
+            assertNull(scheduler2.getNextEvent(System.nanoTime()));
+            assertTrue(multiScheduler.waitNextEvent());
+            assertNull(scheduler0.getNextEvent(System.nanoTime()));
+            assertNull(scheduler1.getNextEvent(System.nanoTime()));
+            assertNotNull(scheduler2.getNextEvent(System.nanoTime()));
+            assertTrue(multiScheduler.waitNextEvent());
+            assertNotNull(scheduler0.getNextEvent(System.nanoTime()));
+            assertNull(scheduler1.getNextEvent(System.nanoTime()));
+            assertNull(scheduler2.getNextEvent(System.nanoTime()));
+        } catch (InterruptedException ex) {
+
+        }
+    }
+
+    @Test
+    public void testSchedulerLargeData() {
+        try {
+            MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(1);
+            assertEquals(1, multiScheduler.getNumEventSchedulers());
+            MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+
+            Random rnd = new Random(42);
+
+            final int arraySize = 1000;
+            byte[] expectedArray = generateRandomByteStream(rnd, arraySize);
+
+            scheduler0.add(scheduler0.createScheduledEvent(expectedArray, 0, arraySize,
+                    timeFromNow(100)));
+            assertTrue(multiScheduler.waitNextEvent());
+            MidiEventScheduler.MidiEvent event =
+                    (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+            assertNotNull(event);
+            compareByteArrays(expectedArray, event.data);
+        } catch (InterruptedException ex) {
+
+        }
+    }
+
+    @Test
+    public void testSchedulerClose() {
+        try {
+            MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(1);
+            assertEquals(1, multiScheduler.getNumEventSchedulers());
+            MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+            scheduler0.close();
+            // After all schedulers are closed, waitNextEvent() should return false.
+            assertFalse(multiScheduler.waitNextEvent());
+        } catch (InterruptedException ex) {
+
+        }
+    }
+
+    @Test
+    public void testSchedulerMultiClose() {
+        try {
+            MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(3);
+            assertEquals(3, multiScheduler.getNumEventSchedulers());
+            multiScheduler.close();
+            // After all schedulers are closed, waitNextEvent() should return false.
+            assertFalse(multiScheduler.waitNextEvent());
+        } catch (InterruptedException ex) {
+
+        }
+    }
+
+    @Test
+    public void testSchedulerNoPreemptiveClose() {
+        try {
+            MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(3);
+            assertEquals(3, multiScheduler.getNumEventSchedulers());
+            MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+            MidiEventScheduler scheduler1 = multiScheduler.getEventScheduler(1);
+            MidiEventScheduler scheduler2 = multiScheduler.getEventScheduler(2);
+            scheduler0.close();
+            scheduler1.close();
+            scheduler2.add(scheduler2.createScheduledEvent(new byte[]{(byte) 0xf5, (byte) 0xf6},
+                    0, 2, timeFromNow(100)));
+            assertTrue(multiScheduler.waitNextEvent());
+            scheduler2.close();
+            // After all schedulers are closed, waitNextEvent() should return false.
+            assertFalse(multiScheduler.waitNextEvent());
+        } catch (InterruptedException ex) {
+
+        }
+    }
+
+    @Test
+    public void testSchedulerSpamEvents() {
+        MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(1);
+        assertEquals(1, multiScheduler.getNumEventSchedulers());
+        MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+        // Create a msg with size 1
+        byte[] msg = new byte[1];
+        for (int i = 0; i < 1000; i++) {
+            msg[0] = (byte) i;
+            scheduler0.add(scheduler0.createScheduledEvent(msg, 0, 1, timeFromNow(0)));
+            MidiEventScheduler.MidiEvent event =
+                    (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+            assertNotNull(event);
+            assertEquals(1, event.count);
+            assertEquals(msg[0], event.data[0]);
+        }
+        assertNull(scheduler0.getNextEvent(System.nanoTime()));
+    }
+
+    @Test
+    public void testSchedulerSpamEventsPullLater() {
+        MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(1);
+        assertEquals(1, multiScheduler.getNumEventSchedulers());
+        MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+        // Create a msg with size 1
+        byte[] msg = new byte[1];
+        for (int i = 0; i < 1000; i++) {
+            msg[0] = (byte) i;
+            scheduler0.add(scheduler0.createScheduledEvent(msg, 0, 1, timeFromNow(0)));
+        }
+
+        for (int i = 0; i < 1000; i++) {
+            MidiEventScheduler.MidiEvent event =
+                    (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+            assertNotNull(event);
+            assertEquals(1, event.count);
+            assertEquals((byte) i, event.data[0]);
+        }
+        assertNull(scheduler0.getNextEvent(System.nanoTime()));
+    }
+
+    @Test
+    public void testSchedulerSpamEventsCallbackLater() {
+        MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(1);
+        assertEquals(1, multiScheduler.getNumEventSchedulers());
+        MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+        // Create a msg with size 1
+        byte[] msg = new byte[1];
+        for (int i = 0; i < 1000; i++) {
+            msg[0] = (byte) i;
+            scheduler0.add(scheduler0.createScheduledEvent(msg, 0, 1, timeFromNow(0)));
+        }
+
+        for (int i = 0; i < 1000; i++) {
+            try {
+                assertTrue(multiScheduler.waitNextEvent());
+            } catch (InterruptedException ex) {
+            }
+            MidiEventScheduler.MidiEvent event =
+                    (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+            assertNotNull(event);
+            assertEquals(1, event.count);
+            assertEquals((byte) i, event.data[0]);
+        }
+        assertNull(scheduler0.getNextEvent(System.nanoTime()));
+    }
+
+    @Test
+    public void testMultiSchedulerOutOfOrder() {
+        try {
+            MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(3);
+            assertEquals(3, multiScheduler.getNumEventSchedulers());
+            MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+            MidiEventScheduler scheduler1 = multiScheduler.getEventScheduler(1);
+            MidiEventScheduler scheduler2 = multiScheduler.getEventScheduler(2);
+
+            scheduler0.add(scheduler0.createScheduledEvent(new byte[]{(byte) 0xf3},
+                    0, 1,
+                    timeFromNow(400)));
+            scheduler2.add(scheduler2.createScheduledEvent(new byte[]{(byte) 0xf2},
+                    0, 1,
+                    timeFromNow(300)));
+            scheduler1.add(scheduler1.createScheduledEvent(new byte[]{(byte) 0xf1},
+                    0, 1,
+                    timeFromNow(200)));
+            scheduler0.add(scheduler0.createScheduledEvent(new byte[]{(byte) 0xf0},
+                    0, 1,
+                    timeFromNow(100)));
+
+            assertTrue(multiScheduler.waitNextEvent());
+            MidiEventScheduler.MidiEvent event =
+                    (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+            assertNotNull(event);
+            assertEquals(1, event.count);
+            assertEquals((byte) 0xf0, event.data[0]);
+            assertNull(scheduler1.getNextEvent(System.nanoTime()));
+            assertNull(scheduler2.getNextEvent(System.nanoTime()));
+            assertTrue(multiScheduler.waitNextEvent());
+            assertNull(scheduler0.getNextEvent(System.nanoTime()));
+            event = (MidiEventScheduler.MidiEvent) scheduler1.getNextEvent(System.nanoTime());
+            assertNotNull(event);
+            assertEquals(1, event.count);
+            assertEquals((byte) 0xf1, event.data[0]);
+            assertNull(scheduler2.getNextEvent(System.nanoTime()));
+            assertTrue(multiScheduler.waitNextEvent());
+            assertNull(scheduler0.getNextEvent(System.nanoTime()));
+            assertNull(scheduler1.getNextEvent(System.nanoTime()));
+            event = (MidiEventScheduler.MidiEvent) scheduler2.getNextEvent(System.nanoTime());
+            assertNotNull(event);
+            assertEquals(1, event.count);
+            assertEquals((byte) 0xf2, event.data[0]);
+            assertTrue(multiScheduler.waitNextEvent());
+            event = (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+            assertNotNull(event);
+            assertEquals(1, event.count);
+            assertEquals((byte) 0xf3, event.data[0]);
+            assertNull(scheduler1.getNextEvent(System.nanoTime()));
+            assertNull(scheduler2.getNextEvent(System.nanoTime()));
+        } catch (InterruptedException ex) {
+
+        }
+    }
+
+    @Test
+    public void testMultiSchedulerOutOfOrderNegativeTime() {
+        try {
+            MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(3);
+            assertEquals(3, multiScheduler.getNumEventSchedulers());
+            MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+            MidiEventScheduler scheduler1 = multiScheduler.getEventScheduler(1);
+            MidiEventScheduler scheduler2 = multiScheduler.getEventScheduler(2);
+
+            scheduler0.add(scheduler0.createScheduledEvent(new byte[]{(byte) 0xf3},
+                    0, 1,
+                    timeFromNow(-100)));
+            scheduler2.add(scheduler2.createScheduledEvent(new byte[]{(byte) 0xf2},
+                    0, 1,
+                    timeFromNow(-200)));
+            scheduler1.add(scheduler1.createScheduledEvent(new byte[]{(byte) 0xf1},
+                    0, 1,
+                    timeFromNow(-300)));
+            scheduler0.add(scheduler0.createScheduledEvent(new byte[]{(byte) 0xf0},
+                    0, 1,
+                    timeFromNow(-400)));
+
+            assertTrue(multiScheduler.waitNextEvent());
+            MidiEventScheduler.MidiEvent event =
+                    (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+            assertNotNull(event);
+            assertEquals(1, event.count);
+            assertEquals((byte) 0xf0, event.data[0]);
+            assertTrue(multiScheduler.waitNextEvent());
+            event = (MidiEventScheduler.MidiEvent) scheduler1.getNextEvent(System.nanoTime());
+            assertNotNull(event);
+            assertEquals(1, event.count);
+            assertEquals((byte) 0xf1, event.data[0]);
+            assertTrue(multiScheduler.waitNextEvent());
+            event = (MidiEventScheduler.MidiEvent) scheduler2.getNextEvent(System.nanoTime());
+            assertNotNull(event);
+            assertEquals(1, event.count);
+            assertEquals((byte) 0xf2, event.data[0]);
+            assertNull(scheduler1.getNextEvent(System.nanoTime()));
+            assertTrue(multiScheduler.waitNextEvent());
+            event = (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+            assertNotNull(event);
+            assertEquals(1, event.count);
+            assertEquals((byte) 0xf3, event.data[0]);
+            assertNull(scheduler1.getNextEvent(System.nanoTime()));
+            assertNull(scheduler2.getNextEvent(System.nanoTime()));
+        } catch (InterruptedException ex) {
+
+        }
+    }
+}
diff --git a/tests/MotionPrediction/src/test/motionprediction/DrawingView.kt b/tests/MotionPrediction/src/test/motionprediction/DrawingView.kt
index f529bf7..229d0c8 100644
--- a/tests/MotionPrediction/src/test/motionprediction/DrawingView.kt
+++ b/tests/MotionPrediction/src/test/motionprediction/DrawingView.kt
@@ -97,8 +97,8 @@
         }
 
         // Draw predictions. Convert to nanos and hardcode to +20ms into the future
-        val predictionList = predictor.predict(eventTime * 1000000 + 20000000)
-        for (prediction in predictionList) {
+        val prediction = predictor.predict(eventTime * 1000000 + 20000000)
+        if (prediction != null) {
             val realEvents = events.get(prediction.deviceId)!!
             drawLine(canvas, realEvents[realEvents.size - 1], prediction, predictionPaint)
         }
diff --git a/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapImage.kt b/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapImage.kt
index 3875644..e079b6d 100644
--- a/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapImage.kt
+++ b/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapImage.kt
@@ -80,10 +80,10 @@
         spinner.adapter = adapter
         spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
             override fun onItemSelected(
-                parent: AdapterView<*>?,
-                view: View?,
-                position: Int,
-                id: Long
+                    parent: AdapterView<*>?,
+                    view: View?,
+                    position: Int,
+                    id: Long
             ) {
                 setImage(position)
             }
@@ -108,7 +108,7 @@
         if (selectedImage == position) return
         selectedImage = position
         val source = ImageDecoder.createSource(resources.assets,
-            "gainmaps/${gainmapImages[position]}")
+                "gainmaps/${gainmapImages[position]}")
         doDecode(source)
     }
 
@@ -137,16 +137,16 @@
                 gainmapVisualizer = map
             } else {
                 gainmapVisualizer = Bitmap.createBitmap(map.width, map.height,
-                    Bitmap.Config.ARGB_8888)
+                        Bitmap.Config.ARGB_8888)
                 val canvas = Canvas(gainmapVisualizer!!)
                 val paint = Paint()
                 paint.colorFilter = ColorMatrixColorFilter(
-                    floatArrayOf(
-                        0f, 0f, 0f, 1f, 0f,
-                        0f, 0f, 0f, 1f, 0f,
-                        0f, 0f, 0f, 1f, 0f,
-                        0f, 0f, 0f, 0f, 255f
-                    )
+                        floatArrayOf(
+                                0f, 0f, 0f, 1f, 0f,
+                                0f, 0f, 0f, 1f, 0f,
+                                0f, 0f, 0f, 1f, 0f,
+                                0f, 0f, 0f, 0f, 255f
+                        )
                 )
                 canvas.drawBitmap(map, 0f, 0f, paint)
                 canvas.setBitmap(null)
@@ -174,8 +174,14 @@
         if (bitmap == null) return
 
         imageView.setImage(ImageSource.cachedBitmap(when (outputMode) {
-            R.id.output_hdr -> { bitmap!!.gainmap = gainmap; bitmap!! }
-            R.id.output_sdr -> { bitmap!!.gainmap = null; bitmap!! }
+            R.id.output_hdr -> {
+                bitmap!!.gainmap = gainmap; bitmap!!
+            }
+
+            R.id.output_sdr -> {
+                bitmap!!.gainmap = null; bitmap!!
+            }
+
             R.id.output_gainmap -> gainmapVisualizer!!
             else -> throw IllegalStateException()
         }))
diff --git a/tests/UsbTests/src/com/android/server/usb/UsbMidiPacketConverterTest.java b/tests/UsbTests/src/com/android/server/usb/UsbMidiPacketConverterTest.java
new file mode 100644
index 0000000..ad701e5
--- /dev/null
+++ b/tests/UsbTests/src/com/android/server/usb/UsbMidiPacketConverterTest.java
@@ -0,0 +1,407 @@
+/*
+ * 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.usb;
+
+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;
+
+import java.util.Arrays;
+import java.util.Random;
+
+/**
+ * Unit tests for com.android.server.usb.UsbMidiPacketConverter.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class UsbMidiPacketConverterTest {
+    private byte[] generateRandomByteStream(Random rnd, int size) {
+        byte[] output = new byte[size];
+        rnd.nextBytes(output);
+        return output;
+    }
+
+    private void compareByteArrays(byte[] expectedArray, byte[] outputArray) {
+        assertEquals(expectedArray.length, outputArray.length);
+        for (int i = 0; i < outputArray.length; i++) {
+            assertEquals(expectedArray[i], outputArray[i]);
+        }
+    }
+
+    @Test
+    public void testDecoderSinglePacket() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createDecoders(2);
+        byte[] input = new byte[] {0x19 /* Cable 1 Note-On */, (byte) 0x91, 0x33, 0x66};
+        byte[] expectedOutputCable0 = new byte[] {};
+        byte[] expectedOutputCable1 = new byte[] {(byte) 0x91, 0x33, 0x66};
+        usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+        byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+        byte[] actualOutputCable1 = usbMidiPacketConverter.pullDecodedMidiPackets(1);
+        compareByteArrays(expectedOutputCable0, actualOutputCable0);
+        compareByteArrays(expectedOutputCable1, actualOutputCable1);
+    }
+
+    @Test
+    public void testDecoderMultiplePackets() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createDecoders(4);
+        byte[] input = new byte[] {
+                0x1B /* Cable 1 Control Change */, (byte) 0xB4, 0x55, 0x6E,
+                0x35 /* Cable 3 Single byte SysEx */, (byte) 0xF8, 0x00, 0x00,
+                0x02 /* Cable 0 Two byte System Common */, (byte) 0xF3, 0x12, 0x00};
+        byte[] expectedOutputCable0 = new byte[] {(byte) 0xF3, 0x12};
+        byte[] expectedOutputCable1 = new byte[] {(byte) 0xB4, 0x55, 0x6E};
+        byte[] expectedOutputCable2 = new byte[] {};
+        byte[] expectedOutputCable3 = new byte[] {(byte) 0xF8};
+        usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+        byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+        byte[] actualOutputCable1 = usbMidiPacketConverter.pullDecodedMidiPackets(1);
+        byte[] actualOutputCable2 = usbMidiPacketConverter.pullDecodedMidiPackets(2);
+        byte[] actualOutputCable3 = usbMidiPacketConverter.pullDecodedMidiPackets(3);
+        compareByteArrays(expectedOutputCable0, actualOutputCable0);
+        compareByteArrays(expectedOutputCable1, actualOutputCable1);
+        compareByteArrays(expectedOutputCable2, actualOutputCable2);
+        compareByteArrays(expectedOutputCable3, actualOutputCable3);
+    }
+
+    @Test
+    public void testDecoderSysExEndFirstByte() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createDecoders(2);
+        byte[] input = new byte[] {
+                0x14 /* Cable 1 SysEx Start */, (byte) 0xF0, 0x00, 0x01,
+                0x15 /* Cable 1 Single byte SysEx End */, (byte) 0xF7, 0x00, 0x00};
+        byte[] expectedOutputCable0 = new byte[] {};
+        byte[] expectedOutputCable1 = new byte[] {
+                (byte) 0xF0, 0x00, 0x01,
+                (byte) 0xF7};
+        usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+        byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+        byte[] actualOutputCable1 = usbMidiPacketConverter.pullDecodedMidiPackets(1);
+        compareByteArrays(expectedOutputCable0, actualOutputCable0);
+        compareByteArrays(expectedOutputCable1, actualOutputCable1);
+    }
+
+    @Test
+    public void testDecoderSysExEndSecondByte() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createDecoders(1);
+        byte[] input = new byte[] {
+                0x04 /* Cable 0 SysEx Start */, (byte) 0xF0, 0x00, 0x01,
+                0x06 /* Cable 0 Two byte SysEx End */, 0x02, (byte) 0xF7, 0x00};
+        byte[] expectedOutputCable0 = new byte[] {
+                (byte) 0xF0, 0x00, 0x01,
+                0x02, (byte) 0xF7};
+        usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+        byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+        compareByteArrays(expectedOutputCable0, actualOutputCable0);
+    }
+
+    @Test
+    public void testDecoderSysExEndThirdByte() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        byte[] input = new byte[] {
+                0x04 /* Cable 0 SysEx Start */, (byte) 0xF0, 0x00, 0x01,
+                0x07 /* Cable 0 Three byte SysEx End */, 0x02, 0x03, (byte) 0xF7};
+        usbMidiPacketConverter.createDecoders(1);
+        byte[] expectedOutputCable0 = new byte[] {
+                (byte) 0xF0, 0x00, 0x01,
+                0x02, 0x03, (byte) 0xF7};
+        usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+        byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+        compareByteArrays(expectedOutputCable0, actualOutputCable0);
+    }
+
+    @Test
+    public void testDecoderSysExStartEnd() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        byte[] input = new byte[] {
+                0x06 /* Cable 0 Two byte SysEx End */, (byte) 0xF0, (byte) 0xF7, 0x00};
+        usbMidiPacketConverter.createDecoders(1);
+        byte[] expectedOutputCable0 = new byte[] {
+                (byte) 0xF0, (byte) 0xF7};
+        usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+        byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+        compareByteArrays(expectedOutputCable0, actualOutputCable0);
+    }
+
+    @Test
+    public void testDecoderSysExStartByteEnd() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        byte[] input = new byte[] {
+                0x07 /* Cable 0 Three byte SysEx End */, (byte) 0xF0, 0x44, (byte) 0xF7};
+        usbMidiPacketConverter.createDecoders(1);
+        byte[] expectedOutputCable0 = new byte[] {
+                (byte) 0xF0, 0x44, (byte) 0xF7};
+        usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+        byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+        compareByteArrays(expectedOutputCable0, actualOutputCable0);
+    }
+
+    @Test
+    public void testDecoderDefaultToFirstCable() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        byte[] input = new byte[] {0x49 /* Cable 4 Note-On */, (byte) 0x91, 0x22, 0x33};
+        usbMidiPacketConverter.createDecoders(1);
+        byte[] expectedOutputCable0 = new byte[] {
+                (byte) 0x91, 0x22, 0x33};
+        usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+        byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+        compareByteArrays(expectedOutputCable0, actualOutputCable0);
+    }
+
+    @Test
+    public void testDecoderLargePacketDoesNotCrash() {
+        for (long seed = 1001; seed < 5000; seed += 777) {
+            UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+            usbMidiPacketConverter.createDecoders(3);
+            Random rnd = new Random(seed);
+            byte[] input = generateRandomByteStream(rnd, 1003 /* arbitrary large size */);
+            usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+            usbMidiPacketConverter.pullDecodedMidiPackets(0);
+            usbMidiPacketConverter.pullDecodedMidiPackets(1);
+            usbMidiPacketConverter.pullDecodedMidiPackets(2);
+        }
+    }
+
+    @Test
+    public void testEncoderBasic() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createEncoders(1);
+        byte[] input = new byte[] {(byte) 0x91 /* Note-On */, 0x33, 0x66};
+        byte[] expectedOutput = new byte[] {
+                0x09 /* Cable 0 Note-On */, (byte) 0x91, 0x33, 0x66};
+        usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+        byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+        compareByteArrays(expectedOutput, output);
+    }
+
+    @Test
+    public void testEncoderMultiplePackets() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createEncoders(3);
+        byte[] inputCable2 = new byte[] {
+                (byte) 0xB4 /* Control Change */, 0x55, 0x6E};
+        byte[] inputCable1 = new byte[] {
+                (byte) 0xF8 /* Timing Clock (Single Byte) */,
+                (byte) 0xF3 /* Song Select (Two Bytes) */, 0x12};
+        byte[] expectedOutput = new byte[] {
+            0x2B /* Cable 2 Control Change */, (byte) 0xB4, 0x55, 0x6E,
+            0x15 /* Cable 1 Timing Clock */, (byte) 0xF8, 0x00, 0x00,
+            0x12 /* Cable 1 Two Byte System Common */, (byte) 0xF3, 0x12, 0x00};
+        usbMidiPacketConverter.encodeMidiPackets(inputCable2, inputCable2.length, 2);
+        usbMidiPacketConverter.encodeMidiPackets(inputCable1, inputCable1.length, 1);
+        byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+        compareByteArrays(expectedOutput, output);
+    }
+
+    @Test
+    public void testEncoderWeavePackets() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createEncoders(2);
+        byte[] inputCable1Msg1 = new byte[] {
+                (byte) 0x93 /* Note-On */, 0x23, 0x43};
+        byte[] inputCable0Msg = new byte[] {
+                (byte) 0xB4 /* Control Change */, 0x65, 0x26};
+        byte[] inputCable1Msg2 = new byte[] {
+                (byte) 0xA4 /* Poly-KeyPress */, 0x52, 0x76};
+        byte[] expectedOutput = new byte[] {
+                0x19 /* Cable 1 Note-On */, (byte) 0x93, 0x23, 0x43,
+                0x0B /* Cable 0 Control Change */, (byte) 0xB4, 0x65, 0x26,
+                0x1A /* Cable 1 Poly-KeyPress */, (byte) 0xA4, 0x52, 0x76};
+        usbMidiPacketConverter.encodeMidiPackets(inputCable1Msg1, inputCable1Msg1.length, 1);
+        usbMidiPacketConverter.encodeMidiPackets(inputCable0Msg, inputCable0Msg.length, 0);
+        usbMidiPacketConverter.encodeMidiPackets(inputCable1Msg2, inputCable1Msg2.length, 1);
+        byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+        compareByteArrays(expectedOutput, output);
+    }
+
+    @Test
+    public void testEncoderSysExEndFirstByte() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createEncoders(1);
+        byte[] input = new byte[] {
+                (byte) 0xF0 /* SysEx Start */, 0x00, 0x01,
+                (byte) 0xF7 /* SysEx End */};
+        byte[] expectedOutput = new byte[] {
+                0x04 /* Cable 0 Three Byte SysEx Start */, (byte) 0xF0, 0x00, 0x01,
+                0x05 /* Cable 0 One Byte SysEx End */, (byte) 0xF7, 0x00, 0x00};
+        usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+        byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+        compareByteArrays(expectedOutput, output);
+    }
+
+    @Test
+    public void testEncoderSysExEndSecondByte() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createEncoders(1);
+        byte[] input = new byte[] {
+                (byte) 0xF0 /* SysEx Start */, 0x00, 0x01,
+                0x02, (byte) 0xF7 /* SysEx End */};
+        byte[] expectedOutput = new byte[] {
+                0x04 /* Cable 0 Three Byte SysEx Start */, (byte) 0xF0, 0x00, 0x01,
+                0x06 /* Cable 0 Two Byte SysEx End */, 0x02, (byte) 0xF7, 0x00};
+        usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+        byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+        compareByteArrays(expectedOutput, output);
+    }
+
+    @Test
+    public void testEncoderSysExEndThirdByte() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createEncoders(1);
+        byte[] input = new byte[] {
+                (byte) 0xF0 /* SysEx Start */, 0x00, 0x01,
+                0x02, 0x03, (byte) 0xF7 /* SysEx End */};
+        byte[] expectedOutput = new byte[] {
+                0x04 /* Cable 0 Three Byte SysEx Start */, (byte) 0xF0, 0x00, 0x01,
+                0x07 /* Cable 0 Three Byte SysEx End */, 0x02, 0x03, (byte) 0xF7};
+        usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+        byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+        compareByteArrays(expectedOutput, output);
+    }
+
+    @Test
+    public void testEncoderSysExStartEnd() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createEncoders(1);
+        byte[] input = new byte[] {
+                (byte) 0xF0 /* SysEx Start */, (byte) 0xF7 /* SysEx End */};
+        byte[] expectedOutput = new byte[] {
+                0x06 /* Cable 0 Two Byte SysEx End */, (byte) 0xF0, (byte) 0xF7, 0x00};
+        usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+        byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+        compareByteArrays(expectedOutput, output);
+    }
+
+    @Test
+    public void testEncoderSysExStartByteEnd() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createEncoders(1);
+        byte[] input = new byte[] {
+                (byte) 0xF0 /* SysEx Start */, 0x44, (byte) 0xF7 /* SysEx End */};
+        byte[] expectedOutput = new byte[] {
+                0x07 /* Cable 0 Three Byte SysEx End */, (byte) 0xF0, 0x44, (byte) 0xF7};
+        usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+        byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+        compareByteArrays(expectedOutput, output);
+    }
+
+    @Test
+    public void testEncoderMultiplePulls() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createEncoders(1);
+
+        byte[] input = new byte[] {
+                (byte) 0xF0 /* SysEx Start */, 0x44, 0x55,
+                0x66, 0x77}; // 0x66 and 0x77 will not be pulled the first time
+        byte[] expectedOutput = new byte[] {
+                0x04 /* SysEx Start */, (byte) 0xF0, 0x44, 0x55};
+        usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+        byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+        compareByteArrays(expectedOutput, output);
+
+        input = new byte[] {
+                0x11, // Combined with 0x66 and 0x77 above
+                0x22, (byte) 0xF7 /* SysEx End */};
+        expectedOutput = new byte[] {
+                0x04 /* Cable 0 SysEx Continue */, 0x66, 0x77, 0x11,
+                0x06 /* Cable 0 Two Byte SysEx End */, 0x22, (byte) 0xF7, 0x00};
+        usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+        output = usbMidiPacketConverter.pullEncodedMidiPackets();
+        compareByteArrays(expectedOutput, output);
+
+        input = new byte[] {
+                (byte) 0xF0 /* SysEx Start */, (byte) 0xF7 /* SysEx End */};
+        expectedOutput = new byte[] {
+                0x06 /* Cable 0 Two Byte SysEx End */, (byte) 0xF0, (byte) 0xF7, 0x00};
+        usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+        output = usbMidiPacketConverter.pullEncodedMidiPackets();
+        compareByteArrays(expectedOutput, output);
+    }
+
+    @Test
+    public void testEncoderDefaultToFirstCable() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createEncoders(2);
+        byte[] input = new byte[] {(byte) 0x91 /* Note-On */, 0x22, 0x33};
+        byte[] expectedOutput = new byte[] {
+                0x09 /* Cable 0 Note-On */, (byte) 0x91, 0x22, 0x33};
+        usbMidiPacketConverter.encodeMidiPackets(input, input.length, 4);
+        byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+        compareByteArrays(expectedOutput, output);
+    }
+
+    @Test
+    public void testEncoderLargePacketDoesNotCrash() {
+        for (long seed = 234; seed < 4000; seed += 666) {
+            Random rnd = new Random(seed);
+            UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+            usbMidiPacketConverter.createEncoders(4);
+            for (int cableNumber = 0; cableNumber < 4; cableNumber++) {
+                byte[] input = generateRandomByteStream(rnd, 1003 /* arbitrary large size */);
+                usbMidiPacketConverter.encodeMidiPackets(input, input.length, cableNumber);
+            }
+            usbMidiPacketConverter.pullEncodedMidiPackets();
+        }
+    }
+
+    @Test
+    public void testEncodeDecode() {
+        final int bufferSize = 30;
+        final int numCables = 16;
+        final int bytesToEncodePerEncoding = 10;
+        byte[][] rawMidi = new byte[numCables][bufferSize];
+        for (long seed = 45; seed < 3000; seed += 300) {
+            Random rnd = new Random(seed);
+            for (int cableNumber = 0; cableNumber < numCables; cableNumber++) {
+                rawMidi[cableNumber] =  generateRandomByteStream(rnd, bufferSize);
+
+                // Change the last byte to SysEx End.
+                // This way the encoder is guaranteed to flush all packets.
+                rawMidi[cableNumber][bufferSize - 1] = (byte) 0xF7;
+            }
+            UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+            usbMidiPacketConverter.createEncoders(numCables);
+            // Encode packets and interweave them
+            for (int startByte = 0; startByte < bufferSize;
+                    startByte += bytesToEncodePerEncoding) {
+                for (int cableNumber = 0; cableNumber < numCables; cableNumber++) {
+                    byte[] bytesToEncode = Arrays.copyOfRange(rawMidi[cableNumber], startByte,
+                            startByte + bytesToEncodePerEncoding);
+                    usbMidiPacketConverter.encodeMidiPackets(bytesToEncode, bytesToEncode.length,
+                            cableNumber);
+                }
+            }
+            byte[] usbMidi = usbMidiPacketConverter.pullEncodedMidiPackets();
+
+            usbMidiPacketConverter.createDecoders(numCables);
+
+            // Now decode the MIDI packets to check if they are the same as the original
+            usbMidiPacketConverter.decodeMidiPackets(usbMidi, usbMidi.length);
+            for (int cableNumber = 0; cableNumber < numCables; cableNumber++) {
+                byte[] decodedRawMidi = usbMidiPacketConverter.pullDecodedMidiPackets(cableNumber);
+                compareByteArrays(rawMidi[cableNumber], decodedRawMidi);
+            }
+        }
+    }
+}
diff --git a/tests/testables/src/android/testing/TestableContext.java b/tests/testables/src/android/testing/TestableContext.java
index e2668bc..0f04d6a 100644
--- a/tests/testables/src/android/testing/TestableContext.java
+++ b/tests/testables/src/android/testing/TestableContext.java
@@ -33,11 +33,15 @@
 import android.util.ArrayMap;
 import android.view.LayoutInflater;
 
+import androidx.annotation.Nullable;
+
 import org.junit.rules.TestRule;
 import org.junit.rules.TestWatcher;
 import org.junit.runner.Description;
 import org.junit.runners.model.Statement;
 
+import java.util.ArrayList;
+
 /**
  * A ContextWrapper with utilities specifically designed to make Testing easier.
  *
@@ -61,6 +65,7 @@
     private final TestableContentResolver mTestableContentResolver;
     private final TestableSettingsProvider mSettingsProvider;
 
+    private ArrayList<MockServiceResolver> mMockServiceResolvers;
     private ArrayMap<String, Object> mMockSystemServices;
     private ArrayMap<ComponentName, IBinder> mMockServices;
     private ArrayMap<ServiceConnection, ComponentName> mActiveServices;
@@ -214,12 +219,15 @@
     /**
      * Adds a mock service to be connected to by a bindService call.
      * <p>
-     *     Normally a TestableContext will pass through all bind requests to the base context
-     *     but when addMockService has been called for a ComponentName being bound, then
-     *     TestableContext will immediately trigger a {@link ServiceConnection#onServiceConnected}
-     *     with the specified service, and will call {@link ServiceConnection#onServiceDisconnected}
-     *     when the service is unbound.
+     * Normally a TestableContext will pass through all bind requests to the base context
+     * but when addMockService has been called for a ComponentName being bound, then
+     * TestableContext will immediately trigger a {@link ServiceConnection#onServiceConnected}
+     * with the specified service, and will call {@link ServiceConnection#onServiceDisconnected}
+     * when the service is unbound.
      * </p>
+     *
+     * @see #addMockServiceResolver(MockServiceResolver) for custom resolution of service Intents to
+     * ComponentNames
      */
     public void addMockService(ComponentName component, IBinder service) {
         if (mMockServices == null) mMockServices = new ArrayMap<>();
@@ -227,12 +235,38 @@
     }
 
     /**
+     * Strategy to resolve a service {@link Intent} to a mock service {@link ComponentName}.
+     */
+    public interface MockServiceResolver {
+        @Nullable
+        ComponentName resolve(Intent service);
+    }
+
+    /**
+     * Registers a strategy to resolve service intents to registered mock services.
+     * <p>
+     * The result of the first {@link MockServiceResolver} to return a non-null
+     * {@link ComponentName} is used to look up a mock service. The mock service must be registered
+     * via {@link #addMockService(ComponentName, IBinder)} separately, using the same component
+     * name.
+     *
+     * If none of the resolvers return a non-null value, or the first returned component name
+     * does not link to a registered mock service, the bind requests are passed to the base context
+     *
+     * The resolvers are queried in order of registration.
+     */
+    public void addMockServiceResolver(MockServiceResolver resolver) {
+        if (mMockServiceResolvers == null) mMockServiceResolvers = new ArrayList<>();
+        mMockServiceResolvers.add(resolver);
+    }
+
+    /**
      * @see #addMockService(ComponentName, IBinder)
      */
     @Override
     public boolean bindService(Intent service, ServiceConnection conn, int flags) {
         if (mService != null) mService.getLeakInfo(conn).addAllocation(new Throwable());
-        if (checkMocks(service.getComponent(), conn)) return true;
+        if (checkMocks(service, conn)) return true;
         return super.bindService(service, conn, flags);
     }
 
@@ -243,7 +277,7 @@
     public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
             Handler handler, UserHandle user) {
         if (mService != null) mService.getLeakInfo(conn).addAllocation(new Throwable());
-        if (checkMocks(service.getComponent(), conn)) return true;
+        if (checkMocks(service, conn)) return true;
         return super.bindServiceAsUser(service, conn, flags, handler, user);
     }
 
@@ -254,18 +288,36 @@
     public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
             UserHandle user) {
         if (mService != null) mService.getLeakInfo(conn).addAllocation(new Throwable());
-        if (checkMocks(service.getComponent(), conn)) return true;
+        if (checkMocks(service, conn)) return true;
         return super.bindServiceAsUser(service, conn, flags, user);
     }
 
-    private boolean checkMocks(ComponentName component, ServiceConnection conn) {
-        if (mMockServices != null && component != null && mMockServices.containsKey(component)) {
-            if (mActiveServices == null) mActiveServices = new ArrayMap<>();
-            mActiveServices.put(conn, component);
-            conn.onServiceConnected(component, mMockServices.get(component));
-            return true;
+    private boolean checkMocks(Intent service, ServiceConnection conn) {
+        if (mMockServices == null) return false;
+
+        ComponentName serviceComponent = resolveMockServiceComponent(service);
+        if (serviceComponent == null) return false;
+
+        IBinder serviceImpl = mMockServices.get(serviceComponent);
+        if (serviceImpl == null) return false;
+
+        if (mActiveServices == null) mActiveServices = new ArrayMap<>();
+        mActiveServices.put(conn, serviceComponent);
+        conn.onServiceConnected(serviceComponent, serviceImpl);
+        return true;
+    }
+
+    private ComponentName resolveMockServiceComponent(Intent service) {
+        ComponentName specifiedComponentName = service.getComponent();
+        if (specifiedComponentName != null) return specifiedComponentName;
+
+        if (mMockServiceResolvers == null) return null;
+
+        for (MockServiceResolver resolver : mMockServiceResolvers) {
+            ComponentName resolvedComponent = resolver.resolve(service);
+            if (resolvedComponent != null) return resolvedComponent;
         }
-        return false;
+        return null;
     }
 
     /**
diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk
index 7b94e71..34a1b11 100644
--- a/tools/aapt2/Android.mk
+++ b/tools/aapt2/Android.mk
@@ -15,7 +15,7 @@
 $(aapt2_results): $(HOST_OUT_NATIVE_TESTS)/aapt2_tests/aapt2_tests
 	-$(HOST_OUT_NATIVE_TESTS)/aapt2_tests/aapt2_tests --gtest_output=xml:$@ > /dev/null 2>&1
 
-$(call declare-0p-target,$(aapt2_results))
+$(call declare-1p-target,$(aapt2_results))
 
 aapt2_results :=
 
diff --git a/tools/codegen/Android.bp b/tools/codegen/Android.bp
index e53ba3e..a1df878 100644
--- a/tools/codegen/Android.bp
+++ b/tools/codegen/Android.bp
@@ -9,7 +9,7 @@
 
 java_binary_host {
     name: "codegen_cli",
-    manifest: "manifest.txt",
+    main_class: "com.android.codegen.MainKt",
     srcs: [
         "src/**/*.kt",
     ],
diff --git a/tools/codegen/BUILD.bazel b/tools/codegen/BUILD.bazel
deleted file mode 100644
index c14046d..0000000
--- a/tools/codegen/BUILD.bazel
+++ /dev/null
@@ -1,21 +0,0 @@
-# TODO(b/245731902): auto-generate these with bp2build.
-load("@rules_kotlin//kotlin:jvm_library.bzl", "kt_jvm_library")
-
-java_binary(
-    name = "codegen_cli",
-    main_class = "com.android.codegen.MainKt",
-    runtime_deps = [
-        ":codegen_cli_kt_lib",
-    ],
-)
-
-kt_jvm_library(
-    name = "codegen_cli_kt_lib",
-    srcs = glob(["src/**/*.kt"]),
-    deps = ["//external/javaparser"],
-)
-
-kt_jvm_library(
-    name = "codegen-version-info",
-    srcs = glob(["src/**/SharedConstants.kt"]),
-)
diff --git a/tools/codegen/manifest.txt b/tools/codegen/manifest.txt
deleted file mode 100644
index 6e1018b..0000000
--- a/tools/codegen/manifest.txt
+++ /dev/null
@@ -1 +0,0 @@
-Main-class: com.android.codegen.MainKt
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.aidl
similarity index 95%
rename from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
rename to wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.aidl
index 35d5c15..f9c4829 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.aidl
@@ -16,4 +16,4 @@
 
 package android.net.wifi.sharedconnectivity.app;
 
-parcelable DeviceInfo;
\ No newline at end of file
+parcelable HotspotNetwork;
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.java
similarity index 67%
rename from wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.java
rename to wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.java
index af4fd4a..9bfeb63 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.java
@@ -25,22 +25,22 @@
 import android.net.wifi.sharedconnectivity.service.SharedConnectivityService;
 import android.os.Parcel;
 import android.os.Parcelable;
-
+import android.util.ArraySet;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
 import java.util.Objects;
+import java.util.Set;
 
 /**
- * A data class representing an Instant Tether network.
+ * A data class representing a hotspot network.
  * This class is used in IPC calls between the implementer of {@link SharedConnectivityService} and
  * the consumers of {@link com.android.wifitrackerlib}.
  *
  * @hide
  */
 @SystemApi
-public final class TetherNetwork implements Parcelable {
+public final class HotspotNetwork implements Parcelable {
     /**
      * Remote device is connected to the internet via an unknown connection.
      */
@@ -71,34 +71,44 @@
             NETWORK_TYPE_WIFI,
             NETWORK_TYPE_ETHERNET
     })
-    public @interface NetworkType {}
+    public @interface NetworkType {
+    }
 
     private final long mDeviceId;
-    private final DeviceInfo mDeviceInfo;
-    @NetworkType private final int mNetworkType;
+    private final NetworkProviderInfo mNetworkProviderInfo;
+    @NetworkType
+    private final int mNetworkType;
     private final String mNetworkName;
-    @Nullable private final String mHotspotSsid;
-    @Nullable private final String mHotspotBssid;
-    @Nullable @SecurityType private final int[] mHotspotSecurityTypes;
+    @Nullable
+    private final String mHotspotSsid;
+    @Nullable
+    private final String mHotspotBssid;
+    @Nullable
+    @SecurityType
+    private final ArraySet<Integer> mHotspotSecurityTypes;
 
     /**
-     * Builder class for {@link TetherNetwork}.
+     * Builder class for {@link HotspotNetwork}.
      */
     public static final class Builder {
         private long mDeviceId = -1;
-        private DeviceInfo mDeviceInfo;
-        @NetworkType private int mNetworkType;
+        private NetworkProviderInfo mNetworkProviderInfo;
+        @NetworkType
+        private int mNetworkType;
         private String mNetworkName;
-        @Nullable private String mHotspotSsid;
-        @Nullable private String mHotspotBssid;
-        @Nullable @SecurityType private int[] mHotspotSecurityTypes;
-
-        public Builder() {}
+        @Nullable
+        private String mHotspotSsid;
+        @Nullable
+        private String mHotspotBssid;
+        @Nullable
+        @SecurityType
+        private final ArraySet<Integer> mHotspotSecurityTypes =
+                new ArraySet<>();
 
         /**
          * Set the remote device ID.
          *
-         * @param deviceId Locally unique ID for this Instant Tether network.
+         * @param deviceId Locally unique ID for this Hotspot network.
          * @return Returns the Builder object.
          */
         @NonNull
@@ -110,12 +120,12 @@
         /**
          * Sets information about the device providing connectivity.
          *
-         * @param deviceInfo The device information object.
+         * @param networkProviderInfo The device information object.
          * @return Returns the Builder object.
          */
         @NonNull
-        public Builder setDeviceInfo(@NonNull DeviceInfo deviceInfo) {
-            mDeviceInfo = deviceInfo;
+        public Builder setNetworkProviderInfo(@NonNull NetworkProviderInfo networkProviderInfo) {
+            mNetworkProviderInfo = networkProviderInfo;
             return this;
         }
 
@@ -126,7 +136,7 @@
          * @return Returns the Builder object.
          */
         @NonNull
-        public Builder setNetworkType(@NetworkType int networkType) {
+        public Builder setHostNetworkType(@NetworkType int networkType) {
             mNetworkType = networkType;
             return this;
         }
@@ -168,28 +178,27 @@
         }
 
         /**
-         * Sets the hotspot security types supported by the remote device, or null if hotspot is
-         * off.
+         * Adds a security type supported by the hotspot created by the remote device.
          *
-         * @param hotspotSecurityTypes The array of security types supported by the hotspot.
+         * @param hotspotSecurityType A security type supported by the hotspot.
          * @return Returns the Builder object.
          */
         @NonNull
-        public Builder setHotspotSecurityTypes(@NonNull @SecurityType int[] hotspotSecurityTypes) {
-            mHotspotSecurityTypes = hotspotSecurityTypes;
+        public Builder addHotspotSecurityType(@SecurityType int hotspotSecurityType) {
+            mHotspotSecurityTypes.add(hotspotSecurityType);
             return this;
         }
 
         /**
-         * Builds the {@link TetherNetwork} object.
+         * Builds the {@link HotspotNetwork} object.
          *
-         * @return Returns the built {@link TetherNetwork} object.
+         * @return Returns the built {@link HotspotNetwork} object.
          */
         @NonNull
-        public TetherNetwork build() {
-            return new TetherNetwork(
+        public HotspotNetwork build() {
+            return new HotspotNetwork(
                     mDeviceId,
-                    mDeviceInfo,
+                    mNetworkProviderInfo,
                     mNetworkType,
                     mNetworkName,
                     mHotspotSsid,
@@ -198,10 +207,14 @@
         }
     }
 
-    private static void validate(long deviceId, int networkType, String networkName) {
+    private static void validate(long deviceId, @NetworkType int networkType, String networkName,
+            NetworkProviderInfo networkProviderInfo) {
         if (deviceId < 0) {
             throw new IllegalArgumentException("DeviceId must be set");
         }
+        if (Objects.isNull(networkProviderInfo)) {
+            throw new IllegalArgumentException("NetworkProviderInfo must be set");
+        }
         if (networkType != NETWORK_TYPE_CELLULAR && networkType != NETWORK_TYPE_WIFI
                 && networkType != NETWORK_TYPE_ETHERNET && networkType != NETWORK_TYPE_UNKNOWN) {
             throw new IllegalArgumentException("Illegal network type");
@@ -211,30 +224,31 @@
         }
     }
 
-    private TetherNetwork(
+    private HotspotNetwork(
             long deviceId,
-            DeviceInfo deviceInfo,
+            NetworkProviderInfo networkProviderInfo,
             @NetworkType int networkType,
             @NonNull String networkName,
             @Nullable String hotspotSsid,
             @Nullable String hotspotBssid,
-            @Nullable @SecurityType int[] hotspotSecurityTypes) {
+            @Nullable @SecurityType ArraySet<Integer> hotspotSecurityTypes) {
         validate(deviceId,
                 networkType,
-                networkName);
+                networkName,
+                networkProviderInfo);
         mDeviceId = deviceId;
-        mDeviceInfo = deviceInfo;
+        mNetworkProviderInfo = networkProviderInfo;
         mNetworkType = networkType;
         mNetworkName = networkName;
         mHotspotSsid = hotspotSsid;
         mHotspotBssid = hotspotBssid;
-        mHotspotSecurityTypes = hotspotSecurityTypes;
+        mHotspotSecurityTypes = new ArraySet<>(hotspotSecurityTypes);
     }
 
     /**
      * Gets the remote device ID.
      *
-     * @return Returns the locally unique ID for this Instant Tether network.
+     * @return Returns the locally unique ID for this Hotspot network.
      */
     public long getDeviceId() {
         return mDeviceId;
@@ -243,11 +257,11 @@
     /**
      * Gets information about the device providing connectivity.
      *
-     * @return Returns the information of the device providing the Instant Tether network.
+     * @return Returns the information of the device providing the Hotspot network.
      */
     @NonNull
-    public DeviceInfo getDeviceInfo() {
-        return mDeviceInfo;
+    public NetworkProviderInfo getNetworkProviderInfo() {
+        return mNetworkProviderInfo;
     }
 
     /**
@@ -256,7 +270,7 @@
      * @return Returns the network type as represented by IntDef {@link NetworkType}.
      */
     @NetworkType
-    public int getNetworkType() {
+    public int getHostNetworkType() {
         return mNetworkType;
     }
 
@@ -293,31 +307,31 @@
     /**
      * Gets the hotspot security types supported by the remote device.
      *
-     * @return Returns the array of security types supported by the hotspot.
+     * @return Returns a set of the security types supported by the hotspot.
      */
-    @Nullable
+    @NonNull
     @SecurityType
-    public int[] getHotspotSecurityTypes() {
+    public Set<Integer> getHotspotSecurityTypes() {
         return mHotspotSecurityTypes;
     }
 
     @Override
     public boolean equals(Object obj) {
-        if (!(obj instanceof TetherNetwork)) return false;
-        TetherNetwork other = (TetherNetwork) obj;
+        if (!(obj instanceof HotspotNetwork)) return false;
+        HotspotNetwork other = (HotspotNetwork) obj;
         return mDeviceId == other.getDeviceId()
-                && Objects.equals(mDeviceInfo, other.getDeviceInfo())
-                && mNetworkType == other.getNetworkType()
+                && Objects.equals(mNetworkProviderInfo, other.getNetworkProviderInfo())
+                && mNetworkType == other.getHostNetworkType()
                 && Objects.equals(mNetworkName, other.getNetworkName())
                 && Objects.equals(mHotspotSsid, other.getHotspotSsid())
                 && Objects.equals(mHotspotBssid, other.getHotspotBssid())
-                && Arrays.equals(mHotspotSecurityTypes, other.getHotspotSecurityTypes());
+                && Objects.equals(mHotspotSecurityTypes, other.getHotspotSecurityTypes());
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mDeviceId, mDeviceInfo, mNetworkName, mHotspotSsid, mHotspotBssid,
-                Arrays.hashCode(mHotspotSecurityTypes));
+        return Objects.hash(mDeviceId, mNetworkProviderInfo, mNetworkName, mHotspotSsid,
+                mHotspotBssid, mHotspotSecurityTypes);
     }
 
     @Override
@@ -328,49 +342,49 @@
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeLong(mDeviceId);
-        mDeviceInfo.writeToParcel(dest, flags);
+        mNetworkProviderInfo.writeToParcel(dest, flags);
         dest.writeInt(mNetworkType);
         dest.writeString(mNetworkName);
         dest.writeString(mHotspotSsid);
         dest.writeString(mHotspotBssid);
-        dest.writeIntArray(mHotspotSecurityTypes);
+        dest.writeArraySet(mHotspotSecurityTypes);
     }
 
     /**
-     * Creates a {@link TetherNetwork} object from a parcel.
+     * Creates a {@link HotspotNetwork} object from a parcel.
      *
      * @hide
      */
     @NonNull
-    public static TetherNetwork readFromParcel(@NonNull Parcel in) {
-        return new TetherNetwork(in.readLong(), DeviceInfo.readFromParcel(in),
+    public static HotspotNetwork readFromParcel(@NonNull Parcel in) {
+        return new HotspotNetwork(in.readLong(), NetworkProviderInfo.readFromParcel(in),
                 in.readInt(), in.readString(), in.readString(), in.readString(),
-                in.createIntArray());
+                (ArraySet<Integer>) in.readArraySet(null));
     }
 
     @NonNull
-    public static final Creator<TetherNetwork> CREATOR = new Creator<>() {
+    public static final Creator<HotspotNetwork> CREATOR = new Creator<>() {
         @Override
-        public TetherNetwork createFromParcel(Parcel in) {
+        public HotspotNetwork createFromParcel(Parcel in) {
             return readFromParcel(in);
         }
 
         @Override
-        public TetherNetwork[] newArray(int size) {
-            return new TetherNetwork[size];
+        public HotspotNetwork[] newArray(int size) {
+            return new HotspotNetwork[size];
         }
     };
 
     @Override
     public String toString() {
-        return new StringBuilder("TetherNetwork[")
+        return new StringBuilder("HotspotNetwork[")
                 .append("deviceId=").append(mDeviceId)
                 .append(", networkType=").append(mNetworkType)
-                .append(", deviceInfo=").append(mDeviceInfo.toString())
+                .append(", networkProviderInfo=").append(mNetworkProviderInfo.toString())
                 .append(", networkName=").append(mNetworkName)
                 .append(", hotspotSsid=").append(mHotspotSsid)
                 .append(", hotspotBssid=").append(mHotspotBssid)
-                .append(", hotspotSecurityTypes=").append(Arrays.toString(mHotspotSecurityTypes))
+                .append(", hotspotSecurityTypes=").append(mHotspotSecurityTypes.toString())
                 .append("]").toString();
     }
 }
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.aidl
similarity index 93%
copy from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
copy to wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.aidl
index 35d5c15..d32d15e 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.aidl
@@ -16,4 +16,4 @@
 
 package android.net.wifi.sharedconnectivity.app;
 
-parcelable DeviceInfo;
\ No newline at end of file
+parcelable HotspotNetworkConnectionStatus;
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.java
new file mode 100644
index 0000000..69767f3
--- /dev/null
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.java
@@ -0,0 +1,276 @@
+/*
+ * 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.net.wifi.sharedconnectivity.app;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * The status of a connection to a hotspot network after the client called
+ * {@link SharedConnectivityManager#connectHotspotNetwork}.
+ *
+ * @hide
+ */
+@SystemApi
+public final class HotspotNetworkConnectionStatus implements Parcelable {
+
+    /**
+     * Connection status is unknown.
+     */
+    public static final int CONNECTION_STATUS_UNKNOWN = 0;
+
+    /**
+     * The connection is being initiated.
+     */
+    public static final int CONNECTION_STATUS_ENABLING_HOTSPOT = 1;
+
+    /**
+     * Device providing the hotspot failed to initiate it.
+     */
+    public static final int CONNECTION_STATUS_UNKNOWN_ERROR = 2;
+
+    /**
+     * Failed to provision tethering.
+     */
+    public static final int CONNECTION_STATUS_PROVISIONING_FAILED = 3;
+
+    /**
+     * Timeout while trying to provision tethering.
+     */
+    public static final int CONNECTION_STATUS_TETHERING_TIMEOUT = 4;
+
+    /**
+     * Device doesn't support tethering.
+     */
+    public static final int CONNECTION_STATUS_TETHERING_UNSUPPORTED = 5;
+
+    /**
+     * Device has no cell data.
+     */
+    public static final int CONNECTION_STATUS_NO_CELL_DATA = 6;
+
+    /**
+     * Device failed to enable hotspot
+     */
+    public static final int CONNECTION_STATUS_ENABLING_HOTSPOT_FAILED = 7;
+
+    /**
+     * Timeout while trying to enable hotspot
+     */
+    public static final int CONNECTION_STATUS_ENABLING_HOTSPOT_TIMEOUT = 8;
+
+    /**
+     * Failed to connect to hotspot
+     */
+    public static final int CONNECTION_STATUS_CONNECT_TO_HOTSPOT_FAILED = 9;
+
+    /**
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            CONNECTION_STATUS_UNKNOWN,
+            CONNECTION_STATUS_ENABLING_HOTSPOT,
+            CONNECTION_STATUS_UNKNOWN_ERROR,
+            CONNECTION_STATUS_PROVISIONING_FAILED,
+            CONNECTION_STATUS_TETHERING_TIMEOUT,
+            CONNECTION_STATUS_TETHERING_UNSUPPORTED,
+            CONNECTION_STATUS_NO_CELL_DATA,
+            CONNECTION_STATUS_ENABLING_HOTSPOT_FAILED,
+            CONNECTION_STATUS_ENABLING_HOTSPOT_TIMEOUT,
+            CONNECTION_STATUS_CONNECT_TO_HOTSPOT_FAILED,
+    })
+    public @interface ConnectionStatus {
+    }
+
+    @ConnectionStatus
+    private final int mStatus;
+    private final HotspotNetwork mHotspotNetwork;
+    private final Bundle mExtras;
+
+    /**
+     * Builder class for {@link HotspotNetworkConnectionStatus}.
+     */
+    public static final class Builder {
+        @ConnectionStatus
+        private int mStatus;
+        private HotspotNetwork mHotspotNetwork;
+        private Bundle mExtras;
+
+        /**
+         * Sets the status of the connection
+         *
+         * @return Returns the Builder object.
+         */
+        @NonNull
+        public Builder setStatus(@ConnectionStatus int status) {
+            mStatus = status;
+            return this;
+        }
+
+        /**
+         * Sets the {@link HotspotNetwork} object of the connection.
+         *
+         * @return Returns the Builder object.
+         */
+        @NonNull
+        public Builder setHotspotNetwork(@NonNull HotspotNetwork hotspotNetwork) {
+            mHotspotNetwork = hotspotNetwork;
+            return this;
+        }
+
+        /**
+         * Sets the extras bundle
+         *
+         * @return Returns the Builder object.
+         */
+        @NonNull
+        public Builder setExtras(@NonNull Bundle extras) {
+            mExtras = extras;
+            return this;
+        }
+
+        /**
+         * Builds the {@link HotspotNetworkConnectionStatus} object.
+         *
+         * @return Returns the built {@link HotspotNetworkConnectionStatus} object.
+         */
+        @NonNull
+        public HotspotNetworkConnectionStatus build() {
+            return new HotspotNetworkConnectionStatus(mStatus, mHotspotNetwork, mExtras);
+        }
+    }
+
+    private static void validate(@ConnectionStatus int status) {
+        if (status != CONNECTION_STATUS_UNKNOWN
+                && status != CONNECTION_STATUS_ENABLING_HOTSPOT
+                && status != CONNECTION_STATUS_UNKNOWN_ERROR
+                && status != CONNECTION_STATUS_PROVISIONING_FAILED
+                && status != CONNECTION_STATUS_TETHERING_TIMEOUT
+                && status != CONNECTION_STATUS_TETHERING_UNSUPPORTED
+                && status != CONNECTION_STATUS_NO_CELL_DATA
+                && status != CONNECTION_STATUS_ENABLING_HOTSPOT_FAILED
+                && status != CONNECTION_STATUS_ENABLING_HOTSPOT_TIMEOUT
+                && status != CONNECTION_STATUS_CONNECT_TO_HOTSPOT_FAILED) {
+            throw new IllegalArgumentException("Illegal connection status");
+        }
+    }
+
+    private HotspotNetworkConnectionStatus(@ConnectionStatus int status,
+            HotspotNetwork hotspotNetwork, Bundle extras) {
+        validate(status);
+        mStatus = status;
+        mHotspotNetwork = hotspotNetwork;
+        mExtras = extras;
+    }
+
+    /**
+     * Gets the status of the connection
+     *
+     * @return Returns true for enabled, false otherwise.
+     */
+    @ConnectionStatus
+    public int getStatus() {
+        return mStatus;
+    }
+
+    /**
+     * Gets the {@link HotspotNetwork} object of the connection.
+     *
+     * @return Returns a HotspotNetwork object.
+     */
+    @NonNull
+    public HotspotNetwork getHotspotNetwork() {
+        return mHotspotNetwork;
+    }
+
+    /**
+     * Gets the extras Bundle.
+     *
+     * @return Returns a Bundle object.
+     */
+    @NonNull
+    public Bundle getExtras() {
+        return mExtras;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof HotspotNetworkConnectionStatus)) return false;
+        HotspotNetworkConnectionStatus other = (HotspotNetworkConnectionStatus) obj;
+        return mStatus == other.getStatus()
+                && Objects.equals(mHotspotNetwork, other.getHotspotNetwork());
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mStatus, mHotspotNetwork);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mStatus);
+        mHotspotNetwork.writeToParcel(dest, flags);
+        dest.writeBundle(mExtras);
+    }
+
+    /**
+     * Creates a {@link HotspotNetworkConnectionStatus} object from a parcel.
+     *
+     * @hide
+     */
+    @NonNull
+    public static HotspotNetworkConnectionStatus readFromParcel(@NonNull Parcel in) {
+        return new HotspotNetworkConnectionStatus(in.readInt(),
+                HotspotNetwork.readFromParcel(in), in.readBundle());
+    }
+
+    @NonNull
+    public static final Creator<HotspotNetworkConnectionStatus> CREATOR = new Creator<>() {
+        @Override
+        public HotspotNetworkConnectionStatus createFromParcel(Parcel in) {
+            return readFromParcel(in);
+        }
+
+        @Override
+        public HotspotNetworkConnectionStatus[] newArray(int size) {
+            return new HotspotNetworkConnectionStatus[size];
+        }
+    };
+
+    @Override
+    public String toString() {
+        return new StringBuilder("HotspotNetworkConnectionStatus[")
+                .append("status=").append(mStatus)
+                .append("hotspot network=").append(mHotspotNetwork.toString())
+                .append("extras=").append(mExtras.toString())
+                .append("]").toString();
+    }
+}
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.java
index 161c83c..64412bc 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.java
@@ -20,15 +20,17 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
+import android.util.ArraySet;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
 import java.util.Objects;
+import java.util.Set;
 
 /**
  * A data class representing a known Wi-Fi network.
@@ -37,41 +39,51 @@
  */
 @SystemApi
 public final class KnownNetwork implements Parcelable {
+
+    /**
+     * Network source is unknown.
+     */
+    public static final int NETWORK_SOURCE_UNKNOWN = 0;
+
     /**
      * Network is known by a nearby device with the same user account.
      */
-    public static final int NETWORK_SOURCE_NEARBY_SELF = 0;
+    public static final int NETWORK_SOURCE_NEARBY_SELF = 1;
 
     /**
      * Network is known via cloud storage associated with this device's user account.
      */
-    public static final int NETWORK_SOURCE_CLOUD_SELF = 1;
+    public static final int NETWORK_SOURCE_CLOUD_SELF = 2;
 
     /**
      * @hide
      */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({
+            NETWORK_SOURCE_UNKNOWN,
             NETWORK_SOURCE_NEARBY_SELF,
             NETWORK_SOURCE_CLOUD_SELF
     })
-    public @interface NetworkSource {}
+    public @interface NetworkSource {
+    }
 
-    @NetworkSource private final int mNetworkSource;
+    @NetworkSource
+    private final int mNetworkSource;
     private final String mSsid;
-    @SecurityType private final int[] mSecurityTypes;
-    private final DeviceInfo mDeviceInfo;
+    @SecurityType
+    private final ArraySet<Integer> mSecurityTypes;
+    private final NetworkProviderInfo mNetworkProviderInfo;
 
     /**
      * Builder class for {@link KnownNetwork}.
      */
     public static final class Builder {
-        @NetworkSource private int mNetworkSource = -1;
+        @NetworkSource
+        private int mNetworkSource = -1;
         private String mSsid;
-        @SecurityType private int[] mSecurityTypes;
-        private android.net.wifi.sharedconnectivity.app.DeviceInfo mDeviceInfo;
-
-        public Builder() {}
+        @SecurityType
+        private final ArraySet<Integer> mSecurityTypes = new ArraySet<>();
+        private NetworkProviderInfo mNetworkProviderInfo;
 
         /**
          * Sets the indicated source of the known network.
@@ -98,26 +110,27 @@
         }
 
         /**
-         * Sets the security types of the known network.
+         * Adds a security type of the known network.
          *
-         * @param securityTypes The array of security types supported by the known network.
+         * @param securityType A security type supported by the known network.
          * @return Returns the Builder object.
          */
         @NonNull
-        public Builder setSecurityTypes(@NonNull @SecurityType int[] securityTypes) {
-            mSecurityTypes = securityTypes;
+        public Builder addSecurityType(@SecurityType int securityType) {
+            mSecurityTypes.add(securityType);
             return this;
         }
 
         /**
          * Sets the device information of the device providing connectivity.
+         * Must be set if network source is {@link KnownNetwork#NETWORK_SOURCE_NEARBY_SELF}.
          *
-         * @param deviceInfo The device information object.
+         * @param networkProviderInfo The device information object.
          * @return Returns the Builder object.
          */
         @NonNull
-        public Builder setDeviceInfo(@NonNull DeviceInfo deviceInfo) {
-            mDeviceInfo = deviceInfo;
+        public Builder setNetworkProviderInfo(@Nullable NetworkProviderInfo networkProviderInfo) {
+            mNetworkProviderInfo = networkProviderInfo;
             return this;
         }
 
@@ -132,33 +145,40 @@
                     mNetworkSource,
                     mSsid,
                     mSecurityTypes,
-                    mDeviceInfo);
+                    mNetworkProviderInfo);
         }
     }
 
-    private static void validate(int networkSource, String ssid, int [] securityTypes) {
-        if (networkSource != NETWORK_SOURCE_CLOUD_SELF && networkSource
-                != NETWORK_SOURCE_NEARBY_SELF) {
+    private static void validate(@NetworkSource int networkSource, String ssid,
+            @SecurityType Set<Integer> securityTypes,
+            NetworkProviderInfo networkProviderInfo) {
+        if (networkSource != NETWORK_SOURCE_UNKNOWN
+                && networkSource != NETWORK_SOURCE_CLOUD_SELF
+                && networkSource != NETWORK_SOURCE_NEARBY_SELF) {
             throw new IllegalArgumentException("Illegal network source");
         }
         if (TextUtils.isEmpty(ssid)) {
             throw new IllegalArgumentException("SSID must be set");
         }
-        if (securityTypes == null || securityTypes.length == 0) {
+        if (securityTypes.isEmpty()) {
             throw new IllegalArgumentException("SecurityTypes must be set");
         }
+        if (networkSource == NETWORK_SOURCE_NEARBY_SELF && networkProviderInfo == null) {
+            throw new IllegalArgumentException("Device info must be provided when network source"
+                    + " is NETWORK_SOURCE_NEARBY_SELF");
+        }
     }
 
     private KnownNetwork(
             @NetworkSource int networkSource,
             @NonNull String ssid,
-            @NonNull @SecurityType int[] securityTypes,
-            @NonNull DeviceInfo deviceInfo) {
-        validate(networkSource, ssid, securityTypes);
+            @NonNull @SecurityType ArraySet<Integer> securityTypes,
+            @Nullable NetworkProviderInfo networkProviderInfo) {
+        validate(networkSource, ssid, securityTypes, networkProviderInfo);
         mNetworkSource = networkSource;
         mSsid = ssid;
-        mSecurityTypes = securityTypes;
-        mDeviceInfo = deviceInfo;
+        mSecurityTypes = new ArraySet<>(securityTypes);
+        mNetworkProviderInfo = networkProviderInfo;
     }
 
     /**
@@ -184,22 +204,23 @@
     /**
      * Gets the security types of the known network.
      *
-     * @return Returns the array of security types supported by the known network.
+     * @return Returns a set with security types supported by the known network.
      */
     @NonNull
     @SecurityType
-    public int[] getSecurityTypes() {
+    public Set<Integer> getSecurityTypes() {
         return mSecurityTypes;
     }
 
     /**
      * Gets the device information of the device providing connectivity.
      *
-     * @return Returns the information of the device providing the known network.
+     * @return Returns the information of the device providing the known network. Can be null if the
+     * network source is cloud or unknown.
      */
-    @NonNull
-    public DeviceInfo getDeviceInfo() {
-        return mDeviceInfo;
+    @Nullable
+    public NetworkProviderInfo getNetworkProviderInfo() {
+        return mNetworkProviderInfo;
     }
 
     @Override
@@ -208,14 +229,13 @@
         KnownNetwork other = (KnownNetwork) obj;
         return mNetworkSource == other.getNetworkSource()
                 && Objects.equals(mSsid, other.getSsid())
-                && Arrays.equals(mSecurityTypes, other.getSecurityTypes())
-                && Objects.equals(mDeviceInfo, other.getDeviceInfo());
+                && Objects.equals(mSecurityTypes, other.getSecurityTypes())
+                && Objects.equals(mNetworkProviderInfo, other.getNetworkProviderInfo());
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mNetworkSource, mSsid, Arrays.hashCode(mSecurityTypes),
-                mDeviceInfo.hashCode());
+        return Objects.hash(mNetworkSource, mSsid, mSecurityTypes, mNetworkProviderInfo);
     }
 
     @Override
@@ -227,8 +247,8 @@
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeInt(mNetworkSource);
         dest.writeString(mSsid);
-        dest.writeIntArray(mSecurityTypes);
-        mDeviceInfo.writeToParcel(dest, flags);
+        dest.writeArraySet(mSecurityTypes);
+        mNetworkProviderInfo.writeToParcel(dest, flags);
     }
 
     /**
@@ -238,8 +258,9 @@
      */
     @NonNull
     public static KnownNetwork readFromParcel(@NonNull Parcel in) {
-        return new KnownNetwork(in.readInt(), in.readString(), in.createIntArray(),
-                DeviceInfo.readFromParcel(in));
+        return new KnownNetwork(in.readInt(), in.readString(),
+                (ArraySet<Integer>) in.readArraySet(null),
+                NetworkProviderInfo.readFromParcel(in));
     }
 
     @NonNull
@@ -260,8 +281,8 @@
         return new StringBuilder("KnownNetwork[")
                 .append("NetworkSource=").append(mNetworkSource)
                 .append(", ssid=").append(mSsid)
-                .append(", securityTypes=").append(Arrays.toString(mSecurityTypes))
-                .append(", deviceInfo=").append(mDeviceInfo.toString())
+                .append(", securityTypes=").append(mSecurityTypes.toString())
+                .append(", networkProviderInfo=").append(mNetworkProviderInfo.toString())
                 .append("]").toString();
     }
 }
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatus.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatus.java
index b2f04ff..6bd0a5e 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatus.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatus.java
@@ -120,8 +120,16 @@
         }
     }
 
+    private static void validate(@ConnectionStatus int status) {
+        if (status != CONNECTION_STATUS_UNKNOWN && status != CONNECTION_STATUS_SAVED
+                && status != CONNECTION_STATUS_SAVE_FAILED) {
+            throw new IllegalArgumentException("Illegal connection status");
+        }
+    }
+
     private KnownNetworkConnectionStatus(@ConnectionStatus int status, KnownNetwork knownNetwork,
             Bundle extras) {
+        validate(status);
         mStatus = status;
         mKnownNetwork = knownNetwork;
         mExtras = extras;
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.aidl
similarity index 95%
copy from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
copy to wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.aidl
index 35d5c15..f3cbbc2 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.aidl
@@ -16,4 +16,4 @@
 
 package android.net.wifi.sharedconnectivity.app;
 
-parcelable DeviceInfo;
\ No newline at end of file
+parcelable NetworkProviderInfo;
\ No newline at end of file
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java
similarity index 79%
rename from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.java
rename to wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java
index 52abf33..ed4d699 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java
@@ -36,7 +36,7 @@
  * @hide
  */
 @SystemApi
-public final class DeviceInfo implements Parcelable {
+public final class NetworkProviderInfo implements Parcelable {
 
     /**
      * Device type providing connectivity is unknown.
@@ -59,6 +59,16 @@
     public static final int DEVICE_TYPE_LAPTOP = 3;
 
     /**
+     * Device providing connectivity is a watch.
+     */
+    public static final int DEVICE_TYPE_WATCH = 4;
+
+    /**
+     * Device providing connectivity is a watch.
+     */
+    public static final int DEVICE_TYPE_AUTO = 5;
+
+    /**
      * @hide
      */
     @Retention(RetentionPolicy.SOURCE)
@@ -66,18 +76,22 @@
             DEVICE_TYPE_UNKNOWN,
             DEVICE_TYPE_PHONE,
             DEVICE_TYPE_TABLET,
-            DEVICE_TYPE_LAPTOP
+            DEVICE_TYPE_LAPTOP,
+            DEVICE_TYPE_WATCH,
+            DEVICE_TYPE_AUTO
     })
-    public @interface DeviceType {}
+    public @interface DeviceType {
+    }
 
-    @DeviceType private final int mDeviceType;
+    @DeviceType
+    private final int mDeviceType;
     private final String mDeviceName;
     private final String mModelName;
     private final int mBatteryPercentage;
     private final int mConnectionStrength;
 
     /**
-     * Builder class for {@link DeviceInfo}.
+     * Builder class for {@link NetworkProviderInfo}.
      */
     public static final class Builder {
         private int mDeviceType;
@@ -86,7 +100,12 @@
         private int mBatteryPercentage;
         private int mConnectionStrength;
 
-        public Builder() {}
+        public Builder(@NonNull String deviceName, @NonNull String modelName) {
+            Objects.requireNonNull(deviceName);
+            Objects.requireNonNull(modelName);
+            mDeviceName = deviceName;
+            mModelName = modelName;
+        }
 
         /**
          * Sets the device type that provides connectivity.
@@ -108,6 +127,7 @@
          */
         @NonNull
         public Builder setDeviceName(@NonNull String deviceName) {
+            Objects.requireNonNull(deviceName);
             mDeviceName = deviceName;
             return this;
         }
@@ -120,6 +140,7 @@
          */
         @NonNull
         public Builder setModelName(@NonNull String modelName) {
+            Objects.requireNonNull(modelName);
             mModelName = modelName;
             return this;
         }
@@ -149,29 +170,24 @@
         }
 
         /**
-         * Builds the {@link DeviceInfo} object.
+         * Builds the {@link NetworkProviderInfo} object.
          *
-         * @return Returns the built {@link DeviceInfo} object.
+         * @return Returns the built {@link NetworkProviderInfo} object.
          */
         @NonNull
-        public DeviceInfo build() {
-            return new DeviceInfo(mDeviceType, mDeviceName, mModelName, mBatteryPercentage,
+        public NetworkProviderInfo build() {
+            return new NetworkProviderInfo(mDeviceType, mDeviceName, mModelName, mBatteryPercentage,
                     mConnectionStrength);
         }
     }
 
-    private static void validate(int deviceType, String deviceName, String modelName,
+    private static void validate(@DeviceType int deviceType, String deviceName, String modelName,
             int batteryPercentage, int connectionStrength) {
         if (deviceType != DEVICE_TYPE_UNKNOWN && deviceType != DEVICE_TYPE_PHONE
-                && deviceType != DEVICE_TYPE_TABLET && deviceType != DEVICE_TYPE_LAPTOP) {
+                && deviceType != DEVICE_TYPE_TABLET && deviceType != DEVICE_TYPE_LAPTOP
+                && deviceType != DEVICE_TYPE_WATCH && deviceType != DEVICE_TYPE_AUTO) {
             throw new IllegalArgumentException("Illegal device type");
         }
-        if (Objects.isNull(deviceName)) {
-            throw new IllegalArgumentException("DeviceName must be set");
-        }
-        if (Objects.isNull(modelName)) {
-            throw new IllegalArgumentException("ModelName must be set");
-        }
         if (batteryPercentage < 0 || batteryPercentage > 100) {
             throw new IllegalArgumentException("BatteryPercentage must be in range 0-100");
         }
@@ -180,7 +196,7 @@
         }
     }
 
-    private DeviceInfo(@DeviceType int deviceType, @NonNull String deviceName,
+    private NetworkProviderInfo(@DeviceType int deviceType, @NonNull String deviceName,
             @NonNull String modelName, int batteryPercentage, int connectionStrength) {
         validate(deviceType, deviceName, modelName, batteryPercentage, connectionStrength);
         mDeviceType = deviceType;
@@ -242,8 +258,8 @@
 
     @Override
     public boolean equals(Object obj) {
-        if (!(obj instanceof DeviceInfo)) return false;
-        DeviceInfo other = (DeviceInfo) obj;
+        if (!(obj instanceof NetworkProviderInfo)) return false;
+        NetworkProviderInfo other = (NetworkProviderInfo) obj;
         return mDeviceType == other.getDeviceType()
                 && Objects.equals(mDeviceName, other.mDeviceName)
                 && Objects.equals(mModelName, other.mModelName)
@@ -256,6 +272,7 @@
         return Objects.hash(mDeviceType, mDeviceName, mModelName, mBatteryPercentage,
                 mConnectionStrength);
     }
+
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeInt(mDeviceType);
@@ -271,32 +288,32 @@
     }
 
     /**
-     * Creates a {@link DeviceInfo} object from a parcel.
+     * Creates a {@link NetworkProviderInfo} object from a parcel.
      *
      * @hide
      */
     @NonNull
-    public static DeviceInfo readFromParcel(@NonNull Parcel in) {
-        return new DeviceInfo(in.readInt(), in.readString(), in.readString(), in.readInt(),
+    public static NetworkProviderInfo readFromParcel(@NonNull Parcel in) {
+        return new NetworkProviderInfo(in.readInt(), in.readString(), in.readString(), in.readInt(),
                 in.readInt());
     }
 
     @NonNull
-    public static final Creator<DeviceInfo> CREATOR = new Creator<DeviceInfo>() {
+    public static final Creator<NetworkProviderInfo> CREATOR = new Creator<NetworkProviderInfo>() {
         @Override
-        public DeviceInfo createFromParcel(Parcel in) {
+        public NetworkProviderInfo createFromParcel(Parcel in) {
             return readFromParcel(in);
         }
 
         @Override
-        public DeviceInfo[] newArray(int size) {
-            return new DeviceInfo[size];
+        public NetworkProviderInfo[] newArray(int size) {
+            return new NetworkProviderInfo[size];
         }
     };
 
     @Override
     public String toString() {
-        return new StringBuilder("DeviceInfo[")
+        return new StringBuilder("NetworkProviderInfo[")
                 .append("deviceType=").append(mDeviceType)
                 .append(", deviceName=").append(mDeviceName)
                 .append(", modelName=").append(mModelName)
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityClientCallback.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityClientCallback.java
index d2b9be7..eb04df6 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityClientCallback.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityClientCallback.java
@@ -32,14 +32,16 @@
 public interface SharedConnectivityClientCallback {
     /**
      * This method is being called by {@link SharedConnectivityService} to notify of a change in the
-     * list of available Tether Networks.
-     * @param networks Updated Tether Network list.
+     * list of available Hotspot Networks.
+     *
+     * @param networks Updated Hotspot Network list.
      */
-    void onTetherNetworksUpdated(@NonNull List<TetherNetwork> networks);
+    void onHotspotNetworksUpdated(@NonNull List<HotspotNetwork> networks);
 
     /**
      * This method is being called by {@link SharedConnectivityService} to notify of a change in the
      * list of available Known Networks.
+     *
      * @param networks Updated Known Network list.
      */
     void onKnownNetworksUpdated(@NonNull List<KnownNetwork> networks);
@@ -47,20 +49,23 @@
     /**
      * This method is being called by {@link SharedConnectivityService} to notify of a change in the
      * state of share connectivity settings.
+     *
      * @param state The new state.
      */
     void onSharedConnectivitySettingsChanged(@NonNull SharedConnectivitySettingsState state);
 
     /**
      * This method is being called by {@link SharedConnectivityService} to notify of a change in the
-     * status of the current tether network connection.
+     * status of the current hotspot network connection.
+     *
      * @param status The new status.
      */
-    void onTetherNetworkConnectionStatusChanged(@NonNull TetherNetworkConnectionStatus status);
+    void onHotspotNetworkConnectionStatusChanged(@NonNull HotspotNetworkConnectionStatus status);
 
     /**
      * This method is being called by {@link SharedConnectivityService} to notify of a change in the
      * status of the current known network connection.
+     *
      * @param status The new status.
      */
     void onKnownNetworkConnectionStatusChanged(@NonNull KnownNetworkConnectionStatus status);
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java
index a19510b..15fd817 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java
@@ -19,6 +19,7 @@
 import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
@@ -48,7 +49,7 @@
  * This class is the library used by consumers of Shared Connectivity data to bind to the service,
  * receive callbacks from, and send user actions to the service.
  *
- * The methods {@link #connectTetherNetwork}, {@link #disconnectTetherNetwork},
+ * The methods {@link #connectHotspotNetwork}, {@link #disconnectHotspotNetwork},
  * {@link #connectKnownNetwork} and {@link #forgetKnownNetwork} are not valid and will return false
  * if not called between {@link SharedConnectivityClientCallback#onServiceConnected()}
  * and {@link SharedConnectivityClientCallback#onServiceDisconnected()} or if
@@ -73,12 +74,11 @@
             mCallback = callback;
         }
 
-        @Override
-        public void onTetherNetworksUpdated(@NonNull List<TetherNetwork> networks) {
+        public void onHotspotNetworksUpdated(@NonNull List<HotspotNetwork> networks) {
             if (mCallback != null) {
                 final long token = Binder.clearCallingIdentity();
                 try {
-                    mExecutor.execute(() -> mCallback.onTetherNetworksUpdated(networks));
+                    mExecutor.execute(() -> mCallback.onHotspotNetworksUpdated(networks));
                 } finally {
                     Binder.restoreCallingIdentity(token);
                 }
@@ -110,14 +110,13 @@
             }
         }
 
-        @Override
-        public void onTetherNetworkConnectionStatusChanged(
-                @NonNull TetherNetworkConnectionStatus status) {
+        public void onHotspotNetworkConnectionStatusChanged(
+                @NonNull HotspotNetworkConnectionStatus status) {
             if (mCallback != null) {
                 final long token = Binder.clearCallingIdentity();
                 try {
                     mExecutor.execute(() ->
-                            mCallback.onTetherNetworkConnectionStatusChanged(status));
+                            mCallback.onHotspotNetworkConnectionStatusChanged(status));
                 } finally {
                     Binder.restoreCallingIdentity(token);
                 }
@@ -151,7 +150,7 @@
      * Creates a new instance of {@link SharedConnectivityManager}.
      *
      * Automatically binds to implementation of {@link SharedConnectivityService} specified in
-     * device overlay.
+     * the device overlay.
      *
      * @return An instance of {@link SharedConnectivityManager} or null if the shared connectivity
      * service is not found.
@@ -162,9 +161,9 @@
         Resources resources = context.getResources();
         try {
             String servicePackageName = resources.getString(
-                    R.string.shared_connectivity_service_package);
+                    R.string.config_sharedConnectivityServicePackage);
             String serviceIntentAction = resources.getString(
-                    R.string.shared_connectivity_service_intent_action);
+                    R.string.config_sharedConnectivityServiceIntentAction);
             return new SharedConnectivityManager(context, servicePackageName, serviceIntentAction);
         } catch (Resources.NotFoundException e) {
             Log.e(TAG, "To support shared connectivity service on this device, the service's"
@@ -258,17 +257,18 @@
     }
 
     /**
-     * Registers a callback for receiving updates to the list of Tether Networks, Known Networks,
-     * shared connectivity settings state, tether network connection status and known network
+     * Registers a callback for receiving updates to the list of Hotspot Networks, Known Networks,
+     * shared connectivity settings state, hotspot network connection status and known network
      * connection status.
      * The {@link SharedConnectivityClientCallback#onRegisterCallbackFailed} will be called if the
      * registration failed.
      *
      * @param executor The Executor used to invoke the callback.
      * @param callback The callback of type {@link SharedConnectivityClientCallback} that is invoked
-     *                 when the service updates either the list of Tether Networks or Known
-     *                 Networks.
+     *                 when the service updates its data.
      */
+    @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD})
     public void registerCallback(@NonNull @CallbackExecutor Executor executor,
             @NonNull SharedConnectivityClientCallback callback) {
         Objects.requireNonNull(executor, "executor cannot be null");
@@ -297,6 +297,8 @@
      *
      * @return Returns true if the callback was successfully unregistered, false otherwise.
      */
+    @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD})
     public boolean unregisterCallback(
             @NonNull SharedConnectivityClientCallback callback) {
         Objects.requireNonNull(callback, "callback cannot be null");
@@ -325,26 +327,28 @@
         return true;
     }
 
-     /**
+    /**
      * Send command to the implementation of {@link SharedConnectivityService} requesting connection
-     * to the specified Tether Network.
+     * to the specified Hotspot Network.
      *
-     * @param network {@link TetherNetwork} object representing the network the user has requested
+     * @param network {@link HotspotNetwork} object representing the network the user has requested
      *                a connection to.
      * @return Returns true if the service received the command. Does not guarantee that the
-     *         connection was successful.
+     * connection was successful.
      */
-    public boolean connectTetherNetwork(@NonNull TetherNetwork network) {
-        Objects.requireNonNull(network, "Tether network cannot be null");
+    @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD})
+    public boolean connectHotspotNetwork(@NonNull HotspotNetwork network) {
+        Objects.requireNonNull(network, "Hotspot network cannot be null");
 
         if (mService == null) {
             return false;
         }
 
         try {
-            mService.connectTetherNetwork(network);
+            mService.connectHotspotNetwork(network);
         } catch (RemoteException e) {
-            Log.e(TAG, "Exception in connectTetherNetwork", e);
+            Log.e(TAG, "Exception in connectHotspotNetwork", e);
             return false;
         }
         return true;
@@ -352,22 +356,24 @@
 
     /**
      * Send command to the implementation of {@link SharedConnectivityService} requesting
-     * disconnection from the active Tether Network.
+     * disconnection from the active Hotspot Network.
      *
-     * @param network {@link TetherNetwork} object representing the network the user has requested
+     * @param network {@link HotspotNetwork} object representing the network the user has requested
      *                to disconnect from.
      * @return Returns true if the service received the command. Does not guarantee that the
-     *         disconnection was successful.
+     * disconnection was successful.
      */
-    public boolean disconnectTetherNetwork(@NonNull TetherNetwork network) {
+    @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD})
+    public boolean disconnectHotspotNetwork(@NonNull HotspotNetwork network) {
         if (mService == null) {
             return false;
         }
 
         try {
-            mService.disconnectTetherNetwork(network);
+            mService.disconnectHotspotNetwork(network);
         } catch (RemoteException e) {
-            Log.e(TAG, "Exception in disconnectTetherNetwork", e);
+            Log.e(TAG, "Exception in disconnectHotspotNetwork", e);
             return false;
         }
         return true;
@@ -380,8 +386,10 @@
      * @param network {@link KnownNetwork} object representing the network the user has requested
      *                a connection to.
      * @return Returns true if the service received the command. Does not guarantee that the
-     *         connection was successful.
+     * connection was successful.
      */
+    @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD})
     public boolean connectKnownNetwork(@NonNull KnownNetwork network) {
         Objects.requireNonNull(network, "Known network cannot be null");
 
@@ -403,8 +411,10 @@
      * the specified Known Network from the list of Known Networks.
      *
      * @return Returns true if the service received the command. Does not guarantee that the
-     *         forget action was successful.
+     * forget action was successful.
      */
+    @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD})
     public boolean forgetKnownNetwork(@NonNull KnownNetwork network) {
         Objects.requireNonNull(network, "Known network cannot be null");
 
@@ -422,33 +432,39 @@
     }
 
     /**
-     * Gets the list of tether networks the user can select to connect to.
+     * Gets the list of hotspot networks the user can select to connect to.
      *
-     * @return Returns a {@link List} of {@link TetherNetwork} objects, empty list on failure.
+     * @return Returns a {@link List} of {@link HotspotNetwork} objects, null on failure.
      */
-    @NonNull
-    public List<TetherNetwork> getTetherNetworks() {
+    @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD})
+    @SuppressWarnings("NullableCollection")
+    @Nullable
+    public List<HotspotNetwork> getHotspotNetworks() {
         if (mService == null) {
-            return List.of();
+            return null;
         }
 
         try {
-            return mService.getTetherNetworks();
+            return mService.getHotspotNetworks();
         } catch (RemoteException e) {
-            Log.e(TAG, "Exception in getTetherNetworks", e);
+            Log.e(TAG, "Exception in getHotspotNetworks", e);
         }
-        return List.of();
+        return null;
     }
 
     /**
      * Gets the list of known networks the user can select to connect to.
      *
-     * @return Returns a {@link List} of {@link KnownNetwork} objects, empty list on failure.
+     * @return Returns a {@link List} of {@link KnownNetwork} objects, null on failure.
      */
-    @NonNull
+    @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD})
+    @SuppressWarnings("NullableCollection")
+    @Nullable
     public List<KnownNetwork> getKnownNetworks() {
         if (mService == null) {
-            return List.of();
+            return null;
         }
 
         try {
@@ -456,7 +472,7 @@
         } catch (RemoteException e) {
             Log.e(TAG, "Exception in getKnownNetworks", e);
         }
-        return List.of();
+        return null;
     }
 
     /**
@@ -465,6 +481,8 @@
      * @return Returns a {@link SharedConnectivitySettingsState} object with the state, null on
      * failure.
      */
+    @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD})
     @Nullable
     public SharedConnectivitySettingsState getSettingsState() {
         if (mService == null) {
@@ -480,22 +498,24 @@
     }
 
     /**
-     * Gets the connection status of the tether network the user selected to connect to.
+     * Gets the connection status of the hotspot network the user selected to connect to.
      *
-     * @return Returns a {@link TetherNetworkConnectionStatus} object with the connection status,
+     * @return Returns a {@link HotspotNetworkConnectionStatus} object with the connection status,
      * null on failure. If no connection is active the status will be
-     * {@link TetherNetworkConnectionStatus#CONNECTION_STATUS_UNKNOWN}.
+     * {@link HotspotNetworkConnectionStatus#CONNECTION_STATUS_UNKNOWN}.
      */
+    @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD})
     @Nullable
-    public TetherNetworkConnectionStatus getTetherNetworkConnectionStatus() {
+    public HotspotNetworkConnectionStatus getHotspotNetworkConnectionStatus() {
         if (mService == null) {
             return null;
         }
 
         try {
-            return mService.getTetherNetworkConnectionStatus();
+            return mService.getHotspotNetworkConnectionStatus();
         } catch (RemoteException e) {
-            Log.e(TAG, "Exception in getTetherNetworkConnectionStatus", e);
+            Log.e(TAG, "Exception in getHotspotNetworkConnectionStatus", e);
         }
         return null;
     }
@@ -507,6 +527,8 @@
      * null on failure. If no connection is active the status will be
      * {@link KnownNetworkConnectionStatus#CONNECTION_STATUS_UNKNOWN}.
      */
+    @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD})
     @Nullable
     public KnownNetworkConnectionStatus getKnownNetworkConnectionStatus() {
         if (mService == null) {
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.aidl
deleted file mode 100644
index 6cc4cfe..0000000
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.sharedconnectivity.app;
-
-parcelable TetherNetwork;
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatus.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatus.aidl
deleted file mode 100644
index c677a6c..0000000
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatus.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.sharedconnectivity.app;
-
-parcelable TetherNetworkConnectionStatus;
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatus.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatus.java
deleted file mode 100644
index 3cf44ed..0000000
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatus.java
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.sharedconnectivity.app;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Objects;
-
-/**
- * The status of a connection to an instant tether network after the client called
- * {@link SharedConnectivityManager#connectTetherNetwork}.
- *
- * @hide
- */
-@SystemApi
-public final class TetherNetworkConnectionStatus implements Parcelable {
-
-    /**
-     * Connection status is unknown.
-     */
-    public static final int CONNECTION_STATUS_UNKNOWN  = 0;
-
-    /**
-     * The connection is being initiated.
-     */
-    public static final int CONNECTION_STATUS_ENABLING_HOTSPOT  = 1;
-
-    /**
-     * Device providing the hotspot failed to initiate it.
-     */
-    public static final int CONNECTION_STATUS_UNKNOWN_ERROR = 2;
-
-    /**
-     * Failed to provision tethering.
-     */
-    public static final int CONNECTION_STATUS_PROVISIONING_FAILED = 3;
-
-    /**
-     * Timeout while trying to provision tethering.
-     */
-    public static final int CONNECTION_STATUS_TETHERING_TIMEOUT = 4;
-
-    /**
-     * Device doesn't support tethering.
-     */
-    public static final int CONNECTION_STATUS_TETHERING_UNSUPPORTED = 5;
-
-    /**
-     * Device has no cell data.
-     */
-    public static final int CONNECTION_STATUS_NO_CELL_DATA = 6;
-
-    /**
-     * Device failed to enable hotspot
-     */
-    public static final int CONNECTION_STATUS_ENABLING_HOTSPOT_FAILED = 7;
-
-    /**
-     * Timeout while trying to enable hotspot
-     */
-    public static final int CONNECTION_STATUS_ENABLING_HOTSPOT_TIMEOUT = 8;
-
-    /**
-     * Failed to connect to hotspot
-     */
-    public static final int CONNECTION_STATUS_CONNECT_TO_HOTSPOT_FAILED = 9;
-
-    /**
-     * @hide
-     */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({
-            CONNECTION_STATUS_UNKNOWN,
-            CONNECTION_STATUS_ENABLING_HOTSPOT,
-            CONNECTION_STATUS_UNKNOWN_ERROR,
-            CONNECTION_STATUS_PROVISIONING_FAILED,
-            CONNECTION_STATUS_TETHERING_TIMEOUT,
-            CONNECTION_STATUS_TETHERING_UNSUPPORTED,
-            CONNECTION_STATUS_NO_CELL_DATA,
-            CONNECTION_STATUS_ENABLING_HOTSPOT_FAILED,
-            CONNECTION_STATUS_ENABLING_HOTSPOT_TIMEOUT,
-            CONNECTION_STATUS_CONNECT_TO_HOTSPOT_FAILED,
-    })
-    public @interface ConnectionStatus {}
-
-    @ConnectionStatus private final int mStatus;
-    private final TetherNetwork mTetherNetwork;
-    private final Bundle mExtras;
-
-    /**
-     * Builder class for {@link TetherNetworkConnectionStatus}.
-     */
-    public static final class Builder {
-        @ConnectionStatus private int mStatus;
-        private TetherNetwork mTetherNetwork;
-        private Bundle mExtras;
-
-        public Builder() {}
-
-        /**
-         * Sets the status of the connection
-         *
-         * @return Returns the Builder object.
-         */
-        @NonNull
-        public Builder setStatus(@ConnectionStatus int status) {
-            mStatus = status;
-            return this;
-        }
-
-        /**
-         * Sets the {@link TetherNetwork} object of the connection.
-         *
-         * @return Returns the Builder object.
-         */
-        @NonNull
-        public Builder setTetherNetwork(@NonNull TetherNetwork tetherNetwork) {
-            mTetherNetwork = tetherNetwork;
-            return this;
-        }
-
-        /**
-         * Sets the extras bundle
-         *
-         * @return Returns the Builder object.
-         */
-        @NonNull
-        public Builder setExtras(@NonNull Bundle extras) {
-            mExtras = extras;
-            return this;
-        }
-
-        /**
-         * Builds the {@link TetherNetworkConnectionStatus} object.
-         *
-         * @return Returns the built {@link TetherNetworkConnectionStatus} object.
-         */
-        @NonNull
-        public TetherNetworkConnectionStatus build() {
-            return new TetherNetworkConnectionStatus(mStatus, mTetherNetwork, mExtras);
-        }
-    }
-
-    private TetherNetworkConnectionStatus(@ConnectionStatus int status, TetherNetwork tetherNetwork,
-            Bundle extras) {
-        mStatus = status;
-        mTetherNetwork = tetherNetwork;
-        mExtras = extras;
-    }
-
-    /**
-     * Gets the status of the connection
-     *
-     * @return Returns true for enabled, false otherwise.
-     */
-    @ConnectionStatus
-    public int getStatus() {
-        return mStatus;
-    }
-
-    /**
-     * Gets the {@link TetherNetwork} object of the connection.
-     *
-     * @return Returns a TetherNetwork object.
-     */
-    @NonNull
-    public TetherNetwork getTetherNetwork() {
-        return mTetherNetwork;
-    }
-
-    /**
-     * Gets the extras Bundle.
-     *
-     * @return Returns a Bundle object.
-     */
-    @NonNull
-    public Bundle getExtras() {
-        return mExtras;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (!(obj instanceof TetherNetworkConnectionStatus)) return false;
-        TetherNetworkConnectionStatus other = (TetherNetworkConnectionStatus) obj;
-        return mStatus == other.getStatus()
-                && Objects.equals(mTetherNetwork, other.getTetherNetwork());
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(mStatus, mTetherNetwork);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeInt(mStatus);
-        mTetherNetwork.writeToParcel(dest, flags);
-        dest.writeBundle(mExtras);
-    }
-
-    /**
-     * Creates a {@link TetherNetworkConnectionStatus} object from a parcel.
-     *
-     * @hide
-     */
-    @NonNull
-    public static TetherNetworkConnectionStatus readFromParcel(@NonNull Parcel in) {
-        return new TetherNetworkConnectionStatus(in.readInt(),
-                TetherNetwork.readFromParcel(in), in.readBundle());
-    }
-
-    @NonNull
-    public static final Creator<TetherNetworkConnectionStatus> CREATOR = new Creator<>() {
-        @Override
-        public TetherNetworkConnectionStatus createFromParcel(Parcel in) {
-            return readFromParcel(in);
-        }
-
-        @Override
-        public TetherNetworkConnectionStatus[] newArray(int size) {
-            return new TetherNetworkConnectionStatus[size];
-        }
-    };
-
-    @Override
-    public String toString() {
-        return new StringBuilder("TetherNetworkConnectionStatus[")
-                .append("status=").append(mStatus)
-                .append("tether network=").append(mTetherNetwork.toString())
-                .append("extras=").append(mExtras.toString())
-                .append("]").toString();
-    }
-}
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityCallback.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityCallback.aidl
index 6f6f162..737aa6d 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityCallback.aidl
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityCallback.aidl
@@ -19,15 +19,15 @@
 import android.net.wifi.sharedconnectivity.app.KnownNetwork;
 import android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus;
 import android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState;
-import android.net.wifi.sharedconnectivity.app.TetherNetwork;
-import android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus;
+import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
+import android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus;
 
 /*
  * @hide
  */
 interface ISharedConnectivityCallback {
-    oneway void onTetherNetworksUpdated(in List<TetherNetwork> networks);
-    oneway void onTetherNetworkConnectionStatusChanged(in TetherNetworkConnectionStatus status);
+    oneway void onHotspotNetworksUpdated(in List<HotspotNetwork> networks);
+    oneway void onHotspotNetworkConnectionStatusChanged(in HotspotNetworkConnectionStatus status);
     oneway void onKnownNetworksUpdated(in List<KnownNetwork> networks);
     oneway void onKnownNetworkConnectionStatusChanged(in KnownNetworkConnectionStatus status);
     oneway void onSharedConnectivitySettingsChanged(in SharedConnectivitySettingsState state);
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityService.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityService.aidl
index 9f33e99..c81380d 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityService.aidl
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityService.aidl
@@ -17,10 +17,10 @@
 package android.net.wifi.sharedconnectivity.service;
 
 import android.net.wifi.sharedconnectivity.app.KnownNetwork;
-import android.net.wifi.sharedconnectivity.app.TetherNetwork;
+import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
 import android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus;
 import android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState;
-import android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus;
+import android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus;
 import android.net.wifi.sharedconnectivity.service.ISharedConnectivityCallback;
 
 /*
@@ -29,13 +29,13 @@
 interface ISharedConnectivityService {
     void registerCallback(in ISharedConnectivityCallback callback);
     void unregisterCallback(in ISharedConnectivityCallback callback);
-    void connectTetherNetwork(in TetherNetwork network);
-    void disconnectTetherNetwork(in TetherNetwork network);
+    void connectHotspotNetwork(in HotspotNetwork network);
+    void disconnectHotspotNetwork(in HotspotNetwork network);
     void connectKnownNetwork(in KnownNetwork network);
     void forgetKnownNetwork(in KnownNetwork network);
-    List<TetherNetwork> getTetherNetworks();
+    List<HotspotNetwork> getHotspotNetworks();
     List<KnownNetwork> getKnownNetworks();
     SharedConnectivitySettingsState getSettingsState();
-    TetherNetworkConnectionStatus getTetherNetworkConnectionStatus();
+    HotspotNetworkConnectionStatus getHotspotNetworkConnectionStatus();
     KnownNetworkConnectionStatus getKnownNetworkConnectionStatus();
 }
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java b/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
index d2cea61..57108e4 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
@@ -25,14 +25,15 @@
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.app.Service;
+import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
+import android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus;
 import android.net.wifi.sharedconnectivity.app.KnownNetwork;
 import android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus;
 import android.net.wifi.sharedconnectivity.app.SharedConnectivityManager;
 import android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState;
-import android.net.wifi.sharedconnectivity.app.TetherNetwork;
-import android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -40,8 +41,11 @@
 import android.os.RemoteException;
 import android.util.Log;
 
+import com.android.internal.R;
+
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 
 
 /**
@@ -62,14 +66,14 @@
     private Handler mHandler;
     private final RemoteCallbackList<ISharedConnectivityCallback> mRemoteCallbackList =
             new RemoteCallbackList<>();
-    private List<TetherNetwork> mTetherNetworks = Collections.emptyList();
+    private List<HotspotNetwork> mHotspotNetworks = Collections.emptyList();
     private List<KnownNetwork> mKnownNetworks = Collections.emptyList();
     private SharedConnectivitySettingsState mSettingsState =
             new SharedConnectivitySettingsState.Builder().setInstantTetherEnabled(false)
                     .setExtras(Bundle.EMPTY).build();
-    private TetherNetworkConnectionStatus mTetherNetworkConnectionStatus =
-            new TetherNetworkConnectionStatus.Builder()
-                    .setStatus(TetherNetworkConnectionStatus.CONNECTION_STATUS_UNKNOWN)
+    private HotspotNetworkConnectionStatus mHotspotNetworkConnectionStatus =
+            new HotspotNetworkConnectionStatus.Builder()
+                    .setStatus(HotspotNetworkConnectionStatus.CONNECTION_STATUS_UNKNOWN)
                     .setExtras(Bundle.EMPTY).build();
     private KnownNetworkConnectionStatus mKnownNetworkConnectionStatus =
             new KnownNetworkConnectionStatus.Builder()
@@ -82,66 +86,147 @@
         if (DEBUG) Log.i(TAG, "onBind intent=" + intent);
         mHandler = new Handler(getMainLooper());
         IBinder serviceStub = new ISharedConnectivityService.Stub() {
+
+            /**
+             * Registers a callback for receiving updates to the list of Hotspot Networks, Known
+             * Networks, shared connectivity settings state, hotspot network connection status and
+             * known network connection status.
+             *
+             * @param callback The callback of type {@link ISharedConnectivityCallback} to be called
+             *                 when there is update to the data.
+             */
+            @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+                    android.Manifest.permission.NETWORK_SETUP_WIZARD})
             @Override
             public void registerCallback(ISharedConnectivityCallback callback) {
                 checkPermissions();
                 mHandler.post(() -> onRegisterCallback(callback));
             }
 
+            /**
+             * Unregisters a previously registered callback.
+             *
+             * @param callback The callback to unregister.
+             */
+            @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+                    android.Manifest.permission.NETWORK_SETUP_WIZARD})
             @Override
             public void unregisterCallback(ISharedConnectivityCallback callback) {
                 checkPermissions();
                 mHandler.post(() -> onUnregisterCallback(callback));
             }
 
+            /**
+             * Connects to a hotspot network.
+             *
+             * @param network The network to connect to.
+             */
+            @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+                    android.Manifest.permission.NETWORK_SETUP_WIZARD})
             @Override
-            public void connectTetherNetwork(TetherNetwork network) {
+            public void connectHotspotNetwork(HotspotNetwork network) {
                 checkPermissions();
-                mHandler.post(() -> onConnectTetherNetwork(network));
+                mHandler.post(() -> onConnectHotspotNetwork(network));
             }
 
-            @Override
-            public void disconnectTetherNetwork(TetherNetwork network) {
+            /**
+             * Disconnects from a previously connected hotspot network.
+             *
+             * @param network The network to disconnect from.
+             */
+            @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+                    android.Manifest.permission.NETWORK_SETUP_WIZARD})
+            public void disconnectHotspotNetwork(HotspotNetwork network) {
                 checkPermissions();
-                mHandler.post(() -> onDisconnectTetherNetwork(network));
+                mHandler.post(() -> onDisconnectHotspotNetwork(network));
             }
 
+            /**
+             * Adds a known network to the available networks on the device and connects to it.
+             *
+             * @param network The network to connect to.
+             */
+            @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+                    android.Manifest.permission.NETWORK_SETUP_WIZARD})
             @Override
             public void connectKnownNetwork(KnownNetwork network) {
                 checkPermissions();
                 mHandler.post(() -> onConnectKnownNetwork(network));
             }
 
+            /**
+             * Removes a known network from the available networks on the device which will also
+             * disconnect the device from the network if it is connected to it.
+             *
+             * @param network The network to forget.
+             */
             @Override
             public void forgetKnownNetwork(KnownNetwork network) {
                 checkPermissions();
                 mHandler.post(() -> onForgetKnownNetwork(network));
             }
 
+            /**
+             * Gets the list of hotspot networks the user can select to connect to.
+             *
+             * @return Returns a {@link List} of {@link HotspotNetwork} objects
+             */
+            @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+                    android.Manifest.permission.NETWORK_SETUP_WIZARD})
             @Override
-            public List<TetherNetwork> getTetherNetworks() {
+            public List<HotspotNetwork> getHotspotNetworks() {
                 checkPermissions();
-                return mTetherNetworks;
+                return mHotspotNetworks;
             }
 
+            /**
+             * Gets the list of known networks the user can select to connect to.
+             *
+             * @return Returns a {@link List} of {@link KnownNetwork} objects.
+             */
+            @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+                    android.Manifest.permission.NETWORK_SETUP_WIZARD})
             @Override
             public List<KnownNetwork> getKnownNetworks() {
                 checkPermissions();
                 return mKnownNetworks;
             }
 
+            /**
+             * Gets the shared connectivity settings state.
+             *
+             * @return Returns a {@link SharedConnectivitySettingsState} object with the state.
+             */
+            @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+                    android.Manifest.permission.NETWORK_SETUP_WIZARD})
             @Override
             public SharedConnectivitySettingsState getSettingsState() {
                 checkPermissions();
                 return mSettingsState;
             }
 
+            /**
+             * Gets the connection status of the hotspot network the user selected to connect to.
+             *
+             * @return Returns a {@link HotspotNetworkConnectionStatus} object with the connection
+             * status.
+             */
+            @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+                    android.Manifest.permission.NETWORK_SETUP_WIZARD})
             @Override
-            public TetherNetworkConnectionStatus getTetherNetworkConnectionStatus() {
+            public HotspotNetworkConnectionStatus getHotspotNetworkConnectionStatus() {
                 checkPermissions();
-                return mTetherNetworkConnectionStatus;
+                return mHotspotNetworkConnectionStatus;
             }
 
+            /**
+             * Gets the connection status of the known network the user selected to connect to.
+             *
+             * @return Returns a {@link KnownNetworkConnectionStatus} object with the connection
+             * status.
+             */
+            @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+                    android.Manifest.permission.NETWORK_SETUP_WIZARD})
             @Override
             public KnownNetworkConnectionStatus getKnownNetworkConnectionStatus() {
                 checkPermissions();
@@ -172,7 +257,8 @@
 
     /** @hide */
     @TestApi
-    public void onBind() {}
+    public void onBind() {
+    }
 
     private void onRegisterCallback(ISharedConnectivityCallback callback) {
         mRemoteCallbackList.register(callback);
@@ -183,23 +269,23 @@
     }
 
     /**
-     * Implementing application should call this method to provide an up-to-date list of Tether
+     * Implementing application should call this method to provide an up-to-date list of Hotspot
      * Networks to be displayed to the user.
      *
      * This method updates the cached list and notifies all registered callbacks. Any callbacks that
      * are inaccessible will be unregistered.
      *
-     * @param networks The updated list of {@link TetherNetwork} objects.
+     * @param networks The updated list of {@link HotspotNetwork} objects.
      */
-    public final void setTetherNetworks(@NonNull List<TetherNetwork> networks) {
-        mTetherNetworks = networks;
+    public final void setHotspotNetworks(@NonNull List<HotspotNetwork> networks) {
+        mHotspotNetworks = networks;
 
         int count = mRemoteCallbackList.beginBroadcast();
         for (int i = 0; i < count; i++) {
             try {
-                mRemoteCallbackList.getBroadcastItem(i).onTetherNetworksUpdated(mTetherNetworks);
+                mRemoteCallbackList.getBroadcastItem(i).onHotspotNetworksUpdated(mHotspotNetworks);
             } catch (RemoteException e) {
-                if (DEBUG) Log.w(TAG, "Exception in setTetherNetworks", e);
+                if (DEBUG) Log.w(TAG, "Exception in setHotspotNetworks", e);
             }
         }
         mRemoteCallbackList.finishBroadcast();
@@ -236,7 +322,7 @@
      * that are inaccessible will be unregistered.
      *
      * @param settingsState The updated state {@link SharedConnectivitySettingsState}
-     *                 objects.
+     *                      objects.
      */
     public final void setSettingsState(@NonNull SharedConnectivitySettingsState settingsState) {
         mSettingsState = settingsState;
@@ -255,23 +341,22 @@
 
     /**
      * Implementing application should call this method to provide an up-to-date status of enabling
-     * and connecting to the tether network.
+     * and connecting to the hotspot network.
      *
-     * @param status The updated status {@link TetherNetworkConnectionStatus} of the connection.
-     *
+     * @param status The updated status {@link HotspotNetworkConnectionStatus} of the connection.
      */
-    public final void updateTetherNetworkConnectionStatus(
-            @NonNull TetherNetworkConnectionStatus status) {
-        mTetherNetworkConnectionStatus = status;
+    public final void updateHotspotNetworkConnectionStatus(
+            @NonNull HotspotNetworkConnectionStatus status) {
+        mHotspotNetworkConnectionStatus = status;
 
         int count = mRemoteCallbackList.beginBroadcast();
         for (int i = 0; i < count; i++) {
             try {
                 mRemoteCallbackList
-                        .getBroadcastItem(i).onTetherNetworkConnectionStatusChanged(
-                                mTetherNetworkConnectionStatus);
+                        .getBroadcastItem(i).onHotspotNetworkConnectionStatusChanged(
+                                mHotspotNetworkConnectionStatus);
             } catch (RemoteException e) {
-                if (DEBUG) Log.w(TAG, "Exception in updateTetherNetworkConnectionStatus", e);
+                if (DEBUG) Log.w(TAG, "Exception in updateHotspotNetworkConnectionStatus", e);
             }
         }
         mRemoteCallbackList.finishBroadcast();
@@ -282,7 +367,6 @@
      * connecting to a known network.
      *
      * @param status The updated status {@link KnownNetworkConnectionStatus} of the connection.
-     *
      */
     public final void updateKnownNetworkConnectionStatus(
             @NonNull KnownNetworkConnectionStatus status) {
@@ -302,22 +386,46 @@
     }
 
     /**
-     * Implementing application should implement this method.
-     *
-     * Implementation should initiate a connection to the Tether Network indicated.
-     *
-     * @param network Object identifying the Tether Network the user has requested a connection to.
+     * System and settings UI support on the device for instant tether.
+     * @return True if the UI can display Instant Tether network data. False otherwise.
      */
-    public abstract void onConnectTetherNetwork(@NonNull TetherNetwork network);
+    public static boolean areHotspotNetworksEnabledForService(@NonNull Context context) {
+        String servicePackage = context.getResources()
+                .getString(R.string.config_sharedConnectivityServicePackage);
+        return Objects.equals(context.getPackageName(), servicePackage)
+                && context.getResources()
+                        .getBoolean(R.bool.config_hotspotNetworksEnabledForService);
+    }
+
+    /**
+     * System and settings UI support on the device for known networks.
+     * @return True if the UI can display known networks data. False otherwise.
+     */
+    public static boolean areKnownNetworksEnabledForService(@NonNull Context context) {
+        String servicePackage = context.getResources()
+                .getString(R.string.config_sharedConnectivityServicePackage);
+        return Objects.equals(context.getPackageName(), servicePackage)
+                && context.getResources()
+                        .getBoolean(R.bool.config_knownNetworksEnabledForService);
+    }
 
     /**
      * Implementing application should implement this method.
      *
-     * Implementation should initiate a disconnection from the active Tether Network.
+     * Implementation should initiate a connection to the Hotspot Network indicated.
      *
-     * @param network Object identifying the Tether Network the user has requested to disconnect.
+     * @param network Object identifying the Hotspot Network the user has requested a connection to.
      */
-    public abstract void onDisconnectTetherNetwork(@NonNull TetherNetwork network);
+    public abstract void onConnectHotspotNetwork(@NonNull HotspotNetwork network);
+
+    /**
+     * Implementing application should implement this method.
+     *
+     * Implementation should initiate a disconnection from the active Hotspot Network.
+     *
+     * @param network Object identifying the Hotspot Network the user has requested to disconnect.
+     */
+    public abstract void onDisconnectHotspotNetwork(@NonNull HotspotNetwork network);
 
     /**
      * Implementing application should implement this method.
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/DeviceInfoTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/DeviceInfoTest.java
deleted file mode 100644
index f8f0700..0000000
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/DeviceInfoTest.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.sharedconnectivity.app;
-
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_LAPTOP;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_PHONE;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-
-import android.os.Parcel;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-
-/**
- * Unit tests for {@link android.app.sharedconnectivity.DeviceInfo}.
- */
-@SmallTest
-public class DeviceInfoTest {
-
-    private static final int DEVICE_TYPE = DEVICE_TYPE_PHONE;
-    private static final String DEVICE_NAME = "TEST_NAME";
-    private static final String DEVICE_MODEL = "TEST_MODEL";
-    private static final int BATTERY_PERCENTAGE = 50;
-    private static final int CONNECTION_STRENGTH = 2;
-
-    private static final int DEVICE_TYPE_1 = DEVICE_TYPE_LAPTOP;
-    private static final String DEVICE_NAME_1 = "TEST_NAME1";
-    private static final String DEVICE_MODEL_1 = "TEST_MODEL1";
-    private static final int BATTERY_PERCENTAGE_1 = 30;
-    private static final int CONNECTION_STRENGTH_1 = 1;
-
-    /**
-     * Verifies parcel serialization/deserialization.
-     */
-    @Test
-    public void testParcelOperation() {
-        DeviceInfo info = buildDeviceInfoBuilder().build();
-
-        Parcel parcelW = Parcel.obtain();
-        info.writeToParcel(parcelW, 0);
-        byte[] bytes = parcelW.marshall();
-        parcelW.recycle();
-
-        Parcel parcelR = Parcel.obtain();
-        parcelR.unmarshall(bytes, 0, bytes.length);
-        parcelR.setDataPosition(0);
-        DeviceInfo fromParcel = DeviceInfo.CREATOR.createFromParcel(parcelR);
-
-        assertEquals(info, fromParcel);
-        assertEquals(info.hashCode(), fromParcel.hashCode());
-    }
-
-    /**
-     * Verifies the Equals operation
-     */
-    @Test
-    public void testEqualsOperation() {
-        DeviceInfo info1 = buildDeviceInfoBuilder().build();
-        DeviceInfo info2 = buildDeviceInfoBuilder().build();
-        assertEquals(info1, info2);
-
-        DeviceInfo.Builder builder = buildDeviceInfoBuilder().setDeviceType(DEVICE_TYPE_1);
-        assertNotEquals(info1, builder.build());
-
-        builder = buildDeviceInfoBuilder().setDeviceName(DEVICE_NAME_1);
-        assertNotEquals(info1, builder.build());
-
-        builder = buildDeviceInfoBuilder().setModelName(DEVICE_MODEL_1);
-        assertNotEquals(info1, builder.build());
-
-        builder = buildDeviceInfoBuilder()
-                .setBatteryPercentage(BATTERY_PERCENTAGE_1);
-        assertNotEquals(info1, builder.build());
-
-        builder = buildDeviceInfoBuilder()
-                .setConnectionStrength(CONNECTION_STRENGTH_1);
-        assertNotEquals(info1, builder.build());
-    }
-
-    /**
-     * Verifies the get methods return the expected data.
-     */
-    @Test
-    public void testGetMethods() {
-        DeviceInfo info = buildDeviceInfoBuilder().build();
-        assertEquals(info.getDeviceType(), DEVICE_TYPE);
-        assertEquals(info.getDeviceName(), DEVICE_NAME);
-        assertEquals(info.getModelName(), DEVICE_MODEL);
-        assertEquals(info.getBatteryPercentage(), BATTERY_PERCENTAGE);
-        assertEquals(info.getConnectionStrength(), CONNECTION_STRENGTH);
-        assertEquals(info.getConnectionStrength(), CONNECTION_STRENGTH);
-    }
-
-    private DeviceInfo.Builder buildDeviceInfoBuilder() {
-        return new DeviceInfo.Builder().setDeviceType(DEVICE_TYPE).setDeviceName(DEVICE_NAME)
-                .setModelName(DEVICE_MODEL).setBatteryPercentage(BATTERY_PERCENTAGE)
-                .setConnectionStrength(CONNECTION_STRENGTH);
-    }
-}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatusTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatusTest.java
new file mode 100644
index 0000000..b18ab50
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatusTest.java
@@ -0,0 +1,139 @@
+/*
+ * 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.net.wifi.sharedconnectivity.app;
+
+import static android.net.wifi.WifiInfo.SECURITY_TYPE_EAP;
+import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetwork.NETWORK_TYPE_CELLULAR;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.CONNECTION_STATUS_TETHERING_TIMEOUT;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Bundle;
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+import java.util.Arrays;
+
+/**
+ * Unit tests for {@link HotspotNetworkConnectionStatus}.
+ */
+@SmallTest
+public class HotspotNetworkConnectionStatusTest {
+    private static final long DEVICE_ID = 11L;
+    private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
+            new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
+                    .setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
+                    .setBatteryPercentage(50).build();
+    private static final int NETWORK_TYPE = NETWORK_TYPE_CELLULAR;
+    private static final String NETWORK_NAME = "TEST_NETWORK";
+    private static final String HOTSPOT_SSID = "TEST_SSID";
+    private static final String HOTSPOT_BSSID = "TEST _BSSID";
+    private static final int[] HOTSPOT_SECURITY_TYPES = {SECURITY_TYPE_WEP, SECURITY_TYPE_EAP};
+    private static final long DEVICE_ID_1 = 111L;
+    private static final String BUNDLE_KEY = "INT-KEY";
+    private static final int BUNDLE_VALUE = 1;
+
+    /**
+     * Verifies parcel serialization/deserialization.
+     */
+    @Test
+    public void testParcelOperation() {
+        HotspotNetworkConnectionStatus status = buildConnectionStatusBuilder().build();
+
+        Parcel parcelW = Parcel.obtain();
+        status.writeToParcel(parcelW, 0);
+        byte[] bytes = parcelW.marshall();
+        parcelW.recycle();
+
+        Parcel parcelR = Parcel.obtain();
+        parcelR.unmarshall(bytes, 0, bytes.length);
+        parcelR.setDataPosition(0);
+        HotspotNetworkConnectionStatus fromParcel =
+                HotspotNetworkConnectionStatus.CREATOR.createFromParcel(parcelR);
+
+        assertThat(fromParcel).isEqualTo(status);
+        assertThat(fromParcel.hashCode()).isEqualTo(status.hashCode());
+    }
+
+    /**
+     * Verifies the Equals operation
+     */
+    @Test
+    public void testEqualsOperation() {
+        HotspotNetworkConnectionStatus status1 = buildConnectionStatusBuilder().build();
+        HotspotNetworkConnectionStatus status2 = buildConnectionStatusBuilder().build();
+        assertThat(status1).isEqualTo(status2);
+
+        HotspotNetworkConnectionStatus.Builder builder = buildConnectionStatusBuilder()
+                .setStatus(CONNECTION_STATUS_TETHERING_TIMEOUT);
+        assertThat(builder.build()).isNotEqualTo(status1);
+
+        builder = buildConnectionStatusBuilder()
+                .setHotspotNetwork(buildHotspotNetworkBuilder().setDeviceId(DEVICE_ID_1).build());
+        assertThat(builder.build()).isNotEqualTo(status1);
+    }
+
+    /**
+     * Verifies the get methods return the expected data.
+     */
+    @Test
+    public void testGetMethods() {
+        HotspotNetworkConnectionStatus status = buildConnectionStatusBuilder().build();
+        assertThat(status.getStatus()).isEqualTo(CONNECTION_STATUS_ENABLING_HOTSPOT);
+        assertThat(status.getHotspotNetwork()).isEqualTo(buildHotspotNetworkBuilder().build());
+        assertThat(status.getExtras().getInt(BUNDLE_KEY)).isEqualTo(BUNDLE_VALUE);
+    }
+
+    @Test
+    public void testHashCode() {
+        HotspotNetworkConnectionStatus status1 = buildConnectionStatusBuilder().build();
+        HotspotNetworkConnectionStatus status2 = buildConnectionStatusBuilder().build();
+
+        assertThat(status1.hashCode()).isEqualTo(status2.hashCode());
+    }
+
+    private HotspotNetworkConnectionStatus.Builder buildConnectionStatusBuilder() {
+        return new HotspotNetworkConnectionStatus.Builder()
+                .setStatus(CONNECTION_STATUS_ENABLING_HOTSPOT)
+                .setHotspotNetwork(buildHotspotNetworkBuilder().build())
+                .setExtras(buildBundle());
+    }
+
+    private Bundle buildBundle() {
+        Bundle bundle = new Bundle();
+        bundle.putInt(BUNDLE_KEY, BUNDLE_VALUE);
+        return bundle;
+    }
+
+    private HotspotNetwork.Builder buildHotspotNetworkBuilder() {
+        HotspotNetwork.Builder builder = new HotspotNetwork.Builder()
+                .setDeviceId(DEVICE_ID)
+                .setNetworkProviderInfo(NETWORK_PROVIDER_INFO)
+                .setHostNetworkType(NETWORK_TYPE)
+                .setNetworkName(NETWORK_NAME)
+                .setHotspotSsid(HOTSPOT_SSID)
+                .setHotspotBssid(HOTSPOT_BSSID);
+        Arrays.stream(HOTSPOT_SECURITY_TYPES).forEach(builder::addHotspotSecurityType);
+        return builder;
+    }
+}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkTest.java
new file mode 100644
index 0000000..8302094
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkTest.java
@@ -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 android.net.wifi.sharedconnectivity.app;
+
+import static android.net.wifi.WifiInfo.SECURITY_TYPE_EAP;
+import static android.net.wifi.WifiInfo.SECURITY_TYPE_PSK;
+import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetwork.NETWORK_TYPE_CELLULAR;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetwork.NETWORK_TYPE_WIFI;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_PHONE;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+
+import android.os.Parcel;
+import android.util.ArraySet;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+
+/**
+ * Unit tests for {@link HotspotNetwork}.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class HotspotNetworkTest {
+    private static final long DEVICE_ID = 11L;
+    private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
+            new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
+                    .setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
+                    .setBatteryPercentage(50).build();
+    private static final int NETWORK_TYPE = NETWORK_TYPE_CELLULAR;
+    private static final String NETWORK_NAME = "TEST_NETWORK";
+    private static final String HOTSPOT_SSID = "TEST_SSID";
+    private static final String HOTSPOT_BSSID = "TEST _BSSID";
+    private static final int[] HOTSPOT_SECURITY_TYPES = {SECURITY_TYPE_WEP, SECURITY_TYPE_EAP};
+
+    private static final long DEVICE_ID_1 = 111L;
+    private static final NetworkProviderInfo NETWORK_PROVIDER_INFO1 =
+            new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
+                    .setDeviceType(DEVICE_TYPE_PHONE).setConnectionStrength(2)
+                    .setBatteryPercentage(50).build();
+    private static final int NETWORK_TYPE_1 = NETWORK_TYPE_WIFI;
+    private static final String NETWORK_NAME_1 = "TEST_NETWORK1";
+    private static final String HOTSPOT_SSID_1 = "TEST_SSID1";
+    private static final String HOTSPOT_BSSID_1 = "TEST _BSSID1";
+    private static final int[] HOTSPOT_SECURITY_TYPES_1 = {SECURITY_TYPE_PSK, SECURITY_TYPE_EAP};
+
+    /**
+     * Verifies parcel serialization/deserialization.
+     */
+    @Test
+    public void testParcelOperation() {
+        HotspotNetwork network = buildHotspotNetworkBuilder(true).build();
+
+        Parcel parcelW = Parcel.obtain();
+        network.writeToParcel(parcelW, 0);
+        byte[] bytes = parcelW.marshall();
+        parcelW.recycle();
+
+        Parcel parcelR = Parcel.obtain();
+        parcelR.unmarshall(bytes, 0, bytes.length);
+        parcelR.setDataPosition(0);
+        HotspotNetwork fromParcel = HotspotNetwork.CREATOR.createFromParcel(parcelR);
+
+        assertThat(fromParcel).isEqualTo(network);
+        assertThat(fromParcel.hashCode()).isEqualTo(network.hashCode());
+    }
+
+    /**
+     * Verifies the Equals operation
+     */
+    @Test
+    public void testEqualsOperation() {
+        HotspotNetwork network1 = buildHotspotNetworkBuilder(true).build();
+        HotspotNetwork network2 = buildHotspotNetworkBuilder(true).build();
+        assertThat(network1).isEqualTo(network2);
+
+        HotspotNetwork.Builder builder = buildHotspotNetworkBuilder(true).setDeviceId(DEVICE_ID_1);
+        assertThat(builder.build()).isNotEqualTo(network1);
+
+        builder = buildHotspotNetworkBuilder(true).setNetworkProviderInfo(NETWORK_PROVIDER_INFO1);
+        assertThat(builder.build()).isNotEqualTo(network1);
+
+        builder = buildHotspotNetworkBuilder(true).setHostNetworkType(NETWORK_TYPE_1);
+        assertThat(builder.build()).isNotEqualTo(network1);
+
+        builder = buildHotspotNetworkBuilder(true).setNetworkName(NETWORK_NAME_1);
+        assertThat(builder.build()).isNotEqualTo(network1);
+
+        builder = buildHotspotNetworkBuilder(true).setHotspotSsid(HOTSPOT_SSID_1);
+        assertThat(builder.build()).isNotEqualTo(network1);
+
+        builder = buildHotspotNetworkBuilder(true).setHotspotBssid(HOTSPOT_BSSID_1);
+        assertThat(builder.build()).isNotEqualTo(network1);
+
+        builder = buildHotspotNetworkBuilder(true);
+        HotspotNetwork.Builder builder1 = buildHotspotNetworkBuilder(true);
+        Arrays.stream(HOTSPOT_SECURITY_TYPES_1).forEach(builder1::addHotspotSecurityType);
+
+        assertThat(builder1.build()).isNotEqualTo(builder.build());
+    }
+
+    /**
+     * Verifies the get methods return the expected data.
+     */
+    @Test
+    public void testGetMethods() {
+        HotspotNetwork network = buildHotspotNetworkBuilder(true).build();
+        ArraySet<Integer> securityTypes = new ArraySet<>();
+        Arrays.stream(HOTSPOT_SECURITY_TYPES).forEach(securityTypes::add);
+
+        assertThat(network.getDeviceId()).isEqualTo(DEVICE_ID);
+        assertThat(network.getNetworkProviderInfo()).isEqualTo(NETWORK_PROVIDER_INFO);
+        assertThat(network.getHostNetworkType()).isEqualTo(NETWORK_TYPE);
+        assertThat(network.getNetworkName()).isEqualTo(NETWORK_NAME);
+        assertThat(network.getHotspotSsid()).isEqualTo(HOTSPOT_SSID);
+        assertThat(network.getHotspotBssid()).isEqualTo(HOTSPOT_BSSID);
+        assertThat(network.getHotspotSecurityTypes()).containsExactlyElementsIn(securityTypes);
+    }
+
+    @Test
+    public void testHashCode() {
+        HotspotNetwork network1 = buildHotspotNetworkBuilder(true).build();
+        HotspotNetwork network2 = buildHotspotNetworkBuilder(true).build();
+
+        assertThat(network1.hashCode()).isEqualTo(network2.hashCode());
+    }
+
+    @Test
+    public void networkProviderInfoNotSet_shouldThrowException() {
+        Exception e = assertThrows(IllegalArgumentException.class,
+                () -> buildHotspotNetworkBuilder(false).build());
+        assertThat(e.getMessage()).contains("NetworkProviderInfo");
+    }
+
+    private HotspotNetwork.Builder buildHotspotNetworkBuilder(boolean withNetworkProviderInfo) {
+        HotspotNetwork.Builder builder = new HotspotNetwork.Builder()
+                .setDeviceId(DEVICE_ID)
+                .setHostNetworkType(NETWORK_TYPE)
+                .setNetworkName(NETWORK_NAME)
+                .setHotspotSsid(HOTSPOT_SSID)
+                .setHotspotBssid(HOTSPOT_BSSID);
+        Arrays.stream(HOTSPOT_SECURITY_TYPES).forEach(builder::addHotspotSecurityType);
+        if (withNetworkProviderInfo) {
+            builder.setNetworkProviderInfo(NETWORK_PROVIDER_INFO);
+        }
+        return builder;
+    }
+}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatusTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatusTest.java
index 37dca8d..f98a0fc 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatusTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatusTest.java
@@ -17,13 +17,12 @@
 package android.net.wifi.sharedconnectivity.app;
 
 import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_TABLET;
 import static android.net.wifi.sharedconnectivity.app.KnownNetwork.NETWORK_SOURCE_NEARBY_SELF;
 import static android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus.CONNECTION_STATUS_SAVED;
 import static android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus.CONNECTION_STATUS_SAVE_FAILED;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
+import static com.google.common.truth.Truth.assertThat;
 
 import android.os.Bundle;
 import android.os.Parcel;
@@ -32,19 +31,23 @@
 
 import org.junit.Test;
 
+import java.util.Arrays;
+
 /**
- * Unit tests for {@link android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus}.
+ * Unit tests for {@link KnownNetworkConnectionStatus}.
  */
 @SmallTest
 public class KnownNetworkConnectionStatusTest {
     private static final int NETWORK_SOURCE = NETWORK_SOURCE_NEARBY_SELF;
     private static final String SSID = "TEST_SSID";
     private static final int[] SECURITY_TYPES = {SECURITY_TYPE_WEP};
-    private static final DeviceInfo DEVICE_INFO = new DeviceInfo.Builder()
-            .setDeviceType(DEVICE_TYPE_TABLET).setDeviceName("TEST_NAME").setModelName("TEST_MODEL")
-            .setConnectionStrength(2).setBatteryPercentage(50).build();
+    private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
+            new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
+                    .setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
+                    .setBatteryPercentage(50).build();
     private static final String SSID_1 = "TEST_SSID1";
     private static final String BUNDLE_KEY = "INT-KEY";
+    private static final int BUNDLE_VALUE = 1;
 
     /**
      * Verifies parcel serialization/deserialization.
@@ -64,8 +67,8 @@
         KnownNetworkConnectionStatus fromParcel =
                 KnownNetworkConnectionStatus.CREATOR.createFromParcel(parcelR);
 
-        assertEquals(status, fromParcel);
-        assertEquals(status.hashCode(), fromParcel.hashCode());
+        assertThat(fromParcel).isEqualTo(status);
+        assertThat(fromParcel.hashCode()).isEqualTo(status.hashCode());
     }
 
     /**
@@ -75,15 +78,15 @@
     public void testEqualsOperation() {
         KnownNetworkConnectionStatus status1 = buildConnectionStatusBuilder().build();
         KnownNetworkConnectionStatus status2 = buildConnectionStatusBuilder().build();
-        assertEquals(status2, status2);
+        assertThat(status1).isEqualTo(status2);
 
         KnownNetworkConnectionStatus.Builder builder = buildConnectionStatusBuilder()
                 .setStatus(CONNECTION_STATUS_SAVE_FAILED);
-        assertNotEquals(status1, builder.build());
+        assertThat(builder.build()).isNotEqualTo(status1);
 
         builder = buildConnectionStatusBuilder()
                 .setKnownNetwork(buildKnownNetworkBuilder().setSsid(SSID_1).build());
-        assertNotEquals(status1, builder.build());
+        assertThat(builder.build()).isNotEqualTo(status1);
     }
 
     /**
@@ -92,9 +95,17 @@
     @Test
     public void testGetMethods() {
         KnownNetworkConnectionStatus status = buildConnectionStatusBuilder().build();
-        assertEquals(status.getStatus(), CONNECTION_STATUS_SAVED);
-        assertEquals(status.getKnownNetwork(), buildKnownNetworkBuilder().build());
-        assertEquals(status.getExtras().getInt(BUNDLE_KEY), buildBundle().getInt(BUNDLE_KEY));
+        assertThat(status.getStatus()).isEqualTo(CONNECTION_STATUS_SAVED);
+        assertThat(status.getKnownNetwork()).isEqualTo(buildKnownNetworkBuilder().build());
+        assertThat(status.getExtras().getInt(BUNDLE_KEY)).isEqualTo(BUNDLE_VALUE);
+    }
+
+    @Test
+    public void testHashCode() {
+        KnownNetworkConnectionStatus status1 = buildConnectionStatusBuilder().build();
+        KnownNetworkConnectionStatus status2 = buildConnectionStatusBuilder().build();
+
+        assertThat(status1.hashCode()).isEqualTo(status2.hashCode());
     }
 
     private KnownNetworkConnectionStatus.Builder buildConnectionStatusBuilder() {
@@ -106,13 +117,15 @@
 
     private Bundle buildBundle() {
         Bundle bundle = new Bundle();
-        bundle.putInt(BUNDLE_KEY, 1);
+        bundle.putInt(BUNDLE_KEY, BUNDLE_VALUE);
         return bundle;
     }
 
     private KnownNetwork.Builder buildKnownNetworkBuilder() {
-        return new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE).setSsid(SSID)
-                .setSecurityTypes(SECURITY_TYPES).setDeviceInfo(DEVICE_INFO);
+        KnownNetwork.Builder builder = new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE)
+                .setSsid(SSID).setNetworkProviderInfo(NETWORK_PROVIDER_INFO);
+        Arrays.stream(SECURITY_TYPES).forEach(builder::addSecurityType);
+        return builder;
     }
 
 }
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java
index 266afcc..1ecba76 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java
@@ -18,23 +18,24 @@
 
 import static android.net.wifi.WifiInfo.SECURITY_TYPE_PSK;
 import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_PHONE;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_TABLET;
 import static android.net.wifi.sharedconnectivity.app.KnownNetwork.NETWORK_SOURCE_CLOUD_SELF;
 import static android.net.wifi.sharedconnectivity.app.KnownNetwork.NETWORK_SOURCE_NEARBY_SELF;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_PHONE;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
 
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
+import static com.google.common.truth.Truth.assertThat;
 
 import android.os.Parcel;
+import android.util.ArraySet;
 
 import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
 
+import java.util.Arrays;
+
 /**
- * Unit tests for {@link android.app.sharedconnectivity.KnownNetwork}.
+ * Unit tests for {@link KnownNetwork}.
  */
 @SmallTest
 public class KnownNetworkTest {
@@ -42,15 +43,17 @@
     private static final int NETWORK_SOURCE = NETWORK_SOURCE_NEARBY_SELF;
     private static final String SSID = "TEST_SSID";
     private static final int[] SECURITY_TYPES = {SECURITY_TYPE_WEP};
-    private static final DeviceInfo DEVICE_INFO = new DeviceInfo.Builder()
-            .setDeviceType(DEVICE_TYPE_TABLET).setDeviceName("TEST_NAME").setModelName("TEST_MODEL")
-            .setConnectionStrength(2).setBatteryPercentage(50).build();
+    private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
+            new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
+                    .setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
+                    .setBatteryPercentage(50).build();
     private static final int NETWORK_SOURCE_1 = NETWORK_SOURCE_CLOUD_SELF;
     private static final String SSID_1 = "TEST_SSID1";
     private static final int[] SECURITY_TYPES_1 = {SECURITY_TYPE_PSK};
-    private static final DeviceInfo DEVICE_INFO_1 = new DeviceInfo.Builder()
-            .setDeviceType(DEVICE_TYPE_PHONE).setDeviceName("TEST_NAME_1")
-            .setModelName("TEST_MODEL_1").setConnectionStrength(3).setBatteryPercentage(33).build();
+    private static final NetworkProviderInfo NETWORK_PROVIDER_INFO1 =
+            new NetworkProviderInfo.Builder("TEST_NAME_1", "TEST_MODEL_1")
+                    .setDeviceType(DEVICE_TYPE_PHONE).setConnectionStrength(3)
+                    .setBatteryPercentage(33).build();
 
     /**
      * Verifies parcel serialization/deserialization.
@@ -69,8 +72,8 @@
         parcelR.setDataPosition(0);
         KnownNetwork fromParcel = KnownNetwork.CREATOR.createFromParcel(parcelR);
 
-        assertEquals(network, fromParcel);
-        assertEquals(network.hashCode(), fromParcel.hashCode());
+        assertThat(fromParcel).isEqualTo(network);
+        assertThat(fromParcel.hashCode()).isEqualTo(network.hashCode());
     }
 
     /**
@@ -80,20 +83,21 @@
     public void testEqualsOperation() {
         KnownNetwork network1 = buildKnownNetworkBuilder().build();
         KnownNetwork network2 = buildKnownNetworkBuilder().build();
-        assertEquals(network1, network2);
+        assertThat(network1).isEqualTo(network2);
 
         KnownNetwork.Builder builder = buildKnownNetworkBuilder()
                 .setNetworkSource(NETWORK_SOURCE_1);
-        assertNotEquals(network1, builder.build());
+        assertThat(builder.build()).isNotEqualTo(network1);
 
         builder = buildKnownNetworkBuilder().setSsid(SSID_1);
-        assertNotEquals(network1, builder.build());
+        assertThat(builder.build()).isNotEqualTo(network1);
 
-        builder = buildKnownNetworkBuilder().setSecurityTypes(SECURITY_TYPES_1);
-        assertNotEquals(network1, builder.build());
+        builder = buildKnownNetworkBuilder();
+        Arrays.stream(SECURITY_TYPES_1).forEach(builder::addSecurityType);
+        assertThat(builder.build()).isNotEqualTo(network1);
 
-        builder = buildKnownNetworkBuilder().setDeviceInfo(DEVICE_INFO_1);
-        assertNotEquals(network1, builder.build());
+        builder = buildKnownNetworkBuilder().setNetworkProviderInfo(NETWORK_PROVIDER_INFO1);
+        assertThat(builder.build()).isNotEqualTo(network1);
     }
 
     /**
@@ -102,14 +106,27 @@
     @Test
     public void testGetMethods() {
         KnownNetwork network = buildKnownNetworkBuilder().build();
-        assertEquals(network.getNetworkSource(), NETWORK_SOURCE);
-        assertEquals(network.getSsid(), SSID);
-        assertArrayEquals(network.getSecurityTypes(), SECURITY_TYPES);
-        assertEquals(network.getDeviceInfo(), DEVICE_INFO);
+        ArraySet<Integer> securityTypes = new ArraySet<>();
+        Arrays.stream(SECURITY_TYPES).forEach(securityTypes::add);
+
+        assertThat(network.getNetworkSource()).isEqualTo(NETWORK_SOURCE);
+        assertThat(network.getSsid()).isEqualTo(SSID);
+        assertThat(network.getSecurityTypes()).containsExactlyElementsIn(securityTypes);
+        assertThat(network.getNetworkProviderInfo()).isEqualTo(NETWORK_PROVIDER_INFO);
+    }
+
+    @Test
+    public void testHashCode() {
+        KnownNetwork network1 = buildKnownNetworkBuilder().build();
+        KnownNetwork network2 = buildKnownNetworkBuilder().build();
+
+        assertThat(network1.hashCode()).isEqualTo(network2.hashCode());
     }
 
     private KnownNetwork.Builder buildKnownNetworkBuilder() {
-        return new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE).setSsid(SSID)
-                .setSecurityTypes(SECURITY_TYPES).setDeviceInfo(DEVICE_INFO);
+        KnownNetwork.Builder builder = new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE)
+                .setSsid(SSID).setNetworkProviderInfo(NETWORK_PROVIDER_INFO);
+        Arrays.stream(SECURITY_TYPES).forEach(builder::addSecurityType);
+        return builder;
     }
 }
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfoTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfoTest.java
new file mode 100644
index 0000000..8f35d8d
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfoTest.java
@@ -0,0 +1,123 @@
+/*
+ * 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.net.wifi.sharedconnectivity.app;
+
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_LAPTOP;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_PHONE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link NetworkProviderInfo}.
+ */
+@SmallTest
+public class NetworkProviderInfoTest {
+
+    private static final int DEVICE_TYPE = DEVICE_TYPE_PHONE;
+    private static final String DEVICE_NAME = "TEST_NAME";
+    private static final String DEVICE_MODEL = "TEST_MODEL";
+    private static final int BATTERY_PERCENTAGE = 50;
+    private static final int CONNECTION_STRENGTH = 2;
+
+    private static final int DEVICE_TYPE_1 = DEVICE_TYPE_LAPTOP;
+    private static final String DEVICE_NAME_1 = "TEST_NAME1";
+    private static final String DEVICE_MODEL_1 = "TEST_MODEL1";
+    private static final int BATTERY_PERCENTAGE_1 = 30;
+    private static final int CONNECTION_STRENGTH_1 = 1;
+
+    /**
+     * Verifies parcel serialization/deserialization.
+     */
+    @Test
+    public void testParcelOperation() {
+        NetworkProviderInfo info = buildNetworkProviderInfoBuilder().build();
+
+        Parcel parcelW = Parcel.obtain();
+        info.writeToParcel(parcelW, 0);
+        byte[] bytes = parcelW.marshall();
+        parcelW.recycle();
+
+        Parcel parcelR = Parcel.obtain();
+        parcelR.unmarshall(bytes, 0, bytes.length);
+        parcelR.setDataPosition(0);
+        NetworkProviderInfo fromParcel = NetworkProviderInfo.CREATOR.createFromParcel(parcelR);
+
+        assertThat(fromParcel).isEqualTo(info);
+        assertThat(fromParcel.hashCode()).isEqualTo(info.hashCode());
+    }
+
+    /**
+     * Verifies the Equals operation
+     */
+    @Test
+    public void testEqualsOperation() {
+        NetworkProviderInfo info1 = buildNetworkProviderInfoBuilder().build();
+        NetworkProviderInfo info2 = buildNetworkProviderInfoBuilder().build();
+        assertThat(info1).isEqualTo(info2);
+
+        NetworkProviderInfo.Builder builder = buildNetworkProviderInfoBuilder().setDeviceType(
+                DEVICE_TYPE_1);
+        assertThat(builder.build()).isNotEqualTo(info1);
+
+        builder = buildNetworkProviderInfoBuilder().setDeviceName(DEVICE_NAME_1);
+        assertThat(builder.build()).isNotEqualTo(info1);
+
+        builder = buildNetworkProviderInfoBuilder().setModelName(DEVICE_MODEL_1);
+        assertThat(builder.build()).isNotEqualTo(info1);
+
+        builder = buildNetworkProviderInfoBuilder()
+                .setBatteryPercentage(BATTERY_PERCENTAGE_1);
+        assertThat(builder.build()).isNotEqualTo(info1);
+
+        builder = buildNetworkProviderInfoBuilder()
+                .setConnectionStrength(CONNECTION_STRENGTH_1);
+        assertThat(builder.build()).isNotEqualTo(info1);
+    }
+
+    /**
+     * Verifies the get methods return the expected data.
+     */
+    @Test
+    public void testGetMethods() {
+        NetworkProviderInfo info = buildNetworkProviderInfoBuilder().build();
+        assertThat(info.getDeviceType()).isEqualTo(DEVICE_TYPE);
+        assertThat(info.getDeviceName()).isEqualTo(DEVICE_NAME);
+        assertThat(info.getModelName()).isEqualTo(DEVICE_MODEL);
+        assertThat(info.getBatteryPercentage()).isEqualTo(BATTERY_PERCENTAGE);
+        assertThat(info.getConnectionStrength()).isEqualTo(CONNECTION_STRENGTH);
+    }
+
+    @Test
+    public void testHashCode() {
+        NetworkProviderInfo info1 = buildNetworkProviderInfoBuilder().build();
+        NetworkProviderInfo info2 = buildNetworkProviderInfoBuilder().build();
+
+        assertThat(info1.hashCode()).isEqualTo(info2.hashCode());
+    }
+
+    private NetworkProviderInfo.Builder buildNetworkProviderInfoBuilder() {
+        return new NetworkProviderInfo.Builder(DEVICE_NAME, DEVICE_MODEL).setDeviceType(DEVICE_TYPE)
+                .setBatteryPercentage(BATTERY_PERCENTAGE)
+                .setConnectionStrength(CONNECTION_STRENGTH);
+    }
+}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java
index cdb438f..7578dfd 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java
@@ -18,15 +18,12 @@
 
 import static android.net.wifi.WifiInfo.SECURITY_TYPE_EAP;
 import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_TABLET;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetwork.NETWORK_TYPE_CELLULAR;
 import static android.net.wifi.sharedconnectivity.app.KnownNetwork.NETWORK_SOURCE_NEARBY_SELF;
-import static android.net.wifi.sharedconnectivity.app.TetherNetwork.NETWORK_TYPE_CELLULAR;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
 
-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 com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doThrow;
@@ -49,6 +46,7 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.Executor;
 
@@ -58,9 +56,10 @@
 @SmallTest
 public class SharedConnectivityManagerTest {
     private static final long DEVICE_ID = 11L;
-    private static final DeviceInfo DEVICE_INFO = new DeviceInfo.Builder()
-            .setDeviceType(DEVICE_TYPE_TABLET).setDeviceName("TEST_NAME").setModelName("TEST_MODEL")
-            .setConnectionStrength(2).setBatteryPercentage(50).build();
+    private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
+            new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
+                    .setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
+                    .setBatteryPercentage(50).build();
     private static final int NETWORK_TYPE = NETWORK_TYPE_CELLULAR;
     private static final String NETWORK_NAME = "TEST_NETWORK";
     private static final String HOTSPOT_SSID = "TEST_SSID";
@@ -74,13 +73,16 @@
     private static final String SERVICE_INTENT_ACTION = "TEST_INTENT_ACTION";
 
 
-    @Mock Context mContext;
+    @Mock
+    Context mContext;
     @Mock
     ISharedConnectivityService mService;
-    @Mock Executor mExecutor;
+    @Mock
+    Executor mExecutor;
     @Mock
     SharedConnectivityClientCallback mClientCallback;
-    @Mock Resources mResources;
+    @Mock
+    Resources mResources;
     @Mock
     ISharedConnectivityService.Stub mIBinder;
 
@@ -110,7 +112,7 @@
     public void resourcesNotDefined() {
         when(mResources.getString(anyInt())).thenThrow(new Resources.NotFoundException());
 
-        assertNull(SharedConnectivityManager.create(mContext));
+        assertThat(SharedConnectivityManager.create(mContext)).isNull();
     }
 
     /**
@@ -183,7 +185,7 @@
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(null);
 
-        assertFalse(manager.unregisterCallback(mClientCallback));
+        assertThat(manager.unregisterCallback(mClientCallback)).isFalse();
     }
 
     @Test
@@ -191,7 +193,7 @@
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
 
-        assertFalse(manager.unregisterCallback(mClientCallback));
+        assertThat(manager.unregisterCallback(mClientCallback)).isFalse();
     }
 
     @Test
@@ -201,7 +203,7 @@
 
         manager.registerCallback(mExecutor, mClientCallback);
 
-        assertTrue(manager.unregisterCallback(mClientCallback));
+        assertThat(manager.unregisterCallback(mClientCallback)).isTrue();
         verify(mService).unregisterCallback(any());
     }
 
@@ -213,7 +215,7 @@
         manager.registerCallback(mExecutor, mClientCallback);
         manager.unregisterCallback(mClientCallback);
 
-        assertFalse(manager.unregisterCallback(mClientCallback));
+        assertThat(manager.unregisterCallback(mClientCallback)).isFalse();
     }
 
     @Test
@@ -224,7 +226,7 @@
         manager.registerCallback(mExecutor, mClientCallback);
         manager.unregisterCallback(mClientCallback);
 
-        assertFalse(manager.unregisterCallback(mClientCallback));
+        assertThat(manager.unregisterCallback(mClientCallback)).isFalse();
     }
 
     @Test
@@ -234,7 +236,7 @@
 
         doThrow(new RemoteException()).when(mService).unregisterCallback(any());
 
-        assertFalse(manager.unregisterCallback(mClientCallback));
+        assertThat(manager.unregisterCallback(mClientCallback)).isFalse();
     }
 
     /**
@@ -286,69 +288,69 @@
     }
 
     /**
-     * Verifies connectTetherNetwork behavior.
+     * Verifies connectHotspotNetwork behavior.
      */
     @Test
-    public void connectTetherNetwork_serviceNotConnected_shouldFail() {
-        TetherNetwork network = buildTetherNetwork();
+    public void connectHotspotNetwork_serviceNotConnected_shouldFail() {
+        HotspotNetwork network = buildHotspotNetwork();
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(null);
 
-        assertFalse(manager.connectTetherNetwork(network));
+        assertThat(manager.connectHotspotNetwork(network)).isFalse();
     }
 
     @Test
-    public void connectTetherNetwork() throws RemoteException {
-        TetherNetwork network = buildTetherNetwork();
+    public void connectHotspotNetwork() throws RemoteException {
+        HotspotNetwork network = buildHotspotNetwork();
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
 
-        manager.connectTetherNetwork(network);
+        manager.connectHotspotNetwork(network);
 
-        verify(mService).connectTetherNetwork(network);
+        verify(mService).connectHotspotNetwork(network);
     }
 
     @Test
-    public void connectTetherNetwork_remoteException_shouldFail() throws RemoteException {
-        TetherNetwork network = buildTetherNetwork();
+    public void connectHotspotNetwork_remoteException_shouldFail() throws RemoteException {
+        HotspotNetwork network = buildHotspotNetwork();
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
-        doThrow(new RemoteException()).when(mService).connectTetherNetwork(network);
+        doThrow(new RemoteException()).when(mService).connectHotspotNetwork(network);
 
-        assertFalse(manager.connectTetherNetwork(network));
+        assertThat(manager.connectHotspotNetwork(network)).isFalse();
     }
 
     /**
-     * Verifies disconnectTetherNetwork behavior.
+     * Verifies disconnectHotspotNetwork behavior.
      */
     @Test
-    public void disconnectTetherNetwork_serviceNotConnected_shouldFail() {
-        TetherNetwork network = buildTetherNetwork();
+    public void disconnectHotspotNetwork_serviceNotConnected_shouldFail() {
+        HotspotNetwork network = buildHotspotNetwork();
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(null);
 
-        assertFalse(manager.disconnectTetherNetwork(network));
+        assertThat(manager.disconnectHotspotNetwork(network)).isFalse();
     }
 
     @Test
-    public void disconnectTetherNetwork() throws RemoteException {
-        TetherNetwork network = buildTetherNetwork();
+    public void disconnectHotspotNetwork() throws RemoteException {
+        HotspotNetwork network = buildHotspotNetwork();
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
 
-        manager.disconnectTetherNetwork(network);
+        manager.disconnectHotspotNetwork(network);
 
-        verify(mService).disconnectTetherNetwork(network);
+        verify(mService).disconnectHotspotNetwork(network);
     }
 
     @Test
-    public void disconnectTetherNetwork_remoteException_shouldFail() throws RemoteException {
-        TetherNetwork network = buildTetherNetwork();
+    public void disconnectHotspotNetwork_remoteException_shouldFail() throws RemoteException {
+        HotspotNetwork network = buildHotspotNetwork();
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
-        doThrow(new RemoteException()).when(mService).disconnectTetherNetwork(any());
+        doThrow(new RemoteException()).when(mService).disconnectHotspotNetwork(any());
 
-        assertFalse(manager.disconnectTetherNetwork(network));
+        assertThat(manager.disconnectHotspotNetwork(network)).isFalse();
     }
 
     /**
@@ -360,7 +362,7 @@
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(null);
 
-        assertFalse(manager.connectKnownNetwork(network));
+        assertThat(manager.connectKnownNetwork(network)).isFalse();
     }
 
     @Test
@@ -381,7 +383,7 @@
         manager.setService(mService);
         doThrow(new RemoteException()).when(mService).connectKnownNetwork(network);
 
-        assertFalse(manager.connectKnownNetwork(network));
+        assertThat(manager.connectKnownNetwork(network)).isFalse();
     }
 
     /**
@@ -393,7 +395,7 @@
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(null);
 
-        assertFalse(manager.forgetKnownNetwork(network));
+        assertThat(manager.forgetKnownNetwork(network)).isFalse();
     }
 
     @Test
@@ -414,67 +416,65 @@
         manager.setService(mService);
         doThrow(new RemoteException()).when(mService).forgetKnownNetwork(network);
 
-        assertFalse(manager.forgetKnownNetwork(network));
+        assertThat(manager.forgetKnownNetwork(network)).isFalse();
     }
 
     /**
      * Verify getters.
      */
     @Test
-    public void getTetherNetworks_serviceNotConnected_shouldReturnEmptyList() {
+    public void getHotspotNetworks_serviceNotConnected_shouldReturnNull() {
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(null);
 
-        assertArrayEquals(List.of().toArray(), manager.getTetherNetworks().toArray());
+        assertThat(manager.getHotspotNetworks()).isNull();
     }
 
     @Test
-    public void getTetherNetworks_remoteException_shouldReturnEmptyList() throws RemoteException {
+    public void getHotspotNetworks_remoteException_shouldReturnNull() throws RemoteException {
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
-        doThrow(new RemoteException()).when(mService).getTetherNetworks();
+        doThrow(new RemoteException()).when(mService).getHotspotNetworks();
 
-        assertArrayEquals(List.of().toArray(), manager.getTetherNetworks().toArray());
+        assertThat(manager.getHotspotNetworks()).isNull();
     }
 
     @Test
-    public void getTetherNetworks_shouldReturnNetworksList() throws RemoteException {
+    public void getHotspotNetworks_shouldReturnNetworksList() throws RemoteException {
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
-        List<TetherNetwork> networks = List.of(buildTetherNetwork());
-        List<TetherNetwork> expected = List.of(buildTetherNetwork());
+        List<HotspotNetwork> networks = List.of(buildHotspotNetwork());
         manager.setService(mService);
-        when(mService.getTetherNetworks()).thenReturn(networks);
+        when(mService.getHotspotNetworks()).thenReturn(networks);
 
-        assertArrayEquals(expected.toArray(), manager.getTetherNetworks().toArray());
+        assertThat(manager.getHotspotNetworks()).containsExactly(buildHotspotNetwork());
     }
 
     @Test
-    public void getKnownNetworks_serviceNotConnected_shouldReturnEmptyList()
+    public void getKnownNetworks_serviceNotConnected_shouldReturnNull()
             throws RemoteException {
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(null);
 
-        assertArrayEquals(List.of().toArray(), manager.getKnownNetworks().toArray());
+        assertThat(manager.getKnownNetworks()).isNull();
     }
 
     @Test
-    public void getKnownNetworks_remoteException_shouldReturnEmptyList() throws RemoteException {
+    public void getKnownNetworks_remoteException_shouldReturnNull() throws RemoteException {
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
         doThrow(new RemoteException()).when(mService).getKnownNetworks();
 
-        assertArrayEquals(List.of().toArray(), manager.getKnownNetworks().toArray());
+        assertThat(manager.getKnownNetworks()).isNull();
     }
 
     @Test
     public void getKnownNetworks_shouldReturnNetworksList() throws RemoteException {
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         List<KnownNetwork> networks = List.of(buildKnownNetwork());
-        List<KnownNetwork> expected = List.of(buildKnownNetwork());
         manager.setService(mService);
         when(mService.getKnownNetworks()).thenReturn(networks);
 
-        assertArrayEquals(expected.toArray(), manager.getKnownNetworks().toArray());
+        assertThat(manager.getKnownNetworks()).containsExactly(buildKnownNetwork());
     }
 
     @Test
@@ -482,7 +482,7 @@
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(null);
 
-        assertNull(manager.getSettingsState());
+        assertThat(manager.getSettingsState()).isNull();
     }
 
     @Test
@@ -491,7 +491,7 @@
         manager.setService(mService);
         doThrow(new RemoteException()).when(mService).getSettingsState();
 
-        assertNull(manager.getSettingsState());
+        assertThat(manager.getSettingsState()).isNull();
     }
 
     @Test
@@ -502,39 +502,39 @@
         manager.setService(mService);
         when(mService.getSettingsState()).thenReturn(state);
 
-        assertEquals(state, manager.getSettingsState());
+        assertThat(manager.getSettingsState()).isEqualTo(state);
     }
 
     @Test
-    public void getTetherNetworkConnectionStatus_serviceNotConnected_shouldReturnNull()
+    public void getHotspotNetworkConnectionStatus_serviceNotConnected_shouldReturnNull()
             throws RemoteException {
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(null);
 
-        assertNull(manager.getTetherNetworkConnectionStatus());
+        assertThat(manager.getHotspotNetworkConnectionStatus()).isNull();
     }
 
     @Test
-    public void getTetherNetworkConnectionStatus_remoteException_shouldReturnNull()
+    public void getHotspotNetworkConnectionStatus_remoteException_shouldReturnNull()
             throws RemoteException {
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
-        doThrow(new RemoteException()).when(mService).getTetherNetworkConnectionStatus();
+        doThrow(new RemoteException()).when(mService).getHotspotNetworkConnectionStatus();
 
-        assertNull(manager.getTetherNetworkConnectionStatus());
+        assertThat(manager.getHotspotNetworkConnectionStatus()).isNull();
     }
 
     @Test
-    public void getTetherNetworkConnectionStatus_serviceConnected_shouldReturnStatus()
+    public void getHotspotNetworkConnectionStatus_serviceConnected_shouldReturnStatus()
             throws RemoteException {
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
-        TetherNetworkConnectionStatus status = new TetherNetworkConnectionStatus.Builder()
-                .setStatus(TetherNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT)
+        HotspotNetworkConnectionStatus status = new HotspotNetworkConnectionStatus.Builder()
+                .setStatus(HotspotNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT)
                 .setExtras(new Bundle()).build();
         manager.setService(mService);
-        when(mService.getTetherNetworkConnectionStatus()).thenReturn(status);
+        when(mService.getHotspotNetworkConnectionStatus()).thenReturn(status);
 
-        assertEquals(status, manager.getTetherNetworkConnectionStatus());
+        assertThat(manager.getHotspotNetworkConnectionStatus()).isEqualTo(status);
     }
 
     @Test
@@ -543,7 +543,7 @@
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(null);
 
-        assertNull(manager.getKnownNetworkConnectionStatus());
+        assertThat(manager.getKnownNetworkConnectionStatus()).isNull();
     }
 
     @Test
@@ -553,7 +553,7 @@
         manager.setService(mService);
         doThrow(new RemoteException()).when(mService).getKnownNetworkConnectionStatus();
 
-        assertNull(manager.getKnownNetworkConnectionStatus());
+        assertThat(manager.getKnownNetworkConnectionStatus()).isNull();
     }
 
     @Test
@@ -566,7 +566,7 @@
         manager.setService(mService);
         when(mService.getKnownNetworkConnectionStatus()).thenReturn(status);
 
-        assertEquals(status, manager.getKnownNetworkConnectionStatus());
+        assertThat(manager.getKnownNetworkConnectionStatus()).isEqualTo(status);
     }
 
     private void setResources(@Mock Context context) {
@@ -575,19 +575,21 @@
                 .thenReturn(SERVICE_PACKAGE_NAME, SERVICE_INTENT_ACTION);
     }
 
-    private TetherNetwork buildTetherNetwork() {
-        return new TetherNetwork.Builder()
+    private HotspotNetwork buildHotspotNetwork() {
+        HotspotNetwork.Builder builder = new HotspotNetwork.Builder()
                 .setDeviceId(DEVICE_ID)
-                .setDeviceInfo(DEVICE_INFO)
-                .setNetworkType(NETWORK_TYPE)
+                .setNetworkProviderInfo(NETWORK_PROVIDER_INFO)
+                .setHostNetworkType(NETWORK_TYPE)
                 .setNetworkName(NETWORK_NAME)
-                .setHotspotSsid(HOTSPOT_SSID)
-                .setHotspotSecurityTypes(HOTSPOT_SECURITY_TYPES)
-                .build();
+                .setHotspotSsid(HOTSPOT_SSID);
+        Arrays.stream(HOTSPOT_SECURITY_TYPES).forEach(builder::addHotspotSecurityType);
+        return builder.build();
     }
 
     private KnownNetwork buildKnownNetwork() {
-        return new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE).setSsid(SSID)
-                .setSecurityTypes(SECURITY_TYPES).build();
+        KnownNetwork.Builder builder = new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE)
+                .setSsid(SSID).setNetworkProviderInfo(NETWORK_PROVIDER_INFO);
+        Arrays.stream(SECURITY_TYPES).forEach(builder::addSecurityType);
+        return builder.build();
     }
 }
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsStateTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsStateTest.java
index 3137c72..752b749 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsStateTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsStateTest.java
@@ -16,8 +16,7 @@
 
 package android.net.wifi.sharedconnectivity.app;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
+import static com.google.common.truth.Truth.assertThat;
 
 import android.os.Parcel;
 
@@ -26,7 +25,7 @@
 import org.junit.Test;
 
 /**
- * Unit tests for {@link android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState}.
+ * Unit tests for {@link SharedConnectivitySettingsState}.
  */
 @SmallTest
 public class SharedConnectivitySettingsStateTest {
@@ -51,8 +50,8 @@
         SharedConnectivitySettingsState fromParcel =
                 SharedConnectivitySettingsState.CREATOR.createFromParcel(parcelR);
 
-        assertEquals(state, fromParcel);
-        assertEquals(state.hashCode(), fromParcel.hashCode());
+        assertThat(fromParcel).isEqualTo(state);
+        assertThat(fromParcel.hashCode()).isEqualTo(state.hashCode());
     }
 
     /**
@@ -62,11 +61,11 @@
     public void testEqualsOperation() {
         SharedConnectivitySettingsState state1 = buildSettingsStateBuilder().build();
         SharedConnectivitySettingsState state2 = buildSettingsStateBuilder().build();
-        assertEquals(state1, state2);
+        assertThat(state1).isEqualTo(state2);
 
         SharedConnectivitySettingsState.Builder builder = buildSettingsStateBuilder()
                 .setInstantTetherEnabled(INSTANT_TETHER_STATE_1);
-        assertNotEquals(state1, builder.build());
+        assertThat(builder.build()).isNotEqualTo(state1);
     }
 
     /**
@@ -75,7 +74,15 @@
     @Test
     public void testGetMethods() {
         SharedConnectivitySettingsState state = buildSettingsStateBuilder().build();
-        assertEquals(state.isInstantTetherEnabled(), INSTANT_TETHER_STATE);
+        assertThat(state.isInstantTetherEnabled()).isEqualTo(INSTANT_TETHER_STATE);
+    }
+
+    @Test
+    public void testHashCode() {
+        SharedConnectivitySettingsState state1 = buildSettingsStateBuilder().build();
+        SharedConnectivitySettingsState state2 = buildSettingsStateBuilder().build();
+
+        assertThat(state1.hashCode()).isEqualTo(state2.hashCode());
     }
 
     private SharedConnectivitySettingsState.Builder buildSettingsStateBuilder() {
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatusTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatusTest.java
deleted file mode 100644
index 1d9c2e6..0000000
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatusTest.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.sharedconnectivity.app;
-
-import static android.net.wifi.WifiInfo.SECURITY_TYPE_EAP;
-import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_TABLET;
-import static android.net.wifi.sharedconnectivity.app.TetherNetwork.NETWORK_TYPE_CELLULAR;
-import static android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT;
-import static android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus.CONNECTION_STATUS_TETHERING_TIMEOUT;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-
-import android.os.Bundle;
-import android.os.Parcel;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-
-/**
- * Unit tests for {@link android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus}.
- */
-@SmallTest
-public class TetherNetworkConnectionStatusTest {
-    private static final long DEVICE_ID = 11L;
-    private static final DeviceInfo DEVICE_INFO = new DeviceInfo.Builder()
-            .setDeviceType(DEVICE_TYPE_TABLET).setDeviceName("TEST_NAME").setModelName("TEST_MODEL")
-            .setConnectionStrength(2).setBatteryPercentage(50).build();
-    private static final int NETWORK_TYPE = NETWORK_TYPE_CELLULAR;
-    private static final String NETWORK_NAME = "TEST_NETWORK";
-    private static final String HOTSPOT_SSID = "TEST_SSID";
-    private static final String HOTSPOT_BSSID = "TEST _BSSID";
-    private static final int[] HOTSPOT_SECURITY_TYPES = {SECURITY_TYPE_WEP, SECURITY_TYPE_EAP};
-    private static final long DEVICE_ID_1 = 111L;
-    private static final String BUNDLE_KEY = "INT-KEY";
-
-    /**
-     * Verifies parcel serialization/deserialization.
-     */
-    @Test
-    public void testParcelOperation() {
-        TetherNetworkConnectionStatus status = buildConnectionStatusBuilder().build();
-
-        Parcel parcelW = Parcel.obtain();
-        status.writeToParcel(parcelW, 0);
-        byte[] bytes = parcelW.marshall();
-        parcelW.recycle();
-
-        Parcel parcelR = Parcel.obtain();
-        parcelR.unmarshall(bytes, 0, bytes.length);
-        parcelR.setDataPosition(0);
-        TetherNetworkConnectionStatus fromParcel =
-                TetherNetworkConnectionStatus.CREATOR.createFromParcel(parcelR);
-
-        assertEquals(status, fromParcel);
-        assertEquals(status.hashCode(), fromParcel.hashCode());
-    }
-
-    /**
-     * Verifies the Equals operation
-     */
-    @Test
-    public void testEqualsOperation() {
-        TetherNetworkConnectionStatus status1 = buildConnectionStatusBuilder().build();
-        TetherNetworkConnectionStatus status2 = buildConnectionStatusBuilder().build();
-        assertEquals(status2, status2);
-
-        TetherNetworkConnectionStatus.Builder builder = buildConnectionStatusBuilder()
-                .setStatus(CONNECTION_STATUS_TETHERING_TIMEOUT);
-        assertNotEquals(status1, builder.build());
-
-        builder = buildConnectionStatusBuilder()
-                .setTetherNetwork(buildTetherNetworkBuilder().setDeviceId(DEVICE_ID_1).build());
-        assertNotEquals(status1, builder.build());
-    }
-
-    /**
-     * Verifies the get methods return the expected data.
-     */
-    @Test
-    public void testGetMethods() {
-        TetherNetworkConnectionStatus status = buildConnectionStatusBuilder().build();
-        assertEquals(status.getStatus(), CONNECTION_STATUS_ENABLING_HOTSPOT);
-        assertEquals(status.getTetherNetwork(), buildTetherNetworkBuilder().build());
-        assertEquals(status.getExtras().getInt(BUNDLE_KEY), buildBundle().getInt(BUNDLE_KEY));
-    }
-
-    private TetherNetworkConnectionStatus.Builder buildConnectionStatusBuilder() {
-
-        return new TetherNetworkConnectionStatus.Builder()
-                .setStatus(CONNECTION_STATUS_ENABLING_HOTSPOT)
-                .setTetherNetwork(buildTetherNetworkBuilder().build())
-                .setExtras(buildBundle());
-    }
-
-    private Bundle buildBundle() {
-        Bundle bundle = new Bundle();
-        bundle.putInt(BUNDLE_KEY, 1);
-        return bundle;
-    }
-
-    private TetherNetwork.Builder buildTetherNetworkBuilder() {
-        return new TetherNetwork.Builder()
-                .setDeviceId(DEVICE_ID)
-                .setDeviceInfo(DEVICE_INFO)
-                .setNetworkType(NETWORK_TYPE)
-                .setNetworkName(NETWORK_NAME)
-                .setHotspotSsid(HOTSPOT_SSID)
-                .setHotspotBssid(HOTSPOT_BSSID)
-                .setHotspotSecurityTypes(HOTSPOT_SECURITY_TYPES);
-    }
-}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkTest.java
deleted file mode 100644
index b01aec4..0000000
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkTest.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.sharedconnectivity.app;
-
-import static android.net.wifi.WifiInfo.SECURITY_TYPE_EAP;
-import static android.net.wifi.WifiInfo.SECURITY_TYPE_PSK;
-import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_PHONE;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_TABLET;
-import static android.net.wifi.sharedconnectivity.app.TetherNetwork.NETWORK_TYPE_CELLULAR;
-import static android.net.wifi.sharedconnectivity.app.TetherNetwork.NETWORK_TYPE_WIFI;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-
-import android.os.Parcel;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-
-/**
- * Unit tests for {@link android.net.wifi.sharedconnectivity.app.TetherNetwork}.
- */
-@SmallTest
-public class TetherNetworkTest {
-    private static final long DEVICE_ID = 11L;
-    private static final DeviceInfo DEVICE_INFO = new DeviceInfo.Builder()
-            .setDeviceType(DEVICE_TYPE_TABLET).setDeviceName("TEST_NAME").setModelName("TEST_MODEL")
-            .setConnectionStrength(2).setBatteryPercentage(50).build();
-    private static final int NETWORK_TYPE = NETWORK_TYPE_CELLULAR;
-    private static final String NETWORK_NAME = "TEST_NETWORK";
-    private static final String HOTSPOT_SSID = "TEST_SSID";
-    private static final String HOTSPOT_BSSID = "TEST _BSSID";
-    private static final int[] HOTSPOT_SECURITY_TYPES = {SECURITY_TYPE_WEP, SECURITY_TYPE_EAP};
-
-    private static final long DEVICE_ID_1 = 111L;
-    private static final DeviceInfo DEVICE_INFO_1 = new DeviceInfo.Builder()
-            .setDeviceType(DEVICE_TYPE_PHONE).setDeviceName("TEST_NAME").setModelName("TEST_MODEL")
-            .setConnectionStrength(2).setBatteryPercentage(50).build();
-    private static final int NETWORK_TYPE_1 = NETWORK_TYPE_WIFI;
-    private static final String NETWORK_NAME_1 = "TEST_NETWORK1";
-    private static final String HOTSPOT_SSID_1 = "TEST_SSID1";
-    private static final String HOTSPOT_BSSID_1 = "TEST _BSSID1";
-    private static final int[] HOTSPOT_SECURITY_TYPES_1 = {SECURITY_TYPE_PSK, SECURITY_TYPE_EAP};
-
-    /**
-     * Verifies parcel serialization/deserialization.
-     */
-    @Test
-    public void testParcelOperation() {
-        TetherNetwork network = buildTetherNetworkBuilder().build();
-
-        Parcel parcelW = Parcel.obtain();
-        network.writeToParcel(parcelW, 0);
-        byte[] bytes = parcelW.marshall();
-        parcelW.recycle();
-
-        Parcel parcelR = Parcel.obtain();
-        parcelR.unmarshall(bytes, 0, bytes.length);
-        parcelR.setDataPosition(0);
-        TetherNetwork fromParcel = TetherNetwork.CREATOR.createFromParcel(parcelR);
-
-        assertEquals(network, fromParcel);
-        assertEquals(network.hashCode(), fromParcel.hashCode());
-    }
-
-    /**
-     * Verifies the Equals operation
-     */
-    @Test
-    public void testEqualsOperation() {
-        TetherNetwork network1 = buildTetherNetworkBuilder().build();
-        TetherNetwork network2 = buildTetherNetworkBuilder().build();
-        assertEquals(network1, network2);
-
-        TetherNetwork.Builder builder = buildTetherNetworkBuilder().setDeviceId(DEVICE_ID_1);
-        assertNotEquals(network1, builder.build());
-
-        builder = buildTetherNetworkBuilder().setDeviceInfo(DEVICE_INFO_1);
-        assertNotEquals(network1, builder.build());
-
-        builder = buildTetherNetworkBuilder().setNetworkType(NETWORK_TYPE_1);
-        assertNotEquals(network1, builder.build());
-
-        builder = buildTetherNetworkBuilder().setNetworkName(NETWORK_NAME_1);
-        assertNotEquals(network1, builder.build());
-
-        builder = buildTetherNetworkBuilder().setHotspotSsid(HOTSPOT_SSID_1);
-        assertNotEquals(network1, builder.build());
-
-        builder = buildTetherNetworkBuilder().setHotspotBssid(HOTSPOT_BSSID_1);
-        assertNotEquals(network1, builder.build());
-
-        builder = buildTetherNetworkBuilder().setHotspotSecurityTypes(HOTSPOT_SECURITY_TYPES_1);
-        assertNotEquals(network1, builder.build());
-    }
-
-    /**
-     * Verifies the get methods return the expected data.
-     */
-    @Test
-    public void testGetMethods() {
-        TetherNetwork network = buildTetherNetworkBuilder().build();
-        assertEquals(network.getDeviceId(), DEVICE_ID);
-        assertEquals(network.getDeviceInfo(), DEVICE_INFO);
-        assertEquals(network.getNetworkType(), NETWORK_TYPE);
-        assertEquals(network.getNetworkName(), NETWORK_NAME);
-        assertEquals(network.getHotspotSsid(), HOTSPOT_SSID);
-        assertEquals(network.getHotspotBssid(), HOTSPOT_BSSID);
-        assertArrayEquals(network.getHotspotSecurityTypes(), HOTSPOT_SECURITY_TYPES);
-    }
-
-    private TetherNetwork.Builder buildTetherNetworkBuilder() {
-        return new TetherNetwork.Builder()
-                .setDeviceId(DEVICE_ID)
-                .setDeviceInfo(DEVICE_INFO)
-                .setNetworkType(NETWORK_TYPE)
-                .setNetworkName(NETWORK_NAME)
-                .setHotspotSsid(HOTSPOT_SSID)
-                .setHotspotBssid(HOTSPOT_BSSID)
-                .setHotspotSecurityTypes(HOTSPOT_SECURITY_TYPES);
-    }
-}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java
index a04526a..b8b6b767 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java
@@ -18,25 +18,26 @@
 
 import static android.net.wifi.WifiInfo.SECURITY_TYPE_EAP;
 import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_TABLET;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetwork.NETWORK_TYPE_CELLULAR;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.CONNECTION_STATUS_UNKNOWN;
 import static android.net.wifi.sharedconnectivity.app.KnownNetwork.NETWORK_SOURCE_NEARBY_SELF;
 import static android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus.CONNECTION_STATUS_SAVED;
-import static android.net.wifi.sharedconnectivity.app.TetherNetwork.NETWORK_TYPE_CELLULAR;
-import static android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus.CONNECTION_STATUS_UNKNOWN;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
 
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
 import android.content.Intent;
-import android.net.wifi.sharedconnectivity.app.DeviceInfo;
+import android.content.res.Resources;
+import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
+import android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus;
 import android.net.wifi.sharedconnectivity.app.KnownNetwork;
 import android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus;
+import android.net.wifi.sharedconnectivity.app.NetworkProviderInfo;
 import android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState;
-import android.net.wifi.sharedconnectivity.app.TetherNetwork;
-import android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus;
 import android.os.Bundle;
 import android.os.Looper;
 import android.os.RemoteException;
@@ -52,31 +53,34 @@
 import java.util.List;
 
 /**
- * Unit tests for {@link android.net.wifi.sharedconnectivity.service.SharedConnectivityService}.
+ * Unit tests for {@link SharedConnectivityService}.
  */
 @SmallTest
 public class SharedConnectivityServiceTest {
-    private static final int[] SECURITY_TYPES = {SECURITY_TYPE_WEP, SECURITY_TYPE_EAP};
-    private static final DeviceInfo DEVICE_INFO = new DeviceInfo.Builder()
-            .setDeviceType(DEVICE_TYPE_TABLET).setDeviceName("TEST_NAME").setModelName("TEST_MODEL")
-            .setConnectionStrength(2).setBatteryPercentage(50).build();
-    private static final TetherNetwork TETHER_NETWORK =
-            new TetherNetwork.Builder().setDeviceId(1).setDeviceInfo(DEVICE_INFO)
-                    .setNetworkType(NETWORK_TYPE_CELLULAR).setNetworkName("TEST_NETWORK")
+    private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
+            new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
+                    .setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
+                    .setBatteryPercentage(50).build();
+    private static final HotspotNetwork HOTSPOT_NETWORK =
+            new HotspotNetwork.Builder().setDeviceId(1).setNetworkProviderInfo(
+                            NETWORK_PROVIDER_INFO)
+                    .setHostNetworkType(NETWORK_TYPE_CELLULAR).setNetworkName("TEST_NETWORK")
                     .setHotspotSsid("TEST_SSID").setHotspotBssid("TEST_BSSID")
-                    .setHotspotSecurityTypes(SECURITY_TYPES).build();
-    private static final List<TetherNetwork> TETHER_NETWORKS = List.of(TETHER_NETWORK);
+                    .addHotspotSecurityType(SECURITY_TYPE_WEP)
+                    .addHotspotSecurityType(SECURITY_TYPE_EAP).build();
+    private static final List<HotspotNetwork> HOTSPOT_NETWORKS = List.of(HOTSPOT_NETWORK);
     private static final KnownNetwork KNOWN_NETWORK =
             new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE_NEARBY_SELF)
-                    .setSsid("TEST_SSID").setSecurityTypes(SECURITY_TYPES)
-                    .setDeviceInfo(DEVICE_INFO).build();
+                    .setSsid("TEST_SSID").addSecurityType(SECURITY_TYPE_WEP)
+                    .addSecurityType(SECURITY_TYPE_EAP).setNetworkProviderInfo(
+                            NETWORK_PROVIDER_INFO).build();
     private static final List<KnownNetwork> KNOWN_NETWORKS = List.of(KNOWN_NETWORK);
     private static final SharedConnectivitySettingsState SETTINGS_STATE =
             new SharedConnectivitySettingsState.Builder().setInstantTetherEnabled(true)
                     .setExtras(Bundle.EMPTY).build();
-    private static final TetherNetworkConnectionStatus TETHER_NETWORK_CONNECTION_STATUS =
-            new TetherNetworkConnectionStatus.Builder().setStatus(CONNECTION_STATUS_UNKNOWN)
-                    .setTetherNetwork(TETHER_NETWORK).setExtras(Bundle.EMPTY).build();
+    private static final HotspotNetworkConnectionStatus TETHER_NETWORK_CONNECTION_STATUS =
+            new HotspotNetworkConnectionStatus.Builder().setStatus(CONNECTION_STATUS_UNKNOWN)
+                    .setHotspotNetwork(HOTSPOT_NETWORK).setExtras(Bundle.EMPTY).build();
     private static final KnownNetworkConnectionStatus KNOWN_NETWORK_CONNECTION_STATUS =
             new KnownNetworkConnectionStatus.Builder().setStatus(CONNECTION_STATUS_SAVED)
                     .setKnownNetwork(KNOWN_NETWORK).setExtras(Bundle.EMPTY).build();
@@ -84,22 +88,29 @@
     @Mock
     Context mContext;
 
+    @Mock
+    Resources mResources;
+
     static class FakeSharedConnectivityService extends SharedConnectivityService {
         public void attachBaseContext(Context context) {
             super.attachBaseContext(context);
         }
 
         @Override
-        public void onConnectTetherNetwork(@NonNull TetherNetwork network) {}
+        public void onConnectHotspotNetwork(@NonNull HotspotNetwork network) {
+        }
 
         @Override
-        public void onDisconnectTetherNetwork(@NonNull TetherNetwork network) {}
+        public void onDisconnectHotspotNetwork(@NonNull HotspotNetwork network) {
+        }
 
         @Override
-        public void onConnectKnownNetwork(@NonNull KnownNetwork network) {}
+        public void onConnectKnownNetwork(@NonNull KnownNetwork network) {
+        }
 
         @Override
-        public void onForgetKnownNetwork(@NonNull KnownNetwork network) {}
+        public void onForgetKnownNetwork(@NonNull KnownNetwork network) {
+        }
     }
 
     @Before
@@ -111,17 +122,20 @@
     @Test
     public void onBind_isNotNull() {
         SharedConnectivityService service = createService();
-        assertNotNull(service.onBind(new Intent()));
+
+        assertThat(service.onBind(new Intent())).isNotNull();
     }
 
     @Test
-    public void getTetherNetworks() throws RemoteException {
+    public void getHotspotNetworks() throws RemoteException {
         SharedConnectivityService service = createService();
         ISharedConnectivityService.Stub binder =
                 (ISharedConnectivityService.Stub) service.onBind(new Intent());
 
-        service.setTetherNetworks(TETHER_NETWORKS);
-        assertArrayEquals(TETHER_NETWORKS.toArray(), binder.getTetherNetworks().toArray());
+        service.setHotspotNetworks(HOTSPOT_NETWORKS);
+
+        assertThat(binder.getHotspotNetworks())
+                .containsExactlyElementsIn(List.copyOf(HOTSPOT_NETWORKS));
     }
 
     @Test
@@ -131,7 +145,9 @@
                 (ISharedConnectivityService.Stub) service.onBind(new Intent());
 
         service.setKnownNetworks(KNOWN_NETWORKS);
-        assertArrayEquals(KNOWN_NETWORKS.toArray(), binder.getKnownNetworks().toArray());
+
+        assertThat(binder.getKnownNetworks())
+                .containsExactlyElementsIn(List.copyOf(KNOWN_NETWORKS));
     }
 
     @Test
@@ -141,17 +157,20 @@
                 (ISharedConnectivityService.Stub) service.onBind(new Intent());
 
         service.setSettingsState(SETTINGS_STATE);
-        assertEquals(SETTINGS_STATE, binder.getSettingsState());
+
+        assertThat(binder.getSettingsState()).isEqualTo(SETTINGS_STATE);
     }
 
     @Test
-    public void updateTetherNetworkConnectionStatus() throws RemoteException {
+    public void updateHotspotNetworkConnectionStatus() throws RemoteException {
         SharedConnectivityService service = createService();
         ISharedConnectivityService.Stub binder =
                 (ISharedConnectivityService.Stub) service.onBind(new Intent());
 
-        service.updateTetherNetworkConnectionStatus(TETHER_NETWORK_CONNECTION_STATUS);
-        assertEquals(TETHER_NETWORK_CONNECTION_STATUS, binder.getTetherNetworkConnectionStatus());
+        service.updateHotspotNetworkConnectionStatus(TETHER_NETWORK_CONNECTION_STATUS);
+
+        assertThat(binder.getHotspotNetworkConnectionStatus())
+                .isEqualTo(TETHER_NETWORK_CONNECTION_STATUS);
     }
 
     @Test
@@ -161,7 +180,51 @@
                 (ISharedConnectivityService.Stub) service.onBind(new Intent());
 
         service.updateKnownNetworkConnectionStatus(KNOWN_NETWORK_CONNECTION_STATUS);
-        assertEquals(KNOWN_NETWORK_CONNECTION_STATUS, binder.getKnownNetworkConnectionStatus());
+
+        assertThat(binder.getKnownNetworkConnectionStatus())
+                .isEqualTo(KNOWN_NETWORK_CONNECTION_STATUS);
+    }
+
+    @Test
+    public void areHotspotNetworksEnabledForService() {
+        when(mContext.getResources()).thenReturn(mResources);
+        when(mContext.getPackageName()).thenReturn("package");
+        when(mResources.getString(anyInt())).thenReturn("package");
+        when(mResources.getBoolean(anyInt())).thenReturn(true);
+
+        assertThat(SharedConnectivityService.areHotspotNetworksEnabledForService(mContext))
+                .isTrue();
+    }
+
+    @Test
+    public void areHotspotNetworksEnabledForService_notSamePackage_shouldReturnFalse() {
+        when(mContext.getResources()).thenReturn(mResources);
+        when(mContext.getPackageName()).thenReturn("package");
+        when(mResources.getString(anyInt())).thenReturn("other_package");
+        when(mResources.getBoolean(anyInt())).thenReturn(true);
+
+        assertThat(SharedConnectivityService.areHotspotNetworksEnabledForService(mContext))
+                .isFalse();
+    }
+
+    @Test
+    public void areKnownNetworksEnabledForService() {
+        when(mContext.getResources()).thenReturn(mResources);
+        when(mContext.getPackageName()).thenReturn("package");
+        when(mResources.getString(anyInt())).thenReturn("package");
+        when(mResources.getBoolean(anyInt())).thenReturn(true);
+
+        assertThat(SharedConnectivityService.areKnownNetworksEnabledForService(mContext)).isTrue();
+    }
+
+    @Test
+    public void areKnownNetworksEnabledForService_notSamePackage_shouldReturnFalse() {
+        when(mContext.getResources()).thenReturn(mResources);
+        when(mContext.getPackageName()).thenReturn("package");
+        when(mResources.getString(anyInt())).thenReturn("other_package");
+        when(mResources.getBoolean(anyInt())).thenReturn(true);
+
+        assertThat(SharedConnectivityService.areKnownNetworksEnabledForService(mContext)).isFalse();
     }
 
     private SharedConnectivityService createService() {